⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 output-file.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
📖 第 1 页 / 共 3 页
字号:
	    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 + -