📄 output-file.c
字号:
g_fprintf(f, "%lld %lld %zu\n", (long long)fi->ri[r].start_record, (long long)fi->ri[r].end_record, fi->ri[r].record_size); } afclose(f); fi->ri_altered = 0; }common_exit: amfree(filename);}/* * Release any files beyond a given position current position and reset * file_count to file_current to indicate EOM. */static voidfile_release( int fd){ off_t position; char *filename; off_t pos; char number[NUM_STR_SIZE]; struct file_info **fi_p; /* * If the current file is open, release everything beyond it. * If it is not open, release everything from current. */ if (volume_info[fd].fd >= 0) { position = volume_info[fd].file_current + 1; } else { position = volume_info[fd].file_current; } for (pos = position; pos < volume_info[fd].file_count; pos++) { assert(pos < (off_t)SSIZE_MAX); fi_p = &volume_info[fd].fi; amtable_alloc((void **)fi_p, &volume_info[fd].fi_limit, SIZEOF(*volume_info[fd].fi), (size_t)(pos + 1), 10, NULL); if (volume_info[fd].fi[pos].name != NULL) { g_snprintf(number, SIZEOF(number), "%05lld", (long long)pos); filename = vstralloc(volume_info[fd].basename, number, DATA_INDICATOR, volume_info[fd].fi[pos].name, NULL); unlink(filename); amfree(filename); filename = vstralloc(volume_info[fd].basename, number, RECORD_INDICATOR, volume_info[fd].fi[pos].name, NULL); unlink(filename); amfree(filename); amfree(volume_info[fd].fi[pos].name); volume_info[fd].fi[pos].ri_count = 0; } } volume_info[fd].file_count = position;}/* * Get the size of a particular record. We assume the record information is * sorted, does not overlap and does not have gaps. */static size_tget_record_size( struct file_info * fi, off_t record){ size_t r; struct record_info *ri; for(r = 0; r < fi->ri_count; r++) { ri = &fi->ri[r]; if (record <= ri->end_record) { return ri->record_size; } } /* * For historical reasons, the default record size is 32 KBytes. * This allows us to read files written by Amanda with that block * size before the record information was being kept. */ return 32 * 1024;}/* * Update the record information. We assume the record information is * sorted, does not overlap and does not have gaps. */static voidput_record_size( struct file_info * fi, off_t record, size_t size){ size_t r; struct record_info *ri; struct record_info **ri_p; fi->ri_altered = 1; if (record == (off_t)0) { fi->ri_count = 0; /* start over */ } for(r = 0; r < fi->ri_count; r++) { ri = &fi->ri[r]; if ((record - (off_t)1) <= ri->end_record) { /* * If this record is the same size as the rest of the records * in this entry, or it would replace the entire entry, * reset the end record number and size, then zap the chain * beyond this point. */ if (record == ri->start_record || ri->record_size == size) { ri->end_record = record; ri->record_size = size; fi->ri_count = r + 1; return; } /* * This record needs a new entry right after the current one. */ ri->end_record = record - (off_t)1; fi->ri_count = r + 1; break; } } /* * Add a new entry. */ ri_p = &fi->ri; amtable_alloc((void **)ri_p, &fi->ri_limit, SIZEOF(*fi->ri), (size_t)fi->ri_count + 1, 10, NULL); ri = &fi->ri[fi->ri_count]; ri->start_record = record; ri->end_record = record; ri->record_size = size; fi->ri_count++;}/* * The normal interface routines ... */intfile_tape_open( char * filename, int flags, mode_t mask){ int fd; int save_errno; char *info_file; struct volume_info **volume_info_p = &volume_info; /* * Use only O_RDONLY and O_RDWR. */ if ((flags & 3) != O_RDONLY) { flags &= ~3; flags |= O_RDWR; } /* * If the caller did not set O_CREAT (and thus, pass a mask * parameter), we may still end up creating data files and need a * "reasonable" value. Pick a "tight" value on the "better safe * than sorry" theory. */ if ((flags & O_CREAT) == 0) { mask = 0600; } /* * Open/create the info file for this "tape". */ info_file = stralloc2(filename, "/info"); if ((fd = open(info_file, O_RDWR|O_CREAT, 0600)) < 0) { goto common_exit; } /* * Create the internal info structure for this "tape". */ amtable_alloc((void **)volume_info_p, &open_count, SIZEOF(*volume_info), (size_t)fd + 1, 10, NULL); volume_info[fd].flags = flags; volume_info[fd].mask = mask; volume_info[fd].file_count = 0; volume_info[fd].file_current = 0; volume_info[fd].record_current = (off_t)0; volume_info[fd].fd = -1; volume_info[fd].is_online = 0; /* true when .../data found */ volume_info[fd].at_bof = 1; /* by definition */ volume_info[fd].at_eof = 0; /* do not know yet */ volume_info[fd].at_eom = 0; /* may get reset below */ volume_info[fd].last_operation_write = 0; volume_info[fd].amount_written = (off_t)0; /* * Save the base directory name and see if we are "online". */ volume_info[fd].basename = stralloc2(filename, "/data/"); if (check_online(fd)) { save_errno = errno; aclose(fd); fd = -1; amfree(volume_info[fd].basename); errno = save_errno; goto common_exit; }common_exit: amfree(info_file); /* * Return the info file descriptor as the unique descriptor for * this open. */ return fd;}ssize_tfile_tapefd_read( int fd, void * buffer, size_t count){ ssize_t result; int file_fd; off_t pos; size_t record_size; size_t read_size; /* * Make sure we are online. */ if (check_online(fd) != 0) { return -1; } if (! volume_info[fd].is_online) { errno = EIO; return -1; } /* * Do not allow any more reads after we find EOF. */ if (volume_info[fd].at_eof) { errno = EIO; return -1; } /* * If we are at EOM, set EOF and return a zero length result. */ if (volume_info[fd].at_eom) { volume_info[fd].at_eof = 1; return 0; } /* * Open the file, if needed. */ if ((file_fd = file_open(fd)) < 0) { return -1; } /* * Make sure we do not read too much. */ pos = volume_info[fd].file_current; record_size = get_record_size(&volume_info[fd].fi[pos], volume_info[fd].record_current); if (record_size <= count) { read_size = record_size; } else { read_size = count; } /* * Read the data. If we ask for less than the record size, skip to * the next record boundary. */ result = read(file_fd, buffer, read_size); if (result > 0) { volume_info[fd].at_bof = 0; if ((size_t)result < record_size) { if (lseek(file_fd, (off_t)(record_size-result), SEEK_CUR) == (off_t)-1) { dbprintf(_("file_tapefd_read: lseek failed: <%s>\n"), strerror(errno)); } } volume_info[fd].record_current += (off_t)1; } else if (result == 0) { volume_info[fd].at_eof = 1; } return result;}ssize_tfile_tapefd_write( int fd, const void *buffer, size_t count){ int file_fd; ssize_t write_count = (ssize_t)count; off_t length; off_t kbytes_left; ssize_t result; off_t pos; /* * Make sure we are online. */ if (check_online(fd) != 0) { return -1; } if (! volume_info[fd].is_online) { errno = EIO; return -1; } /* * Check for write access first. */ if ((volume_info[fd].flags & 3) == O_RDONLY) { errno = EBADF; return -1; } /* * Special case: allow negative buffer size. */ if (write_count <= 0) { return 0; /* special case */ } /* * If we are at EOM, it takes precedence over EOF. */ if (volume_info[fd].at_eom) { volume_info[fd].at_eof = 0; }#if 0 /*JJ*/ /* * Writes are only allowed at BOF and EOM. */ if (! (volume_info[fd].at_bof || volume_info[fd].at_eom)) { errno = EIO; return -1; }#endif /*JJ*/ /* * Writes are only allowed if we are not at EOF. */ if (volume_info[fd].at_eof) { errno = EIO; return -1; } /* * Open the file, if needed. */ if((file_fd = volume_info[fd].fd) < 0) { file_release(fd); if ((file_fd = file_open(fd)) < 0) { return -1; } } /* * Truncate the write if requested and return a simulated ENOSPC. */ if ((length = tapefd_getinfo_length(fd)) > (off_t)0) { kbytes_left = length - volume_info[fd].amount_written; if ((off_t)(write_count / 1024) > kbytes_left) { write_count = (ssize_t)kbytes_left * 1024; } } volume_info[fd].amount_written += (off_t)((write_count + 1023) / 1024); if (write_count <= 0) { volume_info[fd].at_bof = 0; volume_info[fd].at_eom = 1; errno = ENOSPC; return -1; } /* * Do the write and truncate the file, if needed. Checking for * last_operation_write is an optimization so we only truncate * once. */ if (! volume_info[fd].last_operation_write) { off_t curpos; if ((curpos = lseek(file_fd, (off_t)0, SEEK_CUR)) < 0) { dbprintf(_(": Can not determine current file position <%s>"), strerror(errno)); return -1; } if (ftruncate(file_fd, curpos) != 0) { dbprintf(_("ftruncate failed; Can not trim output file <%s>"), strerror(errno)); return -1; } volume_info[fd].at_bof = 0; volume_info[fd].at_eom = 1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -