1.1 --- a/.hgtags Sat Dec 29 15:23:55 2007 +0100
1.2 +++ b/.hgtags Sat Dec 29 15:25:21 2007 +0100
1.3 @@ -1,2 +1,3 @@
1.4 d85c12073deaa1b5048d3a8c761d9dd55d8169a1 0.6.2
1.5 6bcb44b9edb16f763d32184678a6f6627675c0ab 0.6.3
1.6 +d09ec85ffdfeffa93a5c341bef50509d40d215bc 0.6.4beta
2.1 --- a/CHANGES Sat Dec 29 15:23:55 2007 +0100
2.2 +++ b/CHANGES Sat Dec 29 15:25:21 2007 +0100
2.3 @@ -1,3 +1,15 @@
2.4 +0.6.4beta
2.5 +---------
2.6 +- added support for file based backups (virtual image).
2.7 +- added DVD support (needs cdrecord-ProDVD).
2.8 +- added CRC checksum to ensure backup integrity.
2.9 +- now auto-detecting media size (via cdrecord -atip).
2.10 +- now using defaults from environment vars CDR_DEVICE & CDR_SPEED.
2.11 +- fixed a typo in the man page (Debian Bug#180279).
2.12 +- check return value of read() in diskchange.
2.13 +- fixed missing stderr in fprintf() calls.
2.14 +- added some glue to compile on SunOS.
2.15 +
2.16 0.6.3
2.17 -----
2.18 - added -F option to cdrestore to force starting restore in the
3.1 --- a/CREDITS Sat Dec 29 15:23:55 2007 +0100
3.2 +++ b/CREDITS Sat Dec 29 15:25:21 2007 +0100
3.3 @@ -20,3 +20,8 @@
3.4 E: huels@iname.com
3.5 D: multidisk support, code cleanup, bugfixes
3.6 S: Monheim, Germany
3.7 +
3.8 +N: Alejandro Marín
3.9 +E: amarin@servpast.org
3.10 +D: SunOS port
3.11 +S: San José, Costa Rica
4.1 --- a/Makefile Sat Dec 29 15:23:55 2007 +0100
4.2 +++ b/Makefile Sat Dec 29 15:25:21 2007 +0100
4.3 @@ -22,15 +22,15 @@
4.4 $(CC) $(CFLAGS) -c $< -o $@
4.5
4.6 $(DEPFILE): Makefile
4.7 - @$(CC) $(DEPFLAGS) cdbackup.c cdrestore.c cdrom.c misc.c > $@
4.8 + @$(CC) $(DEPFLAGS) cdbackup.c cdrestore.c cdrom.c virtual.c misc.c > $@
4.9
4.10 include $(DEPFILE)
4.11
4.12 -cdbackup: cdbackup.o cdrom.o misc.o
4.13 - $(CC) $(CFLAGS) -o cdbackup cdbackup.o cdrom.o misc.o
4.14 +cdbackup: cdbackup.o cdrom.o virtual.o virtual-backup.o misc.o
4.15 + $(CC) $(CFLAGS) -o $@ $^
4.16
4.17 -cdrestore: cdrestore.o cdrom.o misc.o
4.18 - $(CC) $(CFLAGS) -o cdrestore cdrestore.o cdrom.o misc.o
4.19 +cdrestore: cdrestore.o cdrom.o virtual.o misc.o
4.20 + $(CC) $(CFLAGS) -o $@ $^
4.21
4.22 strip: $(TARGETS)
4.23 strip $(TARGETS)
5.1 --- a/README Sat Dec 29 15:23:55 2007 +0100
5.2 +++ b/README Sat Dec 29 15:25:21 2007 +0100
5.3 @@ -1,19 +1,23 @@
5.4 -cdbackup, cdrestore - CD archive utilities version 0.6.3
5.5 -Copyright (c) 2000-2002 Craig Condit, Stefan Hülswitt. All rights reserved.
5.6 +cdbackup, cdrestore - CD archive utilities version 0.6.4beta
5.7 +Copyright (c) 2000-2004 Craig Condit, Stefan Hülswitt. All rights reserved.
5.8
5.9 This software is released under a BSD-style license - see the LICENSE file.
5.10
5.11 cdbackup and cdrestore are a pair of utilities designed to facilitiate
5.12 -streaming backup to and from CD-R(W) disks. Specificially, they were
5.13 -designed to work with dump/restore, but tar/cpio/whatever you want should
5.14 +streaming backup to and from CD-R(W)/DVD-R(W) disks. Specificially, they were
5.15 +designed to work with dump/restore, but tar/cpio/afio/whatever you want should
5.16 work, so long as it writes to stdout for backups and reads from stdin for
5.17 restores.
5.18
5.19 -NOTE: this program REQUIRES that a recent version of cdrecord be present
5.20 -in the PATH.
5.21 +NOTE: this program REQUIRES that a recent version of cdrecord (or
5.22 +cdrecord-ProDVD for DVD support) be present in the PATH.
5.23
5.24 See manpages for further details.
5.25
5.26 +This release has beta-state as it introduces many new features
5.27 +and also changed on-disk data format. It has been carefully
5.28 +tested, but for now I cannot be sure that it's as reliable and
5.29 +stable as the 0.6.3 release. Take care!
5.30
5.31 INSTALL:
5.32 --------
5.33 @@ -45,7 +49,7 @@
5.34 CONTACT:
5.35 --------
5.36
5.37 -Project maintainer is: Stefan Hülswitt <huels@iname.com>
5.38 +Project maintainer is: Stefan Hülswitt <s.huelswitt@gmx.de>
5.39 Homepage: http://www.muempf.de/
5.40
5.41 Any comments, suggestions, bug reports, patches and fixes
6.1 --- a/TODO Sat Dec 29 15:23:55 2007 +0100
6.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
6.3 @@ -1,1 +0,0 @@
6.4 --increase buffer size on restore for speed?
7.1 --- a/cdbackup.1 Sat Dec 29 15:23:55 2007 +0100
7.2 +++ b/cdbackup.1 Sat Dec 29 15:25:21 2007 +0100
7.3 @@ -1,17 +1,24 @@
7.4 -.TH "cdbackup" "1" "0.6.3" "Stefan Hülswitt" ""
7.5 +.TH "cdbackup" "1" "0.6.4beta" "Stefan Hülswitt" ""
7.6 .SH "NAME"
7.7 .LP
7.8 -cdbackup \- Streaming backup to CD\-R(W)
7.9 +cdbackup \- Streaming backup to CD\-R(W)/DVR\-R(W)
7.10 .SH "SYNOPSIS"
7.11 .LP
7.12 -cdbackup [\-mvDVX] [\-d \fIdevice\fP] [\-r \fIscsi\-dev\fP] [\-s \fIspeed\fP]
7.13 - [\-p \fInum\fP] [\-l \fIsize\fP] [\-a \fIlabel\fP] [\-c \fIcommand\fP]
7.14 - [\-\- \fIcdrecord\-options\fP]
7.15 +cdbackup [\-mvwCDRVX] [\-d \fIdevice\fP] [\-r \fIscsi\-dev\fP] [\-s \fIspeed\fP]
7.16 + [\-i \fIimage\fP] [\-p \fInum\fP] [\-l \fIsize\fP] [\-a \fIlabel\fP]
7.17 + [\-c \fIcommand\fP] [\-\- \fIcdrecord\-options\fP]
7.18 .SH "DESCRIPTION"
7.19 .LP
7.20 -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).
7.21 -.LP
7.22 -\fINOTE:\fR this program REQUIRES that a recent version of \fBcdrecord\fR(1) is present in the PATH.
7.23 +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).
7.24 +.LP
7.25 +\fINOTE:\fR this program REQUIRES that a recent version of \fBcdrecord\fR(1) (or
7.26 +cdrecord\-ProDVD for DVD support) is present in the PATH.
7.27 +.LP
7.28 +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.
7.29 +.br
7.30 +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.
7.31 +.br
7.32 +Virtual image files are never deleted by cdbackup. After dumping an image, you have to delete it by your self.
7.33 .LP
7.34 \fIWARNING!\fR When using this program under Linux, be sure not to use dump on a mounted
7.35 filesystem. This has a high potential for creating corrupted backups. As of kernel version
7.36 @@ -29,13 +36,13 @@
7.37 \fB\-r\fR \fIscsi\-device\fP
7.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.
7.39 .br
7.40 -(default: none)
7.41 +(default: none or the contents of the environment variable CDR_DEVICE)
7.42
7.43 .TP
7.44 \fB\-s\fR \fIspeed\fP
7.45 The writing speed which is passed to \fBcdrecord\fR(1) (via speed=\fIspeed\fP).
7.46 .br
7.47 -(default: 4)
7.48 +(default: 4 or the contents of the environment variable CDR_SPEED)
7.49
7.50 .TP
7.51 \fB\-p\fR \fInum\fP
7.52 @@ -48,10 +55,41 @@
7.53 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).
7.54
7.55 .TP
7.56 +\fB\-R\fR
7.57 +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.
7.58 +.br
7.59 +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.
7.60 +.br
7.61 +In DVD mode the options \-p and \-X have no effect.
7.62 +
7.63 +.TP
7.64 +\fB\-i\fR \fIimage\fP
7.65 +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.
7.66 +You can add up to 96 backups to an virtual image.
7.67 +.br
7.68 +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).
7.69 +.br
7.70 +(default: none)
7.71 +
7.72 +.TP
7.73 +\fB\-w\fR
7.74 +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.
7.75 +.br
7.76 +Virtual images (even when dumped to media) are not compatible with older cdbackup versions.
7.77 +
7.78 +.TP
7.79 \fB\-l\fR \fIsize\fP
7.80 -The media size in megabytes. This value is used to calculate how much data can be stored on the media.
7.81 -.br
7.82 -(default: 650)
7.83 +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.
7.84 +.br
7.85 +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).
7.86 +.br
7.87 +(default: auto\-detect)
7.88 +
7.89 +.TP
7.90 +\fB\-C\fR
7.91 +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.
7.92 +.br
7.93 +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.
7.94
7.95 .TP
7.96 \fB\-a\fR \fIlabel\fP
7.97 @@ -95,6 +133,21 @@
7.98 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:
7.99 .IP
7.100 tar cf \- /usr | cdbackup \-d /dev/sr1 \-r 1,4,0 \-s 12 \-m \-v
7.101 +
7.102 +.LP
7.103 +To create a backup on a virtual image:
7.104 +.IP
7.105 +tar cf \- /usr | cdbackup \-i /tmp/vimage \-l 4488m
7.106 +
7.107 +.LP
7.108 +Add another backup to the same virtual image (with multi\-disk mode):
7.109 +.IP
7.110 +tar cf \- /home | cdbackup \-i /tmp/vimage \-l 4488m
7.111 +
7.112 +.LP
7.113 +Dump the virtual image to one (or several) DVD media on /dev/cdrom (scsi\-ide device 0,0,0), enabling BURNFREE:
7.114 +.IP
7.115 +cdbackup \-i /tmp/vimage \-w \-R \-d /dev/cdrom \-r 0,0,0 \-s 4 \-m \-\- driveropts=burnfree
7.116 .SH "KNOWN PROBLEMS"
7.117 .LP
7.118 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.
7.119 @@ -120,12 +173,12 @@
7.120 Please contact the author if you can contribute additional information about the problem.
7.121 .SH "AUTHORS"
7.122 .LP
7.123 -Stefan Hülswitt <huels@iname.com>
7.124 +Stefan Hülswitt <s.huelswitt@gmx.de>
7.125 .SH "SEE ALSO"
7.126 .LP
7.127 \fBcdrestore\fR(1), \fBcdrecord\fR(1)
7.128 .SH "LICENSE"
7.129 -Copyright (c) 2000\-2002 Craig Condit, Stefan Hülswitt.
7.130 +Copyright (c) 2000\-2004 Craig Condit, Stefan Hülswitt.
7.131
7.132 Redistribution and use in source and binary forms, with or without
7.133 modification, are permitted provided that the following conditions are met:
8.1 --- a/cdbackup.c Sat Dec 29 15:23:55 2007 +0100
8.2 +++ b/cdbackup.c Sat Dec 29 15:25:21 2007 +0100
8.3 @@ -1,5 +1,5 @@
8.4 /* cdbackup.c
8.5 -Copyright (c) 2000-2002 Craig Condit, Stefan Hülswitt.
8.6 +Copyright (c) 2000-2004 Craig Condit, Stefan Hülswitt.
8.7
8.8 Redistribution and use in source and binary forms, with or without
8.9 modification, are permitted provided that the following conditions are met:
8.10 @@ -24,69 +24,135 @@
8.11 */
8.12
8.13 #define _LARGEFILE64_SOURCE
8.14 +#define _GNU_SOURCE
8.15
8.16 #include <stdlib.h>
8.17 #include <stdio.h>
8.18 +#include <stdarg.h>
8.19 #include <unistd.h>
8.20 #include <fcntl.h>
8.21 #include <string.h>
8.22 #include <time.h>
8.23 #include <errno.h>
8.24 -#include <getopt.h>
8.25 #include <sys/wait.h>
8.26 #include <sys/ioctl.h>
8.27 #include <netinet/in.h>
8.28 -#include <linux/cdrom.h>
8.29 +
8.30 +#ifndef sun
8.31 +#include <getopt.h>
8.32 +#endif
8.33
8.34 #include "cdbackup.h"
8.35 #include "cdrom.h"
8.36 +#include "virtual.h"
8.37 #include "misc.h"
8.38 #include "debug.h"
8.39 #include "version.h"
8.40
8.41 -/* #define DEBUGOUT */
8.42 -
8.43 /* defaults */
8.44 -char * prg_name ="cdbackup";
8.45 -char * cd_dev ="/dev/burner";
8.46 -char * cdr_dev =0; /* no default here, too dangerous */
8.47 -char * cd_label ="CDBackup Track";
8.48 -int cd_speed =4;
8.49 -long cd_len =333000; /* blocks */
8.50 -int padsize =15; /* blocks */
8.51 -int multidisk=0;
8.52 -char * multicmd =0;
8.53 -int verbose =0;
8.54 -int xamode2 =0;
8.55 -int debug =0;
8.56 +char *prg_name ="cdbackup";
8.57 +char *cd_dev ="/dev/burner";
8.58 +char *cdr_dev =0; /* no default here, too dangerous */
8.59 +char *cd_label ="CDBackup Track";
8.60 +int cd_speed =4;
8.61 +long cd_len =-1; /* blocks */
8.62 +int padsize =15; /* blocks */
8.63 +int multidisk=0;
8.64 +char *multicmd =0;
8.65 +int verbose =0;
8.66 +int xamode2 =0;
8.67 +int crc =1;
8.68 +int debug =0;
8.69 +int virtual =0;
8.70 +char *virt_name=0;
8.71 +int virt_dump=0;
8.72 +int dvd =0;
8.73
8.74 char **cdrec_opt=0;
8.75 int cdrec_opt_count=0;
8.76
8.77 -long long totalSize;
8.78 +long long totalSize=0;
8.79 +int disknum=1;
8.80 +int secs;
8.81 struct tm curtime; /* global, so multi-disks get all the same time */
8.82 -
8.83 -/****************************************************************************/
8.84 -
8.85 -void usage()
8.86 -{
8.87 - fprintf(stderr,
8.88 - "Usage: %s [options ...] [-- cdrecord-options ...]\n"
8.89 - "Reads from standard input, block formats and writes to CD-R(W).\n\n"
8.90 - " -d DEVICE DEVICE for CD queries (default /dev/burner)\n"
8.91 - " -l N CD-R has a size of N MB (default 650)\n"
8.92 - " -r DEVICE DEVICE for CD recording (e.g. 0,4,0)\n"
8.93 - " -s N record CD at speed N (default 4)\n"
8.94 - " -X enable CDROM XA2 mode in cdrecord\n"
8.95 - " -a LABEL use LABEL as CD session title\n"
8.96 - " -p N use a padsize of N sectors for the session (default 15)\n"
8.97 - " -m enable multi-disk mode\n"
8.98 - " -c COMMAND call COMMAND on disk change in multi-disk mode\n"
8.99 - " -v be verbose\n"
8.100 - " -D enable DEBUG output\n"
8.101 - " -V prints version & exits\n"
8.102 - " -- pass rest of commandline to cdrecord\n"
8.103 - "\n", prg_name);
8.104 +int auto_size=0;
8.105 +
8.106 +/****************************************************************************/
8.107 +
8.108 +char *make_arg(const char *format, ...)
8.109 +{
8.110 + char *ptr;
8.111 + va_list ap;
8.112 + va_start(ap,format);
8.113 + if(vasprintf(&ptr,format,ap)<0) serror("No memory for cdrecord args\n");
8.114 + va_end(ap);
8.115 + return ptr;
8.116 +}
8.117 +
8.118 +void start_cdrecord(void)
8.119 +{
8.120 + char **args, **p, *exname;
8.121 + int l;
8.122 +
8.123 + if(!(p=args=calloc(cdrec_opt_count+10,sizeof(char *))))
8.124 + serror("No memory for cdrecord args\n");
8.125 +
8.126 + if(dvd) exname="dvdrecord"; else exname="cdrecord";
8.127 + *p++=exname;
8.128 +
8.129 + if(virt_dump || dvd) {
8.130 + *p++="-dao";
8.131 + *p++=make_arg("tsize=%ds",secs);
8.132 + }
8.133 + else {
8.134 + *p++="-multi";
8.135 + *p++=make_arg("padsize=%ds",padsize);
8.136 + }
8.137 +
8.138 + *p++=make_arg("speed=%d",cd_speed);
8.139 + *p++=make_arg("dev=%s",cdr_dev);
8.140 +
8.141 + for(l=0 ; l<cdrec_opt_count ; l++) *p++=cdrec_opt[l];
8.142 +
8.143 + if(xamode2 && !dvd) *p++="-xa2"; else *p++="-data";
8.144 + *p++="-";
8.145 + *p++=0;
8.146 +
8.147 + if(debug) {
8.148 + fprintf(stderr,"%s: cdrecord command:",prg_name);
8.149 + for(p=args ; *p ; p++) fprintf(stderr," %s",*p);
8.150 + fprintf(stderr,"\n");
8.151 + }
8.152 +
8.153 + execvp(exname,args);
8.154 + error("Exec failed (cdrecord)");
8.155 +}
8.156 +
8.157 +long atip_cdrecord(void)
8.158 +{
8.159 + char *cmd;
8.160 + FILE *p;
8.161 + long size=-1;
8.162 +
8.163 + asprintf(&cmd,"%srecord 2>&1 dev=%s -atip",dvd ? "dvd":"cd",cdr_dev);
8.164 + DEBUG("%s: cdrecord atip command: %s\n",prg_name,cmd);
8.165 +
8.166 + p=popen(cmd,"r");
8.167 + if(!p) fprintf(stderr,"%s: atip command failed\n",prg_name);
8.168 + else {
8.169 + char buff[256];
8.170 + while(fgets(buff,sizeof(buff),p)) {
8.171 + if(dvd && !strncmp(buff,"rzone size:",11)) size=strtol(&buff[12],NULL,10);
8.172 + else if(!strncmp(buff," ATIP start of lead out:",25)) size=strtol(&buff[26],NULL,10);
8.173 + }
8.174 + }
8.175 + pclose(p);
8.176 + free(cmd);
8.177 + if(size>0 && verbose) {
8.178 + char buff[16];
8.179 + fprintf(stderr,"%s: auto-detected media size %s (%ld blocks)\n",prg_name,FlexSize(buff,(long long)size*CD_FRAMESIZE),size);
8.180 + }
8.181 + return size;
8.182 }
8.183
8.184 /****************************************************************************/
8.185 @@ -94,11 +160,24 @@
8.186 void parse_cmdline(char argc, char *argv[])
8.187 {
8.188 int i;
8.189 -
8.190 - while ((i=getopt(argc,argv,"d:r:l:s:p:a:c:mvVXD"))>0) {
8.191 + char *val;
8.192 +
8.193 + /* get some default from the environment */
8.194 + val=getenv("CDR_DEVICE");
8.195 + if(val) {
8.196 + cdr_dev=strdup(val);
8.197 + DEBUG("cdbackup: using recording device %s from CDR_DEVICE\n",cdr_dev);
8.198 + }
8.199 + val=getenv("CDR_SPEED");
8.200 + if(val) {
8.201 + cd_speed=strtol(val,NULL,10);
8.202 + DEBUG("cdbackup: using speed %d from CDR_SPEED\n",cd_speed);
8.203 + }
8.204 +
8.205 + while ((i=getopt(argc,argv,"d:r:l:s:p:a:c:mvVXDCi:wR"))>0) {
8.206 switch (i) {
8.207 case 'V': fprintf(stderr,"cdbackup "VERSION" (compiled "__DATE__")\n"
8.208 - "Copyright (C) 2000-2002\n"
8.209 + "Copyright (C) 2000-2004\n"
8.210 "This is free software; see the source for copying conditions.\n"
8.211 "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n"
8.212 "PARTICULAR PURPOSE.\n");
8.213 @@ -110,20 +189,45 @@
8.214 case 'd': cd_dev=optarg; break;
8.215 case 'r': cdr_dev=optarg; break;
8.216 case 'a': cd_label=optarg; break;
8.217 + case 'C': crc=0; break;
8.218 + case 'i': virt_name=optarg; virtual=1; break;
8.219 + case 'w': virt_dump=1; break;
8.220 + case 'R': dvd=1;
8.221 + DEBUG("cdbackup: DVD mode enabled\n");
8.222 + break;
8.223 case 'D': verbose=1; debug=1;
8.224 DEBUG("cdbackup: DEBUG output enabled ("VERSION")\n");
8.225 break;
8.226 - case 'l': errno=0; cd_len=strtol(optarg,NULL,10);
8.227 - if(errno==ERANGE || cd_len<1) serror("Option -l: length out of range (must be >=1)\n");
8.228 - cd_len = (long long)cd_len * (1024*1024) / CD_FRAMESIZE; /* convert to blocks */
8.229 - break;
8.230 + case 'l': cd_len=(long)(FlexLen(optarg)/CD_FRAMESIZE);
8.231 + break;
8.232 case 's': errno=0; cd_speed=strtol(optarg,NULL,10);
8.233 if(errno==ERANGE || cd_speed<1) serror("Option -s: speed out of range (must be >=1)\n");
8.234 break;
8.235 case 'p': errno=0; padsize=strtol(optarg,NULL,10);
8.236 if(errno==ERANGE || padsize<15) serror("Option -p: padsize out of range (must be >=15)\n");
8.237 break;
8.238 - default: usage(); exit(0);
8.239 + default: fprintf(stderr,
8.240 + "Usage: %s [options ...] [-- cdrecord-options ...]\n"
8.241 + "Reads from standard input, block formats and writes to CD-R(W).\n\n"
8.242 + " -d DEVICE DEVICE for CD queries (default /dev/burner)\n"
8.243 + " -l N set media size, disable auto-detect\n"
8.244 + " -r DEVICE DEVICE for CD recording (e.g. 0,4,0)\n"
8.245 + " -s N record CD at speed N (default 4)\n"
8.246 + " -X enable CDROM XA2 mode in cdrecord\n"
8.247 + " -a LABEL use LABEL as CD session title\n"
8.248 + " -p N use a padsize of N sectors for the session (default 15)\n"
8.249 + " -m enable multi-disk mode\n"
8.250 + " -c COMMAND call COMMAND on disk change in multi-disk mode\n"
8.251 + " -C disable checksum creation for datablocks\n"
8.252 + " -i IMAGE use virtual image IMAGE for recording\n"
8.253 + " -w dump virtual image to media\n"
8.254 + " -R enables DVD mode\n"
8.255 + " -v be verbose\n"
8.256 + " -D enable DEBUG output\n"
8.257 + " -V prints version & exits\n"
8.258 + " -- pass rest of commandline to cdrecord\n"
8.259 + "\n", prg_name);
8.260 + exit(0);
8.261 }
8.262 }
8.263
8.264 @@ -132,173 +236,215 @@
8.265 cdrec_opt=&argv[optind];
8.266 }
8.267
8.268 - if(!cdr_dev) serror("You must specify a device for cdrecord with -r\n");
8.269 -}
8.270 -
8.271 -/****************************************************************************/
8.272 -
8.273 -#define MARG(ptr,len,form,arg) { int l=(len);\
8.274 - if(!(*ptr=(char *)malloc(l+1))) serror("No memory for cdrecord args\n");\
8.275 - snprintf(*ptr++,l,form,arg);\
8.276 - }
8.277 -
8.278 -void start_cdrecord()
8.279 -{
8.280 - char **args, **p;
8.281 - int l;
8.282 -
8.283 - if(!(p=args=calloc(cdrec_opt_count+8,sizeof(char *))))
8.284 - serror("No memory for cdrecord args\n");
8.285 -
8.286 - *p++="cdrecord";
8.287 - *p++="-multi";
8.288 - MARG(p,16,"speed=%d",cd_speed);
8.289 - MARG(p,6+strlen(cdr_dev),"dev=%s",cdr_dev);
8.290 -
8.291 - for(l=0 ; l<cdrec_opt_count ; l++) *p++=cdrec_opt[l];
8.292 -
8.293 - MARG(p,20,"padsize=%ds",padsize);
8.294 - if(xamode2) *p++="-xa2"; else *p++="-data";
8.295 - *p++="-";
8.296 - *p++=0;
8.297 -
8.298 - if(debug) {
8.299 - fprintf(stderr,"%s: cdrecord command:",prg_name);
8.300 - for(p=args ; *p ; p++) fprintf(stderr," %s",*p);
8.301 - fprintf(stderr,"\n");
8.302 - }
8.303 -
8.304 - execvp("cdrecord",args);
8.305 - error("Unable to launch cdrecord");
8.306 -}
8.307 -
8.308 -/****************************************************************************/
8.309 -
8.310 -int backup(char disk_set)
8.311 -{
8.312 - pid_t childpid;
8.313 - int fd[2];
8.314 - int outpipe, bytes;
8.315 + if(cd_len<0) {
8.316 + auto_size=1;
8.317 + if(virtual && !virt_dump) serror("Can't auto-detect media size in virtual mode. Use option -l to set media size\n");
8.318 + }
8.319 + if(virtual && dvd && !virt_dump) {
8.320 + fprintf(stderr,"Option -R ignored in virtual mode\n");
8.321 + dvd=0;
8.322 + }
8.323 + if(dvd) {
8.324 + if(xamode2) fprintf(stderr,"Option -X ignored in DVD mode\n");
8.325 + padsize=0;
8.326 + }
8.327 + if(virt_dump && !virtual) serror("To dump an image you must supply the image name with -i\n");
8.328 + if(!cdr_dev && (!virtual || virt_dump)) serror("You must specify a device for cdrecord with -r\n");
8.329 +}
8.330 +
8.331 +/****************************************************************************/
8.332 +
8.333 +void autosize(void)
8.334 +{
8.335 + if(auto_size) {
8.336 + cd_len=atip_cdrecord();
8.337 + if(cd_len<0) serror("Media size detection failed. Use option -l to set media size\n");
8.338 + }
8.339 +}
8.340 +
8.341 +/****************************************************************************/
8.342 +
8.343 +void dump(void)
8.344 +{
8.345 + int n, cont;
8.346 + char buffer[CD_FRAMESIZE];
8.347 + long long grandTotal;
8.348 +
8.349 + do {
8.350 + int change;
8.351 + do {
8.352 + autosize();
8.353 + virtual=1;
8.354 + Vopen(1); n=VreadToc(0);
8.355 + if(n<1) serror("It's not usefull to dump an empty image");
8.356 + secs=Vsize(); cont=VhasCont();
8.357 + if(cd_avail<secs*CD_FRAMESIZE) serror("Image doesn't fits to media");
8.358 + Vseek(-1); VprepareDump();
8.359 +
8.360 + virtual=0; change=0;
8.361 + Vopen(0); n=VreadToc(0); VprintSpace();
8.362 + if(n!=0) {
8.363 + fprintf(stderr,"Can't dump to non-empty disk! Try another disk\n");
8.364 + change=1;
8.365 + }
8.366 +
8.367 + if(change) {
8.368 + Vclose();
8.369 + diskchange(multicmd,cd_dev);
8.370 + }
8.371 + } while(change);
8.372 +
8.373 + if(verbose)
8.374 + fprintf(stderr,"%s: Dumping image (%d blocks) to %s\n",prg_name,secs,VdevName());
8.375 + VnewTrack();
8.376 +
8.377 + grandTotal=0;
8.378 + while(secs>0) {
8.379 + VvirtRead(buffer);
8.380 + Vwrite(buffer); grandTotal+=CD_FRAMESIZE;
8.381 + secs--;
8.382 + }
8.383 +
8.384 + VcloseTrack(0);
8.385 +
8.386 + totalSize+=grandTotal;
8.387 + if(verbose) {
8.388 + char str1[16], str2[16];
8.389 + fprintf(stderr,"%s: Dumping finished. %s written (%s on this disk)\n",
8.390 + prg_name,FlexSize(str1,totalSize),FlexSize(str2,grandTotal));
8.391 + }
8.392 +
8.393 + if(multidisk==0) {
8.394 + if(cont) fprintf(stderr,"Multi-disk not enabled, ignoring continuation image(s)!\n");
8.395 + cont=0;
8.396 + }
8.397 + else {
8.398 + disknum++;
8.399 + diskchange(multicmd,cd_dev);
8.400 + }
8.401 + } while(cont);
8.402 +}
8.403 +
8.404 +/****************************************************************************/
8.405 +
8.406 +int backup(void)
8.407 +{
8.408 long long grandTotal=0;
8.409 struct header_block header;
8.410 + int flags, datasize, result=0;
8.411
8.412 char buffer[CD_FRAMESIZE];
8.413 struct data_block *db=(struct data_block *)&buffer[0];
8.414
8.415 - sprintf(buffer, "%04d%02d%02d%02d%02d", curtime.tm_year + 1900,
8.416 - curtime.tm_mon + 1, curtime.tm_mday, curtime.tm_hour, curtime.tm_min);
8.417 + flags=F_NONE;
8.418 + datasize=DATASIZE;
8.419 + if(crc) { flags|=F_CRC; datasize-=4; }
8.420 +
8.421 + sprintf(buffer,"%04d%02d%02d%02d%02d",curtime.tm_year+1900,
8.422 + curtime.tm_mon+1,curtime.tm_mday,curtime.tm_hour,curtime.tm_min);
8.423
8.424 - strncpy(header.id_str,HDR_STRING,32); header.id_str[32] = 0;
8.425 - strncpy(header.vol_id,cd_label,32); header.vol_id[32] = 0;
8.426 - strncpy(header.t_stamp,buffer,12); header.t_stamp[12] = 0;
8.427 - header.disk_set = disk_set;
8.428 + strncpy(header.id_str,HDR_STRING,32); header.id_str[32]=0;
8.429 + strncpy(header.vol_id,cd_label,32); header.vol_id[32]=0;
8.430 + strncpy(header.t_stamp,buffer,12); header.t_stamp[12]=0;
8.431 + header.disk_set = disknum;
8.432 + header.flags = flags;
8.433
8.434 if(verbose)
8.435 - fprintf(stderr,"%s: Recording to device %s, multidisk %s, disk %d\n",prg_name,cdr_dev,multidisk?"enabled":"disabled",disk_set);
8.436 -
8.437 -#ifndef DEBUGOUT /* the "real" code */
8.438 - /* launch cdrecord */
8.439 - if(pipe(fd) == -1) error("Unable to create pipe handles");
8.440 - if((childpid=fork()) == -1) error("Fork failed");
8.441 - if(childpid == 0) { /* child */
8.442 - close(fd[1]);
8.443 - close(0); /* stdin */
8.444 - dup2(fd[0], 0);
8.445 - start_cdrecord(); /* doesn't return */
8.446 - }
8.447 -
8.448 - close(fd[0]); outpipe=fd[1];
8.449 -
8.450 - /* output the header block */
8.451 + fprintf(stderr,"%s: Recording to %s, multidisk %s, CRC %s, disk %d\n",
8.452 + prg_name,VdevName(),
8.453 + multidisk?"enabled":"disabled",
8.454 + crc?"enabled":"disabled",
8.455 + disknum);
8.456 + secs=cd_len;
8.457 + VnewTrack();
8.458 +
8.459 memset(buffer,0,CD_FRAMESIZE);
8.460 memcpy(buffer,&header,sizeof(struct header_block));
8.461 - if((bytes=write(outpipe, buffer, CD_FRAMESIZE)) != CD_FRAMESIZE) error("Error writing header block");
8.462 -
8.463 - cd_avail-=bytes; grandTotal+=bytes;
8.464 - /* account for the padsize */
8.465 - cd_avail-=padsize*CD_FRAMESIZE;
8.466 -#else
8.467 - /* debug code; send data to /dev/null. Don't need the pipe. */
8.468 - fprintf(stderr, "DEBUG CODE: sending data to /dev/null!\n");
8.469 - outpipe = open("/dev/null", O_WRONLY);
8.470 - if (outpipe < 0) { perror("/dev/null"); exit(1); }
8.471 -#endif
8.472 -
8.473 - db->reserved = 0;
8.474 + Vwrite(buffer); grandTotal+=CD_FRAMESIZE;
8.475
8.476 do {
8.477 - /* read a block */
8.478 - db->status = 0; /* this isn't the last block (for now) */
8.479 - bytes=full_read(0,&buffer[DBSIZE],DATASIZE);
8.480 - if (bytes < 0) error("Error reading input");
8.481 - if (bytes != DATASIZE) db->status=1; /* EOF, this is the last block */
8.482 - db->datasize = htons(bytes);
8.483 -
8.484 - /* check for free space */
8.485 - if(cd_avail < (CD_FRAMESIZE*2)) { /* less than 2 block free */
8.486 - if(db->status==0) db->status=2; /* if not last block, mark disk as full */
8.487 - }
8.488 -
8.489 - /* write a block */
8.490 - bytes = write(outpipe, buffer, CD_FRAMESIZE);
8.491 - if(bytes != CD_FRAMESIZE) error("Error writing data block");
8.492 -
8.493 - grandTotal+=bytes; cd_avail-=bytes;
8.494 + int bytes;
8.495 +
8.496 + db->flags=flags;
8.497 + db->status=0; /* this isn't the last block (for now) */
8.498 + bytes=full_read(0,&buffer[DBSIZE],datasize);
8.499 + if(bytes!=datasize) db->status=1; /* EOF, this is the last block */
8.500 + db->datasize=htons(bytes);
8.501 +
8.502 + if(cd_avail<(CD_FRAMESIZE*2)) { /* less than 2 block free */
8.503 + if(db->status==0) { /* if not last block, mark disk as full */
8.504 + db->status=2;
8.505 + result=1;
8.506 + }
8.507 + }
8.508 + if(crc) {
8.509 + int l=crc32(buffer,bytes+DBSIZE);
8.510 + *((unsigned long *)(&buffer[CD_FRAMESIZE-4]))=l;
8.511 + }
8.512 + Vwrite(buffer); grandTotal+=CD_FRAMESIZE;
8.513 } while(db->status==0);
8.514
8.515 - /* close pipe and wait for child termination */
8.516 - close(outpipe);
8.517 - while (wait(0) != childpid);
8.518 + if(dvd && cd_avail>=CD_FRAMESIZE) { /* pad up the track with zeros */
8.519 + memset(buffer,0,CD_FRAMESIZE);
8.520 + if(verbose) fprintf(stderr,"%s: padding up the track\n",prg_name);
8.521 + while(cd_avail>=CD_FRAMESIZE) Vwrite(buffer);
8.522 + }
8.523 +
8.524 + VcloseTrack(result);
8.525
8.526 totalSize+=grandTotal;
8.527 - if(verbose) fprintf(stderr,"%s: Recording finished. %lld kB written (%lld kB on this disk)\n",
8.528 - prg_name,totalSize/1024,grandTotal/1024);
8.529 -
8.530 - if(db->status==2) return 1; /* disk was full */
8.531 + if(verbose) {
8.532 + char str1[16], str2[16];
8.533 + fprintf(stderr,"%s: Recording finished. %s written (%s on this disk)\n",
8.534 + prg_name,FlexSize(str1,totalSize),FlexSize(str2,grandTotal));
8.535 + }
8.536 + return result;
8.537 +}
8.538 +
8.539 +/****************************************************************************/
8.540 +
8.541 +int main(int argc, char *argv[])
8.542 +{
8.543 + int result, loop;
8.544 + time_t curtime_t;
8.545 +
8.546 + curtime_t=time(0); curtime=*localtime(&curtime_t);
8.547 + parse_cmdline(argc,argv);
8.548 +
8.549 + if(virt_dump) {
8.550 + dump();
8.551 + }
8.552 + else {
8.553 + do {
8.554 + do {
8.555 + autosize();
8.556 + Vopen(0); result=VreadToc(0); VprintSpace();
8.557 + loop=1;
8.558 +
8.559 + if(disknum>1 && result!=0) {
8.560 + Vclose();
8.561 + fprintf(stderr,"%s: Can't do multidisk continuation on non-empty disk! Try another disk\n", prg_name);
8.562 + diskchange(multicmd,cd_dev);
8.563 + }
8.564 + else if(cd_avail<(padsize+MIN_BLOCKS)*CD_FRAMESIZE) {
8.565 + Vclose();
8.566 + if(multidisk) {
8.567 + fprintf(stderr,"%s: Not enough free space on disk! Try another disk\n", prg_name);
8.568 + diskchange(multicmd,cd_dev);
8.569 + }
8.570 + else serror("Not enough free space on disk");
8.571 + }
8.572 + else loop=0;
8.573 + } while(loop);
8.574 +
8.575 + result=backup();
8.576 + if(result==1) {
8.577 + if(multidisk==0) serror("Disk full, multi-disk not enabled. Aborting");
8.578 +
8.579 + disknum++;
8.580 + if(!VisRegular()) diskchange(multicmd,cd_dev);
8.581 + }
8.582 + } while(result!=0);
8.583 + }
8.584 return 0;
8.585 }
8.586 -
8.587 -/****************************************************************************/
8.588 -
8.589 -int main(int argc, char *argv[])
8.590 -{
8.591 - int cdr;
8.592 - int disknum, result, loop;
8.593 - time_t curtime_t;
8.594 -
8.595 - disknum=1; totalSize=0;
8.596 - curtime_t=time(0); curtime=*localtime(&curtime_t);
8.597 -
8.598 - parse_cmdline(argc,argv);
8.599 -
8.600 - do {
8.601 - do {
8.602 - cdr=open_cdr(cd_dev); result=read_toc(cdr,0); close_cdr(cdr);
8.603 - print_space();
8.604 - loop=1;
8.605 -
8.606 - if(disknum>1 && result!=0) {
8.607 - fprintf(stderr,"%s: Can't do multidisk continuation on non-empty disk! Try another disk\n", prg_name);
8.608 - if(start_diskchange(multicmd,cd_dev)) serror("Diskchange command failed");
8.609 - }
8.610 - else if(cd_avail<(padsize+MIN_BLOCKS)*CD_FRAMESIZE) {
8.611 - if(multidisk) {
8.612 - fprintf(stderr,"%s: Not enough free space on disk! Try another disk\n", prg_name);
8.613 - if(start_diskchange(multicmd,cd_dev)) serror("Diskchange command failed");
8.614 - }
8.615 - else serror("Not enough free space on disk");
8.616 - }
8.617 - else loop=0;
8.618 - } while(loop);
8.619 -
8.620 - result = backup(disknum);
8.621 - if(result == 1) {
8.622 - if(multidisk == 0) serror("Disk full, multi-disk not enabled. Aborting");
8.623 -
8.624 - disknum++;
8.625 - if(start_diskchange(multicmd,cd_dev)) serror("Diskchange command failed");
8.626 - }
8.627 - } while (result != 0);
8.628 -
8.629 - return 0;
8.630 -}
9.1 --- a/cdbackup.h Sat Dec 29 15:23:55 2007 +0100
9.2 +++ b/cdbackup.h Sat Dec 29 15:25:21 2007 +0100
9.3 @@ -1,5 +1,5 @@
9.4 /* cdbackup.h.
9.5 -Copyright (c) 2000-2002 Craig Condit, Stefan Hülswitt.
9.6 +Copyright (c) 2000-2004 Craig Condit, Stefan Hülswitt.
9.7
9.8 Redistribution and use in source and binary forms, with or without
9.9 modification, are permitted provided that the following conditions are met:
9.10 @@ -34,19 +34,30 @@
9.11
9.12 #define MIN_BLOCKS 2 /* min. required blocks for a session: header block, one data block */
9.13
9.14 +#define F_NONE 0 /* flag values */
9.15 +#define F_CRC 1 /* backup has CRC checksum */
9.16 +
9.17 struct header_block {
9.18 char id_str[33]; /* recorder id string (32 chars) */
9.19 char vol_id[33]; /* volume label (32 characters) */
9.20 char t_stamp[13]; /* timestamp */
9.21 char disk_set; /* disk number - starts with 1 on multi-disk set */
9.22 + char flags; /* flags for the backup set */
9.23 };
9.24
9.25 struct data_block {
9.26 char status; /* status of block (0=continue, 1=done, 2=disk full) */
9.27 - char reserved; /* reserved byte to make structure 4 bytes long */
9.28 + char flags; /* flags for this data block */
9.29 short datasize; /* # of bytes in block (max = CD_FRAMESIZE-this) */
9.30 };
9.31
9.32 +extern int padsize;
9.33 +extern long cd_len;
9.34 +extern int verbose;
9.35 +extern char *prg_name;
9.36 +
9.37 +void start_cdrecord(void);
9.38 +
9.39 #define DBSIZE sizeof(struct data_block)
9.40 #define DATASIZE (CD_FRAMESIZE-DBSIZE)
9.41
10.1 --- a/cdrestore.1 Sat Dec 29 15:23:55 2007 +0100
10.2 +++ b/cdrestore.1 Sat Dec 29 15:25:21 2007 +0100
10.3 @@ -1,14 +1,14 @@
10.4 -.TH "cdrestore" "1" "0.6.3" "Stefan Hülswitt" ""
10.5 +.TH "cdrestore" "1" "0.6.4beta" "Stefan Hülswitt" ""
10.6 .SH "NAME"
10.7 .LP
10.8 -cdrestore \- Streaming restore from CD\-R(W)
10.9 +cdrestore \- Streaming restore from CD\-R(W)/DVD\-R(W)
10.10 .SH "SYNOPSIS"
10.11 .LP
10.12 -cdrestore [\-qvDFRTV] [\-d \fIdevice\fP] [\-l \fIsize\fP] [\-t \fItrack\fP]
10.13 - [\-c \fIcommand\fP]
10.14 +cdrestore [\-qvDFRTV] [\-d \fIdevice\fP] [\-i \fIimage\fP] [\-l \fIsize\fP]
10.15 + [\-t \fItrack\fP] [\-c \fIcommand\fP]
10.16 .SH "DESCRIPTION"
10.17 .LP
10.18 -cdrestore is a utility to make streaming restores from CD\-R(W) disks. It's designed to work with any backup tool which is able to restore from stdin (like tar/cpio/afio).
10.19 +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).
10.20 .SH "OPTIONS"
10.21 .LP
10.22 .TP
10.23 @@ -18,10 +18,18 @@
10.24 (default: /dev/cdrom)
10.25
10.26 .TP
10.27 +\fB\-i\fR \fIimage\fP
10.28 +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.
10.29 +.br
10.30 +(default: none)
10.31 +
10.32 +.TP
10.33 \fB\-l\fR \fIsize\fP
10.34 -The media size in megabytes. This value is used to calculate the free space on the media.
10.35 +Specifies the media size. This value is used to display the free space on the media only.
10.36 .br
10.37 -(default: 650)
10.38 +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).
10.39 +.br
10.40 +(default: 650m)
10.41
10.42 .TP
10.43 \fB\-t\fR \fItrack\fP
10.44 @@ -31,9 +39,9 @@
10.45
10.46 .TP
10.47 \fB\-T\fR
10.48 -Enables test mode. The complete restore process is done to test data integrity, but no data is output.
10.49 +Enables test mode. The complete restore process is done to test data integrity (includes CRC checksum test, if available), but no data is output.
10.50 .br
10.51 -\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.
10.52 +\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.
10.53
10.54 .TP
10.55 \fB\-F\fR
10.56 @@ -69,22 +77,32 @@
10.57 Prints out version information and exits.
10.58 .SH "EXAMPLES"
10.59 .LP
10.60 -To query the 700 MB media on /dev/sr0:
10.61 +Query the 700 MB media on /dev/sr0:
10.62 .IP
10.63 cdrestore \-d /dev/sr0 \-l 700 \-q
10.64
10.65 .LP
10.66 -To restore a tar archive to the current directory from track 2 of a 702 MB media on /dev/scd0:
10.67 +Restore a tar archive to the current directory from track 2 of a 702 MB media on /dev/scd0:
10.68 .IP
10.69 cdrestore \-d /dev/scd0 \-l 702 \-t 2 | tar xf \-
10.70 +
10.71 +.LP
10.72 +Query the contents of a virtual image:
10.73 +.IP
10.74 +cdrestore \-i /tmp/vimage \-l 4488m \-q
10.75 +
10.76 +.LP
10.77 +Check data integrity of track 3 in a virtual image after dumping it to DVD media:
10.78 +.IP
10.79 +cdrestore \-i /dev/dvd \-t 3 \-T
10.80 .SH "AUTHORS"
10.81 .LP
10.82 -Stefan Hülswitt <huels@iname.com>
10.83 +Stefan Hülswitt <s.huelswitt@gmx.de>
10.84 .SH "SEE ALSO"
10.85 .LP
10.86 \fBcdbackup\fR(1)
10.87 .SH "LICENSE"
10.88 -Copyright (c) 2000\-2002 Craig Condit, Stefan Hülswitt.
10.89 +Copyright (c) 2000\-2004 Craig Condit, Stefan Hülswitt.
10.90
10.91 Redistribution and use in source and binary forms, with or without
10.92 modification, are permitted provided that the following conditions are met:
11.1 --- a/cdrestore.c Sat Dec 29 15:23:55 2007 +0100
11.2 +++ b/cdrestore.c Sat Dec 29 15:25:21 2007 +0100
11.3 @@ -1,5 +1,5 @@
11.4 /* cdrestore.c
11.5 -Copyright (c) 2000-2002 Craig Condit, Stefan Hülswitt.
11.6 +Copyright (c) 2000-2004 Craig Condit, Stefan Hülswitt.
11.7
11.8 Redistribution and use in source and binary forms, with or without
11.9 modification, are permitted provided that the following conditions are met:
11.10 @@ -24,38 +24,40 @@
11.11 */
11.12
11.13 #define _LARGEFILE64_SOURCE
11.14 +#define _GNU_SOURCE
11.15
11.16 #include <stdio.h>
11.17 #include <stdlib.h>
11.18 #include <string.h>
11.19 #include <unistd.h>
11.20 -#include <fcntl.h>
11.21 #include <time.h>
11.22 #include <errno.h>
11.23 +#ifndef sun
11.24 #include <getopt.h>
11.25 -#include <sys/ioctl.h>
11.26 -#include <sys/wait.h>
11.27 +#endif
11.28 #include <netinet/in.h>
11.29 -#include <linux/cdrom.h>
11.30
11.31 #include "cdbackup.h"
11.32 +#include "virtual.h"
11.33 #include "cdrom.h"
11.34 #include "misc.h"
11.35 #include "debug.h"
11.36 #include "version.h"
11.37
11.38 /* defaults */
11.39 -char * prg_name ="cdrestore";
11.40 -int cd_track =-1;
11.41 -char * cd_dev ="/dev/cdrom";
11.42 -long cd_len =333000; /* blocks */
11.43 -char * multicmd =0;
11.44 -int verbose =0;
11.45 -int force =0;
11.46 -int query =0;
11.47 -int verify =0;
11.48 -int ahead =0;
11.49 -int debug =0;
11.50 +char *prg_name ="cdrestore";
11.51 +int cd_track =-1;
11.52 +char *cd_dev ="/dev/cdrom";
11.53 +long cd_len =333000; /* blocks */
11.54 +char *multicmd =0;
11.55 +int verbose =0;
11.56 +int force =0;
11.57 +int query =0;
11.58 +int verify =0;
11.59 +int ahead =0;
11.60 +int debug =0;
11.61 +int virtual =0;
11.62 +char *virt_name=0;
11.63
11.64 int tracks;
11.65 int disknum;
11.66 @@ -64,35 +66,14 @@
11.67
11.68 /****************************************************************************/
11.69
11.70 -void usage()
11.71 -{
11.72 - fprintf(stderr,
11.73 - "Usage: %s [OPTION]...\n"
11.74 - "Reads block input from CD-R(W) and writes it to standard output.\n\n"
11.75 - " -d DEVICE DEVICE for CD queries (e.g. /dev/sr0)\n"
11.76 - " -q query disk and print TOC only\n"
11.77 - " -t N restore from track N\n"
11.78 - " -l N CD-R has a size of N MB\n"
11.79 - " -c COMMAND call COMMAND on disk change in multi-disk mode\n"
11.80 - " -T don't restore, test data integrity only\n"
11.81 - " -F force starting restore in the middle of a multi-disk set\n"
11.82 - " -R set the kernel read-ahead to zero during restore\n"
11.83 - " -v be verbose\n"
11.84 - " -D enable DEBUG output\n"
11.85 - " -V prints version & exits\n"
11.86 - "\n", prg_name);
11.87 -}
11.88 -
11.89 -/****************************************************************************/
11.90 -
11.91 void parse_cmdline(char argc, char *argv[])
11.92 {
11.93 int i;
11.94
11.95 - while ((i=getopt(argc,argv,"d:l:c:t:qvVFTDR"))>0) {
11.96 + while ((i=getopt(argc,argv,"d:l:c:t:qvVFTDRi:"))>0) {
11.97 switch (i) {
11.98 case 'V': fprintf(stderr,"cdrestore "VERSION" (compiled "__DATE__")\n"
11.99 - "Copyright (C) 2000-2002\n"
11.100 + "Copyright (C) 2000-2004\n"
11.101 "This is free software; see the source for copying conditions.\n"
11.102 "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n"
11.103 "PARTICULAR PURPOSE.\n");
11.104 @@ -104,17 +85,32 @@
11.105 case 'R': ahead=1; break;
11.106 case 'T': verify=1; break;
11.107 case 'v': verbose=1; break;
11.108 + case 'i': virt_name=optarg; virtual=1; break;
11.109 case 'D': verbose=1; debug=1;
11.110 DEBUG("cdrestore: DEBUG output enabled ("VERSION")\n");
11.111 break;
11.112 case 't': errno=0; cd_track=strtol(optarg,NULL,10);
11.113 if(errno==ERANGE || cd_track<1) serror("Option -t: invalid track (must be >=1)\n");
11.114 break;
11.115 - case 'l': errno=0; cd_len=strtol(optarg,NULL,10);
11.116 - if(errno==ERANGE || cd_len<1) serror("Option -l: length out of range (must be >=1)\n");
11.117 - cd_len = (long long)cd_len * (1024*1024) / CD_FRAMESIZE; /* convert to blocks */
11.118 + case 'l': cd_len=(long)(FlexLen(optarg)/CD_FRAMESIZE);
11.119 break;
11.120 - default: usage(); exit(0);
11.121 + default: fprintf(stderr,
11.122 + "Usage: %s [OPTION]...\n"
11.123 + "Reads block input from CD-R(W) and writes it to standard output.\n\n"
11.124 + " -d DEVICE DEVICE for CD queries (e.g. /dev/sr0)\n"
11.125 + " -q query disk and print TOC only\n"
11.126 + " -t N restore from track N\n"
11.127 + " -l N set media size\n"
11.128 + " -c COMMAND call COMMAND on disk change in multi-disk mode\n"
11.129 + " -T don't restore, test data integrity only\n"
11.130 + " -F force starting restore in the middle of a multi-disk set\n"
11.131 + " -R set the kernel read-ahead to zero during restore\n"
11.132 + " -i IMAGE use virtual image IMAGE for operation\n"
11.133 + " -v be verbose\n"
11.134 + " -D enable DEBUG output\n"
11.135 + " -V prints version & exits\n"
11.136 + "\n", prg_name);
11.137 + exit(0);
11.138 }
11.139 }
11.140
11.141 @@ -124,21 +120,22 @@
11.142
11.143 /****************************************************************************/
11.144
11.145 -void print_track(int track, char *stamp, char *id, int disk, int startsec, int endsec)
11.146 -{
11.147 - char timestr[32], size[32];
11.148 -
11.149 - snprintf(timestr,sizeof(timestr)-1,"%02d/%02d/%04d %02d:%02d",
11.150 +void print_track(int track, char *stamp, char *id, int disk, int startsec, int endsec, char flags)
11.151 +{
11.152 + char timestr[32], size[32], flstr[12];
11.153 +
11.154 + snprintf(timestr,sizeof(timestr),"%02d/%02d/%04d %02d:%02d",
11.155 (stamp[4]-'0')*10 + (stamp[5]-'0'),
11.156 (stamp[6]-'0')*10 + (stamp[7]-'0'),
11.157 (stamp[0]-'0')*1000 + (stamp[1]-'0')*100 + (stamp[2]-'0')*10 + (stamp[3]-'0'),
11.158 (stamp[8]-'0')*10 + (stamp[9]-'0'),
11.159 (stamp[10]-'0')*10 + (stamp[11]-'0'));
11.160
11.161 - if(startsec>=0) snprintf(size,sizeof(size)-1," %3ld MB:",(long)((long long)(endsec-startsec+1)*CD_FRAMESIZE/(1024*1024)));
11.162 + if(startsec>=0) snprintf(size,sizeof(size)," %s:",FlexSize(flstr,((long long)(endsec-startsec+1)*CD_FRAMESIZE)));
11.163 else size[0]=0;
11.164 -
11.165 - fprintf(stderr,"Track %02d:%s %s Part %d: %s\n", track, size, timestr, disk, id);
11.166 + snprintf(flstr,sizeof(flstr),"%c",flags&F_CRC?'C':'.');
11.167 +
11.168 + fprintf(stderr,"Track %02d:%s %s Part %d %s : %s\n", track, size, timestr, disk, flstr, id);
11.169 if(startsec>=0) DEBUG(" Start sector %7d Last sector %7d\n",startsec,endsec);
11.170 }
11.171
11.172 @@ -146,39 +143,22 @@
11.173
11.174 int restore(int disktrack)
11.175 {
11.176 - int infile;
11.177 int result=0, i, bytes;
11.178 - long long totalRead, startPos;
11.179 + long long totalRead=0, startPos;
11.180 struct header_block header;
11.181 char buffer[CD_FRAMESIZE];
11.182 struct data_block *db=(struct data_block *)&buffer[0];
11.183 - unsigned long r_ahead, r_fahead;
11.184 -
11.185 - if((infile=open(cd_dev, O_RDONLY)) < 0) error("Error opening device");
11.186 - if(ahead) {
11.187 - get_param(infile,&r_ahead,&r_fahead);
11.188 - set_param(infile,0,0);
11.189 - }
11.190 -
11.191 - /* seek to proper CD-R(W) track */
11.192 - for(i=tracks;i>0;i--) if(toc[i].track_no==disktrack) break;
11.193 - if(!i) { fprintf(stderr, "%s: Can't find track %d\n", prg_name, disktrack); exit(1); }
11.194 -
11.195 - startPos=(long long)toc[i].sec_start*CD_FRAMESIZE;
11.196 - if(lseek64(infile,startPos,SEEK_SET) != startPos) error("Error seeking to track");
11.197 -
11.198 - /* read header block */
11.199 - bytes=full_read(infile,buffer,CD_FRAMESIZE);
11.200 - if (bytes < 0) error("Error reading header block");
11.201 - if (bytes != CD_FRAMESIZE) error("Unexpected EOF reading header block");
11.202 - totalRead = bytes;
11.203 -
11.204 +
11.205 + for(i=tracks-1; i>=0; i--) if(toc[i].track_no==disktrack) break;
11.206 + if(i<0) { fprintf(stderr, "%s: Can't find track %d\n", prg_name, disktrack); exit(1); }
11.207 + startPos=Vseek(i);
11.208 +
11.209 + Vread(buffer); totalRead+=CD_FRAMESIZE;
11.210 memcpy(&header,buffer,sizeof(header));
11.211 -
11.212 if(!strncmp(SHORT_HDR,header.id_str,strlen(SHORT_HDR))) {
11.213 if(verbose) {
11.214 fprintf(stderr,"%s: ", prg_name);
11.215 - print_track(disktrack, header.t_stamp, header.vol_id, header.disk_set, -1, -1);
11.216 + print_track(disktrack, header.t_stamp, header.vol_id, header.disk_set, -1, -1, header.flags);
11.217 }
11.218
11.219 if(disknum==1) {
11.220 @@ -194,11 +174,11 @@
11.221 }
11.222 else {
11.223 if(strcmp(header.t_stamp,headersave.t_stamp) || strcmp(header.vol_id,headersave.vol_id)) {
11.224 - fprintf(stderr,"%s: This disk doesn't belong to the current set!\n",prg_name);
11.225 + 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);
11.226 result=-1;
11.227 }
11.228 else if(header.disk_set!=disknum) {
11.229 - fprintf(stderr,"%s: Wrong sequence. You need disk %d now!\n",prg_name,disknum);
11.230 + fprintf(stderr,"%s: Wrong sequence. This is disk %d, but you need disk %d now!\n",prg_name,header.disk_set,disknum);
11.231 result=-1;
11.232 }
11.233 else if(verbose) fprintf(stderr, "%s: Beginning restore (Disk %d)\n", prg_name,disknum);
11.234 @@ -213,24 +193,28 @@
11.235 while(!result) {
11.236 int size;
11.237
11.238 - /* read data block */
11.239 DEBUG("\rReading sector %7ld ",(long)((startPos+totalRead)/CD_FRAMESIZE));
11.240 - bytes = full_read(infile, buffer, CD_FRAMESIZE);
11.241 - if (bytes < 0) error("Error reading data");
11.242 - if (bytes != CD_FRAMESIZE) error("Unexpected EOF reading data");
11.243 - totalRead += bytes;
11.244 -
11.245 - /* sanity check */
11.246 + Vread(buffer);
11.247 +
11.248 size=ntohs(db->datasize);
11.249 if(size>DATASIZE) {
11.250 if(verbose) fprintf(stderr,"%s: Warning! Bad datasize at %lld\n",prg_name,totalRead);
11.251 size=DATASIZE;
11.252 }
11.253
11.254 + if(db->flags&F_CRC) {
11.255 + int l=crc32(buffer,size+DBSIZE);
11.256 + if(*((unsigned long *)(&buffer[CD_FRAMESIZE-4]))!=l) {
11.257 + if(verbose) fprintf(stderr,"%s: bad CRC checksum at %lld\n",prg_name,totalRead);
11.258 + serror("Bad checksum, block corrupted, restore failed");
11.259 + }
11.260 + }
11.261 +
11.262 + totalRead+=CD_FRAMESIZE;
11.263 +
11.264 if(!verify) {
11.265 - /* write the data block */
11.266 - bytes=write(1,&buffer[DBSIZE], size);
11.267 - if(bytes!=size) error("Error writing data");
11.268 + bytes=write(1,&buffer[DBSIZE],size);
11.269 + if(bytes!=size) error("Write failed (stdout)");
11.270 }
11.271
11.272 if(db->status == 1) break; /* end of backup*/
11.273 @@ -240,14 +224,12 @@
11.274
11.275 /* print status */
11.276 totalSize+=totalRead;
11.277 - if(result>=0 && verbose)
11.278 - fprintf(stderr, "%s: Restore complete. %lld kB read (%lld kB from this disk)\n",prg_name, totalSize/1024, totalRead/1024);
11.279 -
11.280 - if(ahead) {
11.281 - set_param(infile,r_ahead,r_fahead);
11.282 - get_param(infile,&r_ahead,&r_fahead);
11.283 - }
11.284 - close(infile);
11.285 + if(result>=0 && verbose) {
11.286 + char str1[16], str2[16];
11.287 + fprintf(stderr, "%s: Restore complete. %s read (%s from this disk)\n",
11.288 + prg_name,FlexSize(str1,totalSize),FlexSize(str2,totalRead));
11.289 + }
11.290 +
11.291 return(result);
11.292 }
11.293
11.294 @@ -258,14 +240,16 @@
11.295 int i;
11.296
11.297 fprintf(stderr,"Tracks: %d\n",tracks);
11.298 - print_space();
11.299 + VprintSpace();
11.300 fprintf(stderr,"\n");
11.301
11.302 - for (i = 1; i <= tracks; i++) {
11.303 - if(toc[i].is_data==0) fprintf(stderr,"Track %02d: Non-data\n", toc[i].track_no);
11.304 - else if (toc[i].is_cdbackup == 1)
11.305 - print_track(i, toc[i].t_stamp, toc[i].vol_id, toc[i].disk_set, toc[i].sec_start, toc[i].sec_end);
11.306 - else fprintf(stderr,"Track %02d: Data\n", toc[i].track_no);
11.307 + for(i=0; i<tracks; i++) {
11.308 + if(!toc[i].is_data)
11.309 + fprintf(stderr,"Track %02d: Non-data\n",toc[i].track_no);
11.310 + else if(toc[i].is_cdbackup)
11.311 + print_track(toc[i].track_no,toc[i].t_stamp,toc[i].vol_id,toc[i].disk_set,toc[i].sec_start,toc[i].sec_end,toc[i].flags);
11.312 + else
11.313 + fprintf(stderr,"Track %02d: Data\n", toc[i].track_no);
11.314 }
11.315 }
11.316
11.317 @@ -273,11 +257,10 @@
11.318
11.319 int main(int argc, char *argv[])
11.320 {
11.321 - int cdr;
11.322 -
11.323 parse_cmdline(argc, argv);
11.324
11.325 - cdr=open_cdr(cd_dev); tracks=read_toc(cdr,(query || debug)); close_cdr(cdr);
11.326 + disknum=1; totalSize=0;
11.327 + Vopen(1); tracks=VreadToc(query || debug);
11.328 if(query || debug) {
11.329 verbose=1;
11.330 print_toc();
11.331 @@ -285,15 +268,22 @@
11.332 if(!query) {
11.333 int result;
11.334 if(verify) fprintf(stderr,"%s: Verify mode enabled, no data output!\n",prg_name);
11.335 - totalSize=0; disknum=1;
11.336 + if(ahead) { VgetAhead(); VsetAhead(0); }
11.337 do {
11.338 result=restore(cd_track);
11.339 if(result) {
11.340 if(result>0) { disknum++; cd_track=1; }
11.341 - fprintf(stderr,"%s: Next disk needed: disk %d from %s\n",prg_name,disknum,headersave.vol_id);
11.342 - if(start_diskchange(multicmd,cd_dev)) serror("Diskchange command failed");
11.343 + Vclose();
11.344 + if(!VisRegular()) {
11.345 + fprintf(stderr,"%s: Next disk needed: disk %d from %s\n",prg_name,disknum,headersave.vol_id);
11.346 + diskchange(multicmd,cd_dev);
11.347 + }
11.348 + else if(result<0) break;
11.349 + Vopen(1); tracks=VreadToc(0);
11.350 }
11.351 } while(result);
11.352 - }
11.353 + if(ahead) VsetAhead(1);
11.354 + }
11.355 + Vclose();
11.356 return 0;
11.357 }
12.1 --- a/cdrom.c Sat Dec 29 15:23:55 2007 +0100
12.2 +++ b/cdrom.c Sat Dec 29 15:25:21 2007 +0100
12.3 @@ -1,5 +1,5 @@
12.4 /* cdrom.c
12.5 -Copyright (c) 2000-2002 Craig Condit, Stefan Hülswitt.
12.6 +Copyright (c) 2000-2004 Craig Condit, Stefan Hülswitt.
12.7
12.8 Redistribution and use in source and binary forms, with or without
12.9 modification, are permitted provided that the following conditions are met:
12.10 @@ -27,47 +27,28 @@
12.11
12.12 #include <stdlib.h>
12.13 #include <stdio.h>
12.14 -#include <unistd.h>
12.15 -#include <fcntl.h>
12.16 -#include <string.h>
12.17 -#include <linux/cdrom.h>
12.18 -#include <linux/fs.h>
12.19 #include <sys/ioctl.h>
12.20
12.21 +#ifdef linux
12.22 +#include <linux/fs.h>
12.23 +#endif
12.24 +
12.25 #include "cdrom.h"
12.26 -#include "cdbackup.h"
12.27 #include "misc.h"
12.28 #include "debug.h"
12.29
12.30 /* size of leadin/out depending of how many tracks are on cd */
12.31 -#define MIN_FREE_1 (11400*CD_FRAMESIZE) /* 1th track */
12.32 -#define MIN_FREE_2 (6900*CD_FRAMESIZE) /* 2nd and more tracks */
12.33 +#define LEADOUT_1 11400 /* 1th track */
12.34 +#define LEADOUT_2 6900 /* 2nd and more tracks */
12.35 /* number of (unreadable) runout sectos */
12.36 #define RUNOUT 2
12.37
12.38 -struct toc_entry *toc=0;
12.39 -long long cd_used, cd_avail;
12.40 -
12.41 -extern long cd_len;
12.42 +extern int fd;
12.43 extern int verbose;
12.44 extern char *prg_name;
12.45
12.46 /****************************************************************************/
12.47
12.48 -int open_cdr(char *device)
12.49 -{
12.50 - return open(device, O_RDONLY | O_NONBLOCK);
12.51 -}
12.52 -
12.53 -/****************************************************************************/
12.54 -
12.55 -void close_cdr(int cd_fd)
12.56 -{
12.57 - close(cd_fd);
12.58 -}
12.59 -
12.60 -/****************************************************************************/
12.61 -
12.62 void get_param(int fd, unsigned long *ahead, unsigned long *fahead)
12.63 {
12.64 #if defined(BLKRAGET) && defined(BLKFRAGET)
12.65 @@ -76,7 +57,7 @@
12.66 ioctl(fd,BLKFRAGET,fahead);
12.67 DEBUG("get_param: readahead=%ld freadahead=%ld\n",*ahead,*fahead);
12.68 #else
12.69 - fprintf("Can't get readahead parameter. Ioctl's not available\n");
12.70 + fprintf(stderr,"Can't get readahead parameter. Ioctl's not available\n");
12.71 #endif
12.72 }
12.73
12.74 @@ -85,125 +66,52 @@
12.75 void set_param(int fd, unsigned long ahead, unsigned long fahead)
12.76 {
12.77 #if defined(BLKRAGET) && defined(BLKFRAGET)
12.78 - ioctl(fd, BLKRASET, ahead);
12.79 - ioctl(fd, BLKFRASET, fahead);
12.80 + ioctl(fd,BLKRASET,ahead);
12.81 + ioctl(fd,BLKFRASET,fahead);
12.82 DEBUG("set_param: readahead=%ld freadahead=%ld\n",ahead,fahead);
12.83 #else
12.84 - fprintf("Can't set readahead parameter. Ioctl's not available\n");
12.85 + fprintf(stderr,"Can't set readahead parameter. Ioctl's not available\n");
12.86 #endif
12.87 }
12.88
12.89 /****************************************************************************/
12.90
12.91 -int full_read(int fd, void *buf, int count)
12.92 +int getCdHeader(struct cd_header *cd)
12.93 {
12.94 - int total=0;
12.95 -
12.96 - while(count>0) {
12.97 - int bytes;
12.98 - bytes=read(fd,buf,count); if(bytes<0) return bytes;
12.99 - if(bytes==0) break;
12.100 - count-=bytes; total+=bytes; buf+=bytes;
12.101 - }
12.102 - return total;
12.103 -}
12.104 -
12.105 -/****************************************************************************/
12.106 -
12.107 -void free_toc()
12.108 -{
12.109 - if(toc) { free(toc); toc=0; }
12.110 -}
12.111 -
12.112 -/****************************************************************************/
12.113 -
12.114 -int read_toc(int cd_fd, int trackinfos)
12.115 -{
12.116 - int i;
12.117 struct cdrom_tochdr cd_header;
12.118 struct cdrom_tocentry cd_entry;
12.119 - int tracks,start_track;
12.120 -
12.121 - /* read table of contents header */
12.122 - if(ioctl(cd_fd,CDROMREADTOCHDR,&cd_header)) {
12.123 - if(verbose) fprintf(stderr,"%s: Unable to read CD header, assuming empty CD-R\n", prg_name);
12.124 - cd_used=0; cd_avail=(long long)cd_len*CD_FRAMESIZE; return 0;
12.125 + int tracks;
12.126 +
12.127 + if(ioctl(fd,CDROMREADTOCHDR,&cd_header)<0) {
12.128 + if(verbose) fprintf(stderr,"%s: Unable to read CD header, assuming empty CD-R\n",prg_name);
12.129 + cd->start_track=1; cd->end_track=0;
12.130 + cd->used=0;
12.131 + return 0;
12.132 }
12.133
12.134 - /* get start and end tracks */
12.135 - start_track = cd_header.cdth_trk0;
12.136 - tracks = cd_header.cdth_trk1-start_track+1;
12.137 - DEBUG("read_toc: starttrack=%d tracks=%d\n",start_track,tracks);
12.138 + cd->start_track=cd_header.cdth_trk0;
12.139 + cd->end_track =cd_header.cdth_trk1;
12.140 + tracks=cd->end_track-cd->start_track+1;
12.141
12.142 - free_toc();
12.143 - if(!(toc=calloc(tracks+1,sizeof(struct toc_entry)))) serror("No memory for TOC");
12.144 + cd_entry.cdte_format=CDROM_LBA;
12.145 + cd_entry.cdte_track=CDROM_LEADOUT;
12.146 + if(ioctl(fd,CDROMREADTOCENTRY,&cd_entry)<0) error("Ioctl failed (lead-out)");
12.147
12.148 - /* set some parameters */
12.149 - cd_entry.cdte_format=CDROM_LBA;
12.150 -
12.151 - /* read lead-out */
12.152 - cd_entry.cdte_track=CDROM_LEADOUT;
12.153 - if(ioctl(cd_fd,CDROMREADTOCENTRY,&cd_entry)) error("Error reading lead-out");
12.154 -
12.155 - toc[0].track_no=CDROM_LEADOUT; /* not a real track */
12.156 - toc[0].sec_start=cd_entry.cdte_addr.lba;
12.157 -
12.158 - cd_used =(long long)toc[0].sec_start*CD_FRAMESIZE;
12.159 - cd_avail =(long long)cd_len*CD_FRAMESIZE-cd_used;
12.160 - cd_avail-=(tracks>1?MIN_FREE_2:MIN_FREE_1);
12.161 - 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);
12.162 -
12.163 - if(cd_avail<0) cd_avail=0; /* can be <0 due to assumed additional lead-in/out */
12.164 -
12.165 - /* read rest of tracks */
12.166 - for(i=1; i<=tracks; i++) {
12.167 - cd_entry.cdte_track=start_track+i-1;
12.168 - if(ioctl(cd_fd,CDROMREADTOCENTRY,&cd_entry)) error("Error reading TOC");
12.169 -
12.170 - toc[i].track_no=start_track+i-1;
12.171 - toc[i].sec_start=cd_entry.cdte_addr.lba;
12.172 - if(cd_entry.cdte_ctrl&CDROM_DATA_TRACK) toc[i].is_data=1;
12.173 - }
12.174 -
12.175 - /* calculate end sectors */
12.176 - toc[tracks].sec_end = toc[ 0].sec_start - 1 - RUNOUT;
12.177 - for(i=1; i<tracks; i++)
12.178 - toc[i].sec_end = toc[i+1].sec_start - 1 - RUNOUT - (i>1?(MIN_FREE_2/CD_FRAMESIZE):(MIN_FREE_1/CD_FRAMESIZE));
12.179 -
12.180 - if(trackinfos)
12.181 - /* now loop through tracks and read header info */
12.182 - for(i=1; i<=tracks; i++) {
12.183 - char inbuffer[CD_FRAMESIZE];
12.184 - struct header_block *track_header=(struct header_block *)&inbuffer[0];
12.185 -
12.186 - if (toc[i].is_data == 1) {
12.187 - if(lseek64(cd_fd,(long long)toc[i].sec_start*CD_FRAMESIZE,SEEK_SET)<0) error("Seek failed");
12.188 -
12.189 - if(full_read(cd_fd,inbuffer,CD_FRAMESIZE)==CD_FRAMESIZE) {
12.190 - if(!strncmp(SHORT_HDR,track_header->id_str,strlen(SHORT_HDR))) {
12.191 - toc[i].is_cdbackup=1;
12.192 - strncpy(toc[i].id_str,track_header->id_str,32); toc[i].id_str[32]=0;
12.193 - strncpy(toc[i].vol_id, track_header->vol_id,32); toc[i].vol_id[32]=0;
12.194 - strncpy(toc[i].t_stamp, track_header->t_stamp,12); toc[i].t_stamp[12]=0;
12.195 - toc[i].disk_set = track_header->disk_set;
12.196 - }
12.197 - }
12.198 - }
12.199 - }
12.200 -
12.201 + cd->used=cd_entry.cdte_addr.lba + (tracks==1 ? LEADOUT_1:LEADOUT_2);
12.202 return tracks;
12.203 }
12.204
12.205 /****************************************************************************/
12.206
12.207 -void print_space()
12.208 +void getCdTrack(int num, struct cd_track *cd)
12.209 {
12.210 - if(verbose)
12.211 - fprintf(stderr,
12.212 - "Disk size: %7lld kB (%7ld blocks)\n"
12.213 - "Space used: %7lld kB (%7lld blocks)\n"
12.214 - "Space avail:%7lld kB (%7lld blocks)\n",
12.215 - (long long)cd_len*CD_FRAMESIZE/1024,cd_len,
12.216 - cd_used/1024, cd_used/CD_FRAMESIZE,
12.217 - cd_avail/1024, cd_avail/CD_FRAMESIZE);
12.218 + struct cdrom_tocentry cd_entry;
12.219 +
12.220 + cd_entry.cdte_format=CDROM_LBA;
12.221 + cd_entry.cdte_track=num;
12.222 + if(ioctl(fd,CDROMREADTOCENTRY,&cd_entry)<0) error("Ioctl failed (toc entry)");
12.223 +
12.224 + cd->start_sec =cd_entry.cdte_addr.lba;
12.225 + cd->leadout_size=RUNOUT+(num==cd->start_track ? LEADOUT_1:LEADOUT_2);
12.226 + cd->is_data =(cd_entry.cdte_ctrl&CDROM_DATA_TRACK) ? 1:0;
12.227 }
13.1 --- a/cdrom.h Sat Dec 29 15:23:55 2007 +0100
13.2 +++ b/cdrom.h Sat Dec 29 15:25:21 2007 +0100
13.3 @@ -1,5 +1,5 @@
13.4 /* cdrom.h
13.5 -Copyright (c) 2000-2002 Craig Condit, Stefan Hülswitt.
13.6 +Copyright (c) 2000-2004 Craig Condit, Stefan Hülswitt.
13.7
13.8 Redistribution and use in source and binary forms, with or without
13.9 modification, are permitted provided that the following conditions are met:
13.10 @@ -26,28 +26,33 @@
13.11 #ifndef _CDBACKUP_CDROM_H
13.12 #define _CDBACKUP_CDROM_H
13.13
13.14 -extern struct toc_entry *toc;
13.15 -extern long long cd_used, cd_avail;
13.16 +#ifdef linux
13.17 +#include <linux/cdrom.h>
13.18 +#endif
13.19
13.20 -struct toc_entry {
13.21 - u_char track_no; /* track number */
13.22 - char is_data; /* 1 = data track */
13.23 - char is_cdbackup; /* was it created by CD-Backup? */
13.24 - int sec_start; /* start sector */
13.25 - int sec_end; /* last sector */
13.26 - char id_str[33]; /* recorder id string (32 chars) */
13.27 - char vol_id[33]; /* volume label (32 characters) */
13.28 - char t_stamp[13]; /* time stamp: yyyymmddhhmm */
13.29 - char disk_set; /* disk number */
13.30 -};
13.31 +#ifdef sun
13.32 +#include <sys/cdio.h>
13.33 +#endif
13.34
13.35 -int open_cdr(char *device);
13.36 -void close_cdr(int cd_fd);
13.37 +#ifndef CD_FRAMESIZE
13.38 +#define CD_FRAMESIZE 2048
13.39 +#endif
13.40 +
13.41 +struct cd_header {
13.42 + int start_track, end_track;
13.43 + int used;
13.44 + };
13.45 +
13.46 +struct cd_track {
13.47 + int start_sec;
13.48 + int leadout_size;
13.49 + int is_data;
13.50 + int start_track;
13.51 + };
13.52 +
13.53 void get_param(int fd, unsigned long *ahead, unsigned long *fahead);
13.54 void set_param(int fd, unsigned long ahead, unsigned long fahead);
13.55 -int full_read(int fd, void *buf, int count);
13.56 -int read_toc(int cd_fd, int trackinfos);
13.57 -void free_toc();
13.58 -void print_space();
13.59 +int getCdHeader(struct cd_header *cd);
13.60 +void getCdTrack(int num, struct cd_track *cd);
13.61
13.62 #endif
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/examples/cdload Sat Dec 29 15:25:21 2007 +0100
14.3 @@ -0,0 +1,55 @@
14.4 +#!/bin/bash
14.5 +
14.6 +# defaults
14.7 +
14.8 +DEVICE="/dev/sr1"
14.9 +TRACK="1"
14.10 +LIST=0
14.11 +
14.12 +# process command-line options
14.13 +
14.14 +while getopts ":d:t:l" optn; do
14.15 + case $optn in
14.16 + d ) DEVICE=$OPTARG
14.17 + ;;
14.18 + t ) TRACK=$OPTARG
14.19 + ;;
14.20 + l ) LIST=1
14.21 + ;;
14.22 + \? ) echo "Usage: `basename $0` [-d device] [-t track] [-l] [filespec]"
14.23 + echo ""
14.24 + echo "Defaults: -d /dev/sr1"
14.25 + echo " -t 1"
14.26 + echo ""
14.27 + echo "if -l is given, archive is listed not restored."
14.28 + exit 1
14.29 + ;;
14.30 + esac
14.31 +done
14.32 +shift $(($OPTIND - 1))
14.33 +
14.34 +# process input-files
14.35 +
14.36 +TMP="/tmp/cdload.$$"
14.37 +rm -f $TMP
14.38 +
14.39 +SPECOPT=""
14.40 +for filespec in "$@"; do
14.41 + echo "$filespec" >>$TMP
14.42 + SPECOPT="-w $TMP"
14.43 + done
14.44 +#echo "-$SPECOPT-"
14.45 +#cat $TMP
14.46 +#echo "--"
14.47 +
14.48 +if [ $LIST -eq 1 ]; then
14.49 + aopt="-t" # list archive
14.50 + echo "`basename $0`: listing archive"
14.51 +else
14.52 + aopt="-i" # restore archive
14.53 + echo "`basename $0`: restoring archive"
14.54 +fi
14.55 +
14.56 +cdrestore -d $DEVICE -t $TRACK | afio $aopt -vnz $SPECOPT -
14.57 +
14.58 +rm -f $TMP
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/examples/cdsave Sat Dec 29 15:25:21 2007 +0100
15.3 @@ -0,0 +1,65 @@
15.4 +#!/bin/bash
15.5 +
15.6 +# defaults
15.7 +
15.8 +LABEL="Afio-Backup"
15.9 +SCSIDEV="0,4,0"
15.10 +DEVICE="/dev/sr1"
15.11 +SPEED="8"
15.12 +LEN="702"
15.13 +MULTI=""
15.14 +
15.15 +# process command-line options
15.16 +
15.17 +while getopts ":a:d:r:s:l:m" optn; do
15.18 + case $optn in
15.19 + a ) LABEL=$OPTARG
15.20 + ;;
15.21 + d ) DEVICE=$OPTARG
15.22 + ;;
15.23 + r ) SCSIDEV=$OPTARG
15.24 + ;;
15.25 + s ) SPEED=$OPTARG
15.26 + ;;
15.27 + l ) LEN=$OPTARG
15.28 + ;;
15.29 + m ) MULTI="-m"
15.30 + ;;
15.31 + \? ) echo "Usage: `basename $0` [-a label] [-l cd_len] [-m] [-d device] [-r scsidev] [-s speed] file1 file2 ..."
15.32 + echo ""
15.33 + echo "Defaults: -a Afio-Backup"
15.34 + echo " -d /dev/sr1"
15.35 + echo " -r 0,4,0"
15.36 + echo " -s 8"
15.37 + echo " -l 702"
15.38 + exit 1
15.39 + ;;
15.40 + esac
15.41 +done
15.42 +shift $(($OPTIND - 1))
15.43 +
15.44 +# process input-files
15.45 +
15.46 +TMP="/tmp/cdsave.$$"
15.47 +rm -f $TMP
15.48 +
15.49 +for filename in "$@"; do
15.50 + case $filename in
15.51 + *[*?]* ) # means shell couldn´t extend *.wav, etc.
15.52 + echo "warning: no $filename file(s) found"
15.53 + ;;
15.54 + * )
15.55 + echo >>$TMP "$filename"
15.56 + ;;
15.57 + esac
15.58 +done
15.59 +
15.60 +if [ -s $TMP ] ; then
15.61 + cat $TMP | \
15.62 + afio -o -uz - | \
15.63 + cdbackup -v -a "$LABEL" $MULTI -l "$LEN" -d "$DEVICE" -r "$SCSIDEV" -s "$SPEED" -- -v fs=8m
15.64 +else
15.65 + echo "Error: no files specified"
15.66 +fi
15.67 +rm -f $TMP
15.68 +
16.1 --- a/misc.c Sat Dec 29 15:23:55 2007 +0100
16.2 +++ b/misc.c Sat Dec 29 15:25:21 2007 +0100
16.3 @@ -1,5 +1,5 @@
16.4 /* misc.c
16.5 -Copyright (c) 2000-2002 Craig Condit, Stefan Hülswitt.
16.6 +Copyright (c) 2000-2004 Craig Condit, Stefan Hülswitt.
16.7
16.8 Redistribution and use in source and binary forms, with or without
16.9 modification, are permitted provided that the following conditions are met:
16.10 @@ -30,6 +30,9 @@
16.11 #include <sys/wait.h>
16.12 #include <errno.h>
16.13
16.14 +#include "cdrom.h"
16.15 +#include "debug.h"
16.16 +
16.17 extern char *prg_name;
16.18
16.19 /****************************************************************************/
16.20 @@ -50,34 +53,156 @@
16.21
16.22 /****************************************************************************/
16.23
16.24 -int start_diskchange(char *multicmd, char *cd_dev)
16.25 -{
16.26 -int pid, status=0;
16.27 -char buffer[12];
16.28 -
16.29 -if(multicmd) { /* we have an external script */
16.30 - if((pid=fork())<0) error("Fork failed in diskchange");
16.31 - if(pid==0) { /* child */
16.32 - char *argv[3];
16.33 -
16.34 - dup2(2,0); dup2(2,1); /* duplicate stderr as stdin/stdout */
16.35 - argv[0] = multicmd;
16.36 - argv[1] = cd_dev;
16.37 - argv[2] = 0;
16.38 - execvp(multicmd, argv);
16.39 - error("Starting diskchange command failed");
16.40 - }
16.41 -
16.42 - while(1) {
16.43 - if(waitpid(pid,&status,0)==-1) { if (errno != EINTR) { status=-1; break; } }
16.44 - else break;
16.45 - }
16.46 - }
16.47 -else { /* use internal diskchange */
16.48 - fprintf(stderr,"\n\nPlease insert next disk and press RETURN\n\n\n");
16.49 - do {
16.50 - pid=read(2,buffer,sizeof(buffer));
16.51 - } while(pid==sizeof(buffer) && buffer[sizeof(buffer)-1]!='\n');
16.52 - }
16.53 -return status;
16.54 -}
16.55 +long long FlexLen(char *optarg)
16.56 +{
16.57 + char *end;
16.58 + long long len;
16.59 + errno=0; len=strtoll(optarg,&end,10);
16.60 + if(errno==ERANGE || len<1) serror("Option -l: length out of range (must be >=1)\n");
16.61 + switch(*end) {
16.62 + case 'K': /* kilo-bytes*/
16.63 + case 'k':
16.64 + len*=1024; break;
16.65 + case 0: /* mega-bytes */
16.66 + case 'M':
16.67 + case 'm':
16.68 + len*=(1024*1024); break;
16.69 + case 'G':
16.70 + case 'g':
16.71 + len*=(1024*1024*1024LL); break;
16.72 + case 's':
16.73 + case 'S':
16.74 + len*=CD_FRAMESIZE; break;
16.75 + default:
16.76 + serror("Unknown extention for media size");
16.77 + }
16.78 + DEBUG("media size len=%lld blocks=%lld\n",len,len/CD_FRAMESIZE);
16.79 + return len;
16.80 +}
16.81 +
16.82 +/****************************************************************************/
16.83 +
16.84 +char *FlexSize(char *buff, long long val)
16.85 +{
16.86 + char *unit=" ";
16.87 + if(val > 1024*1024*1024*16LL) { val/=1024*1024*1024LL; unit="G"; }
16.88 + else if(val > 1024*1024*16LL) { val/=1024*1024LL; unit="M"; }
16.89 + else if(val > 1024*16LL) { val/=1024LL; unit="k"; }
16.90 + sprintf(buff,"%5lld %sB",val,unit);
16.91 + return buff;
16.92 +}
16.93 +
16.94 +/****************************************************************************/
16.95 +
16.96 +int full_read(int fd, void *buf, int count)
16.97 +{
16.98 + int total=0;
16.99 + while(count>0) {
16.100 + int bytes;
16.101 + bytes=read(fd,buf,count);
16.102 + if(bytes==0) break;
16.103 + else if(bytes<0) {
16.104 + if(errno!=EAGAIN) error("Read failed");
16.105 + usleep(200*1000);
16.106 + }
16.107 + else {
16.108 + count-=bytes; buf+=bytes; total+=bytes;
16.109 + }
16.110 + }
16.111 + return total;
16.112 +}
16.113 +
16.114 +/****************************************************************************/
16.115 +
16.116 +void diskchange(char *multicmd, char *cd_dev)
16.117 +{
16.118 + int pid, status=0;
16.119 + char buffer[12];
16.120 +
16.121 + if(multicmd) { /* we have an external script */
16.122 + DEBUG("external diskchange started '%s'\n",multicmd);
16.123 + if((pid=fork())<0) error("Fork failed (diskchange)");
16.124 + if(pid==0) { /* child */
16.125 + char *argv[3];
16.126 +
16.127 + dup2(2,0); dup2(2,1); /* duplicate stderr as stdin/stdout */
16.128 + argv[0] = multicmd;
16.129 + argv[1] = cd_dev;
16.130 + argv[2] = 0;
16.131 + execvp(multicmd, argv);
16.132 + error("Exec failed (diskchange)");
16.133 + }
16.134 +
16.135 + while(1) {
16.136 + if(waitpid(pid,&status,0)==-1) { if (errno!=EINTR) { status=-1; break; } }
16.137 + else break;
16.138 + }
16.139 + }
16.140 + else { /* use internal diskchange */
16.141 + DEBUG("internal diskchange started\n");
16.142 + fprintf(stderr,"\n\nPlease insert next disk and press RETURN\n\n\n");
16.143 + do {
16.144 + pid=read(2,buffer,sizeof(buffer));
16.145 + if(pid<0 && errno!=EAGAIN) error("Read failed (diskchange)");
16.146 + } while(pid<=0 || (pid==sizeof(buffer) && buffer[sizeof(buffer)-1]!='\n'));
16.147 + }
16.148 + if(status) serror("Diskchange command failed");
16.149 + DEBUG("diskchange completed\n");
16.150 +}
16.151 +
16.152 +/****************************************************************************/
16.153 +
16.154 +static unsigned long crc_table[256] = {
16.155 + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
16.156 + 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
16.157 + 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
16.158 + 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
16.159 + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
16.160 + 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
16.161 + 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
16.162 + 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
16.163 + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
16.164 + 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
16.165 + 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
16.166 + 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
16.167 + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
16.168 + 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
16.169 + 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
16.170 + 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
16.171 + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
16.172 + 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
16.173 + 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
16.174 + 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
16.175 + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
16.176 + 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
16.177 + 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
16.178 + 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
16.179 + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
16.180 + 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
16.181 + 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
16.182 + 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
16.183 + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
16.184 + 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
16.185 + 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
16.186 + 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
16.187 + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
16.188 + 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
16.189 + 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
16.190 + 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
16.191 + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
16.192 + 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
16.193 + 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
16.194 + 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
16.195 + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
16.196 + 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
16.197 + 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
16.198 + };
16.199 +
16.200 +unsigned long crc32(char *data, int len)
16.201 +{
16.202 + unsigned long crc=0xffffffff;
16.203 + int i;
16.204 + for(i=0 ; i<len ; i++)
16.205 + crc=(crc<<8) ^ crc_table[((crc>>24)^*data++)&0xff];
16.206 + return crc;
16.207 +}
17.1 --- a/misc.h Sat Dec 29 15:23:55 2007 +0100
17.2 +++ b/misc.h Sat Dec 29 15:25:21 2007 +0100
17.3 @@ -1,5 +1,5 @@
17.4 /* misc.h
17.5 -Copyright (c) 2000-2002 Craig Condit, Stefan Hülswitt.
17.6 +Copyright (c) 2000-2004 Craig Condit, Stefan Hülswitt.
17.7
17.8 Redistribution and use in source and binary forms, with or without
17.9 modification, are permitted provided that the following conditions are met:
17.10 @@ -26,8 +26,12 @@
17.11 #ifndef _CDBACKUP_MISC_H
17.12 #define _CDBACKUP_MISC_H
17.13
17.14 -int start_diskchange(char *multicmd, char *cd_dev);
17.15 +unsigned long crc32(char *data, int len);
17.16 +void diskchange(char *multicmd, char *cd_dev);
17.17 +int full_read(int fd, void *buf, int count);
17.18 void error(char *text);
17.19 void serror(char *text);
17.20 +char *FlexSize(char *buff, long long val);
17.21 +long long FlexLen(char *optarg);
17.22
17.23 #endif
18.1 --- a/version.h Sat Dec 29 15:23:55 2007 +0100
18.2 +++ b/version.h Sat Dec 29 15:25:21 2007 +0100
18.3 @@ -2,7 +2,7 @@
18.4 #define _CDBACKUP_VERSION_H
18.5
18.6 #ifndef VERSION
18.7 -#define VERSION "0.6.3"
18.8 +#define VERSION "0.6.4beta"
18.9 #endif
18.10
18.11 #endif
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
19.2 +++ b/virtual-backup.c Sat Dec 29 15:25:21 2007 +0100
19.3 @@ -0,0 +1,154 @@
19.4 +/* virtual-backup.c
19.5 +Copyright (c) 2000-2004 Craig Condit, Stefan Hülswitt.
19.6 +
19.7 +Redistribution and use in source and binary forms, with or without
19.8 +modification, are permitted provided that the following conditions are met:
19.9 +
19.10 +1. Redistributions of source code must retain the above copyright notice,
19.11 + this list of conditions and the following disclaimer.
19.12 +2. Redistributions in binary form must reproduce the above copyright notice,
19.13 + this list of conditions and the following disclaimer in the documentation
19.14 + and/or other materials provided with the distribution.
19.15 +
19.16 +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
19.17 +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19.18 +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19.19 +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
19.20 +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19.21 +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19.22 +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
19.23 +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
19.24 +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
19.25 +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
19.26 +SUCH DAMAGE.
19.27 +*/
19.28 +
19.29 +#define _LARGEFILE64_SOURCE
19.30 +#define _GNU_SOURCE
19.31 +
19.32 +#include <stdlib.h>
19.33 +#include <stdio.h>
19.34 +#include <unistd.h>
19.35 +#include <fcntl.h>
19.36 +#include <errno.h>
19.37 +#include <string.h>
19.38 +#include <sys/wait.h>
19.39 +#include <sys/stat.h>
19.40 +
19.41 +#include "virtual.h"
19.42 +#include "cdbackup.h"
19.43 +#include "cdrom.h"
19.44 +#include "misc.h"
19.45 +#include "debug.h"
19.46 +
19.47 +//#define DEBUGOUT
19.48 +
19.49 +extern int virtual, multi;
19.50 +
19.51 +extern int fd;
19.52 +extern struct virt_header *virt_header;
19.53 +extern int virtualMissing;
19.54 +extern char *real_virt_name;
19.55 +
19.56 +#ifndef DEBUGOUT
19.57 +static pid_t childpid;
19.58 +#endif
19.59 +static int vfd=-1;
19.60 +
19.61 +/****************************************************************************/
19.62 +
19.63 +void VnewTrack(void)
19.64 +{
19.65 + if(virtual) {
19.66 + long long pos;
19.67 + if(virtualMissing) {
19.68 + if((fd=open64(real_virt_name,O_RDWR|O_CREAT,S_IRUSR|S_IWUSR|S_IRGRP| S_IROTH))<0) error("Open failed (new track)");
19.69 + if(write(fd,virt_header,CD_FRAMESIZE)!=CD_FRAMESIZE) error("Write failed (new track)");
19.70 + virtualMissing=0;
19.71 + }
19.72 + if(virt_header->tracks>=MAX_VIRT_TRACKS-1) serror("Maximum number of virtual tracks reached");
19.73 + pos=(virt_header->start[virt_header->tracks]=virt_header->leadout)*CD_FRAMESIZE;
19.74 + virt_header->tracks++;
19.75 + if(lseek64(fd,pos,SEEK_SET)<0) error("Seek failed (new track)");
19.76 + }
19.77 + else {
19.78 +#ifndef DEBUGOUT
19.79 + int pd[2];
19.80 + Vclose();
19.81 + if(pipe(pd)<0) error("Pipe failed (new track)");
19.82 + if((childpid=fork())<0) error("Fork failed (new track)");
19.83 + if(childpid==0) { /* child */
19.84 + close(pd[1]);
19.85 + close(0);
19.86 + dup2(pd[0],0);
19.87 + start_cdrecord(); /* doesn't returns */
19.88 + }
19.89 + close(pd[0]); fd=pd[1];
19.90 +#else
19.91 + /* debug code; send data to /dev/null. */
19.92 + Vclose();
19.93 + fprintf(stderr,"DEBUG CODE: NO recording, sending data to /dev/null!\n");
19.94 + if((fd=open("/dev/null",O_WRONLY))<0) error("Open failed (/dev/null)");
19.95 +#endif
19.96 + cd_avail-=padsize*CD_FRAMESIZE;
19.97 + }
19.98 +}
19.99 +
19.100 +/****************************************************************************/
19.101 +
19.102 +int Vsize(void)
19.103 +{
19.104 + return virt_header->leadout;
19.105 +}
19.106 +
19.107 +/****************************************************************************/
19.108 +
19.109 +int VhasCont(void)
19.110 +{
19.111 + return virt_header->has_cont;
19.112 +}
19.113 +
19.114 +/****************************************************************************/
19.115 +
19.116 +void VprepareDump(void)
19.117 +{
19.118 + if((vfd=dup(fd))<0) error("Dup failed");
19.119 + Vclose();
19.120 +}
19.121 +
19.122 +/****************************************************************************/
19.123 +
19.124 +void VvirtRead(void *buf)
19.125 +{
19.126 + if(full_read(vfd,buf,CD_FRAMESIZE)!=CD_FRAMESIZE)
19.127 + serror("Unexpected EOF reading data");
19.128 +}
19.129 +
19.130 +/****************************************************************************/
19.131 +
19.132 +void VcloseTrack(int cont)
19.133 +{
19.134 + if(virtual) {
19.135 + if(lseek64(fd,0,SEEK_SET)<0) error("Seek failed (close track)");
19.136 + virt_header->has_cont=cont;
19.137 + if(write(fd,virt_header,CD_FRAMESIZE)!=CD_FRAMESIZE) error("Write failed (close track)");
19.138 + Vclose();
19.139 + }
19.140 + else {
19.141 + Vclose();
19.142 +#ifndef DEBUGOUT
19.143 + DEBUG("VcloseTrack: waiting for child termination\n");
19.144 + while(wait(0)!=childpid);
19.145 +#endif
19.146 + }
19.147 + if(vfd>=0) { close(vfd); vfd=-1; }
19.148 +}
19.149 +
19.150 +/****************************************************************************/
19.151 +
19.152 +void Vwrite(const void *buf)
19.153 +{
19.154 + if(write(fd,buf,CD_FRAMESIZE)!=CD_FRAMESIZE) error("Write failed");
19.155 + if(virtual) virt_header->leadout++;
19.156 + cd_avail-=CD_FRAMESIZE;
19.157 +}
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
20.2 +++ b/virtual.c Sat Dec 29 15:25:21 2007 +0100
20.3 @@ -0,0 +1,287 @@
20.4 +/* virtual.c
20.5 +Copyright (c) 2000-2004 Craig Condit, Stefan Hülswitt.
20.6 +
20.7 +Redistribution and use in source and binary forms, with or without
20.8 +modification, are permitted provided that the following conditions are met:
20.9 +
20.10 +1. Redistributions of source code must retain the above copyright notice,
20.11 + this list of conditions and the following disclaimer.
20.12 +2. Redistributions in binary form must reproduce the above copyright notice,
20.13 + this list of conditions and the following disclaimer in the documentation
20.14 + and/or other materials provided with the distribution.
20.15 +
20.16 +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
20.17 +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20.18 +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20.19 +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
20.20 +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20.21 +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20.22 +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
20.23 +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20.24 +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
20.25 +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
20.26 +SUCH DAMAGE.
20.27 +*/
20.28 +
20.29 +#define _LARGEFILE64_SOURCE
20.30 +#define _GNU_SOURCE
20.31 +
20.32 +#include <stdlib.h>
20.33 +#include <stdio.h>
20.34 +#include <unistd.h>
20.35 +#include <fcntl.h>
20.36 +#include <errno.h>
20.37 +#include <string.h>
20.38 +#include <sys/wait.h>
20.39 +#include <sys/stat.h>
20.40 +
20.41 +#include "virtual.h"
20.42 +#include "cdbackup.h"
20.43 +#include "cdrom.h"
20.44 +#include "misc.h"
20.45 +#include "debug.h"
20.46 +
20.47 +int fd=-1;
20.48 +struct toc_entry *toc=0;
20.49 +long long cd_used, cd_avail;
20.50 +
20.51 +static struct cd_header cd_header;
20.52 +
20.53 +static unsigned char virt_buffer[VIRT_HEADER_LEN];
20.54 +struct virt_header *virt_header=(struct virt_header *)virt_buffer;
20.55 +int virtualMissing=0, virt_off=-1, virt_regular;
20.56 +char *real_virt_name=0;
20.57 +
20.58 +extern int virtual;
20.59 +extern int disknum;
20.60 +extern char *virt_name, *cd_dev;
20.61 +
20.62 +/****************************************************************************/
20.63 +
20.64 +void Vopen(int ro)
20.65 +{
20.66 + Vclose();
20.67 + if(!virtual) {
20.68 + if((fd=open64(cd_dev,O_RDONLY|O_NONBLOCK))<0)
20.69 + error("Open failed (device)");
20.70 + }
20.71 + else {
20.72 + free(real_virt_name);
20.73 + if(disknum==1) {
20.74 + real_virt_name=strdup(virt_name);
20.75 + }
20.76 + else if(virt_off>0) {
20.77 + char *strip=strdup(virt_name);
20.78 + char *dot=rindex(strip,'.');
20.79 + if(dot) {
20.80 + *dot=0;
20.81 + asprintf(&real_virt_name,"%s.%d",strip,disknum+virt_off);
20.82 + }
20.83 + else serror("Bad filename format");
20.84 + free(strip);
20.85 + }
20.86 + else {
20.87 + asprintf(&real_virt_name,"%s.%d",virt_name,disknum);
20.88 + }
20.89 + DEBUG("Vopen: real filename is '%s' disknum=%d virt_off=%d\n",
20.90 + real_virt_name,disknum,virt_off);
20.91 + virtualMissing=0; virt_regular=0;
20.92 + if((fd=open64(real_virt_name,ro ? O_RDONLY:O_RDWR))<0) {
20.93 + if(errno==EACCES || errno==ENOENT || errno==ENOTDIR) {
20.94 + virtualMissing=1; virt_regular=1;
20.95 + DEBUG("Vopen: missing virtual image, assuming an empty one\n");
20.96 + }
20.97 + else error("Open failed (virtual)");
20.98 + }
20.99 + else {
20.100 + struct stat64 st;
20.101 + if(fstat64(fd,&st)<0) error("Stat failed (virtual)");
20.102 + if(S_ISREG(st.st_mode)) virt_regular=1;
20.103 + }
20.104 + }
20.105 +}
20.106 +
20.107 +/****************************************************************************/
20.108 +
20.109 +void Vclose(void)
20.110 +{
20.111 + if(fd>=0) {
20.112 + close(fd);
20.113 + fd=-1;
20.114 + }
20.115 +}
20.116 +
20.117 +/****************************************************************************/
20.118 +
20.119 +int VisRegular(void)
20.120 +{
20.121 + return virt_regular;
20.122 +}
20.123 +
20.124 +/****************************************************************************/
20.125 +
20.126 +static int VgetCdHeader(struct cd_header *cd)
20.127 +{
20.128 + if(virtualMissing) {
20.129 + if(verbose)
20.130 + fprintf(stderr,"%s: Unable to get virtual image header, assuming new virtual image\n",prg_name);
20.131 + memset(virt_buffer,0,VIRT_HEADER_LEN);
20.132 + virt_header->magic=VIRT_MAGIC;
20.133 + virt_header->version=VIRT_VERSION;
20.134 + virt_header->leadout=1;
20.135 + virt_header->count=disknum + (virt_off>0 ? virt_off:0);
20.136 + }
20.137 + else {
20.138 + int n;
20.139 + if((n=read(fd,virt_buffer,VIRT_HEADER_LEN))<0)
20.140 + error("Read failed (virtual header)");
20.141 + if(n!=VIRT_HEADER_LEN)
20.142 + serror("Short read on virtual header");
20.143 + if(virt_header->magic!=VIRT_MAGIC)
20.144 + serror("Missing magic value in virtual header. Really a virtual image?");
20.145 + if(virt_header->version>VIRT_VERSION)
20.146 + serror("Don't know how to handle this virtual image version");
20.147 + }
20.148 +
20.149 + if(virt_off<0 && disknum==1) {
20.150 + virt_off=virt_header->count-1;
20.151 + DEBUG("VgetCdHeader: setting virt_off=%d\n",virt_off);
20.152 + }
20.153 + cd->start_track=1; cd->end_track=virt_header->tracks;
20.154 + cd->used=virt_header->leadout;
20.155 + return cd->end_track;
20.156 +}
20.157 +
20.158 +/****************************************************************************/
20.159 +
20.160 +static void VgetCdTrack(int num, struct cd_track *cd)
20.161 +{
20.162 + cd->start_sec=virt_header->start[num-1];
20.163 + cd->leadout_size=0;
20.164 + cd->is_data=1;
20.165 +}
20.166 +
20.167 +/****************************************************************************/
20.168 +
20.169 +int VreadToc(int trackInfos)
20.170 +{
20.171 + struct cd_track cd_track;
20.172 + int i, tracks;
20.173 +
20.174 + tracks=virtual ? VgetCdHeader(&cd_header) : getCdHeader(&cd_header);
20.175 + if(!tracks) {
20.176 + cd_used=0; cd_avail=(long long)cd_len*CD_FRAMESIZE;
20.177 + DEBUG("Vreadtoc: empty media\n");
20.178 + return 0;
20.179 + }
20.180 + DEBUG("Vreadtoc: starttrack=%d endtrack=%d tracks=%d\n",
20.181 + cd_header.start_track,cd_header.end_track,tracks);
20.182 +
20.183 + cd_used =(long long)cd_header.used*CD_FRAMESIZE;
20.184 + cd_avail =(long long)cd_len*CD_FRAMESIZE-cd_used;
20.185 + if(cd_avail<0) cd_avail=0;
20.186 + DEBUG("Vreadtoc: cd_used=%lld (%lld secs) cd_avail=%lld (%lld secs)\n",
20.187 + cd_used,cd_used/CD_FRAMESIZE,cd_avail,cd_avail/CD_FRAMESIZE);
20.188 +
20.189 + free(toc);
20.190 + if(!(toc=calloc(tracks,sizeof(struct toc_entry)))) serror("No memory for TOC");
20.191 +
20.192 + cd_track.start_track=cd_header.start_track;
20.193 + for(i=tracks-1; i>=0; i--) {
20.194 + int t=cd_header.start_track+i;
20.195 + if(virtual) VgetCdTrack(t,&cd_track); else getCdTrack(t,&cd_track);
20.196 + toc[i].track_no=t;
20.197 + toc[i].sec_start=cd_track.start_sec;
20.198 + toc[i].sec_end=((i==tracks-1) ? cd_header.used : toc[i+1].sec_start)-1-cd_track.leadout_size;
20.199 + toc[i].is_data=cd_track.is_data;
20.200 + DEBUG("Vreadtoc: index=%d track=%d sec_start=%d sec_end=%d data=%d\n",
20.201 + i,t,toc[i].sec_start,toc[i].sec_end,toc[i].is_data);
20.202 + }
20.203 +
20.204 + if(trackInfos) {
20.205 + for(i=0; i<tracks; i++) {
20.206 + char inbuffer[CD_FRAMESIZE];
20.207 + struct header_block *track_header=(struct header_block *)inbuffer;
20.208 +
20.209 + if(toc[i].is_data) {
20.210 + Vseek(i);
20.211 + Vread(inbuffer);
20.212 + if(!strncmp(SHORT_HDR,track_header->id_str,strlen(SHORT_HDR))) {
20.213 + toc[i].is_cdbackup=1;
20.214 + strncpy(toc[i].id_str,track_header->id_str,32); toc[i].id_str[32]=0;
20.215 + strncpy(toc[i].vol_id, track_header->vol_id,32); toc[i].vol_id[32]=0;
20.216 + strncpy(toc[i].t_stamp, track_header->t_stamp,12); toc[i].t_stamp[12]=0;
20.217 + toc[i].disk_set = track_header->disk_set;
20.218 + toc[i].flags = track_header->flags;
20.219 + }
20.220 + }
20.221 + }
20.222 + }
20.223 +
20.224 + return tracks;
20.225 +}
20.226 +
20.227 +/****************************************************************************/
20.228 +
20.229 +const char *VdevName(void)
20.230 +{
20.231 + static char buff[80];
20.232 + if(virtual) snprintf(buff,sizeof(buff),"image %s",virt_name);
20.233 + else snprintf(buff,sizeof(buff),"device %s",cd_dev);
20.234 + return buff;
20.235 +}
20.236 +
20.237 +/****************************************************************************/
20.238 +
20.239 +void VprintSpace(void)
20.240 +{
20.241 + if(verbose) {
20.242 + char flex1[16], flex2[16], flex3[16];
20.243 + fprintf(stderr,
20.244 + "Disk size: %s (%7ld blocks)\n"
20.245 + "Space used: %s (%7lld blocks)\n"
20.246 + "Space avail:%s (%7lld blocks)\n",
20.247 + FlexSize(flex1,(long long)cd_len*CD_FRAMESIZE),cd_len,
20.248 + FlexSize(flex2,cd_used), cd_used/CD_FRAMESIZE,
20.249 + FlexSize(flex3,cd_avail), cd_avail/CD_FRAMESIZE);
20.250 + }
20.251 +}
20.252 +
20.253 +/****************************************************************************/
20.254 +
20.255 +long long Vseek(int trackNum)
20.256 +{
20.257 + long long pos=0;
20.258 + if(trackNum>=0) pos=(long long)toc[trackNum].sec_start*CD_FRAMESIZE;
20.259 + DEBUG("Vseek: seeking to index %d, track %d, offset %lld (%s)\n",
20.260 + trackNum,toc[trackNum].track_no,pos,virtual ? "virtual":"real");
20.261 + if(lseek64(fd,pos,SEEK_SET)<0) error("Seek failed");
20.262 + return pos;
20.263 +}
20.264 +
20.265 +/****************************************************************************/
20.266 +
20.267 +void Vread(void *buf)
20.268 +{
20.269 + if(full_read(fd,buf,CD_FRAMESIZE)!=CD_FRAMESIZE)
20.270 + serror("Unexpected EOF reading data");
20.271 +}
20.272 +
20.273 +/****************************************************************************/
20.274 +
20.275 +static unsigned long r_ahead, r_fahead;
20.276 +
20.277 +void VgetAhead(void)
20.278 +{
20.279 + if(!virtual) get_param(fd,&r_ahead,&r_fahead);
20.280 +}
20.281 +
20.282 +/****************************************************************************/
20.283 +
20.284 +void VsetAhead(int restore)
20.285 +{
20.286 + if(!virtual) {
20.287 + if(restore) set_param(fd,r_ahead,r_fahead);
20.288 + else set_param(fd,0,0);
20.289 + }
20.290 +}
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
21.2 +++ b/virtual.h Sat Dec 29 15:25:21 2007 +0100
21.3 @@ -0,0 +1,78 @@
21.4 +/* virtual.h
21.5 +Copyright (c) 2000-2004 Craig Condit, Stefan Hülswitt.
21.6 +
21.7 +Redistribution and use in source and binary forms, with or without
21.8 +modification, are permitted provided that the following conditions are met:
21.9 +
21.10 +1. Redistributions of source code must retain the above copyright notice,
21.11 + this list of conditions and the following disclaimer.
21.12 +2. Redistributions in binary form must reproduce the above copyright notice,
21.13 + this list of conditions and the following disclaimer in the documentation
21.14 + and/or other materials provided with the distribution.
21.15 +
21.16 +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
21.17 +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21.18 +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21.19 +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
21.20 +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21.21 +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21.22 +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21.23 +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21.24 +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21.25 +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
21.26 +SUCH DAMAGE.
21.27 +*/
21.28 +
21.29 +#ifndef _CDBACKUP_VIRTUAL_H
21.30 +#define _CDBACKUP_VIRTUAL_H
21.31 +
21.32 +#define VIRT_VERSION 1
21.33 +#define VIRT_MAGIC 0x144391C83A78412FLL
21.34 +#define MAX_VIRT_TRACKS 96
21.35 +#define VIRT_HEADER_LEN CD_FRAMESIZE
21.36 +
21.37 +struct virt_header {
21.38 + long long magic;
21.39 + int version;
21.40 + int tracks;
21.41 + int leadout;
21.42 + int count, has_cont;
21.43 + int reserved[25];
21.44 + int start[MAX_VIRT_TRACKS];
21.45 + };
21.46 +
21.47 +struct toc_entry {
21.48 + u_char track_no; /* track number */
21.49 + char is_data; /* 1 = data track */
21.50 + char is_cdbackup; /* was it created by CD-Backup? */
21.51 + int sec_start; /* start sector */
21.52 + int sec_end; /* last sector */
21.53 + char id_str[33]; /* recorder id string (32 chars) */
21.54 + char vol_id[33]; /* volume label (32 characters) */
21.55 + char t_stamp[13]; /* time stamp: yyyymmddhhmm */
21.56 + char disk_set; /* disk number */
21.57 + char flags; /* backup flags */
21.58 + };
21.59 +
21.60 +extern struct toc_entry *toc;
21.61 +extern long long cd_used, cd_avail;
21.62 +
21.63 +void Vopen(int ro);
21.64 +void Vclose(void);
21.65 +int VisRegular(void);
21.66 +int VreadToc(int trackInfos);
21.67 +void VprintSpace(void);
21.68 +const char *VdevName(void);
21.69 +long long Vseek(int trackNum);
21.70 +void Vread(void *buf);
21.71 +void VnewTrack(void);
21.72 +void VcloseTrack(int cont);
21.73 +void Vwrite(const void *buf);
21.74 +void VgetAhead(void);
21.75 +void VsetAhead(int restore);
21.76 +int Vsize(void);
21.77 +int VhasCont(void);
21.78 +void VprepareDump(void);
21.79 +void VvirtRead(void *buf);
21.80 +
21.81 +#endif