cdbackup-0.7.0/0040755000000000000000000000000010121313621011762 5ustar rootrootcdbackup-0.7.0/CHANGES0100644000000000000000000000377510121254645013000 0ustar rootroot0.7.0 ----- - fixed a length check which prevented dumping of images which are bigger than half of their maximum size. 0.6.5beta --------- - fixed adding a track to a virtual image >2GB. - fixed media size detection for DVD+. - Prevent filename change when restoring a multidisk virtual image from a non-regular filename (e.g. /dev/cdrom). 0.6.4beta --------- - added support for file based backups (virtual image). - added DVD support (needs cdrecord-ProDVD). - added CRC checksum to ensure backup integrity. - now auto-detecting media size (via cdrecord -atip). - now using defaults from environment vars CDR_DEVICE & CDR_SPEED. - fixed a typo in the man page (Debian Bug#180279). - check return value of read() in diskchange. - fixed missing stderr in fprintf() calls. - added some glue to compile on SunOS. 0.6.3 ----- - added -F option to cdrestore to force starting restore in the middle of a multi-disk set. - added -T option to cdrestore for testing data integrity. - added -R option to cdrestore to disable kernel read-ahead during restore. - added debug output with option -D for cdbackup/cdrestore. - added a "known problems" section to the man page covering the read-error-at-end-of-session problem. - improved Makefile. 0.6.2 ----- - some more fixes to allow >2GB data on a single disk (SH) - added commandline option to specify padsize and enable CDROM XA2 mode (SH) - changed gcc options in Makefile (SH) - code cleanup (SH) - added man page, updated README (SH) 0.6.1 ----- - fixed size calculations with multi-disk backups > 2GB (SH) - minor message cleanups (CC) 0.6 --- - multidisk-support (SH) - unix-like commandline options (SH) - can pass additional options to cdrecord (SH) - code cleanup (SH) - various bugs fixed (SH) 0.5.2 ----- - Revamped Makefile (CC) 0.5.1 ----- - Fixed bug in command-line parsing (JY) - Added error messages to command-line parsing (JY, CC) - Various sloppy code fixes (JY, CC) - Changed Makefile to check for compiler warnings (JY, CC) 0.5.0 ----- Initial public release. cdbackup-0.7.0/CREDITS0100644000000000000000000000117207630516372013023 0ustar rootroot This is list of people who have contributed to cdbackup. It is sorted by name and formatted to allow easy grepping and beautification by scripts. The fields are: name (N), email (E), web-address (W), PGP key ID and fingerprint (P), description (D), and snail-mail address (S). ---------- N: Craig Condit E: ccondit@cableone.net D: Initial development S: Fargo, ND USA N: James Youngman E: jay@gnu.org D: Various bugfixes S: Manchester, UK N: Stefan Huelswitt E: huels@iname.com D: multidisk support, code cleanup, bugfixes S: Monheim, Germany N: Alejandro Marín E: amarin@servpast.org D: SunOS port S: San José, Costa Rica cdbackup-0.7.0/LICENSE0100644000000000000000000000236407436177314013017 0ustar rootrootCopyright (c) 2000-2002 Craig Condit, Stefan Hülswitt. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. cdbackup-0.7.0/Makefile0100644000000000000000000000241310020065170013420 0ustar rootroot# compiler selection and options CC = gcc CFLAGS = -g -O2 -Wall DEPFLAGS = -MM -MG # install location PREFIX=/usr/local BINDIR=$(PREFIX)/bin MANDIR=$(PREFIX)/man ############################################### TARGETS = cdbackup cdrestore VERSION = $(shell grep 'define VERSION' version.h | awk '{ print $$3 }' | sed -e 's/["]//g') ARCHIVE = cdbackup-$(VERSION) DEPFILE = .dependencies TMPDIR = /tmp all: $(TARGETS) %.o: %.c $(CC) $(CFLAGS) -c $< -o $@ $(DEPFILE): Makefile @$(CC) $(DEPFLAGS) cdbackup.c cdrestore.c cdrom.c virtual.c misc.c > $@ include $(DEPFILE) cdbackup: cdbackup.o cdrom.o virtual.o virtual-backup.o misc.o $(CC) $(CFLAGS) -o $@ $^ cdrestore: cdrestore.o cdrom.o virtual.o misc.o $(CC) $(CFLAGS) -o $@ $^ strip: $(TARGETS) strip $(TARGETS) clean: rm -f $(TARGETS) $(DEPFILE) cdbackup-*.tar.gz core *.core *.o dist: clean @-rm -rf $(TMPDIR)/$(ARCHIVE) @mkdir $(TMPDIR)/$(ARCHIVE) @cp -a * $(TMPDIR)/$(ARCHIVE) @tar czf $(ARCHIVE).tar.gz -C $(TMPDIR) $(ARCHIVE) @-rm -rf $(TMPDIR)/$(ARCHIVE) @echo Distribution package created as $(ARCHIVE).tar.gz install: install -d $(BINDIR) install $(TARGETS) $(BINDIR) install -d $(MANDIR)/man1 gzip -c cdbackup.1 >$(MANDIR)/man1/cdbackup.1.gz gzip -c cdrestore.1 >$(MANDIR)/man1/cdrestore.1.gz cdbackup-0.7.0/README0100644000000000000000000000340510121313540012641 0ustar rootrootcdbackup, cdrestore - CD archive utilities version 0.6.4beta Copyright (c) 2000-2004 Craig Condit, Stefan Hülswitt. All rights reserved. This software is released under a BSD-style license - see the LICENSE file. cdbackup and cdrestore are a pair of utilities designed to facilitiate streaming backup to and from CD-R(W)/DVD-R(W) disks. Specificially, they were designed to work with dump/restore, but tar/cpio/afio/whatever you want should work, so long as it writes to stdout for backups and reads from stdin for restores. NOTE: this program REQUIRES that a recent version of cdrecord (or cdrecord-ProDVD for DVD support) be present in the PATH. See manpages for further details. INSTALL: -------- Look at the Makefile, adjust options as you like. The default install location is under /usr/local. make make strip (optionaly) make install DISCLAIMER: ----------- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. CONTACT: -------- Project maintainer is: Stefan Hülswitt Homepage: http://www.muempf.de/ Any comments, suggestions, bug reports, patches and fixes welcome. cdbackup-0.7.0/cdbackup.10100644000000000000000000002323710121313403013622 0ustar rootroot.TH "cdbackup" "1" "0.7.0" "Stefan Hülswitt" "" .SH "NAME" .LP cdbackup \- Streaming backup to CD\-R(W)/DVR\-R(W) .SH "SYNOPSIS" .LP cdbackup [\-mvwCDRVX] [\-d \fIdevice\fP] [\-r \fIscsi\-dev\fP] [\-s \fIspeed\fP] [\-i \fIimage\fP] [\-p \fInum\fP] [\-l \fIsize\fP] [\-a \fIlabel\fP] [\-c \fIcommand\fP] [\-\- \fIcdrecord\-options\fP] .SH "DESCRIPTION" .LP cdbackup is a utility to make streaming backups to CD\-R(W)/DVD\-R(W) disks. It's designed to work with any backup tool which writes the backup to stdout (like tar/cpio/afio). .LP \fINOTE:\fR this program REQUIRES that a recent version of \fBcdrecord\fR(1) (or cdrecord\-ProDVD for DVD support) is present in the PATH. .LP While you can perfectly append several sessions on CD\-R(W) media, I didn't manage to make this work on DVD\-R(W) media. To allow multiple, separate backups on these media, the concept of virtual images has been introduced. .br A virtual image is a plain file on your harddisk. You can append several backups to an image and after completing your backup session, the image is dumped to CDR/DVD media in one burning session. You can dump the same image multiple times too, if you want redundancy on the CDR/DVD media. .br Virtual image files are never deleted by cdbackup. After dumping an image, you have to delete it by your self. .LP \fIWARNING!\fR When using this program under Linux, be sure not to use dump on a mounted filesystem. This has a high potential for creating corrupted backups. As of kernel version 2.4.19, this has not been fixed and it may not be fixed at all. You can read Linus statement about this at .SH "OPTIONS" .LP .TP \fB\-d\fR \fIdevice\fP The device name which is used for reading things like the TOC from a (partly written) media. .br (default: /dev/burner) .TP \fB\-r\fR \fIscsi\-device\fP The scsi device which is passed to \fBcdrecord\fR(1) (via dev=\fIscsi\-device\fP). Must be given as three, comma seperated number: \fIscsibus\fR,\fItarget\fR,\fIlun\fR. .br (default: none or the contents of the environment variable CDR_DEVICE) .TP \fB\-s\fR \fIspeed\fP The writing speed which is passed to \fBcdrecord\fR(1) (via speed=\fIspeed\fP). .br (default: 4 or the contents of the environment variable CDR_SPEED) .TP \fB\-p\fR \fInum\fP The number of sectors (of 2048 byte) to use for padding (see \fBcdrecord\fR(1) padsize). .br (default: 15) .TP \fB\-X\fR Enables the use of CDROM XA2 mode in \fBcdrecord\fR(1). By default CDROM mode 1 is used. The default is possibly causing problems during restore on certain kernel version/CDROM hardware combinations at the end of the last session on a media. Sony drives doesn't support CDROM XA 2 mode (see \fBcdrecord\fR(1) \-multi). .TP \fB\-R\fR Enables DVD writing mode. Cdrecord\-ProDVD is used to burn DVD media, but it's called through a script called "dvdrecord". You should set your cdrecord\-ProDVD key and call cdrecord\-ProDVD from there. .br Remember that you cannot write multiple sessions to DVD media. Either you stick with one backup per media or you have to use virtual images. .br In DVD mode the options \-p and \-X have no effect. .TP \fB\-i\fR \fIimage\fP Enables virtual image mode. The backup stream is written to the given image file. The file is created if it doesn't exists. It's mandatory to give an explicit media size with \-l. Take care that the created virtual image isn't lager that the media size you want to dump it later. You can add up to 96 backups to an virtual image. .br If the backup extends the specified media size and you have enabled multi\-disk mode, additional images files are created (the filenames are derived from the inital image name by adding a dot and a decimal number). .br (default: none) .TP \fB\-w\fR Dump the virtual image specified with \-i to real media. Image dumps are written as single sessions always. If you have enabled multi\-disk mode and additional images are found, you're prompted for media change, so that you can dump all images in turn. .br Virtual images (even when dumped to media) are not compatible with older cdbackup versions. .TP \fB\-l\fR \fIsize\fP For normal operation the media size is auto\-detected from the cdrecord ATIP information. If this fails or for virtual image mode use this option to set the media size. This is used to calculate how much data can be stored on the media. .br By default the given value is taken as megabytes. You can append a single letter to the number to select: (k)ilobytes, (m)egabytes, (g)igabytes or (s)ectors (e.g. 170k, 4488m, 350000s). .br (default: auto\-detect) .TP \fB\-C\fR Disables creation of the datablock CRC checksum. There is no real reason to use this option, unless you can't efford the extra 0,2% media space that is used to store the checksum. .br Although the on\-disk layout of checksumed backups is different, they are fully backwards compatible with older version of cdbackup, but obviously older versions can't check the backup integrity. .TP \fB\-a\fR \fIlabel\fP A text label to identify the backup set. The first 32 characters of this string are save with the backup. .br (default: "CDBackup Track") .TP \fB\-c\fR \fIcommand\fP The command which is executed whenever cdbackup needs to request a new media in multi\-disk mode. This command (or script) should prompt the user and return after the recording device is ready again. The command receives one argument, which is the device name passed with \fB\-d\fR. This can be used to issue commands to the device like ejecting the media. .br (default: use internal diskchange prompt) .TP \fB\-m\fR Enables multi\-disk mode. When the current media is filled, a new media is requested (see option \fB\-c\fR) and the backup is continued. Backups can only be continued to empty media, this means you cannot insert a partly filled media for continuation. .TP \fB\-v\fR Enables verbose mode. .TP \fB\-D\fR Enables DEBUG output (probably not usefull for normal use). .TP \fB\-V\fR Prints out version information and exits. .TP \fB\-\-\fR \fIcdrecord\-options\fP Pass following options to \fBcdrecord\fR(1). .SH "EXAMPLES" .LP To create a tar archive of /home and output it to a 700 MB CD\-R(W) on /dev/scd0 (scsi device 2,0): .IP tar cvf \- /home | cdbackup \-d /dev/scd0 \-r 2,0 \-l 700 \-a "Test Backup" .LP To create a tar archive of /usr and output it to a series (multi\-disk mode) of 650 MB CD\-R(W) on /dev/sr1 (scsi device 1,4,0) with writting speed 12 and verbose output: .IP tar cf \- /usr | cdbackup \-d /dev/sr1 \-r 1,4,0 \-s 12 \-m \-v .LP To create a backup on a virtual image: .IP tar cf \- /usr | cdbackup \-i /tmp/vimage \-l 4488m .LP Add another backup to the same virtual image (with multi\-disk mode): .IP tar cf \- /home | cdbackup \-i /tmp/vimage \-l 4488m .LP Dump the virtual image to one (or several) DVD media on /dev/cdrom (scsi\-ide device 0,0,0), enabling BURNFREE: .IP cdbackup \-i /tmp/vimage \-w \-R \-d /dev/cdrom \-r 0,0,0 \-s 4 \-m \-\- driveropts=burnfree .SH "KNOWN PROBLEMS" .LP Certain combinations of CDROM drivers and kernel versions are causing a problem when restoring data. The restore process aborts with an read error close to the end of the session, while the data on the media is perfectly good. .LP All CDR sessions written in track\-at\-once mode (which is unavoidable for multisessions) end in at least two unreadable runout sectors (for additional information refer to the file README.copy from the cdrecord package). As the kernel does some readahead on the device, it stumbles over these unreadable sectors before reaching the actual end of data. .LP Some drivers are reporting to syslog but doesn't pass the error to the application, while others make the application fail. From user feedback, it seems that pure SCSI setups are mostly working fine, while ide\-scsi setups are likely to fail. .LP The author isn't able to provide a full solution, but some hints which may help: .TP 1. Update to a recent kernel. .TP 2. Disable kernel readahead with option \-R when restoring. .TP 3. Increase the padsize with option \-p. Use values >= 128. .TP 4. Use option \-X if your writer supports this (Sony drives doesn't supports this mode). .LP Please contact the author if you can contribute additional information about the problem. .SH "AUTHORS" .LP Stefan Hülswitt .SH "SEE ALSO" .LP \fBcdrestore\fR(1), \fBcdrecord\fR(1) .SH "LICENSE" Copyright (c) 2000\-2004 Craig Condit, Stefan Hülswitt. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: .TP 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. .TP 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. .LP THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. cdbackup-0.7.0/cdbackup.c0100644000000000000000000003331210121255307013707 0ustar rootroot/* cdbackup.c Copyright (c) 2000-2004 Craig Condit, Stefan Hülswitt. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #define _LARGEFILE64_SOURCE #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #ifndef sun #include #endif #include "cdbackup.h" #include "cdrom.h" #include "virtual.h" #include "misc.h" #include "debug.h" #include "version.h" /* defaults */ char *prg_name ="cdbackup"; char *cd_dev ="/dev/burner"; char *cdr_dev =0; /* no default here, too dangerous */ char *cd_label ="CDBackup Track"; int cd_speed =4; long cd_len =-1; /* blocks */ int padsize =15; /* blocks */ int multidisk=0; char *multicmd =0; int verbose =0; int xamode2 =0; int crc =1; int debug =0; int virtual =0; char *virt_name=0; int virt_dump=0; int dvd =0; char **cdrec_opt=0; int cdrec_opt_count=0; long long totalSize=0; int disknum=1; int secs; struct tm curtime; /* global, so multi-disks get all the same time */ int auto_size=0; /****************************************************************************/ char *make_arg(const char *format, ...) { char *ptr; va_list ap; va_start(ap,format); if(vasprintf(&ptr,format,ap)<0) serror("No memory for cdrecord args\n"); va_end(ap); return ptr; } void start_cdrecord(void) { char **args, **p, *exname; int l; if(!(p=args=calloc(cdrec_opt_count+10,sizeof(char *)))) serror("No memory for cdrecord args\n"); if(dvd) exname="dvdrecord"; else exname="cdrecord"; *p++=exname; if(virt_dump || dvd) { *p++="-dao"; *p++=make_arg("tsize=%ds",secs); } else { *p++="-multi"; *p++=make_arg("padsize=%ds",padsize); } *p++=make_arg("speed=%d",cd_speed); *p++=make_arg("dev=%s",cdr_dev); for(l=0 ; l&1 dev=%s -atip",dvd ? "dvd":"cd",cdr_dev); DEBUG("%s: cdrecord atip command: %s\n",prg_name,cmd); p=popen(cmd,"r"); if(!p) fprintf(stderr,"%s: atip command failed\n",prg_name); else { char buff[256]; while(fgets(buff,sizeof(buff),p)) { if(dvd) { /* DVD-R */ if(!strncmp(buff,"rzone size:",11)) size=strtol(&buff[11],NULL,10); /* DVD+R */ else if(!strncmp(buff,"phys size:...",13)) size=strtol(&buff[13],NULL,10); } else if(!strncmp(buff," ATIP start of lead out:",25)) size=strtol(&buff[25],NULL,10); } } pclose(p); free(cmd); if(size>0 && verbose) { char buff[16]; fprintf(stderr,"%s: auto-detected media size %s (%ld blocks)\n",prg_name,FlexSize(buff,(long long)size*CD_FRAMESIZE),size); } return size; } /****************************************************************************/ void parse_cmdline(char argc, char *argv[]) { int i; char *val; /* get some default from the environment */ val=getenv("CDR_DEVICE"); if(val) { cdr_dev=strdup(val); DEBUG("cdbackup: using recording device %s from CDR_DEVICE\n",cdr_dev); } val=getenv("CDR_SPEED"); if(val) { cd_speed=strtol(val,NULL,10); DEBUG("cdbackup: using speed %d from CDR_SPEED\n",cd_speed); } while ((i=getopt(argc,argv,"d:r:l:s:p:a:c:mvVXDCi:wR"))>0) { switch (i) { case 'V': fprintf(stderr,"cdbackup "VERSION" (compiled "__DATE__")\n" "Copyright (C) 2000-2004\n" "This is free software; see the source for copying conditions.\n" "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n" "PARTICULAR PURPOSE.\n"); exit(0); case 'v': verbose=1; break; case 'm': multidisk=1; break; case 'X': xamode2=1; break; case 'c': multicmd=optarg; break; case 'd': cd_dev=optarg; break; case 'r': cdr_dev=optarg; break; case 'a': cd_label=optarg; break; case 'C': crc=0; break; case 'i': virt_name=optarg; virtual=1; break; case 'w': virt_dump=1; break; case 'R': dvd=1; DEBUG("cdbackup: DVD mode enabled\n"); break; case 'D': verbose=1; debug=1; DEBUG("cdbackup: DEBUG output enabled ("VERSION")\n"); break; case 'l': cd_len=(long)(FlexLen(optarg)/CD_FRAMESIZE); break; case 's': errno=0; cd_speed=strtol(optarg,NULL,10); if(errno==ERANGE || cd_speed<1) serror("Option -s: speed out of range (must be >=1)\n"); break; case 'p': errno=0; padsize=strtol(optarg,NULL,10); if(errno==ERANGE || padsize<15) serror("Option -p: padsize out of range (must be >=15)\n"); break; default: fprintf(stderr, "Usage: %s [options ...] [-- cdrecord-options ...]\n" "Reads from standard input, block formats and writes to CD-R(W).\n\n" " -d DEVICE DEVICE for CD queries (default /dev/burner)\n" " -l N set media size, disable auto-detect\n" " -r DEVICE DEVICE for CD recording (e.g. 0,4,0)\n" " -s N record CD at speed N (default 4)\n" " -X enable CDROM XA2 mode in cdrecord\n" " -a LABEL use LABEL as CD session title\n" " -p N use a padsize of N sectors for the session (default 15)\n" " -m enable multi-disk mode\n" " -c COMMAND call COMMAND on disk change in multi-disk mode\n" " -C disable checksum creation for datablocks\n" " -i IMAGE use virtual image IMAGE for recording\n" " -w dump virtual image to media\n" " -R enables DVD mode\n" " -v be verbose\n" " -D enable DEBUG output\n" " -V prints version & exits\n" " -- pass rest of commandline to cdrecord\n" "\n", prg_name); exit(0); } } if(optind0) { VvirtRead(buffer); Vwrite(buffer); grandTotal+=CD_FRAMESIZE; secs--; } VcloseTrack(0); totalSize+=grandTotal; if(verbose) { char str1[16], str2[16]; fprintf(stderr,"%s: Dumping finished. %s written (%s on this disk)\n", prg_name,FlexSize(str1,totalSize),FlexSize(str2,grandTotal)); } if(multidisk==0) { if(cont) fprintf(stderr,"Multi-disk not enabled, ignoring continuation image(s)!\n"); cont=0; } else { disknum++; diskchange(multicmd,cd_dev); } } while(cont); } /****************************************************************************/ int backup(void) { long long grandTotal=0; struct header_block header; int flags, datasize, result=0; char buffer[CD_FRAMESIZE]; struct data_block *db=(struct data_block *)&buffer[0]; flags=F_NONE; datasize=DATASIZE; if(crc) { flags|=F_CRC; datasize-=4; } sprintf(buffer,"%04d%02d%02d%02d%02d",curtime.tm_year+1900, curtime.tm_mon+1,curtime.tm_mday,curtime.tm_hour,curtime.tm_min); strncpy(header.id_str,HDR_STRING,32); header.id_str[32]=0; strncpy(header.vol_id,cd_label,32); header.vol_id[32]=0; strncpy(header.t_stamp,buffer,12); header.t_stamp[12]=0; header.disk_set = disknum; header.flags = flags; if(verbose) fprintf(stderr,"%s: Recording to %s, multidisk %s, CRC %s, disk %d\n", prg_name,VdevName(), multidisk?"enabled":"disabled", crc?"enabled":"disabled", disknum); secs=cd_len; VnewTrack(); memset(buffer,0,CD_FRAMESIZE); memcpy(buffer,&header,sizeof(struct header_block)); Vwrite(buffer); grandTotal+=CD_FRAMESIZE; do { int bytes; db->flags=flags; db->status=0; /* this isn't the last block (for now) */ bytes=full_read(0,&buffer[DBSIZE],datasize); if(bytes!=datasize) db->status=1; /* EOF, this is the last block */ db->datasize=htons(bytes); if(cd_avail<(CD_FRAMESIZE*2)) { /* less than 2 block free */ if(db->status==0) { /* if not last block, mark disk as full */ db->status=2; result=1; } } if(crc) { int l=crc32(buffer,bytes+DBSIZE); *((unsigned long *)(&buffer[CD_FRAMESIZE-4]))=l; } Vwrite(buffer); grandTotal+=CD_FRAMESIZE; } while(db->status==0); if(dvd && cd_avail>=CD_FRAMESIZE) { /* pad up the track with zeros */ memset(buffer,0,CD_FRAMESIZE); if(verbose) fprintf(stderr,"%s: padding up the track\n",prg_name); while(cd_avail>=CD_FRAMESIZE) Vwrite(buffer); } VcloseTrack(result); totalSize+=grandTotal; if(verbose) { char str1[16], str2[16]; fprintf(stderr,"%s: Recording finished. %s written (%s on this disk)\n", prg_name,FlexSize(str1,totalSize),FlexSize(str2,grandTotal)); } return result; } /****************************************************************************/ int main(int argc, char *argv[]) { int result, loop; time_t curtime_t; curtime_t=time(0); curtime=*localtime(&curtime_t); parse_cmdline(argc,argv); if(virt_dump) { dump(); } else { do { do { autosize(); Vopen(0); result=VreadToc(0); VprintSpace(); loop=1; if(disknum>1 && result!=0) { Vclose(); fprintf(stderr,"%s: Can't do multidisk continuation on non-empty disk! Try another disk\n", prg_name); diskchange(multicmd,cd_dev); } else if(cd_avail<(padsize+MIN_BLOCKS)*CD_FRAMESIZE) { Vclose(); if(multidisk) { fprintf(stderr,"%s: Not enough free space on disk! Try another disk\n", prg_name); diskchange(multicmd,cd_dev); } else serror("Not enough free space on disk"); } else loop=0; } while(loop); result=backup(); if(result==1) { if(multidisk==0) serror("Disk full, multi-disk not enabled. Aborting"); disknum++; if(!VisRegular()) diskchange(multicmd,cd_dev); } } while(result!=0); } return 0; } cdbackup-0.7.0/cdbackup.h0100644000000000000000000000445610020076777013735 0ustar rootroot/* cdbackup.h. Copyright (c) 2000-2004 Craig Condit, Stefan Hülswitt. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _CDBACKUP_H #define _CDBACKUP_H #include "version.h" #define NO_LABEL "CD-Backup Track" #define SHORT_HDR "cdbackup" #define HDR_STRING SHORT_HDR" "VERSION #define MIN_BLOCKS 2 /* min. required blocks for a session: header block, one data block */ #define F_NONE 0 /* flag values */ #define F_CRC 1 /* backup has CRC checksum */ struct header_block { char id_str[33]; /* recorder id string (32 chars) */ char vol_id[33]; /* volume label (32 characters) */ char t_stamp[13]; /* timestamp */ char disk_set; /* disk number - starts with 1 on multi-disk set */ char flags; /* flags for the backup set */ }; struct data_block { char status; /* status of block (0=continue, 1=done, 2=disk full) */ char flags; /* flags for this data block */ short datasize; /* # of bytes in block (max = CD_FRAMESIZE-this) */ }; extern int padsize; extern long cd_len; extern int verbose; extern char *prg_name; void start_cdrecord(void); #define DBSIZE sizeof(struct data_block) #define DATASIZE (CD_FRAMESIZE-DBSIZE) #endif cdbackup-0.7.0/cdrestore.10100644000000000000000000001072110121313420014031 0ustar rootroot.TH "cdrestore" "1" "0.7.0" "Stefan Hülswitt" "" .SH "NAME" .LP cdrestore \- Streaming restore from CD\-R(W)/DVD\-R(W) .SH "SYNOPSIS" .LP cdrestore [\-qvDFRTV] [\-d \fIdevice\fP] [\-i \fIimage\fP] [\-l \fIsize\fP] [\-t \fItrack\fP] [\-c \fIcommand\fP] .SH "DESCRIPTION" .LP cdrestore is a utility to make streaming restores from CD\-R(W)/DVD\-R(W) disks. It's designed to work with any backup tool which is able to restore from stdin (like tar/cpio/afio). .SH "OPTIONS" .LP .TP \fB\-d\fR \fIdevice\fP The device name which is used for reading the backup. .br (default: /dev/cdrom) .TP \fB\-i\fR \fIimage\fP Enables virtual image mode. The backup stream is read from the given image file. You have to use this option, if you are restoring from a dumped image too. .br (default: none) .TP \fB\-l\fR \fIsize\fP Specifies the media size. This value is used to display the free space on the media only. .br By default the given value is taken as megabytes. You can append a single letter to the number to select: (k)ilobytes, (m)egabytes, (g)igabytes or (s)ectors (e.g. 170k, 4488m, 350000s). .br (default: 650m) .TP \fB\-t\fR \fItrack\fP The number of the data track on the media for reading the backup. .br (default: none) .TP \fB\-T\fR Enables test mode. The complete restore process is done to test data integrity (includes CRC checksum test, if available), but no data is output. .br \fINOTE:\fR This only verifies that the data is readable by cdrestore at all. This doesn't guarantee that your backup software will be able to do a real restore with the data. .TP \fB\-F\fR Forces cdrestore to begin the restore in the middle of a multi\-disk set. This may be usefull if you have lost a disk or a disk is badly damaged. .br \fINOTE:\fR This will most probably start the restore in the middle of a file. It's up to your backup software to sync to the beginning of the next file. .TP \fB\-R\fR Disable the kernel readahead for the CDROM device during the restore process. (see \fBcdbackup\fR(1) Known problems) .TP \fB\-c\fR \fIcommand\fP The command which is executed whenever cdrestore needs to request a new media for multi\-disk backups. This command (or script) should prompt the user and return after the device is ready again. The command receives one argument, which is the device name passed with \fB\-d\fR. This can be used to issue commands to the device like ejecting the media. .br (default: use internal diskchange prompt) .TP \fB\-q\fR Queries the media, prints out the contents and exits. .TP \fB\-v\fR Enables verbose mode. .TP \fB\-D\fR Enables DEBUG output (probably not usefull for normal use). .TP \fB\-V\fR Prints out version information and exits. .SH "EXAMPLES" .LP Query the 700 MB media on /dev/sr0: .IP cdrestore \-d /dev/sr0 \-l 700 \-q .LP Restore a tar archive to the current directory from track 2 of a 702 MB media on /dev/scd0: .IP cdrestore \-d /dev/scd0 \-l 702 \-t 2 | tar xf \- .LP Query the contents of a virtual image: .IP cdrestore \-i /tmp/vimage \-l 4488m \-q .LP Check data integrity of track 3 in a virtual image after dumping it to DVD media: .IP cdrestore \-i /dev/dvd \-t 3 \-T .SH "AUTHORS" .LP Stefan Hülswitt .SH "SEE ALSO" .LP \fBcdbackup\fR(1) .SH "LICENSE" Copyright (c) 2000\-2004 Craig Condit, Stefan Hülswitt. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: .TP 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. .TP 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. .LP THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. cdbackup-0.7.0/cdrestore.c0100644000000000000000000002361710034761611014137 0ustar rootroot/* cdrestore.c Copyright (c) 2000-2004 Craig Condit, Stefan Hülswitt. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #define _LARGEFILE64_SOURCE #define _GNU_SOURCE #include #include #include #include #include #include #ifndef sun #include #endif #include #include "cdbackup.h" #include "virtual.h" #include "cdrom.h" #include "misc.h" #include "debug.h" #include "version.h" /* defaults */ char *prg_name ="cdrestore"; int cd_track =-1; char *cd_dev ="/dev/cdrom"; long cd_len =333000; /* blocks */ char *multicmd =0; int verbose =0; int force =0; int query =0; int verify =0; int ahead =0; int debug =0; int virtual =0; char *virt_name=0; int tracks; int disknum; long long totalSize; struct header_block headersave; /****************************************************************************/ void parse_cmdline(char argc, char *argv[]) { int i; while ((i=getopt(argc,argv,"d:l:c:t:qvVFTDRi:"))>0) { switch (i) { case 'V': fprintf(stderr,"cdrestore "VERSION" (compiled "__DATE__")\n" "Copyright (C) 2000-2004\n" "This is free software; see the source for copying conditions.\n" "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n" "PARTICULAR PURPOSE.\n"); exit(0); case 'c': multicmd=optarg; break; case 'd': cd_dev=optarg; break; case 'q': query=1; break; case 'F': force=1; break; case 'R': ahead=1; break; case 'T': verify=1; break; case 'v': verbose=1; break; case 'i': virt_name=optarg; virtual=1; break; case 'D': verbose=1; debug=1; DEBUG("cdrestore: DEBUG output enabled ("VERSION")\n"); break; case 't': errno=0; cd_track=strtol(optarg,NULL,10); if(errno==ERANGE || cd_track<1) serror("Option -t: invalid track (must be >=1)\n"); break; case 'l': cd_len=(long)(FlexLen(optarg)/CD_FRAMESIZE); break; default: fprintf(stderr, "Usage: %s [OPTION]...\n" "Reads block input from CD-R(W) and writes it to standard output.\n\n" " -d DEVICE DEVICE for CD queries (e.g. /dev/sr0)\n" " -q query disk and print TOC only\n" " -t N restore from track N\n" " -l N set media size\n" " -c COMMAND call COMMAND on disk change in multi-disk mode\n" " -T don't restore, test data integrity only\n" " -F force starting restore in the middle of a multi-disk set\n" " -R set the kernel read-ahead to zero during restore\n" " -i IMAGE use virtual image IMAGE for operation\n" " -v be verbose\n" " -D enable DEBUG output\n" " -V prints version & exits\n" "\n", prg_name); exit(0); } } if(!query && cd_track<0) /* need track number */ serror("A track number is required.\n"); } /****************************************************************************/ void print_track(int track, char *stamp, char *id, int disk, int startsec, int endsec, char flags) { char timestr[32], size[32], flstr[12]; snprintf(timestr,sizeof(timestr),"%02d/%02d/%04d %02d:%02d", (stamp[4]-'0')*10 + (stamp[5]-'0'), (stamp[6]-'0')*10 + (stamp[7]-'0'), (stamp[0]-'0')*1000 + (stamp[1]-'0')*100 + (stamp[2]-'0')*10 + (stamp[3]-'0'), (stamp[8]-'0')*10 + (stamp[9]-'0'), (stamp[10]-'0')*10 + (stamp[11]-'0')); if(startsec>=0) snprintf(size,sizeof(size)," %s:",FlexSize(flstr,((long long)(endsec-startsec+1)*CD_FRAMESIZE))); else size[0]=0; snprintf(flstr,sizeof(flstr),"%c",flags&F_CRC?'C':'.'); fprintf(stderr,"Track %02d:%s %s Part %d %s : %s\n", track, size, timestr, disk, flstr, id); if(startsec>=0) DEBUG(" Start sector %7d Last sector %7d\n",startsec,endsec); } /****************************************************************************/ int restore(int disktrack) { int result=0, i, bytes; long long totalRead=0, startPos; struct header_block header; char buffer[CD_FRAMESIZE]; struct data_block *db=(struct data_block *)&buffer[0]; for(i=tracks-1; i>=0; i--) if(toc[i].track_no==disktrack) break; if(i<0) { fprintf(stderr, "%s: Can't find track %d\n", prg_name, disktrack); exit(1); } startPos=Vseek(i); Vread(buffer); totalRead+=CD_FRAMESIZE; memcpy(&header,buffer,sizeof(header)); if(!strncmp(SHORT_HDR,header.id_str,strlen(SHORT_HDR))) { if(verbose) { fprintf(stderr,"%s: ", prg_name); print_track(disktrack, header.t_stamp, header.vol_id, header.disk_set, -1, -1, header.flags); } if(disknum==1) { if(header.disk_set!=1) { if(!force) { fprintf(stderr,"%s: This is disk %d of the multi-disk set! Use -F if you really want to start with this disk.\n",prg_name,header.disk_set); exit(1); } fprintf(stderr,"%s: This is disk %d of the multi-disk set, but -F forces me to continue!\n",prg_name,header.disk_set); disknum=header.disk_set; } headersave=header; /* save header for use with disk 2-n */ } else { if(strcmp(header.t_stamp,headersave.t_stamp) || strcmp(header.vol_id,headersave.vol_id)) { fprintf(stderr,"%s: This disk belongs to the backup set '%s', but you're restoring set '%s'!\n",prg_name,header.vol_id,headersave.vol_id); result=-1; } else if(header.disk_set!=disknum) { fprintf(stderr,"%s: Wrong sequence. This is disk %d, but you need disk %d now!\n",prg_name,header.disk_set,disknum); result=-1; } else if(verbose) fprintf(stderr, "%s: Beginning restore (Disk %d)\n", prg_name,disknum); } } else { fprintf(stderr, "%s: Track %02d was not created with 'cdbackup'\n", prg_name,disktrack); if(disknum==1) exit(1); result=-1; } while(!result) { int size; DEBUG("\rReading sector %7ld ",(long)((startPos+totalRead)/CD_FRAMESIZE)); Vread(buffer); size=ntohs(db->datasize); if(size>DATASIZE) { if(verbose) fprintf(stderr,"%s: Warning! Bad datasize at %lld\n",prg_name,totalRead); size=DATASIZE; } if(db->flags&F_CRC) { int l=crc32(buffer,size+DBSIZE); if(*((unsigned long *)(&buffer[CD_FRAMESIZE-4]))!=l) { if(verbose) fprintf(stderr,"%s: bad CRC checksum at %lld\n",prg_name,totalRead); serror("Bad checksum, block corrupted, restore failed"); } } totalRead+=CD_FRAMESIZE; if(!verify) { bytes=write(1,&buffer[DBSIZE],size); if(bytes!=size) error("Write failed (stdout)"); } if(db->status == 1) break; /* end of backup*/ if(db->status == 2) result=1; /* next disk */ } DEBUG("\n"); /* print status */ totalSize+=totalRead; if(result>=0 && verbose) { char str1[16], str2[16]; fprintf(stderr, "%s: Restore complete. %s read (%s from this disk)\n", prg_name,FlexSize(str1,totalSize),FlexSize(str2,totalRead)); } return(result); } /****************************************************************************/ void print_toc() { int i; fprintf(stderr,"Tracks: %d\n",tracks); VprintSpace(); fprintf(stderr,"\n"); for(i=0; i0) { disknum++; cd_track=1; } Vclose(); if(!VisRegular()) { fprintf(stderr,"%s: Next disk needed: disk %d from %s\n",prg_name,disknum,headersave.vol_id); diskchange(multicmd,cd_dev); } else if(result<0) break; Vopen(1); tracks=VreadToc(0); } } while(result); if(ahead) VsetAhead(1); } Vclose(); return 0; } cdbackup-0.7.0/cdrom.c0100644000000000000000000000744710034770342013255 0ustar rootroot/* cdrom.c Copyright (c) 2000-2004 Craig Condit, Stefan Hülswitt. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #define _LARGEFILE64_SOURCE #include #include #include #ifdef linux #include #endif #include "cdrom.h" #include "misc.h" #include "debug.h" /* size of leadin/out depending of how many tracks are on cd */ #define LEADOUT_1 11400 /* 1th track */ #define LEADOUT_2 6900 /* 2nd and more tracks */ /* number of (unreadable) runout sectos */ #define RUNOUT 2 extern int fd; extern int verbose; extern char *prg_name; /****************************************************************************/ void get_param(int fd, unsigned long *ahead, unsigned long *fahead) { #if defined(BLKRAGET) && defined(BLKFRAGET) *ahead = *fahead = 0; ioctl(fd,BLKRAGET,ahead); ioctl(fd,BLKFRAGET,fahead); DEBUG("get_param: readahead=%ld freadahead=%ld\n",*ahead,*fahead); #else fprintf(stderr,"Can't get readahead parameter. Ioctl's not available\n"); #endif } /****************************************************************************/ void set_param(int fd, unsigned long ahead, unsigned long fahead) { #if defined(BLKRAGET) && defined(BLKFRAGET) ioctl(fd,BLKRASET,ahead); ioctl(fd,BLKFRASET,fahead); DEBUG("set_param: readahead=%ld freadahead=%ld\n",ahead,fahead); #else fprintf(stderr,"Can't set readahead parameter. Ioctl's not available\n"); #endif } /****************************************************************************/ int getCdHeader(struct cd_header *cd) { struct cdrom_tochdr cd_header; struct cdrom_tocentry cd_entry; int tracks; if(ioctl(fd,CDROMREADTOCHDR,&cd_header)<0) { if(verbose) fprintf(stderr,"%s: Unable to read CD header, assuming empty CD-R\n",prg_name); cd->start_track=1; cd->end_track=0; cd->used=0; return 0; } cd->start_track=cd_header.cdth_trk0; cd->end_track =cd_header.cdth_trk1; tracks=cd->end_track-cd->start_track+1; cd_entry.cdte_format=CDROM_LBA; cd_entry.cdte_track=CDROM_LEADOUT; if(ioctl(fd,CDROMREADTOCENTRY,&cd_entry)<0) error("Ioctl failed (lead-out)"); cd->used=cd_entry.cdte_addr.lba + (tracks==1 ? LEADOUT_1:LEADOUT_2); return tracks; } /****************************************************************************/ void getCdTrack(int num, struct cd_track *cd) { struct cdrom_tocentry cd_entry; cd_entry.cdte_format=CDROM_LBA; cd_entry.cdte_track=num; if(ioctl(fd,CDROMREADTOCENTRY,&cd_entry)<0) error("Ioctl failed (toc entry)"); cd->start_sec =cd_entry.cdte_addr.lba; cd->leadout_size=RUNOUT+(num==cd->start_track ? LEADOUT_1:LEADOUT_2); cd->is_data =(cd_entry.cdte_ctrl&CDROM_DATA_TRACK) ? 1:0; } cdbackup-0.7.0/cdrom.h0100644000000000000000000000351610020076221013241 0ustar rootroot/* cdrom.h Copyright (c) 2000-2004 Craig Condit, Stefan Hülswitt. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _CDBACKUP_CDROM_H #define _CDBACKUP_CDROM_H #ifdef linux #include #endif #ifdef sun #include #endif #ifndef CD_FRAMESIZE #define CD_FRAMESIZE 2048 #endif struct cd_header { int start_track, end_track; int used; }; struct cd_track { int start_sec; int leadout_size; int is_data; int start_track; }; void get_param(int fd, unsigned long *ahead, unsigned long *fahead); void set_param(int fd, unsigned long ahead, unsigned long fahead); int getCdHeader(struct cd_header *cd); void getCdTrack(int num, struct cd_track *cd); #endif cdbackup-0.7.0/debug.h0100644000000000000000000000264007543263726013250 0ustar rootroot/* debug.h Copyright (c) 2000-2002 Craig Condit, Stefan Hülswitt. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _CDBACKUP_DEBUG_H #define _CDBACKUP_DEBUG_H extern int debug; #define DEBUG(format,args...) { if(debug) fprintf(stderr,format, ## args); } #endif cdbackup-0.7.0/examples/0040755000000000000000000000000007672626152013627 5ustar rootrootcdbackup-0.7.0/examples/cdbackup-diskchange0100755000000000000000000000027607300521671017415 0ustar rootroot#!/bin/bash # # This is an example diskchange-script # # $1 is the cdrom-device e.g. /dev/sr0 echo echo echo "Disk full!!" eject $1 echo "Please replace and press RETURN" echo echo read cdbackup-0.7.0/examples/cdload0100755000000000000000000000170407414577521015001 0ustar rootroot#!/bin/bash # defaults DEVICE="/dev/sr1" TRACK="1" LIST=0 # process command-line options while getopts ":d:t:l" optn; do case $optn in d ) DEVICE=$OPTARG ;; t ) TRACK=$OPTARG ;; l ) LIST=1 ;; \? ) echo "Usage: `basename $0` [-d device] [-t track] [-l] [filespec]" echo "" echo "Defaults: -d /dev/sr1" echo " -t 1" echo "" echo "if -l is given, archive is listed not restored." exit 1 ;; esac done shift $(($OPTIND - 1)) # process input-files TMP="/tmp/cdload.$$" rm -f $TMP SPECOPT="" for filespec in "$@"; do echo "$filespec" >>$TMP SPECOPT="-w $TMP" done #echo "-$SPECOPT-" #cat $TMP #echo "--" if [ $LIST -eq 1 ]; then aopt="-t" # list archive echo "`basename $0`: listing archive" else aopt="-i" # restore archive echo "`basename $0`: restoring archive" fi cdrestore -d $DEVICE -t $TRACK | afio $aopt -vnz $SPECOPT - rm -f $TMP cdbackup-0.7.0/examples/cdrestore-diskchange0100755000000000000000000000026707300521664017635 0ustar rootroot#!/bin/bash # # This is an example diskchange-script # # $1 is the cdrom-device e.g. /dev/sr0 eject $1 echo echo echo "Please insert next disk and press RETURN" echo echo read cdbackup-0.7.0/examples/cdsave0100755000000000000000000000233407415366122015012 0ustar rootroot#!/bin/bash # defaults LABEL="Afio-Backup" SCSIDEV="0,4,0" DEVICE="/dev/sr1" SPEED="8" LEN="702" MULTI="" # process command-line options while getopts ":a:d:r:s:l:m" optn; do case $optn in a ) LABEL=$OPTARG ;; d ) DEVICE=$OPTARG ;; r ) SCSIDEV=$OPTARG ;; s ) SPEED=$OPTARG ;; l ) LEN=$OPTARG ;; m ) MULTI="-m" ;; \? ) echo "Usage: `basename $0` [-a label] [-l cd_len] [-m] [-d device] [-r scsidev] [-s speed] file1 file2 ..." echo "" echo "Defaults: -a Afio-Backup" echo " -d /dev/sr1" echo " -r 0,4,0" echo " -s 8" echo " -l 702" exit 1 ;; esac done shift $(($OPTIND - 1)) # process input-files TMP="/tmp/cdsave.$$" rm -f $TMP for filename in "$@"; do case $filename in *[*?]* ) # means shell couldn´t extend *.wav, etc. echo "warning: no $filename file(s) found" ;; * ) echo >>$TMP "$filename" ;; esac done if [ -s $TMP ] ; then cat $TMP | \ afio -o -uz - | \ cdbackup -v -a "$LABEL" $MULTI -l "$LEN" -d "$DEVICE" -r "$SCSIDEV" -s "$SPEED" -- -v fs=8m else echo "Error: no files specified" fi rm -f $TMP cdbackup-0.7.0/misc.c0100644000000000000000000001751010020171147013065 0ustar rootroot/* misc.c Copyright (c) 2000-2004 Craig Condit, Stefan Hülswitt. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include "cdrom.h" #include "debug.h" extern char *prg_name; /****************************************************************************/ void error(char *text) { fprintf(stderr,"%s: %s: %s\n",prg_name,text,strerror(errno)); exit(1); } /****************************************************************************/ void serror(char *text) { fprintf(stderr,"%s: %s\n",prg_name,text); exit(1); } /****************************************************************************/ long long FlexLen(char *optarg) { char *end; long long len; errno=0; len=strtoll(optarg,&end,10); if(errno==ERANGE || len<1) serror("Option -l: length out of range (must be >=1)\n"); switch(*end) { case 'K': /* kilo-bytes*/ case 'k': len*=1024; break; case 0: /* mega-bytes */ case 'M': case 'm': len*=(1024*1024); break; case 'G': case 'g': len*=(1024*1024*1024LL); break; case 's': case 'S': len*=CD_FRAMESIZE; break; default: serror("Unknown extention for media size"); } DEBUG("media size len=%lld blocks=%lld\n",len,len/CD_FRAMESIZE); return len; } /****************************************************************************/ char *FlexSize(char *buff, long long val) { char *unit=" "; if(val > 1024*1024*1024*16LL) { val/=1024*1024*1024LL; unit="G"; } else if(val > 1024*1024*16LL) { val/=1024*1024LL; unit="M"; } else if(val > 1024*16LL) { val/=1024LL; unit="k"; } sprintf(buff,"%5lld %sB",val,unit); return buff; } /****************************************************************************/ int full_read(int fd, void *buf, int count) { int total=0; while(count>0) { int bytes; bytes=read(fd,buf,count); if(bytes==0) break; else if(bytes<0) { if(errno!=EAGAIN) error("Read failed"); usleep(200*1000); } else { count-=bytes; buf+=bytes; total+=bytes; } } return total; } /****************************************************************************/ void diskchange(char *multicmd, char *cd_dev) { int pid, status=0; char buffer[12]; if(multicmd) { /* we have an external script */ DEBUG("external diskchange started '%s'\n",multicmd); if((pid=fork())<0) error("Fork failed (diskchange)"); if(pid==0) { /* child */ char *argv[3]; dup2(2,0); dup2(2,1); /* duplicate stderr as stdin/stdout */ argv[0] = multicmd; argv[1] = cd_dev; argv[2] = 0; execvp(multicmd, argv); error("Exec failed (diskchange)"); } while(1) { if(waitpid(pid,&status,0)==-1) { if (errno!=EINTR) { status=-1; break; } } else break; } } else { /* use internal diskchange */ DEBUG("internal diskchange started\n"); fprintf(stderr,"\n\nPlease insert next disk and press RETURN\n\n\n"); do { pid=read(2,buffer,sizeof(buffer)); if(pid<0 && errno!=EAGAIN) error("Read failed (diskchange)"); } while(pid<=0 || (pid==sizeof(buffer) && buffer[sizeof(buffer)-1]!='\n')); } if(status) serror("Diskchange command failed"); DEBUG("diskchange completed\n"); } /****************************************************************************/ static unsigned long crc_table[256] = { 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 }; unsigned long crc32(char *data, int len) { unsigned long crc=0xffffffff; int i; for(i=0 ; i>24)^*data++)&0xff]; return crc; } cdbackup-0.7.0/misc.h0100644000000000000000000000310010020074532013060 0ustar rootroot/* misc.h Copyright (c) 2000-2004 Craig Condit, Stefan Hülswitt. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _CDBACKUP_MISC_H #define _CDBACKUP_MISC_H unsigned long crc32(char *data, int len); void diskchange(char *multicmd, char *cd_dev); int full_read(int fd, void *buf, int count); void error(char *text); void serror(char *text); char *FlexSize(char *buff, long long val); long long FlexLen(char *optarg); #endif cdbackup-0.7.0/version.h0100644000000000000000000000016010121313601013610 0ustar rootroot#ifndef _CDBACKUP_VERSION_H #define _CDBACKUP_VERSION_H #ifndef VERSION #define VERSION "0.7.0" #endif #endif cdbackup-0.7.0/virtual-backup.c0100644000000000000000000001072010036732046015067 0ustar rootroot/* virtual-backup.c Copyright (c) 2000-2004 Craig Condit, Stefan Hülswitt. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #define _LARGEFILE64_SOURCE #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "virtual.h" #include "cdbackup.h" #include "cdrom.h" #include "misc.h" #include "debug.h" //#define DEBUGOUT extern int virtual, multi; extern int fd; extern struct virt_header *virt_header; extern int virtualMissing; extern char *real_virt_name; #ifndef DEBUGOUT static pid_t childpid; #endif static int vfd=-1; /****************************************************************************/ void VnewTrack(void) { if(virtual) { long long pos; if(virtualMissing) { if((fd=open64(real_virt_name,O_RDWR|O_CREAT,S_IRUSR|S_IWUSR|S_IRGRP| S_IROTH))<0) error("Open failed (new track)"); if(write(fd,virt_header,CD_FRAMESIZE)!=CD_FRAMESIZE) error("Write failed (new track)"); virtualMissing=0; } if(virt_header->tracks>=MAX_VIRT_TRACKS-1) serror("Maximum number of virtual tracks reached"); pos=(long long)(virt_header->start[virt_header->tracks]=virt_header->leadout)*CD_FRAMESIZE; virt_header->tracks++; if(lseek64(fd,pos,SEEK_SET)<0) error("Seek failed (new track)"); } else { #ifndef DEBUGOUT int pd[2]; Vclose(); if(pipe(pd)<0) error("Pipe failed (new track)"); if((childpid=fork())<0) error("Fork failed (new track)"); if(childpid==0) { /* child */ close(pd[1]); close(0); dup2(pd[0],0); start_cdrecord(); /* doesn't returns */ } close(pd[0]); fd=pd[1]; #else /* debug code; send data to /dev/null. */ Vclose(); fprintf(stderr,"DEBUG CODE: NO recording, sending data to /dev/null!\n"); if((fd=open("/dev/null",O_WRONLY))<0) error("Open failed (/dev/null)"); #endif cd_avail-=padsize*CD_FRAMESIZE; } } /****************************************************************************/ int Vsize(void) { return virt_header->leadout; } /****************************************************************************/ int VhasCont(void) { return virt_header->has_cont; } /****************************************************************************/ void VprepareDump(void) { if((vfd=dup(fd))<0) error("Dup failed"); Vclose(); } /****************************************************************************/ void VvirtRead(void *buf) { if(full_read(vfd,buf,CD_FRAMESIZE)!=CD_FRAMESIZE) serror("Unexpected EOF reading data"); } /****************************************************************************/ void VcloseTrack(int cont) { if(virtual) { if(lseek64(fd,0,SEEK_SET)<0) error("Seek failed (close track)"); virt_header->has_cont=cont; if(write(fd,virt_header,CD_FRAMESIZE)!=CD_FRAMESIZE) error("Write failed (close track)"); Vclose(); } else { Vclose(); #ifndef DEBUGOUT DEBUG("VcloseTrack: waiting for child termination\n"); while(wait(0)!=childpid); #endif } if(vfd>=0) { close(vfd); vfd=-1; } } /****************************************************************************/ void Vwrite(const void *buf) { if(write(fd,buf,CD_FRAMESIZE)!=CD_FRAMESIZE) error("Write failed"); if(virtual) virt_header->leadout++; cd_avail-=CD_FRAMESIZE; } cdbackup-0.7.0/virtual.c0100644000000000000000000002115410036733057013632 0ustar rootroot/* virtual.c Copyright (c) 2000-2004 Craig Condit, Stefan Hülswitt. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #define _LARGEFILE64_SOURCE #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "virtual.h" #include "cdbackup.h" #include "cdrom.h" #include "misc.h" #include "debug.h" int fd=-1; struct toc_entry *toc=0; long long cd_used, cd_avail; static struct cd_header cd_header; static unsigned char virt_buffer[VIRT_HEADER_LEN]; struct virt_header *virt_header=(struct virt_header *)virt_buffer; int virtualMissing=0, virt_off=-1, virt_regular=0; char *real_virt_name=0; extern int virtual; extern int disknum; extern char *virt_name, *cd_dev; /****************************************************************************/ void Vopen(int ro) { Vclose(); if(!virtual) { if((fd=open64(cd_dev,O_RDONLY|O_NONBLOCK))<0) error("Open failed (device)"); } else { free(real_virt_name); if(disknum==1 || !virt_regular) { real_virt_name=strdup(virt_name); } else if(virt_off>0) { char *strip=strdup(virt_name); char *dot=rindex(strip,'.'); if(dot) { *dot=0; asprintf(&real_virt_name,"%s.%d",strip,disknum+virt_off); } else serror("Bad filename format"); free(strip); } else { asprintf(&real_virt_name,"%s.%d",virt_name,disknum); } DEBUG("Vopen: real filename is '%s' disknum=%d virt_off=%d\n", real_virt_name,disknum,virt_off); virtualMissing=0; virt_regular=0; if((fd=open64(real_virt_name,ro ? O_RDONLY:O_RDWR))<0) { if(errno==EACCES || errno==ENOENT || errno==ENOTDIR) { virtualMissing=1; virt_regular=1; DEBUG("Vopen: missing virtual image, assuming an empty one\n"); } else error("Open failed (virtual)"); } else { struct stat64 st; if(fstat64(fd,&st)<0) error("Stat failed (virtual)"); if(S_ISREG(st.st_mode)) virt_regular=1; } } } /****************************************************************************/ void Vclose(void) { if(fd>=0) { close(fd); fd=-1; } } /****************************************************************************/ int VisRegular(void) { return virt_regular; } /****************************************************************************/ static int VgetCdHeader(struct cd_header *cd) { if(virtualMissing) { if(verbose) fprintf(stderr,"%s: Unable to get virtual image header, assuming new virtual image\n",prg_name); memset(virt_buffer,0,VIRT_HEADER_LEN); virt_header->magic=VIRT_MAGIC; virt_header->version=VIRT_VERSION; virt_header->leadout=1; virt_header->count=disknum + (virt_off>0 ? virt_off:0); } else { int n; if((n=read(fd,virt_buffer,VIRT_HEADER_LEN))<0) error("Read failed (virtual header)"); if(n!=VIRT_HEADER_LEN) serror("Short read on virtual header"); if(virt_header->magic!=VIRT_MAGIC) serror("Missing magic value in virtual header. Really a virtual image?"); if(virt_header->version>VIRT_VERSION) serror("Don't know how to handle this virtual image version"); } if(virt_off<0 && disknum==1) { virt_off=virt_header->count-1; DEBUG("VgetCdHeader: setting virt_off=%d\n",virt_off); } cd->start_track=1; cd->end_track=virt_header->tracks; cd->used=virt_header->leadout; return cd->end_track; } /****************************************************************************/ static void VgetCdTrack(int num, struct cd_track *cd) { cd->start_sec=virt_header->start[num-1]; cd->leadout_size=0; cd->is_data=1; } /****************************************************************************/ int VreadToc(int trackInfos) { struct cd_track cd_track; int i, tracks; tracks=virtual ? VgetCdHeader(&cd_header) : getCdHeader(&cd_header); if(!tracks) { cd_used=0; cd_avail=(long long)cd_len*CD_FRAMESIZE; DEBUG("Vreadtoc: empty media\n"); return 0; } DEBUG("Vreadtoc: starttrack=%d endtrack=%d tracks=%d\n", cd_header.start_track,cd_header.end_track,tracks); cd_used =(long long)cd_header.used*CD_FRAMESIZE; cd_avail =(long long)cd_len*CD_FRAMESIZE-cd_used; if(cd_avail<0) cd_avail=0; DEBUG("Vreadtoc: cd_used=%lld (%lld secs) cd_avail=%lld (%lld secs)\n", cd_used,cd_used/CD_FRAMESIZE,cd_avail,cd_avail/CD_FRAMESIZE); free(toc); if(!(toc=calloc(tracks,sizeof(struct toc_entry)))) serror("No memory for TOC"); cd_track.start_track=cd_header.start_track; for(i=tracks-1; i>=0; i--) { int t=cd_header.start_track+i; if(virtual) VgetCdTrack(t,&cd_track); else getCdTrack(t,&cd_track); toc[i].track_no=t; toc[i].sec_start=cd_track.start_sec; toc[i].sec_end=((i==tracks-1) ? cd_header.used : toc[i+1].sec_start)-1-cd_track.leadout_size; toc[i].is_data=cd_track.is_data; DEBUG("Vreadtoc: index=%d track=%d sec_start=%d sec_end=%d data=%d\n", i,t,toc[i].sec_start,toc[i].sec_end,toc[i].is_data); } if(trackInfos) { for(i=0; iid_str,strlen(SHORT_HDR))) { toc[i].is_cdbackup=1; strncpy(toc[i].id_str,track_header->id_str,32); toc[i].id_str[32]=0; strncpy(toc[i].vol_id, track_header->vol_id,32); toc[i].vol_id[32]=0; strncpy(toc[i].t_stamp, track_header->t_stamp,12); toc[i].t_stamp[12]=0; toc[i].disk_set = track_header->disk_set; toc[i].flags = track_header->flags; } } } } return tracks; } /****************************************************************************/ const char *VdevName(void) { static char buff[80]; if(virtual) snprintf(buff,sizeof(buff),"image %s",virt_name); else snprintf(buff,sizeof(buff),"device %s",cd_dev); return buff; } /****************************************************************************/ void VprintSpace(void) { if(verbose) { char flex1[16], flex2[16], flex3[16]; fprintf(stderr, "Disk size: %s (%7ld blocks)\n" "Space used: %s (%7lld blocks)\n" "Space avail:%s (%7lld blocks)\n", FlexSize(flex1,(long long)cd_len*CD_FRAMESIZE),cd_len, FlexSize(flex2,cd_used), cd_used/CD_FRAMESIZE, FlexSize(flex3,cd_avail), cd_avail/CD_FRAMESIZE); } } /****************************************************************************/ long long Vseek(int trackNum) { long long pos=0; if(trackNum>=0) pos=(long long)toc[trackNum].sec_start*CD_FRAMESIZE; DEBUG("Vseek: seeking to index %d, track %d, offset %lld (%s)\n", trackNum,toc[trackNum].track_no,pos,virtual ? "virtual":"real"); if(lseek64(fd,pos,SEEK_SET)<0) error("Seek failed"); return pos; } /****************************************************************************/ void Vread(void *buf) { if(full_read(fd,buf,CD_FRAMESIZE)!=CD_FRAMESIZE) serror("Unexpected EOF reading data"); } /****************************************************************************/ static unsigned long r_ahead, r_fahead; void VgetAhead(void) { if(!virtual) get_param(fd,&r_ahead,&r_fahead); } /****************************************************************************/ void VsetAhead(int restore) { if(!virtual) { if(restore) set_param(fd,r_ahead,r_fahead); else set_param(fd,0,0); } } cdbackup-0.7.0/virtual.h0100644000000000000000000000504510020354374013632 0ustar rootroot/* virtual.h Copyright (c) 2000-2004 Craig Condit, Stefan Hülswitt. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _CDBACKUP_VIRTUAL_H #define _CDBACKUP_VIRTUAL_H #define VIRT_VERSION 1 #define VIRT_MAGIC 0x144391C83A78412FLL #define MAX_VIRT_TRACKS 96 #define VIRT_HEADER_LEN CD_FRAMESIZE struct virt_header { long long magic; int version; int tracks; int leadout; int count, has_cont; int reserved[25]; int start[MAX_VIRT_TRACKS]; }; struct toc_entry { u_char track_no; /* track number */ char is_data; /* 1 = data track */ char is_cdbackup; /* was it created by CD-Backup? */ int sec_start; /* start sector */ int sec_end; /* last sector */ char id_str[33]; /* recorder id string (32 chars) */ char vol_id[33]; /* volume label (32 characters) */ char t_stamp[13]; /* time stamp: yyyymmddhhmm */ char disk_set; /* disk number */ char flags; /* backup flags */ }; extern struct toc_entry *toc; extern long long cd_used, cd_avail; void Vopen(int ro); void Vclose(void); int VisRegular(void); int VreadToc(int trackInfos); void VprintSpace(void); const char *VdevName(void); long long Vseek(int trackNum); void Vread(void *buf); void VnewTrack(void); void VcloseTrack(int cont); void Vwrite(const void *buf); void VgetAhead(void); void VsetAhead(int restore); int Vsize(void); int VhasCont(void); void VprepareDump(void); void VvirtRead(void *buf); #endif