📄 output-rait.c
字号:
/* write the chunks in the main buffer */ for( i = 0; i < data_fds; i++ ) { res = tapefd_write(pr->fds[i], buf + len*i , len); rait_debug(stderr, _("rait_write: write(%d,%lx,%d) returns %d%s%s\n"), pr->fds[i], (unsigned long)(buf + len*i), len, res, (res < 0) ? ": " : "", (res < 0) ? strerror(errno) : ""); if (res < 0) { total = res; break; } total += res; } if (total >= 0 && pr->nfds > 1) { /* write the sum, don't include it in the total bytes written */ res = tapefd_write(pr->fds[i], pr->xorbuf, len); rait_debug(stderr, _("rait_write: write(%d,%lx,%d) returns %d%s%s\n"), pr->fds[i], (unsigned long)pr->xorbuf, len, res, (res < 0) ? ": " : "", (res < 0) ? strerror(errno) : ""); if (res < 0) { total = res; } } rait_debug(stderr, _("rait_write:returning %d%s%s\n"), total, (total < 0) ? ": " : "", (total < 0) ? strerror(errno) : ""); return total;}/**//*** once again, if there is one data stream do a read, otherwise** do all n reads, and if any of the first n - 1 fail, compute** the missing block from the other three, then return the data.** there's some silliness here for reading tape with bigger buffers** than we wrote with, (thus the extra bcopys down below). On disk if** you read with a bigger buffer size than you wrote with, you just** garble the data...*/ssize_trait_read( int fd, void * bufptr, size_t len){ char *buf = bufptr; int nerrors, neofs, errorblock; ssize_t total; int i; size_t j; RAIT *pr; int data_fds; int save_errno = errno; ssize_t maxreadres = 0; int sum_mismatch = 0; rait_debug(stderr, _("rait_read(%d,%lx,%d)\n"),fd,(unsigned long)buf,len); if ((fd < 0) || ((size_t)fd >= rait_table_count)) { errno = EBADF; rait_debug(stderr, _("rait_read:returning %d: %s\n"), -1, strerror(errno)); return -1; } pr = &rait_table[fd]; if (0 == pr->nopen) { errno = EBADF; rait_debug(stderr, _("rait_read:returning %d: %s\n"), -1, strerror(errno)); return -1; } nerrors = 0; neofs = 0; errorblock = -1; /* once again , we slice it evenly... */ if (pr->nfds > 1) { data_fds = pr->nfds - 1; if (0 != len % data_fds) { errno = EDOM; rait_debug(stderr, _("rait_read:returning %d: %s\n"), -1, strerror(errno)); return -1; } len = len / data_fds; } else { data_fds = 1; } /* try all the reads, save the result codes */ /* count the eof/errors */ for( i = 0; i < data_fds; i++ ) { pr->readres[i] = tapefd_read(pr->fds[i], buf + len*i , len); rait_debug(stderr, _("rait_read: read on fd %d returns %d%s%s\n"), pr->fds[i], pr->readres[i], (pr->readres[i] < 0) ? ": " : "", (pr->readres[i] < 0) ? strerror(errno) : ""); if ( pr->readres[i] <= 0 ) { if ( pr->readres[i] == 0 ) { neofs++; } else { if (0 == nerrors) { save_errno = errno; } nerrors++; } errorblock = i; } else if (pr->readres[i] > maxreadres) { maxreadres = pr->readres[i]; } } if (pr->nfds > 1) { /* make sure we have enough buffer space */ if (len > (size_t)pr->xorbuflen) { if (0 != pr->xorbuf) { amfree(pr->xorbuf); } pr->xorbuf = alloc(len); pr->xorbuflen = len; } pr->readres[i] = tapefd_read(pr->fds[i], pr->xorbuf , len); rait_debug(stderr, _("rait_read: read on fd %d returns %d%s%s\n"), pr->fds[i], pr->readres[i], (pr->readres[i] < 0) ? ": " : "", (pr->readres[i] < 0) ? strerror(errno) : ""); } /* * Make sure all the reads were the same length */ for (j = 0; j < (size_t)pr->nfds; j++) { if (pr->readres[j] != maxreadres) { nerrors++; errorblock = (int)j; } } /* * If no errors, check that the xor sum matches */ if ( nerrors == 0 && pr->nfds > 1 ) { for(i = 0; i < (int)maxreadres; i++ ) { int sum = 0; for(j = 0; (j + 1) < (size_t)pr->nfds; j++) { sum ^= (buf + len * j)[i]; } if (sum != pr->xorbuf[i]) { sum_mismatch = 1; } } } /* ** now decide what "really" happened -- ** all n getting eof is a "real" eof ** just one getting an error/eof is recoverable if we are doing RAIT ** anything else fails */ if (neofs == pr->nfds) { rait_debug(stderr, _("rait_read:returning 0\n")); return 0; } if (sum_mismatch) { errno = EDOM; rait_debug(stderr, _("rait_read:returning %d: %s\n"), -1, _("XOR block mismatch")); return -1; } if (nerrors > 1 || (pr->nfds <= 1 && nerrors > 0)) { errno = save_errno; rait_debug(stderr, _("rait_read:returning %d: %s\n"), -1, strerror(errno)); return -1; } /* ** so now if we failed on a data block, we need to do a recovery ** if we failed on the xor block -- who cares? */ if (nerrors == 1 && pr->nfds > 1 && errorblock != pr->nfds-1) { rait_debug(stderr, _("rait_read: fixing data from fd %d\n"), pr->fds[errorblock]); /* the reads were all *supposed* to be the same size, so... */ pr->readres[errorblock] = maxreadres; /* fill it in first with the xor sum */ memcpy(buf + len * errorblock, pr->xorbuf, len); /* xor back out the other blocks */ for( i = 0; i < data_fds; i++ ) { if( i != errorblock ) { for( j = 0; j < len ; j++ ) { buf[j + len * errorblock] ^= buf[j + len * i]; } } } /* there, now the block is back as if it never failed... */ } /* pack together partial reads... */ total = pr->readres[0]; for( i = 1; i < data_fds; i++ ) { if (total != (ssize_t)(len * i)) { memmove(buf + total, buf + len*i, (size_t)pr->readres[i]); } total += pr->readres[i]; } rait_debug(stderr, _("rait_read:returning %d%s%s\n"), total, (total < 0) ? ": " : "", (total < 0) ? strerror(errno) : ""); return total;}/**/intrait_ioctl( int fd, int op, void * p){ int i, res = 0; RAIT *pr; int errors = 0; rait_debug(stderr, _("rait_ioctl(%d,%d)\n"),fd,op); if ((fd < 0) || ((size_t)fd >= rait_table_count)) { errno = EBADF; rait_debug(stderr, _("rait_ioctl:returning %d: %s\n"), -1, strerror(errno)); return -1; } pr = &rait_table[fd]; if (0 == pr->nopen) { errno = EBADF; rait_debug(stderr, _("rait_ioctl:returning %d: %s\n"), -1, strerror(errno)); return -1; } for( i = 0; i < pr->nfds ; i++ ) { /*@ignore@*/ res = ioctl(pr->fds[i], op, p); /*@end@*/ if ( res != 0 ) { errors++; if (errors > 1) { break; } res = 0; } } rait_debug(stderr, _("rait_ioctl: returning %d%s%s\n"), res, (res < 0) ? ": " : "", (res < 0) ? strerror(errno) : ""); return res;}/*** access() all the devices, returning if any fail*/intrait_access( char * devname, int flags){ int res = 0; char *dev_left; /* string before { */ char *dev_right; /* string after } */ char *dev_next; /* string inside {} */ char *dev_real; /* parsed device name */ /* copy and parse the dev string so we can scribble on it */ devname = stralloc(devname); if (0 == devname) { rait_debug(stderr, _("rait_access:returning %d: %s\n"), -1, _("out of stralloc memory")); return -1; } if ( 0 != tapeio_init_devname(devname, &dev_left, &dev_right, &dev_next)) { rait_debug(stderr, _("rait_access:returning %d: %s\n"), -1, strerror(errno)); return -1; } while( 0 != (dev_real = tapeio_next_devname(dev_left, dev_right, &dev_next))) { res = tape_access(dev_real, flags); rait_debug(stderr,_("rait_access:access( %s, %d ) yields %d\n"), dev_real, flags, res ); amfree(dev_real); if (res < 0) { break; } } amfree(devname); rait_debug(stderr, _("rait_access: returning %d%s%s\n"), res, (res < 0) ? ": " : "", (res < 0) ? strerror(errno) : ""); return res;}/*** stat all the devices, returning the last one unless one fails*/intrait_stat( char * devname, struct stat *buf){ int res = 0; char *dev_left; /* string before { */ char *dev_right; /* string after } */ char *dev_next; /* string inside {} */ char *dev_real; /* parsed device name */ /* copy and parse the dev string so we can scribble on it */ devname = stralloc(devname); if (0 == devname) { rait_debug(stderr, _("rait_access:returning %d: %s\n"), -1, _("out of stralloc memory")); return -1; } if ( 0 != tapeio_init_devname(devname, &dev_left, &dev_right, &dev_next)) { rait_debug(stderr, _("rait_access:returning %d: %s\n"), -1, strerror(errno)); return -1; } while( 0 != (dev_real = tapeio_next_devname(dev_left, dev_right, &dev_next))) { res = tape_stat(dev_real, buf); rait_debug(stderr,_("rait_stat:stat( %s ) yields %d (%s)\n"), dev_real, res, (res != 0) ? strerror(errno) : _("no error") ); amfree(dev_real); if (res != 0) { break; } } amfree(devname); rait_debug(stderr, _("rait_access: returning %d%s%s\n"), res, (res < 0) ? ": " : "", (res < 0) ? strerror(errno) : ""); return res;}/**/intrait_copy( char * f1, char * f2, size_t buflen){ int t1, t2; ssize_t len; ssize_t wres; char *buf; int save_errno; t1 = rait_open(f1,O_RDONLY,0644); if (t1 < 0) { return t1; } t2 = rait_open(f2,O_CREAT|O_RDWR,0644); if (t2 < 0) { save_errno = errno; (void)rait_close(t1); errno = save_errno; return -1; } buf = alloc(buflen); do { len = rait_read(t1,buf,buflen); if (len > 0 ) { wres = rait_write(t2, buf, (size_t)len); if (wres < 0) { len = -1; break; } } } while( len > 0 ); save_errno = errno; amfree(buf); (void)rait_close(t1); (void)rait_close(t2); errno = save_errno; return (len < 0) ? -1 : 0;}/**//*** Amanda Tape API routines:*/static intrait_tapefd_ioctl( int (*func0)(int), int (*func1)(int, off_t), int fd, off_t count){ int i, j, res = 0; RAIT *pr; int errors = 0; pid_t kid; int status = 0; rait_debug(stderr, _("rait_tapefd_ioctl(%d,%d)\n"),fd,count); if ((fd < 0) || ((size_t)fd >= rait_table_count)) { errno = EBADF; rait_debug(stderr, _("rait_tapefd_ioctl:returning %d: %s\n"), -1, strerror(errno)); return -1; } pr = &rait_table[fd]; if (0 == pr->nopen) { errno = EBADF; rait_debug(stderr, _("rait_tapefd_ioctl:returning %d: %s\n"), -1, strerror(errno)); return -1; } if (0 == pr->readres && 0 < pr->nfds) { pr->readres = alloc(pr->nfds * SIZEOF(*pr->readres)); memset(pr->readres, 0, pr->nfds * SIZEOF(*pr->readres)); } for( i = 0; i < pr->nfds ; i++ ) { if(tapefd_can_fork(pr->fds[i])) { if ((kid = fork()) < 1) { rait_debug(stderr, _("in kid, fork returned %d\n"), kid); /* if we are the kid, or fork failed do the action */ if (func0 != NULL) { res = (*func0)(pr->fds[i]); } else { res = (*func1)(pr->fds[i], count); } rait_debug(stderr, _("in kid, func (%d) returned %d errno %s\n"), pr->fds[i], res, strerror(errno)); if (kid == 0) exit(res); } else { rait_debug(stderr, _("in parent, fork returned %d\n"), kid); pr->readres[i] = (ssize_t)kid; } } else { if(func0 != NULL) { j = (*func0)(pr->fds[i]); } else { j = (*func1)(pr->fds[i], count); } if( j != 0) { errors++; } pr->readres[i] = -1; } } for( i = 0; i < pr->nfds ; i++ ) { if(tapefd_can_fork(pr->fds[i])) { rait_debug(stderr, _("in parent, waiting for %d\n"), pr->readres[i]); waitpid((pid_t)pr->readres[i], &status, 0); if( WEXITSTATUS(status) != 0 ) { res = WEXITSTATUS(status); if( res == 255 ) res = -1; } rait_debug(stderr, _("in parent, return code was %d\n"), res); if ( res != 0 ) { errors++; res = 0; } } } if (errors > 0) { res = -1; } rait_debug(stderr, _("rait_tapefd_ioctl: returning %d%s%s\n"), res, (res < 0) ? ": " : "", (res < 0) ? strerror(errno) : ""); return res;}intrait_tapefd_fsf( int fd, off_t count){ return rait_tapefd_ioctl(NULL, tapefd_fsf, fd, count);}intrait_tapefd_rewind( int fd){ return rait_tapefd_ioctl(tapefd_rewind, NULL, fd, (off_t)-1);}intrait_tapefd_unload( int fd){ return rait_tapefd_ioctl(tapefd_unload, NULL, fd, (off_t)-1);}intrait_tapefd_weof( int fd, off_t count){ return rait_tapefd_ioctl(NULL, tapefd_weof, fd, count);}intrait_tape_open( char * name, int flags, mode_t mask){ return rait_open(name, flags, mask);}intrait_tapefd_status( int fd, struct am_mt_status *stat){ int i; RAIT *pr; int res = 0; int errors = 0; rait_debug(stderr, _("rait_tapefd_status(%d)\n"),fd); if ((fd < 0) || ((size_t)fd >= rait_table_count)) { errno = EBADF; rait_debug(stderr, _("rait_tapefd_status:returning %d: %s\n"), -1, strerror(errno)); return -1; } pr = &rait_table[fd]; if (0 == pr->nopen) { errno = EBADF; rait_debug(stderr, _("rait_tapefd_status:returning %d: %s\n"), -1, strerror(errno)); return -1; } for( i = 0; i < pr->nfds ; i++ ) { res = tapefd_status(pr->fds[i], stat); if(res != 0) { errors++; } } if (errors > 0) { res = -1; } return res;}voidrait_tapefd_resetofs( int fd){ (void)rait_lseek(fd, (off_t)0, SEEK_SET);}intrait_tapefd_can_fork( int fd){ (void)fd; /* Quiet unused parameter warning */ return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -