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

📄 chunker.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
📖 第 1 页 / 共 2 页
字号:
    *pc = '/';    if ((outfd = open(tmp_filename, O_RDWR|O_CREAT|O_TRUNC, 0600)) < 0) {	int save_errno = errno;	errstr = squotef(_("holding file \"%s\": %s"),			 tmp_filename,			 strerror(errno));	amfree(tmp_filename);	aclose(infd);	if(save_errno == ENOSPC) {	    putresult(NO_ROOM, "%s %lld\n",	    	      handle, (long long)use);	    return -2;	} else {	    return -1;	}    }    amfree(tmp_filename);    databuf_init(db, outfd, filename, use, chunksize);    db->filename_seq++;    return infd;}static intdo_chunk(    int			infd,    struct databuf *	db){    ssize_t nread;    char header_buf[DISK_BLOCK_BYTES];    startclock();    dumpsize = dumpbytes = filesize = (off_t)0;    headersize = 0;    memset(header_buf, 0, sizeof(header_buf));    /*     * The first thing we should receive is the file header, which we     * need to save into "file", as well as write out.  Later, the     * chunk code will rewrite it.     */    nread = fullread(infd, header_buf, SIZEOF(header_buf));    if (nread != DISK_BLOCK_BYTES) {	if(nread < 0) {	    errstr = vstrallocf(_("cannot read header: %s"), strerror(errno));	} else {	    errstr = vstrallocf(_("cannot read header: got %zd bytes instead of %d"),				nread,				DISK_BLOCK_BYTES);	}	return 0;    }    parse_file_header(header_buf, &file, (size_t)nread);    if(write_tapeheader(db->fd, &file)) {	int save_errno = errno;	errstr = squotef(_("write_tapeheader file %s: %s"),			 db->filename, strerror(errno));	if(save_errno == ENOSPC) {	    putresult(NO_ROOM, "%s %lld\n", handle, 		      (long long)(db->use+db->split_size-dumpsize));	}	return 0;    }    dumpsize += (off_t)DISK_BLOCK_KB;    filesize = (off_t)DISK_BLOCK_KB;    headersize += DISK_BLOCK_KB;    /*     * We've written the file header.  Now, just write data until the     * end.     */    while ((nread = fullread(infd, db->buf,			     (size_t)(db->datalimit - db->datain))) > 0) {	db->datain += nread;	while(db->dataout < db->datain) {	    if(!databuf_flush(db)) {		return 0;	    }	}    }    while(db->dataout < db->datain) {	if(!databuf_flush(db)) {	    return 0;	}    }    if(dumpbytes > (off_t)0) {	dumpsize += (off_t)1;			/* count partial final KByte */	filesize += (off_t)1;    }    return 1;}/* * Initialize a databuf.  Takes a writeable file descriptor. */static voiddatabuf_init(    struct databuf *	db,    int			fd,    char *		filename,    off_t		use,    off_t		chunk_size){    db->fd = fd;    db->filename = stralloc(filename);    db->filename_seq = (off_t)0;    db->chunk_size = chunk_size;    db->split_size = (db->chunk_size > use) ? use : db->chunk_size;    db->use = (use > db->split_size) ? use - db->split_size : (off_t)0;    db->datain = db->dataout = db->buf;    db->datalimit = db->buf + SIZEOF(db->buf);}/* * Write out the buffer to the backing file */static intdatabuf_flush(    struct databuf *	db){    struct cmdargs cmdargs;    int rc = 1;    ssize_t written;    off_t left_in_chunk;    char *arg_filename = NULL;    char *qarg_filename = NULL;    char *new_filename = NULL;    char *tmp_filename = NULL;    char sequence[NUM_STR_SIZE];    int newfd;    filetype_t save_type;    char *q;    int a;    char *pc;    /*     * If there's no data, do nothing.     */    if (db->dataout >= db->datain) {	goto common_exit;    }    /*     * See if we need to split this file.     */    while (db->split_size > (off_t)0 && dumpsize >= db->split_size) {	if( db->use == (off_t)0 ) {	    /*	     * Probably no more space on this disk.  Request some more.	     */	    cmd_t cmd;	    putresult(RQ_MORE_DISK, "%s\n", handle);	    cmd = getcmd(&cmdargs);	    if(command_in_transit == -1 &&	       (cmd == DONE || cmd == TRYAGAIN || cmd == FAILED)) {		command_in_transit = cmd;		cmd = getcmd(&cmdargs);	    }	    if(cmd == CONTINUE) {		/*		 * CONTINUE		 *   serial		 *   filename		 *   chunksize		 *   use		 */		cmdargs.argc++;			/* true count of args */		a = 3;		if(a >= cmdargs.argc) {		    error(_("error [chunker CONTINUE: not enough args: filename]"));		    /*NOTREACHED*/		}		qarg_filename = newstralloc(qarg_filename, cmdargs.argv[a++]);		if (arg_filename != NULL)		    amfree(arg_filename);		arg_filename = unquote_string(qarg_filename);		if(a >= cmdargs.argc) {		    error(_("error [chunker CONTINUE: not enough args: chunksize]"));		    /*NOTREACHED*/		}		db->chunk_size = OFF_T_ATOI(cmdargs.argv[a++]);		db->chunk_size = am_floor(db->chunk_size, (off_t)DISK_BLOCK_KB);		if(a >= cmdargs.argc) {		    error(_("error [chunker CONTINUE: not enough args: use]"));		    /*NOTREACHED*/		}		db->use = OFF_T_ATOI(cmdargs.argv[a++]);		if(a != cmdargs.argc) {		    error(_("error [chunker CONTINUE: too many args: %d != %d]"),			  cmdargs.argc, a);		    /*NOTREACHED*/		}		if(strcmp(db->filename, arg_filename) == 0) {		    /*		     * Same disk, so use what room is left up to the		     * next chunk boundary or the amount we were given,		     * whichever is less.		     */		    left_in_chunk = db->chunk_size - filesize;		    if(left_in_chunk > db->use) {			db->split_size += db->use;			db->use = (off_t)0;		    } else {			db->split_size += left_in_chunk;			db->use -= left_in_chunk;		    }		    if(left_in_chunk > (off_t)0) {			/*			 * We still have space in this chunk.			 */			break;		    }		} else {		    /*		     * Different disk, so use new file.		     */		    db->filename = newstralloc(db->filename, arg_filename);		}	    } else if(cmd == ABORT) {		abort_pending = 1;		errstr = newstralloc(errstr, "ERROR");		putresult(ABORT_FINISHED, "%s\n", handle);		rc = 0;		goto common_exit;	    } else {		if(cmdargs.argc >= 1) {		    q = squote(cmdargs.argv[1]);		} else if(cmdargs.argc >= 0) {		    q = squote(cmdargs.argv[0]);		} else {		    q = stralloc(_("(no input?)"));		}		error(_("error [bad command after RQ-MORE-DISK: \"%s\"]"), q);		/*NOTREACHED*/	    }	}	/*	 * Time to use another file.	 */	/*	 * First, open the new chunk file, and give it a new header	 * that has no cont_filename pointer.	 */	g_snprintf(sequence, SIZEOF(sequence), "%d", db->filename_seq);	new_filename = newvstralloc(new_filename,				    db->filename,				    ".",				    sequence,				    NULL);	tmp_filename = newvstralloc(tmp_filename,				    new_filename,				    ".tmp",				    NULL);	pc = strrchr(tmp_filename, '/');	*pc = '\0';	mkholdingdir(tmp_filename);	*pc = '/';	newfd = open(tmp_filename, O_RDWR|O_CREAT|O_TRUNC, 0600);	if (newfd == -1) {	    int save_errno = errno;	    if(save_errno == ENOSPC) {		putresult(NO_ROOM, "%s %lld\n", handle, 			  (long long)(db->use+db->split_size-dumpsize));		db->use = (off_t)0;			/* force RQ_MORE_DISK */		db->split_size = dumpsize;		continue;	    }	    errstr = squotef(_("creating chunk holding file \"%s\": %s"),			     tmp_filename,			     strerror(errno));	    aclose(db->fd);	    rc = 0;	    goto common_exit;	}	save_type = file.type;	file.type = F_CONT_DUMPFILE;	file.cont_filename[0] = '\0';	if(write_tapeheader(newfd, &file)) {	    int save_errno = errno;	    aclose(newfd);	    if(save_errno == ENOSPC) {		putresult(NO_ROOM, "%s %lld\n", handle, 			  (long long)(db->use+db->split_size-dumpsize));		db->use = (off_t)0;			/* force RQ_MORE DISK */		db->split_size = dumpsize;		continue;	    }	    errstr = squotef(_("write_tapeheader file %s: %s"),			     tmp_filename,			     strerror(errno));	    rc = 0;	    goto common_exit;	}	/*	 * Now, update the header of the current file to point	 * to the next chunk, and then close it.	 */	if (lseek(db->fd, (off_t)0, SEEK_SET) < (off_t)0) {	    errstr = squotef(_("lseek holding file %s: %s"),			     db->filename,			     strerror(errno));	    aclose(newfd);	    rc = 0;	    goto common_exit;	}	file.type = save_type;	strncpy(file.cont_filename, new_filename, SIZEOF(file.cont_filename));	file.cont_filename[SIZEOF(file.cont_filename)] = '\0';	if(write_tapeheader(db->fd, &file)) {	    errstr = squotef(_("write_tapeheader file \"%s\": %s"),			     db->filename,			     strerror(errno));	    aclose(newfd);	    unlink(tmp_filename);	    rc = 0;	    goto common_exit;	}	file.type = F_CONT_DUMPFILE;	/*	 * Now shift the file descriptor.	 */	aclose(db->fd);	db->fd = newfd;	newfd = -1;	/*	 * Update when we need to chunk again	 */	if(db->use <= (off_t)DISK_BLOCK_KB) {	    /*	     * Cheat and use one more block than allowed so we can make	     * some progress.	     */	    db->split_size += (off_t)(2 * DISK_BLOCK_KB);	    db->use = (off_t)0;	} else if(db->chunk_size > db->use) {	    db->split_size += db->use;	    db->use = (off_t)0;	} else {	    db->split_size += db->chunk_size;	    db->use -= db->chunk_size;	}	amfree(tmp_filename);	amfree(new_filename);	dumpsize += (off_t)DISK_BLOCK_KB;	filesize = (off_t)DISK_BLOCK_KB;	headersize += DISK_BLOCK_KB;	db->filename_seq++;    }    /*     * Write out the buffer     */    written = fullwrite(db->fd, db->dataout,			(size_t)(db->datain - db->dataout));    if (written > 0) {	db->dataout += written;	dumpbytes += (off_t)written;    }    dumpsize += (dumpbytes / (off_t)1024);    filesize += (dumpbytes / (off_t)1024);    dumpbytes %= 1024;    if (written < 0) {	if (errno != ENOSPC) {	    errstr = squotef(_("data write: %s"), strerror(errno));	    rc = 0;	    goto common_exit;	}	/*	 * NO-ROOM is informational only.  Later, RQ_MORE_DISK will be	 * issued to use another holding disk.	 */	putresult(NO_ROOM, "%s %lld\n", handle,		  (long long)(db->use+db->split_size-dumpsize));	db->use = (off_t)0;				/* force RQ_MORE_DISK */	db->split_size = dumpsize;	goto common_exit;    }    if (db->datain == db->dataout) {	/*	 * We flushed the whole buffer so reset to use it all.	 */	db->datain = db->dataout = db->buf;    }common_exit:    amfree(new_filename);    /*@i@*/ amfree(tmp_filename);    amfree(arg_filename);    amfree(qarg_filename);    return rc;}/* * Send an Amanda dump header to the output file and set file->blocksize */static ssize_twrite_tapeheader(    int		outfd,    dumpfile_t *file){    char *buffer;    ssize_t written;    file->blocksize = DISK_BLOCK_BYTES;    buffer = build_header(file, DISK_BLOCK_BYTES);    written = fullwrite(outfd, buffer, DISK_BLOCK_BYTES);    amfree(buffer);    if(written == DISK_BLOCK_BYTES) return 0;    if(written < 0) return written;    errno = ENOSPC;    return (ssize_t)-1;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -