# HG changeset patch # User nathan # Date 1198938229 -3600 # Node ID 6bcb44b9edb16f763d32184678a6f6627675c0ab # Parent 6b6864d2c4cede71dcf86337a1f401fc302783fd release 0.6.3 diff -r 6b6864d2c4ce -r 6bcb44b9edb1 CHANGES --- a/CHANGES Sat Dec 29 15:22:44 2007 +0100 +++ b/CHANGES Sat Dec 29 15:23:49 2007 +0100 @@ -1,35 +1,47 @@ +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 ----- -1. some more fixes to allow >2GB data on a single disk (SH) -2. added commandline option to specify padsize and enable CDROM - XA2 mode (SH) -3. changed gcc options in Makefile (SH) -4. code cleanup (SH) -5. added man page, updated README (SH) +- 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 ----- -1. fixed size calculations with multi-disk backups > 2GB (SH) -2. minor message cleanups (CC) +- fixed size calculations with multi-disk backups > 2GB (SH) +- minor message cleanups (CC) 0.6 --- -1. multidisk-support (SH) -2. unix-like commandline options (SH) -3. can pass additional options to cdrecord (SH) -4. code cleanup (SH) -5. various bugs fixed (SH) +- 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 ----- -1. Revamped Makefile (CC) +- Revamped Makefile (CC) 0.5.1 ----- -1. Fixed bug in command-line parsing (JY) -2. Added error messages to command-line parsing (JY, CC) -3. Various sloppy code fixes (JY, CC) -4. Changed Makefile to check for compiler warnings (JY, CC) +- 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 ----- diff -r 6b6864d2c4ce -r 6bcb44b9edb1 Makefile --- a/Makefile Sat Dec 29 15:22:44 2007 +0100 +++ b/Makefile Sat Dec 29 15:23:49 2007 +0100 @@ -1,41 +1,50 @@ # compiler selection and options -CC=gcc -CFLAGS=-g -O2 -Wall +CC = gcc +CFLAGS = -g -O2 -Wall +DEPFLAGS = -MM -MG # install location PREFIX=/usr/local - BINDIR=$(PREFIX)/bin MANDIR=$(PREFIX)/man ############################################### -# executables -TARGETS=cdbackup cdrestore +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) -# ruleset %.o: %.c $(CC) $(CFLAGS) -c $< -o $@ +$(DEPFILE): Makefile + @$(CC) $(DEPFLAGS) cdbackup.c cdrestore.c cdrom.c misc.c > $@ + +include $(DEPFILE) + cdbackup: cdbackup.o cdrom.o misc.o $(CC) $(CFLAGS) -o cdbackup cdbackup.o cdrom.o misc.o cdrestore: cdrestore.o cdrom.o misc.o $(CC) $(CFLAGS) -o cdrestore cdrestore.o cdrom.o misc.o -cdbackup.o: cdbackup.c cdbackup.h cdrom.h misc.h version.h -cdrestore.o: cdrestore.c cdbackup.h cdrom.h misc.h version.h -cdrom.o: cdrom.c cdbackup.h misc.h -misc.o: misc.c misc.h - -# targets strip: $(TARGETS) strip $(TARGETS) clean: - rm -f $(TARGETS) core *.core *.o + 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) diff -r 6b6864d2c4ce -r 6bcb44b9edb1 README --- a/README Sat Dec 29 15:22:44 2007 +0100 +++ b/README Sat Dec 29 15:23:49 2007 +0100 @@ -1,4 +1,4 @@ -cdbackup, cdrestore - CD archive utilities version 0.6.2 +cdbackup, cdrestore - CD archive utilities version 0.6.3 Copyright (c) 2000-2002 Craig Condit, Stefan Hülswitt. All rights reserved. This software is released under a BSD-style license - see the LICENSE file. diff -r 6b6864d2c4ce -r 6bcb44b9edb1 TODO --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TODO Sat Dec 29 15:23:49 2007 +0100 @@ -0,0 +1,1 @@ +-increase buffer size on restore for speed? diff -r 6b6864d2c4ce -r 6bcb44b9edb1 cdbackup.1 --- a/cdbackup.1 Sat Dec 29 15:22:44 2007 +0100 +++ b/cdbackup.1 Sat Dec 29 15:23:49 2007 +0100 @@ -1,22 +1,22 @@ -.TH "cdbackup" "1" "0.6.2" "Stefan Hülswitt" "" +.TH "cdbackup" "1" "0.6.3" "Stefan Hülswitt" "" .SH "NAME" .LP cdbackup \- Streaming backup to CD\-R(W) .SH "SYNOPSIS" .LP -cdbackup [\-mvVX] [\-d \fIdevice\fP] [\-r \fIscsi\-dev\fP] [\-s \fIspeed\fP] +cdbackup [\-mvDVX] [\-d \fIdevice\fP] [\-r \fIscsi\-dev\fP] [\-s \fIspeed\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) disks. It's designed to work with any backup tool which writes the backup to stdout (like tar/cpio/afio). .LP -NOTE: this program REQUIRES that a recent version of cdrecord is present in the PATH. +\fINOTE:\fR this program REQUIRES that a recent version of \fBcdrecord\fR(1) is present in the PATH. .LP -WARNING! When using this program under Linux, be sure not to use dump with -kernels in the 2.4.x series. Using dump on an ext2 filesystem has a very -high potential for causing filesystem corruption. As of kernel version -2.4.18, this has not been fixed and it may not be fixed at all. +\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 @@ -27,13 +27,13 @@ .TP \fB\-r\fR \fIscsi\-device\fP -The scsi device which is passed to cdrecord (via dev=\fIscsi\-device\fP). Must be given as three, comma seperated number: \fIscsibus\fR,\fItarget\fR,\fIlun\fR. +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) .TP \fB\-s\fR \fIspeed\fP -The writing speed which is passed to cdrecord (via speed=\fIspeed\fP). +The writing speed which is passed to \fBcdrecord\fR(1) (via speed=\fIspeed\fP). .br (default: 4) @@ -45,7 +45,7 @@ .TP \fB\-X\fR -Enables the use of CDROM XA2 mode in cdrecord. 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). +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\-l\fR \fIsize\fP @@ -74,12 +74,16 @@ 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 -All options following \fB\-\-\fR are passed to cdrecord. +Pass following options to \fBcdrecord\fR(1). .SH "EXAMPLES" .LP To create a tar archive of /home and @@ -91,6 +95,29 @@ 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 +.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 diff -r 6b6864d2c4ce -r 6bcb44b9edb1 cdbackup.c --- a/cdbackup.c Sat Dec 29 15:22:44 2007 +0100 +++ b/cdbackup.c Sat Dec 29 15:23:49 2007 +0100 @@ -41,6 +41,7 @@ #include "cdbackup.h" #include "cdrom.h" #include "misc.h" +#include "debug.h" #include "version.h" /* #define DEBUGOUT */ @@ -57,6 +58,7 @@ char * multicmd =0; int verbose =0; int xamode2 =0; +int debug =0; char **cdrec_opt=0; int cdrec_opt_count=0; @@ -81,6 +83,7 @@ " -m enable multi-disk mode\n" " -c COMMAND call COMMAND on disk change in multi-disk 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); @@ -92,7 +95,7 @@ { int i; - while ((i=getopt(argc,argv,"d:r:l:s:p:a:c:mvVX"))>0) { + while ((i=getopt(argc,argv,"d:r:l:s:p:a:c:mvVXD"))>0) { switch (i) { case 'V': fprintf(stderr,"cdbackup "VERSION" (compiled "__DATE__")\n" "Copyright (C) 2000-2002\n" @@ -107,6 +110,9 @@ case 'd': cd_dev=optarg; break; case 'r': cdr_dev=optarg; break; case 'a': cd_label=optarg; break; + case 'D': verbose=1; debug=1; + DEBUG("cdbackup: DEBUG output enabled ("VERSION")\n"); + break; case 'l': errno=0; cd_len=strtol(optarg,NULL,10); if(errno==ERANGE || cd_len<1) serror("Option -l: length out of range (must be >=1)\n"); cd_len = (long long)cd_len * (1024*1024) / CD_FRAMESIZE; /* convert to blocks */ @@ -156,7 +162,7 @@ *p++="-"; *p++=0; - if(verbose) { + if(debug) { fprintf(stderr,"%s: cdrecord command:",prg_name); for(p=args ; *p ; p++) fprintf(stderr," %s",*p); fprintf(stderr,"\n"); diff -r 6b6864d2c4ce -r 6bcb44b9edb1 cdbackup.h --- a/cdbackup.h Sat Dec 29 15:22:44 2007 +0100 +++ b/cdbackup.h Sat Dec 29 15:23:49 2007 +0100 @@ -34,17 +34,6 @@ #define MIN_BLOCKS 2 /* min. required blocks for a session: header block, one data block */ -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 */ - 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 */ -}; - struct header_block { char id_str[33]; /* recorder id string (32 chars) */ char vol_id[33]; /* volume label (32 characters) */ diff -r 6b6864d2c4ce -r 6bcb44b9edb1 cdrestore.1 --- a/cdrestore.1 Sat Dec 29 15:22:44 2007 +0100 +++ b/cdrestore.1 Sat Dec 29 15:23:49 2007 +0100 @@ -1,10 +1,10 @@ -.TH "cdrestore" "1" "0.6.2" "Stefan Hülswitt" "" +.TH "cdrestore" "1" "0.6.3" "Stefan Hülswitt" "" .SH "NAME" .LP cdrestore \- Streaming restore from CD\-R(W) .SH "SYNOPSIS" .LP -cdrestore [\-qV] [\-d \fIdevice\fP] [\-l \fIsize\fP] [\-t \fItrack\fP] +cdrestore [\-qvDFRTV] [\-d \fIdevice\fP] [\-l \fIsize\fP] [\-t \fItrack\fP] [\-c \fIcommand\fP] .SH "DESCRIPTION" .LP @@ -30,6 +30,23 @@ (default: none) .TP +\fB\-T\fR +Enables test mode. The complete restore process is done to test data integrity, but no data is output. +.br +\fINOTE:\fR This only verifies that the data is readable by cdrestore at all. This doesn't quaranties 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 @@ -40,6 +57,14 @@ 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" diff -r 6b6864d2c4ce -r 6bcb44b9edb1 cdrestore.c --- a/cdrestore.c Sat Dec 29 15:22:44 2007 +0100 +++ b/cdrestore.c Sat Dec 29 15:23:49 2007 +0100 @@ -41,18 +41,24 @@ #include "cdbackup.h" #include "cdrom.h" #include "misc.h" +#include "debug.h" #include "version.h" /* defaults */ char * prg_name ="cdrestore"; -int cd_mode =0; int cd_track =-1; char * cd_dev ="/dev/cdrom"; long cd_len =333000; /* blocks */ char * multicmd =0; -int verbose =1; +int verbose =0; +int force =0; +int query =0; +int verify =0; +int ahead =0; +int debug =0; int tracks; +int disknum; long long totalSize; struct header_block headersave; @@ -68,6 +74,11 @@ " -t N restore from track N\n" " -l N CD-R has a size of N MB\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" + " -v be verbose\n" + " -D enable DEBUG output\n" " -V prints version & exits\n" "\n", prg_name); } @@ -78,7 +89,7 @@ { int i; - while ((i=getopt(argc,argv,"d:l:c:t:qV"))>0) { + while ((i=getopt(argc,argv,"d:l:c:t:qvVFTDR"))>0) { switch (i) { case 'V': fprintf(stderr,"cdrestore "VERSION" (compiled "__DATE__")\n" "Copyright (C) 2000-2002\n" @@ -88,7 +99,14 @@ exit(0); case 'c': multicmd=optarg; break; case 'd': cd_dev=optarg; break; - case 'q': cd_mode=1; 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 '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; @@ -100,7 +118,7 @@ } } - if(!cd_mode && cd_track<0) /* need track number */ + if(!query && cd_track<0) /* need track number */ serror("A track number is required.\n"); } @@ -117,31 +135,37 @@ (stamp[8]-'0')*10 + (stamp[9]-'0'), (stamp[10]-'0')*10 + (stamp[11]-'0')); - if(startsec>=0) snprintf(size,sizeof(size)-1," %3ld MB:",(long)((long long)(endsec-startsec)*CD_FRAMESIZE/(1024*1024))); + if(startsec>=0) snprintf(size,sizeof(size)-1," %3ld MB:",(long)((long long)(endsec-startsec+1)*CD_FRAMESIZE/(1024*1024))); else size[0]=0; fprintf(stderr,"Track %02d:%s %s Part %d: %s\n", track, size, timestr, disk, id); -} - -/****************************************************************************/ - -int restore(int disknum, int disktrack) + if(startsec>=0) DEBUG(" Start sector %7d Last sector %7d\n",startsec,endsec); +} + +/****************************************************************************/ + +int restore(int disktrack) { int infile; int result=0, i, bytes; - long long totalRead; + long long totalRead, startPos; struct header_block header; char buffer[CD_FRAMESIZE]; struct data_block *db=(struct data_block *)&buffer[0]; - - if ((infile = open(cd_dev, O_RDONLY)) < 0) error("Error opening device"); + unsigned long r_ahead, r_fahead; + + if((infile=open(cd_dev, O_RDONLY)) < 0) error("Error opening device"); + if(ahead) { + get_param(infile,&r_ahead,&r_fahead); + set_param(infile,0,0); + } /* seek to proper CD-R(W) track */ for(i=tracks;i>0;i--) if(toc[i].track_no==disktrack) break; if(!i) { fprintf(stderr, "%s: Can't find track %d\n", prg_name, disktrack); exit(1); } - totalRead=(long long)toc[i].sec_start*CD_FRAMESIZE; - if(lseek64(infile,totalRead,SEEK_SET) != totalRead) error("Error seeking to track"); + startPos=(long long)toc[i].sec_start*CD_FRAMESIZE; + if(lseek64(infile,startPos,SEEK_SET) != startPos) error("Error seeking to track"); /* read header block */ bytes=full_read(infile,buffer,CD_FRAMESIZE); @@ -152,38 +176,45 @@ memcpy(&header,buffer,sizeof(header)); if(!strncmp(SHORT_HDR,header.id_str,strlen(SHORT_HDR))) { - fprintf(stderr,"%s: ", prg_name); - print_track(disktrack, header.t_stamp, header.vol_id, header.disk_set, -1, -1); + if(verbose) { + fprintf(stderr,"%s: ", prg_name); + print_track(disktrack, header.t_stamp, header.vol_id, header.disk_set, -1, -1); + } if(disknum==1) { if(header.disk_set!=1) { - fprintf(stderr,"%s: This is disk %d of a multi-disk set. Restore can only be started with disk 1!\n",prg_name,header.disk_set); - exit(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 doesn't belong to the current set!\n",prg_name); - result=2; + result=-1; } else if(header.disk_set!=disknum) { fprintf(stderr,"%s: Wrong sequence. You need disk %d now!\n",prg_name,disknum); - result=2; + result=-1; } - else fprintf(stderr, "%s: Beginning restore (Disk %d)\n", prg_name,disknum); + 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=2; + result=-1; } while(!result) { int size; /* read data block */ + DEBUG("\rReading sector %7ld ",(long)((startPos+totalRead)/CD_FRAMESIZE)); bytes = full_read(infile, buffer, CD_FRAMESIZE); if (bytes < 0) error("Error reading data"); if (bytes != CD_FRAMESIZE) error("Unexpected EOF reading data"); @@ -192,22 +223,30 @@ /* sanity check */ size=ntohs(db->datasize); if(size>DATASIZE) { - fprintf(stderr,"%s: Warning! Bad datasize at %lld\n",prg_name,totalRead); + if(verbose) fprintf(stderr,"%s: Warning! Bad datasize at %lld\n",prg_name,totalRead); size=DATASIZE; } - /* write the data block */ - bytes=write(1,&buffer[DBSIZE], size); - if(bytes!=size) error("Error writing data"); + if(!verify) { + /* write the data block */ + bytes=write(1,&buffer[DBSIZE], size); + if(bytes!=size) error("Error writing data"); + } if(db->status == 1) break; /* end of backup*/ - if(db->status == 2) result=1; /* disk full */ - } + if(db->status == 2) result=1; /* next disk */ + } + DEBUG("\n"); /* print status */ totalSize+=totalRead; - if(result!=2) fprintf(stderr, "%s: Restore complete. %lld kB read (%lld kB from this disk)\n",prg_name, totalSize/1024, totalRead/1024); - + if(result>=0 && verbose) + fprintf(stderr, "%s: Restore complete. %lld kB read (%lld kB from this disk)\n",prg_name, totalSize/1024, totalRead/1024); + + if(ahead) { + set_param(infile,r_ahead,r_fahead); + get_param(infile,&r_ahead,&r_fahead); + } close(infile); return(result); } @@ -225,7 +264,7 @@ for (i = 1; i <= tracks; i++) { if(toc[i].is_data==0) fprintf(stderr,"Track %02d: Non-data\n", toc[i].track_no); else if (toc[i].is_cdbackup == 1) - print_track(i, toc[i].t_stamp, toc[i].vol_id, toc[i].disk_set, toc[i].sec_start, i==tracks?toc[0].sec_start:toc[i+1].sec_start); + print_track(i, toc[i].t_stamp, toc[i].vol_id, toc[i].disk_set, toc[i].sec_start, toc[i].sec_end); else fprintf(stderr,"Track %02d: Data\n", toc[i].track_no); } } @@ -238,24 +277,23 @@ parse_cmdline(argc, argv); - if(!cd_mode) { - int disknum=1, result; - totalSize=0; + cdr=open_cdr(cd_dev); tracks=read_toc(cdr,(query || debug)); close_cdr(cdr); + if(query || debug) { + verbose=1; + print_toc(); + } + if(!query) { + int result; + if(verify) fprintf(stderr,"%s: Verify mode enabled, no data output!\n",prg_name); + totalSize=0; disknum=1; do { - cdr=open_cdr(cd_dev); tracks=read_toc(cdr,0); close_cdr(cdr); - - result=restore(disknum,cd_track); + result=restore(cd_track); if(result) { - if(result==1) { disknum++; cd_track=1; } + if(result>0) { disknum++; cd_track=1; } fprintf(stderr,"%s: Next disk needed: disk %d from %s\n",prg_name,disknum,headersave.vol_id); if(start_diskchange(multicmd,cd_dev)) serror("Diskchange command failed"); } } while(result); } - else { - cdr=open_cdr(cd_dev); tracks=read_toc(cdr,1); close_cdr(cdr); - print_toc(); - } - return 0; } diff -r 6b6864d2c4ce -r 6bcb44b9edb1 cdrom.c --- a/cdrom.c Sat Dec 29 15:22:44 2007 +0100 +++ b/cdrom.c Sat Dec 29 15:23:49 2007 +0100 @@ -31,14 +31,19 @@ #include #include #include +#include #include +#include "cdrom.h" #include "cdbackup.h" #include "misc.h" +#include "debug.h" /* size of leadin/out depending of how many tracks are on cd */ #define MIN_FREE_1 (11400*CD_FRAMESIZE) /* 1th track */ #define MIN_FREE_2 (6900*CD_FRAMESIZE) /* 2nd and more tracks */ +/* number of (unreadable) runout sectos */ +#define RUNOUT 2 struct toc_entry *toc=0; long long cd_used, cd_avail; @@ -63,6 +68,33 @@ /****************************************************************************/ +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("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("Can't set readahead parameter. Ioctl's not available\n"); +#endif +} + +/****************************************************************************/ + int full_read(int fd, void *buf, int count) { int total=0; @@ -101,6 +133,7 @@ /* get start and end tracks */ start_track = cd_header.cdth_trk0; tracks = cd_header.cdth_trk1-start_track+1; + DEBUG("read_toc: starttrack=%d tracks=%d\n",start_track,tracks); free_toc(); if(!(toc=calloc(tracks+1,sizeof(struct toc_entry)))) serror("No memory for TOC"); @@ -115,8 +148,11 @@ toc[0].track_no=CDROM_LEADOUT; /* not a real track */ toc[0].sec_start=cd_entry.cdte_addr.lba; - cd_used=(long long)toc[0].sec_start*CD_FRAMESIZE; cd_avail=(long long)cd_len*CD_FRAMESIZE-cd_used; + cd_used =(long long)toc[0].sec_start*CD_FRAMESIZE; + cd_avail =(long long)cd_len*CD_FRAMESIZE-cd_used; cd_avail-=(tracks>1?MIN_FREE_2:MIN_FREE_1); + DEBUG("read_toc: cd_used=%lld (%lld secs) cd_avail=%lld (%lld secs)\n",cd_used,cd_used/CD_FRAMESIZE,cd_avail,cd_avail/CD_FRAMESIZE); + if(cd_avail<0) cd_avail=0; /* can be <0 due to assumed additional lead-in/out */ /* read rest of tracks */ @@ -129,6 +165,11 @@ if(cd_entry.cdte_ctrl&CDROM_DATA_TRACK) toc[i].is_data=1; } + /* calculate end sectors */ + toc[tracks].sec_end = toc[ 0].sec_start - 1 - RUNOUT; + for(i=1; i1?(MIN_FREE_2/CD_FRAMESIZE):(MIN_FREE_1/CD_FRAMESIZE)); + if(trackinfos) /* now loop through tracks and read header info */ for(i=1; i<=tracks; i++) { diff -r 6b6864d2c4ce -r 6bcb44b9edb1 cdrom.h --- a/cdrom.h Sat Dec 29 15:22:44 2007 +0100 +++ b/cdrom.h Sat Dec 29 15:23:49 2007 +0100 @@ -29,8 +29,22 @@ extern struct toc_entry *toc; extern long long cd_used, cd_avail; +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 */ +}; + int open_cdr(char *device); void close_cdr(int cd_fd); +void get_param(int fd, unsigned long *ahead, unsigned long *fahead); +void set_param(int fd, unsigned long ahead, unsigned long fahead); int full_read(int fd, void *buf, int count); int read_toc(int cd_fd, int trackinfos); void free_toc(); diff -r 6b6864d2c4ce -r 6bcb44b9edb1 debug.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/debug.h Sat Dec 29 15:23:49 2007 +0100 @@ -0,0 +1,33 @@ +/* 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 diff -r 6b6864d2c4ce -r 6bcb44b9edb1 version.h --- a/version.h Sat Dec 29 15:22:44 2007 +0100 +++ b/version.h Sat Dec 29 15:23:49 2007 +0100 @@ -2,7 +2,7 @@ #define _CDBACKUP_VERSION_H #ifndef VERSION -#define VERSION "0.6.2" +#define VERSION "0.6.3" #endif #endif