release 0.6.3 trunk 0.6.3
authornathan
Sat, 29 Dec 2007 15:23:49 +0100
branchtrunk
changeset 26bcb44b9edb1
parent 1 6b6864d2c4ce
child 3 d09ec85ffdfe
release 0.6.3
CHANGES
Makefile
README
TODO
cdbackup.1
cdbackup.c
cdbackup.h
cdrestore.1
cdrestore.c
cdrom.c
cdrom.h
debug.h
version.h
     1.1 --- a/CHANGES	Sat Dec 29 15:22:44 2007 +0100
     1.2 +++ b/CHANGES	Sat Dec 29 15:23:49 2007 +0100
     1.3 @@ -1,35 +1,47 @@
     1.4 +0.6.3
     1.5 +-----
     1.6 +- added -F option to cdrestore to force starting restore in the
     1.7 +  middle of a multi-disk set.
     1.8 +- added -T option to cdrestore for testing data integrity.
     1.9 +- added -R option to cdrestore to disable kernel read-ahead
    1.10 +  during restore.
    1.11 +- added debug output with option -D for cdbackup/cdrestore.
    1.12 +- added a "known problems" section to the man page covering the
    1.13 +  read-error-at-end-of-session problem.
    1.14 +- improved Makefile.
    1.15 +
    1.16  0.6.2
    1.17  -----
    1.18 -1. some more fixes to allow >2GB data on a single disk (SH)
    1.19 -2. added commandline option to specify padsize and enable CDROM
    1.20 -   XA2 mode (SH)
    1.21 -3. changed gcc options in Makefile (SH)
    1.22 -4. code cleanup (SH)
    1.23 -5. added man page, updated README (SH)
    1.24 +- some more fixes to allow >2GB data on a single disk (SH)
    1.25 +- added commandline option to specify padsize and enable CDROM
    1.26 +  XA2 mode (SH)
    1.27 +- changed gcc options in Makefile (SH)
    1.28 +- code cleanup (SH)
    1.29 +- added man page, updated README (SH)
    1.30   
    1.31  0.6.1
    1.32  -----
    1.33 -1. fixed size calculations with multi-disk backups > 2GB (SH)
    1.34 -2. minor message cleanups (CC)
    1.35 +- fixed size calculations with multi-disk backups > 2GB (SH)
    1.36 +- minor message cleanups (CC)
    1.37  
    1.38  0.6
    1.39  ---
    1.40 -1. multidisk-support (SH)
    1.41 -2. unix-like commandline options (SH)
    1.42 -3. can pass additional options to cdrecord (SH)
    1.43 -4. code cleanup (SH)
    1.44 -5. various bugs fixed (SH)
    1.45 +- multidisk-support (SH)
    1.46 +- unix-like commandline options (SH)
    1.47 +- can pass additional options to cdrecord (SH)
    1.48 +- code cleanup (SH)
    1.49 +- various bugs fixed (SH)
    1.50  
    1.51  0.5.2
    1.52  -----
    1.53 -1. Revamped Makefile (CC)
    1.54 +- Revamped Makefile (CC)
    1.55  
    1.56  0.5.1
    1.57  -----
    1.58 -1. Fixed bug in command-line parsing (JY)
    1.59 -2. Added error messages to command-line parsing (JY, CC)
    1.60 -3. Various sloppy code fixes (JY, CC)
    1.61 -4. Changed Makefile to check for compiler warnings (JY, CC)
    1.62 +- Fixed bug in command-line parsing (JY)
    1.63 +- Added error messages to command-line parsing (JY, CC)
    1.64 +- Various sloppy code fixes (JY, CC)
    1.65 +- Changed Makefile to check for compiler warnings (JY, CC)
    1.66  
    1.67  0.5.0
    1.68  -----
     2.1 --- a/Makefile	Sat Dec 29 15:22:44 2007 +0100
     2.2 +++ b/Makefile	Sat Dec 29 15:23:49 2007 +0100
     2.3 @@ -1,41 +1,50 @@
     2.4  # compiler selection and options
     2.5 -CC=gcc
     2.6 -CFLAGS=-g -O2 -Wall
     2.7 +CC       = gcc
     2.8 +CFLAGS   = -g -O2 -Wall
     2.9 +DEPFLAGS = -MM -MG
    2.10  
    2.11  # install location
    2.12  PREFIX=/usr/local
    2.13 -
    2.14  BINDIR=$(PREFIX)/bin
    2.15  MANDIR=$(PREFIX)/man
    2.16  
    2.17  ###############################################
    2.18  
    2.19 -# executables
    2.20 -TARGETS=cdbackup cdrestore
    2.21 +TARGETS = cdbackup cdrestore
    2.22 +VERSION = $(shell grep 'define VERSION' version.h | awk '{ print $$3 }' | sed -e 's/["]//g')
    2.23 +ARCHIVE = cdbackup-$(VERSION)
    2.24 +DEPFILE = .dependencies
    2.25 +TMPDIR  = /tmp
    2.26  
    2.27  all: $(TARGETS)
    2.28  
    2.29 -# ruleset
    2.30  %.o: %.c
    2.31  	$(CC) $(CFLAGS) -c $< -o $@
    2.32  
    2.33 +$(DEPFILE): Makefile
    2.34 +	@$(CC) $(DEPFLAGS) cdbackup.c cdrestore.c cdrom.c misc.c > $@
    2.35 +
    2.36 +include $(DEPFILE)
    2.37 +
    2.38  cdbackup: cdbackup.o cdrom.o misc.o
    2.39  	$(CC) $(CFLAGS) -o cdbackup cdbackup.o cdrom.o misc.o
    2.40  
    2.41  cdrestore: cdrestore.o cdrom.o misc.o
    2.42  	$(CC) $(CFLAGS) -o cdrestore cdrestore.o cdrom.o misc.o
    2.43  
    2.44 -cdbackup.o: cdbackup.c cdbackup.h cdrom.h misc.h version.h
    2.45 -cdrestore.o: cdrestore.c cdbackup.h cdrom.h misc.h version.h
    2.46 -cdrom.o: cdrom.c cdbackup.h misc.h
    2.47 -misc.o: misc.c misc.h
    2.48 -
    2.49 -# targets
    2.50  strip: $(TARGETS)
    2.51  	strip $(TARGETS)
    2.52  
    2.53  clean:
    2.54 -	rm -f $(TARGETS) core *.core *.o
    2.55 +	rm -f $(TARGETS) $(DEPFILE) cdbackup-*.tar.gz core *.core *.o
    2.56 +
    2.57 +dist: clean
    2.58 +	@-rm -rf $(TMPDIR)/$(ARCHIVE)
    2.59 +	@mkdir $(TMPDIR)/$(ARCHIVE)
    2.60 +	@cp -a * $(TMPDIR)/$(ARCHIVE)
    2.61 +	@tar czf $(ARCHIVE).tar.gz -C $(TMPDIR) $(ARCHIVE)
    2.62 +	@-rm -rf $(TMPDIR)/$(ARCHIVE)
    2.63 +	@echo Distribution package created as $(ARCHIVE).tar.gz
    2.64  
    2.65  install:
    2.66  	install -d $(BINDIR)
     3.1 --- a/README	Sat Dec 29 15:22:44 2007 +0100
     3.2 +++ b/README	Sat Dec 29 15:23:49 2007 +0100
     3.3 @@ -1,4 +1,4 @@
     3.4 -cdbackup, cdrestore - CD archive utilities version 0.6.2
     3.5 +cdbackup, cdrestore - CD archive utilities version 0.6.3
     3.6  Copyright (c) 2000-2002 Craig Condit, Stefan Hülswitt. All rights reserved.
     3.7  
     3.8  This software is released under a BSD-style license - see the LICENSE file.
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/TODO	Sat Dec 29 15:23:49 2007 +0100
     4.3 @@ -0,0 +1,1 @@
     4.4 +-increase buffer size on restore for speed?
     5.1 --- a/cdbackup.1	Sat Dec 29 15:22:44 2007 +0100
     5.2 +++ b/cdbackup.1	Sat Dec 29 15:23:49 2007 +0100
     5.3 @@ -1,22 +1,22 @@
     5.4 -.TH "cdbackup" "1" "0.6.2" "Stefan Hülswitt" ""
     5.5 +.TH "cdbackup" "1" "0.6.3" "Stefan Hülswitt" ""
     5.6  .SH "NAME"
     5.7  .LP 
     5.8  cdbackup \- Streaming backup to CD\-R(W)
     5.9  .SH "SYNOPSIS"
    5.10  .LP 
    5.11 -cdbackup [\-mvVX] [\-d \fIdevice\fP] [\-r \fIscsi\-dev\fP] [\-s \fIspeed\fP]
    5.12 +cdbackup [\-mvDVX] [\-d \fIdevice\fP] [\-r \fIscsi\-dev\fP] [\-s \fIspeed\fP]
    5.13           [\-p \fInum\fP] [\-l \fIsize\fP] [\-a \fIlabel\fP] [\-c \fIcommand\fP]
    5.14           [\-\- \fIcdrecord\-options\fP]
    5.15  .SH "DESCRIPTION"
    5.16  .LP 
    5.17  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).
    5.18  .LP 
    5.19 -NOTE: this program REQUIRES that a recent version of cdrecord is present in the PATH.
    5.20 +\fINOTE:\fR this program REQUIRES that a recent version of \fBcdrecord\fR(1) is present in the PATH.
    5.21  .LP 
    5.22 -WARNING! When using this program under Linux, be sure not to use dump with
    5.23 -kernels in the 2.4.x series. Using dump on an ext2 filesystem has a very
    5.24 -high potential for causing filesystem corruption. As of kernel version
    5.25 -2.4.18, this has not been fixed and it may not be fixed at all.
    5.26 +\fIWARNING!\fR When using this program under Linux, be sure not to use dump on a mounted
    5.27 +filesystem. This has a high potential for creating corrupted backups. As of kernel version
    5.28 +2.4.19, this has not been fixed and it may not be fixed at all.
    5.29 +You can read Linus statement about this at <http://search.alphanet.ch/cgi\-bin/search.cgi?max_results=10&type=long&msgid=Pine.LNX.4.21.0104270953280.2067\-100000@penguin.transmeta.com&domain=ml\-linux\-kernel>
    5.30  .SH "OPTIONS"
    5.31  .LP 
    5.32  .TP 
    5.33 @@ -27,13 +27,13 @@
    5.34  
    5.35  .TP 
    5.36  \fB\-r\fR \fIscsi\-device\fP
    5.37 -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.
    5.38 +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.
    5.39  .br 
    5.40  (default: none)
    5.41  
    5.42  .TP 
    5.43  \fB\-s\fR \fIspeed\fP
    5.44 -The writing speed which is passed to cdrecord (via speed=\fIspeed\fP).
    5.45 +The writing speed which is passed to \fBcdrecord\fR(1) (via speed=\fIspeed\fP).
    5.46  .br 
    5.47  (default: 4)
    5.48  
    5.49 @@ -45,7 +45,7 @@
    5.50  
    5.51  .TP 
    5.52  \fB\-X\fR
    5.53 -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).
    5.54 +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).
    5.55  
    5.56  .TP 
    5.57  \fB\-l\fR \fIsize\fP
    5.58 @@ -74,12 +74,16 @@
    5.59  Enables verbose mode.
    5.60  
    5.61  .TP 
    5.62 +\fB\-D\fR
    5.63 +Enables DEBUG output (probably not usefull for normal use).
    5.64 +
    5.65 +.TP 
    5.66  \fB\-V\fR
    5.67  Prints out version information and exits.
    5.68  
    5.69  .TP 
    5.70  \fB\-\-\fR \fIcdrecord\-options\fP
    5.71 -All options following \fB\-\-\fR are passed to cdrecord.
    5.72 +Pass following options to \fBcdrecord\fR(1).
    5.73  .SH "EXAMPLES"
    5.74  .LP 
    5.75  To create a tar archive of /home and
    5.76 @@ -91,6 +95,29 @@
    5.77  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:
    5.78  .IP 
    5.79  tar cf \- /usr | cdbackup \-d /dev/sr1 \-r 1,4,0 \-s 12 \-m \-v
    5.80 +.SH "KNOWN PROBLEMS"
    5.81 +.LP 
    5.82 +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.
    5.83 +.LP 
    5.84 +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.
    5.85 +.LP 
    5.86 +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.
    5.87 +.LP  
    5.88 +The author isn't able to provide a full solution, but some hints which may help:
    5.89 +.TP 
    5.90 +1.
    5.91 +Update to a recent kernel.
    5.92 +.TP 
    5.93 +2.
    5.94 +Disable kernel readahead with option \-R when restoring.
    5.95 +.TP 
    5.96 +3.
    5.97 +Increase the padsize with option \-p. Use values >= 128.
    5.98 +.TP 
    5.99 +4.
   5.100 +Use option \-X if your writer supports this (Sony drives doesn't supports this mode).
   5.101 +.LP 
   5.102 +Please contact the author if you can contribute additional information about the problem.
   5.103  .SH "AUTHORS"
   5.104  .LP 
   5.105  Stefan Hülswitt <huels@iname.com>
     6.1 --- a/cdbackup.c	Sat Dec 29 15:22:44 2007 +0100
     6.2 +++ b/cdbackup.c	Sat Dec 29 15:23:49 2007 +0100
     6.3 @@ -41,6 +41,7 @@
     6.4  #include "cdbackup.h"
     6.5  #include "cdrom.h"
     6.6  #include "misc.h"
     6.7 +#include "debug.h"
     6.8  #include "version.h"
     6.9  
    6.10  /* #define DEBUGOUT */
    6.11 @@ -57,6 +58,7 @@
    6.12  char * multicmd =0;
    6.13  int    verbose  =0;
    6.14  int    xamode2  =0;
    6.15 +int    debug    =0;
    6.16  
    6.17  char **cdrec_opt=0;
    6.18  int    cdrec_opt_count=0;
    6.19 @@ -81,6 +83,7 @@
    6.20      "  -m             enable multi-disk mode\n"
    6.21      "  -c COMMAND     call COMMAND on disk change in multi-disk mode\n"
    6.22      "  -v             be verbose\n"
    6.23 +    "  -D             enable DEBUG output\n"
    6.24      "  -V             prints version & exits\n"
    6.25      "  --             pass rest of commandline to cdrecord\n"
    6.26      "\n", prg_name);
    6.27 @@ -92,7 +95,7 @@
    6.28  {
    6.29    int i;
    6.30  
    6.31 -  while ((i=getopt(argc,argv,"d:r:l:s:p:a:c:mvVX"))>0) {
    6.32 +  while ((i=getopt(argc,argv,"d:r:l:s:p:a:c:mvVXD"))>0) {
    6.33      switch (i) {
    6.34         case 'V': fprintf(stderr,"cdbackup "VERSION" (compiled "__DATE__")\n"
    6.35  	                        "Copyright (C) 2000-2002\n"
    6.36 @@ -107,6 +110,9 @@
    6.37         case 'd': cd_dev=optarg; break;
    6.38         case 'r': cdr_dev=optarg; break;
    6.39         case 'a': cd_label=optarg; break;
    6.40 +       case 'D': verbose=1; debug=1; 
    6.41 +                 DEBUG("cdbackup: DEBUG output enabled ("VERSION")\n");
    6.42 +                 break;
    6.43         case 'l': errno=0; cd_len=strtol(optarg,NULL,10);
    6.44                   if(errno==ERANGE || cd_len<1) serror("Option -l: length out of range (must be >=1)\n");
    6.45  	         cd_len = (long long)cd_len * (1024*1024) / CD_FRAMESIZE; /* convert to blocks */
    6.46 @@ -156,7 +162,7 @@
    6.47    *p++="-";
    6.48    *p++=0;
    6.49  
    6.50 -  if(verbose) {
    6.51 +  if(debug) {
    6.52      fprintf(stderr,"%s: cdrecord command:",prg_name);
    6.53      for(p=args ; *p ; p++) fprintf(stderr," %s",*p);
    6.54      fprintf(stderr,"\n");
     7.1 --- a/cdbackup.h	Sat Dec 29 15:22:44 2007 +0100
     7.2 +++ b/cdbackup.h	Sat Dec 29 15:23:49 2007 +0100
     7.3 @@ -34,17 +34,6 @@
     7.4  
     7.5  #define MIN_BLOCKS	2   /* min. required blocks for a session: header block, one data block */
     7.6  
     7.7 -struct toc_entry {
     7.8 -  u_char track_no;	/* track number */
     7.9 -  char is_data;		/* 1 = data track */
    7.10 -  char is_cdbackup;	/* was it created by CD-Backup? */
    7.11 -  int sec_start;	/* start sector */
    7.12 -  char id_str[33];	/* recorder id string (32 chars) */
    7.13 -  char vol_id[33];	/* volume label (32 characters) */
    7.14 -  char t_stamp[13];	/* time stamp: yyyymmddhhmm */
    7.15 -  char disk_set;	/* disk number */
    7.16 -};
    7.17 -
    7.18  struct header_block {
    7.19    char id_str[33];	/* recorder id string (32 chars) */
    7.20    char vol_id[33];	/* volume label (32 characters) */
     8.1 --- a/cdrestore.1	Sat Dec 29 15:22:44 2007 +0100
     8.2 +++ b/cdrestore.1	Sat Dec 29 15:23:49 2007 +0100
     8.3 @@ -1,10 +1,10 @@
     8.4 -.TH "cdrestore" "1" "0.6.2" "Stefan Hülswitt" ""
     8.5 +.TH "cdrestore" "1" "0.6.3" "Stefan Hülswitt" ""
     8.6  .SH "NAME"
     8.7  .LP 
     8.8  cdrestore \- Streaming restore from CD\-R(W)
     8.9  .SH "SYNOPSIS"
    8.10  .LP 
    8.11 -cdrestore [\-qV] [\-d \fIdevice\fP] [\-l \fIsize\fP] [\-t \fItrack\fP]
    8.12 +cdrestore [\-qvDFRTV] [\-d \fIdevice\fP] [\-l \fIsize\fP] [\-t \fItrack\fP]
    8.13            [\-c \fIcommand\fP]
    8.14  .SH "DESCRIPTION"
    8.15  .LP 
    8.16 @@ -30,6 +30,23 @@
    8.17  (default: none)
    8.18  
    8.19  .TP 
    8.20 +\fB\-T\fR
    8.21 +Enables test mode. The complete restore process is done to test data integrity, but no data is output.
    8.22 +.br 
    8.23 +\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.
    8.24 +
    8.25 +.TP 
    8.26 +\fB\-F\fR
    8.27 +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.
    8.28 +.br 
    8.29 +\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.
    8.30 +
    8.31 +.TP 
    8.32 +\fB\-R\fR
    8.33 +Disable the kernel readahead for the CDROM device during the restore process.
    8.34 +(see \fBcdbackup\fR(1) Known problems)
    8.35 +
    8.36 +.TP 
    8.37  \fB\-c\fR \fIcommand\fP
    8.38  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.
    8.39  .br 
    8.40 @@ -40,6 +57,14 @@
    8.41  Queries the media, prints out the contents and exits.
    8.42  
    8.43  .TP 
    8.44 +\fB\-v\fR
    8.45 +Enables verbose mode.
    8.46 +
    8.47 +.TP 
    8.48 +\fB\-D\fR
    8.49 +Enables DEBUG output (probably not usefull for normal use).
    8.50 +
    8.51 +.TP 
    8.52  \fB\-V\fR
    8.53  Prints out version information and exits.
    8.54  .SH "EXAMPLES"
     9.1 --- a/cdrestore.c	Sat Dec 29 15:22:44 2007 +0100
     9.2 +++ b/cdrestore.c	Sat Dec 29 15:23:49 2007 +0100
     9.3 @@ -41,18 +41,24 @@
     9.4  #include "cdbackup.h"
     9.5  #include "cdrom.h"
     9.6  #include "misc.h"
     9.7 +#include "debug.h"
     9.8  #include "version.h"
     9.9  
    9.10  /* defaults */
    9.11  char * prg_name ="cdrestore";
    9.12 -int    cd_mode  =0;
    9.13  int    cd_track =-1;
    9.14  char * cd_dev   ="/dev/cdrom";
    9.15  long   cd_len   =333000; /* blocks */
    9.16  char * multicmd =0;
    9.17 -int    verbose  =1;
    9.18 +int    verbose  =0;
    9.19 +int    force    =0;
    9.20 +int    query    =0;
    9.21 +int    verify   =0;
    9.22 +int    ahead    =0;
    9.23 +int    debug    =0;
    9.24  
    9.25  int tracks;
    9.26 +int disknum;
    9.27  long long totalSize;
    9.28  struct header_block headersave;
    9.29  
    9.30 @@ -68,6 +74,11 @@
    9.31      "  -t N           restore from track N\n"
    9.32      "  -l N           CD-R has a size of N MB\n"
    9.33      "  -c COMMAND     call COMMAND on disk change in multi-disk mode\n"
    9.34 +    "  -T             don't restore, test data integrity only\n"
    9.35 +    "  -F             force starting restore in the middle of a multi-disk set\n"
    9.36 +    "  -R             set the kernel read-ahead to zero during restore\n"
    9.37 +    "  -v             be verbose\n"
    9.38 +    "  -D             enable DEBUG output\n"
    9.39      "  -V             prints version & exits\n"
    9.40      "\n", prg_name);
    9.41  }
    9.42 @@ -78,7 +89,7 @@
    9.43  {
    9.44    int i;
    9.45  
    9.46 -  while ((i=getopt(argc,argv,"d:l:c:t:qV"))>0) {
    9.47 +  while ((i=getopt(argc,argv,"d:l:c:t:qvVFTDR"))>0) {
    9.48      switch (i) {
    9.49         case 'V': fprintf(stderr,"cdrestore "VERSION" (compiled "__DATE__")\n"
    9.50  	                        "Copyright (C) 2000-2002\n"
    9.51 @@ -88,7 +99,14 @@
    9.52  	         exit(0);
    9.53         case 'c': multicmd=optarg; break;
    9.54         case 'd': cd_dev=optarg; break;
    9.55 -       case 'q': cd_mode=1; break;
    9.56 +       case 'q': query=1; break;
    9.57 +       case 'F': force=1; break;
    9.58 +       case 'R': ahead=1; break;
    9.59 +       case 'T': verify=1; break;
    9.60 +       case 'v': verbose=1; break;
    9.61 +       case 'D': verbose=1; debug=1; 
    9.62 +                 DEBUG("cdrestore: DEBUG output enabled ("VERSION")\n");
    9.63 +                 break;
    9.64         case 't': errno=0; cd_track=strtol(optarg,NULL,10);
    9.65                   if(errno==ERANGE || cd_track<1) serror("Option -t: invalid track (must be >=1)\n");
    9.66  	         break;
    9.67 @@ -100,7 +118,7 @@
    9.68         }
    9.69      }
    9.70  
    9.71 -  if(!cd_mode && cd_track<0) /* need track number */
    9.72 +  if(!query && cd_track<0) /* need track number */
    9.73      serror("A track number is required.\n");
    9.74  }
    9.75  
    9.76 @@ -117,31 +135,37 @@
    9.77      (stamp[8]-'0')*10   + (stamp[9]-'0'),
    9.78      (stamp[10]-'0')*10  + (stamp[11]-'0'));
    9.79  
    9.80 -  if(startsec>=0) snprintf(size,sizeof(size)-1," %3ld MB:",(long)((long long)(endsec-startsec)*CD_FRAMESIZE/(1024*1024)));
    9.81 +  if(startsec>=0) snprintf(size,sizeof(size)-1," %3ld MB:",(long)((long long)(endsec-startsec+1)*CD_FRAMESIZE/(1024*1024)));
    9.82    else size[0]=0;
    9.83  
    9.84    fprintf(stderr,"Track %02d:%s %s  Part %d: %s\n", track, size, timestr, disk, id);
    9.85 -}
    9.86 -
    9.87 -/****************************************************************************/
    9.88 -
    9.89 -int restore(int disknum, int disktrack)
    9.90 +  if(startsec>=0) DEBUG("          Start sector %7d Last sector %7d\n",startsec,endsec);
    9.91 +}
    9.92 +
    9.93 +/****************************************************************************/
    9.94 +
    9.95 +int restore(int disktrack)
    9.96  {
    9.97    int infile;
    9.98    int result=0, i, bytes;
    9.99 -  long long totalRead;
   9.100 +  long long totalRead, startPos;
   9.101    struct header_block header;
   9.102    char buffer[CD_FRAMESIZE];
   9.103    struct data_block *db=(struct data_block *)&buffer[0];
   9.104 -
   9.105 -  if ((infile = open(cd_dev, O_RDONLY)) < 0) error("Error opening device");
   9.106 +  unsigned long r_ahead, r_fahead;
   9.107 +
   9.108 +  if((infile=open(cd_dev, O_RDONLY)) < 0) error("Error opening device");
   9.109 +  if(ahead) {
   9.110 +    get_param(infile,&r_ahead,&r_fahead);
   9.111 +    set_param(infile,0,0);
   9.112 +    }
   9.113  
   9.114    /* seek to proper CD-R(W) track */
   9.115    for(i=tracks;i>0;i--) if(toc[i].track_no==disktrack) break;
   9.116    if(!i) { fprintf(stderr, "%s: Can't find track %d\n", prg_name, disktrack); exit(1); }
   9.117  
   9.118 -  totalRead=(long long)toc[i].sec_start*CD_FRAMESIZE;
   9.119 -  if(lseek64(infile,totalRead,SEEK_SET) != totalRead) error("Error seeking to track");
   9.120 +  startPos=(long long)toc[i].sec_start*CD_FRAMESIZE;
   9.121 +  if(lseek64(infile,startPos,SEEK_SET) != startPos) error("Error seeking to track");
   9.122  
   9.123    /* read header block */
   9.124    bytes=full_read(infile,buffer,CD_FRAMESIZE);
   9.125 @@ -152,38 +176,45 @@
   9.126    memcpy(&header,buffer,sizeof(header));
   9.127  
   9.128    if(!strncmp(SHORT_HDR,header.id_str,strlen(SHORT_HDR))) {
   9.129 -    fprintf(stderr,"%s: ", prg_name);
   9.130 -    print_track(disktrack, header.t_stamp, header.vol_id, header.disk_set, -1, -1);
   9.131 +    if(verbose) {
   9.132 +      fprintf(stderr,"%s: ", prg_name);
   9.133 +      print_track(disktrack, header.t_stamp, header.vol_id, header.disk_set, -1, -1);
   9.134 +      }
   9.135  
   9.136      if(disknum==1) {
   9.137        if(header.disk_set!=1) {
   9.138 -        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);
   9.139 -        exit(1);
   9.140 +        if(!force) {
   9.141 +          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);
   9.142 +          exit(1);
   9.143 +          }
   9.144 +        fprintf(stderr,"%s: This is disk %d of the multi-disk set, but -F forces me to continue!\n",prg_name,header.disk_set);
   9.145 +        disknum=header.disk_set;
   9.146          }
   9.147        headersave=header;		/* save header for use with disk 2-n */
   9.148        }
   9.149      else {
   9.150        if(strcmp(header.t_stamp,headersave.t_stamp) || strcmp(header.vol_id,headersave.vol_id)) {
   9.151          fprintf(stderr,"%s: This disk doesn't belong to the current set!\n",prg_name);
   9.152 -        result=2;
   9.153 +        result=-1;
   9.154          }
   9.155        else if(header.disk_set!=disknum) {
   9.156          fprintf(stderr,"%s: Wrong sequence. You need disk %d now!\n",prg_name,disknum);
   9.157 -        result=2;
   9.158 +        result=-1;
   9.159          }
   9.160 -      else fprintf(stderr, "%s: Beginning restore (Disk %d)\n", prg_name,disknum);
   9.161 +      else if(verbose) fprintf(stderr, "%s: Beginning restore (Disk %d)\n", prg_name,disknum);
   9.162        }
   9.163      }
   9.164    else {
   9.165      fprintf(stderr, "%s: Track %02d was not created with 'cdbackup'\n", prg_name,disktrack);
   9.166      if(disknum==1) exit(1);
   9.167 -    result=2;
   9.168 +    result=-1;
   9.169      }
   9.170  
   9.171    while(!result) {
   9.172      int size;
   9.173  
   9.174      /* read data block */
   9.175 +    DEBUG("\rReading sector %7ld  ",(long)((startPos+totalRead)/CD_FRAMESIZE));
   9.176      bytes = full_read(infile, buffer, CD_FRAMESIZE);
   9.177      if (bytes < 0) error("Error reading data");
   9.178      if (bytes != CD_FRAMESIZE) error("Unexpected EOF reading data");
   9.179 @@ -192,22 +223,30 @@
   9.180      /* sanity check */
   9.181      size=ntohs(db->datasize);
   9.182      if(size>DATASIZE) {
   9.183 -      fprintf(stderr,"%s: Warning! Bad datasize at %lld\n",prg_name,totalRead);
   9.184 +      if(verbose) fprintf(stderr,"%s: Warning! Bad datasize at %lld\n",prg_name,totalRead);
   9.185        size=DATASIZE;
   9.186        }
   9.187  
   9.188 -    /* write the data block */
   9.189 -    bytes=write(1,&buffer[DBSIZE], size);
   9.190 -    if(bytes!=size) error("Error writing data");
   9.191 +    if(!verify) {
   9.192 +      /* write the data block */
   9.193 +      bytes=write(1,&buffer[DBSIZE], size);
   9.194 +      if(bytes!=size) error("Error writing data");
   9.195 +      }
   9.196  
   9.197      if(db->status == 1) break; 	  /* end of backup*/
   9.198 -    if(db->status == 2) result=1; /* disk full */
   9.199 -    }
   9.200 +    if(db->status == 2) result=1; /* next disk */
   9.201 +    }
   9.202 +  DEBUG("\n");
   9.203  
   9.204    /* print status */
   9.205    totalSize+=totalRead;
   9.206 -  if(result!=2) fprintf(stderr, "%s: Restore complete. %lld kB read (%lld kB from this disk)\n",prg_name, totalSize/1024, totalRead/1024);
   9.207 -
   9.208 +  if(result>=0 && verbose)
   9.209 +    fprintf(stderr, "%s: Restore complete. %lld kB read (%lld kB from this disk)\n",prg_name, totalSize/1024, totalRead/1024);
   9.210 +
   9.211 +  if(ahead) {
   9.212 +    set_param(infile,r_ahead,r_fahead);
   9.213 +    get_param(infile,&r_ahead,&r_fahead);
   9.214 +    }
   9.215    close(infile);
   9.216    return(result);
   9.217  }
   9.218 @@ -225,7 +264,7 @@
   9.219    for (i = 1; i <= tracks; i++) {
   9.220      if(toc[i].is_data==0) fprintf(stderr,"Track %02d: Non-data\n", toc[i].track_no);
   9.221      else if (toc[i].is_cdbackup == 1)
   9.222 -      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);
   9.223 +      print_track(i, toc[i].t_stamp, toc[i].vol_id, toc[i].disk_set, toc[i].sec_start, toc[i].sec_end);
   9.224      else fprintf(stderr,"Track %02d: Data\n", toc[i].track_no);
   9.225      }
   9.226  }
   9.227 @@ -238,24 +277,23 @@
   9.228  
   9.229    parse_cmdline(argc, argv);
   9.230  
   9.231 -  if(!cd_mode) {
   9.232 -    int disknum=1, result;
   9.233 -    totalSize=0;
   9.234 +  cdr=open_cdr(cd_dev); tracks=read_toc(cdr,(query || debug)); close_cdr(cdr);
   9.235 +  if(query || debug) {
   9.236 +    verbose=1;
   9.237 +    print_toc();
   9.238 +    }
   9.239 +  if(!query) {
   9.240 +    int result;
   9.241 +    if(verify) fprintf(stderr,"%s: Verify mode enabled, no data output!\n",prg_name);
   9.242 +    totalSize=0; disknum=1;
   9.243      do {
   9.244 -      cdr=open_cdr(cd_dev); tracks=read_toc(cdr,0); close_cdr(cdr);
   9.245 -
   9.246 -      result=restore(disknum,cd_track);
   9.247 +      result=restore(cd_track);
   9.248        if(result) {
   9.249 -        if(result==1) { disknum++; cd_track=1; }
   9.250 +        if(result>0) { disknum++; cd_track=1; }
   9.251          fprintf(stderr,"%s: Next disk needed: disk %d from %s\n",prg_name,disknum,headersave.vol_id);
   9.252          if(start_diskchange(multicmd,cd_dev)) serror("Diskchange command failed");
   9.253  	}
   9.254        } while(result);
   9.255      }
   9.256 -  else {
   9.257 -    cdr=open_cdr(cd_dev); tracks=read_toc(cdr,1); close_cdr(cdr);
   9.258 -    print_toc();
   9.259 -    }
   9.260 -
   9.261    return 0;
   9.262  }
    10.1 --- a/cdrom.c	Sat Dec 29 15:22:44 2007 +0100
    10.2 +++ b/cdrom.c	Sat Dec 29 15:23:49 2007 +0100
    10.3 @@ -31,14 +31,19 @@
    10.4  #include <fcntl.h>
    10.5  #include <string.h>
    10.6  #include <linux/cdrom.h>
    10.7 +#include <linux/fs.h>
    10.8  #include <sys/ioctl.h>
    10.9  
   10.10 +#include "cdrom.h"
   10.11  #include "cdbackup.h"
   10.12  #include "misc.h"
   10.13 +#include "debug.h"
   10.14  
   10.15  /* size of leadin/out depending of how many tracks are on cd */
   10.16  #define MIN_FREE_1	(11400*CD_FRAMESIZE) /* 1th track */
   10.17  #define MIN_FREE_2	(6900*CD_FRAMESIZE)  /* 2nd and more tracks */
   10.18 +/* number of (unreadable) runout sectos */
   10.19 +#define RUNOUT          2
   10.20  
   10.21  struct toc_entry *toc=0;
   10.22  long long cd_used, cd_avail;
   10.23 @@ -63,6 +68,33 @@
   10.24  
   10.25  /****************************************************************************/
   10.26  
   10.27 +void get_param(int fd, unsigned long *ahead, unsigned long *fahead)
   10.28 +{
   10.29 +#if defined(BLKRAGET) && defined(BLKFRAGET)
   10.30 +  *ahead = *fahead = 0;
   10.31 +  ioctl(fd,BLKRAGET,ahead);
   10.32 +  ioctl(fd,BLKFRAGET,fahead);
   10.33 +  DEBUG("get_param: readahead=%ld freadahead=%ld\n",*ahead,*fahead);
   10.34 +#else
   10.35 +  fprintf("Can't get readahead parameter. Ioctl's not available\n");
   10.36 +#endif
   10.37 +}
   10.38 +
   10.39 +/****************************************************************************/
   10.40 +
   10.41 +void set_param(int fd, unsigned long ahead, unsigned long fahead)
   10.42 +{
   10.43 +#if defined(BLKRAGET) && defined(BLKFRAGET)
   10.44 +  ioctl(fd, BLKRASET, ahead);
   10.45 +  ioctl(fd, BLKFRASET, fahead);
   10.46 +  DEBUG("set_param: readahead=%ld freadahead=%ld\n",ahead,fahead);
   10.47 +#else
   10.48 +  fprintf("Can't set readahead parameter. Ioctl's not available\n");
   10.49 +#endif
   10.50 +}
   10.51 +
   10.52 +/****************************************************************************/
   10.53 +
   10.54  int full_read(int fd, void *buf, int count)
   10.55  {
   10.56    int total=0;
   10.57 @@ -101,6 +133,7 @@
   10.58    /* get start and end tracks */
   10.59    start_track = cd_header.cdth_trk0;
   10.60    tracks = cd_header.cdth_trk1-start_track+1;
   10.61 +  DEBUG("read_toc: starttrack=%d tracks=%d\n",start_track,tracks);
   10.62  
   10.63    free_toc();
   10.64    if(!(toc=calloc(tracks+1,sizeof(struct toc_entry)))) serror("No memory for TOC");
   10.65 @@ -115,8 +148,11 @@
   10.66    toc[0].track_no=CDROM_LEADOUT;  /* not a real track */
   10.67    toc[0].sec_start=cd_entry.cdte_addr.lba;
   10.68  
   10.69 -  cd_used=(long long)toc[0].sec_start*CD_FRAMESIZE; cd_avail=(long long)cd_len*CD_FRAMESIZE-cd_used;
   10.70 +  cd_used  =(long long)toc[0].sec_start*CD_FRAMESIZE;
   10.71 +  cd_avail =(long long)cd_len*CD_FRAMESIZE-cd_used;
   10.72    cd_avail-=(tracks>1?MIN_FREE_2:MIN_FREE_1);
   10.73 +  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);
   10.74 +
   10.75    if(cd_avail<0) cd_avail=0; /* can be <0 due to assumed additional lead-in/out */
   10.76  
   10.77    /* read rest of tracks */
   10.78 @@ -129,6 +165,11 @@
   10.79      if(cd_entry.cdte_ctrl&CDROM_DATA_TRACK) toc[i].is_data=1;
   10.80      }    
   10.81  
   10.82 +  /* calculate end sectors */
   10.83 +  toc[tracks].sec_end = toc[  0].sec_start - 1 - RUNOUT;
   10.84 +  for(i=1; i<tracks; i++)
   10.85 +    toc[i].sec_end = toc[i+1].sec_start - 1 - RUNOUT - (i>1?(MIN_FREE_2/CD_FRAMESIZE):(MIN_FREE_1/CD_FRAMESIZE));
   10.86 +
   10.87   if(trackinfos)
   10.88    /* now loop through tracks and read header info */
   10.89    for(i=1; i<=tracks; i++) {
    11.1 --- a/cdrom.h	Sat Dec 29 15:22:44 2007 +0100
    11.2 +++ b/cdrom.h	Sat Dec 29 15:23:49 2007 +0100
    11.3 @@ -29,8 +29,22 @@
    11.4  extern struct toc_entry *toc;
    11.5  extern long long cd_used, cd_avail;
    11.6  
    11.7 +struct toc_entry {
    11.8 +  u_char track_no;	/* track number */
    11.9 +  char is_data;		/* 1 = data track */
   11.10 +  char is_cdbackup;	/* was it created by CD-Backup? */
   11.11 +  int sec_start;	/* start sector */
   11.12 +  int sec_end;		/* last sector */
   11.13 +  char id_str[33];	/* recorder id string (32 chars) */
   11.14 +  char vol_id[33];	/* volume label (32 characters) */
   11.15 +  char t_stamp[13];	/* time stamp: yyyymmddhhmm */
   11.16 +  char disk_set;	/* disk number */
   11.17 +};
   11.18 +
   11.19  int open_cdr(char *device);
   11.20  void close_cdr(int cd_fd);
   11.21 +void get_param(int fd, unsigned long *ahead, unsigned long *fahead);
   11.22 +void set_param(int fd, unsigned long ahead, unsigned long fahead);
   11.23  int full_read(int fd, void *buf, int count);
   11.24  int read_toc(int cd_fd, int trackinfos);
   11.25  void free_toc();
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/debug.h	Sat Dec 29 15:23:49 2007 +0100
    12.3 @@ -0,0 +1,33 @@
    12.4 +/* debug.h
    12.5 +Copyright (c) 2000-2002 Craig Condit, Stefan Hülswitt.
    12.6 +
    12.7 +Redistribution and use in source and binary forms, with or without
    12.8 +modification, are permitted provided that the following conditions are met: 
    12.9 +
   12.10 +1. Redistributions of source code must retain the above copyright notice,
   12.11 +   this list of conditions and the following disclaimer. 
   12.12 +2. Redistributions in binary form must reproduce the above copyright notice,
   12.13 +   this list of conditions and the following disclaimer in the documentation
   12.14 +   and/or other materials provided with the distribution. 
   12.15 +
   12.16 +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
   12.17 +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   12.18 +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   12.19 +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
   12.20 +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   12.21 +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   12.22 +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   12.23 +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   12.24 +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   12.25 +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   12.26 +SUCH DAMAGE.
   12.27 +*/
   12.28 +
   12.29 +#ifndef _CDBACKUP_DEBUG_H
   12.30 +#define _CDBACKUP_DEBUG_H
   12.31 +
   12.32 +extern int debug;
   12.33 +
   12.34 +#define DEBUG(format,args...) { if(debug) fprintf(stderr,format, ## args); }
   12.35 +
   12.36 +#endif
    13.1 --- a/version.h	Sat Dec 29 15:22:44 2007 +0100
    13.2 +++ b/version.h	Sat Dec 29 15:23:49 2007 +0100
    13.3 @@ -2,7 +2,7 @@
    13.4  #define _CDBACKUP_VERSION_H
    13.5  
    13.6  #ifndef VERSION
    13.7 -#define VERSION "0.6.2"
    13.8 +#define VERSION "0.6.3"
    13.9  #endif
   13.10  
   13.11  #endif