cdbackup.c
branchtrunk
changeset 4 79da91042fcc
parent 2 6bcb44b9edb1
child 6 6262df5a6216
     1.1 --- a/cdbackup.c	Sat Dec 29 15:23:55 2007 +0100
     1.2 +++ b/cdbackup.c	Sat Dec 29 15:25:21 2007 +0100
     1.3 @@ -1,5 +1,5 @@
     1.4  /* cdbackup.c
     1.5 -Copyright (c) 2000-2002 Craig Condit, Stefan Hülswitt.
     1.6 +Copyright (c) 2000-2004 Craig Condit, Stefan Hülswitt.
     1.7  
     1.8  Redistribution and use in source and binary forms, with or without
     1.9  modification, are permitted provided that the following conditions are met: 
    1.10 @@ -24,69 +24,135 @@
    1.11  */
    1.12  
    1.13  #define _LARGEFILE64_SOURCE
    1.14 +#define _GNU_SOURCE
    1.15  
    1.16  #include <stdlib.h>
    1.17  #include <stdio.h>
    1.18 +#include <stdarg.h>
    1.19  #include <unistd.h>
    1.20  #include <fcntl.h>
    1.21  #include <string.h>
    1.22  #include <time.h>
    1.23  #include <errno.h>
    1.24 -#include <getopt.h>
    1.25  #include <sys/wait.h>
    1.26  #include <sys/ioctl.h>
    1.27  #include <netinet/in.h>
    1.28 -#include <linux/cdrom.h>
    1.29 +
    1.30 +#ifndef sun
    1.31 +#include <getopt.h>
    1.32 +#endif
    1.33  
    1.34  #include "cdbackup.h"
    1.35  #include "cdrom.h"
    1.36 +#include "virtual.h"
    1.37  #include "misc.h"
    1.38  #include "debug.h"
    1.39  #include "version.h"
    1.40  
    1.41 -/* #define DEBUGOUT */
    1.42 -
    1.43  /* defaults */
    1.44 -char * prg_name ="cdbackup";
    1.45 -char * cd_dev   ="/dev/burner";
    1.46 -char * cdr_dev  =0;			/* no default here, too dangerous */
    1.47 -char * cd_label ="CDBackup Track";
    1.48 -int    cd_speed =4;
    1.49 -long   cd_len   =333000;		/* blocks */
    1.50 -int    padsize  =15;			/* blocks */
    1.51 -int    multidisk=0;
    1.52 -char * multicmd =0;
    1.53 -int    verbose  =0;
    1.54 -int    xamode2  =0;
    1.55 -int    debug    =0;
    1.56 +char *prg_name ="cdbackup";
    1.57 +char *cd_dev   ="/dev/burner";
    1.58 +char *cdr_dev  =0;                     /* no default here, too dangerous */
    1.59 +char *cd_label ="CDBackup Track";
    1.60 +int   cd_speed =4;
    1.61 +long  cd_len   =-1;                    /* blocks */
    1.62 +int   padsize  =15;                    /* blocks */
    1.63 +int   multidisk=0;
    1.64 +char *multicmd =0;
    1.65 +int   verbose  =0;
    1.66 +int   xamode2  =0;
    1.67 +int   crc      =1;
    1.68 +int   debug    =0;
    1.69 +int   virtual  =0;
    1.70 +char *virt_name=0;
    1.71 +int   virt_dump=0;
    1.72 +int   dvd      =0;
    1.73  
    1.74  char **cdrec_opt=0;
    1.75  int    cdrec_opt_count=0;
    1.76  
    1.77 -long long totalSize;
    1.78 +long long totalSize=0;
    1.79 +int disknum=1;
    1.80 +int secs;
    1.81  struct tm curtime;  /* global, so multi-disks get all the same time */
    1.82 -
    1.83 -/****************************************************************************/
    1.84 -
    1.85 -void usage()
    1.86 -{
    1.87 -  fprintf(stderr,
    1.88 -    "Usage: %s [options ...] [-- cdrecord-options ...]\n"
    1.89 -    "Reads from standard input, block formats and writes to CD-R(W).\n\n"
    1.90 -    "  -d DEVICE      DEVICE for CD queries (default /dev/burner)\n"
    1.91 -    "  -l N           CD-R has a size of N MB (default 650)\n"
    1.92 -    "  -r DEVICE      DEVICE for CD recording (e.g. 0,4,0)\n"
    1.93 -    "  -s N           record CD at speed N (default 4)\n"
    1.94 -    "  -X             enable CDROM XA2 mode in cdrecord\n"
    1.95 -    "  -a LABEL       use LABEL as CD session title\n"
    1.96 -    "  -p N           use a padsize of N sectors for the session (default 15)\n"
    1.97 -    "  -m             enable multi-disk mode\n"
    1.98 -    "  -c COMMAND     call COMMAND on disk change in multi-disk mode\n"
    1.99 -    "  -v             be verbose\n"
   1.100 -    "  -D             enable DEBUG output\n"
   1.101 -    "  -V             prints version & exits\n"
   1.102 -    "  --             pass rest of commandline to cdrecord\n"
   1.103 -    "\n", prg_name);
   1.104 +int auto_size=0;
   1.105 +
   1.106 +/****************************************************************************/
   1.107 +
   1.108 +char *make_arg(const char *format, ...)
   1.109 +{
   1.110 +  char *ptr;
   1.111 +  va_list ap;
   1.112 +  va_start(ap,format);
   1.113 +  if(vasprintf(&ptr,format,ap)<0) serror("No memory for cdrecord args\n");
   1.114 +  va_end(ap);
   1.115 +  return ptr;
   1.116 +}
   1.117 +
   1.118 +void start_cdrecord(void)
   1.119 +{
   1.120 +  char **args, **p, *exname;
   1.121 +  int l;
   1.122 +  
   1.123 +  if(!(p=args=calloc(cdrec_opt_count+10,sizeof(char *))))
   1.124 +    serror("No memory for cdrecord args\n");
   1.125 +
   1.126 +  if(dvd) exname="dvdrecord"; else exname="cdrecord";
   1.127 +  *p++=exname;
   1.128 +
   1.129 +  if(virt_dump || dvd) {
   1.130 +    *p++="-dao";
   1.131 +    *p++=make_arg("tsize=%ds",secs);
   1.132 +    }
   1.133 +  else {
   1.134 +    *p++="-multi";
   1.135 +    *p++=make_arg("padsize=%ds",padsize);
   1.136 +    }
   1.137 +
   1.138 +  *p++=make_arg("speed=%d",cd_speed);
   1.139 +  *p++=make_arg("dev=%s",cdr_dev);
   1.140 +
   1.141 +  for(l=0 ; l<cdrec_opt_count ; l++) *p++=cdrec_opt[l];
   1.142 +
   1.143 +  if(xamode2 && !dvd) *p++="-xa2"; else *p++="-data";
   1.144 +  *p++="-";
   1.145 +  *p++=0;
   1.146 +
   1.147 +  if(debug) {
   1.148 +    fprintf(stderr,"%s: cdrecord command:",prg_name);
   1.149 +    for(p=args ; *p ; p++) fprintf(stderr," %s",*p);
   1.150 +    fprintf(stderr,"\n");
   1.151 +    }
   1.152 +
   1.153 +  execvp(exname,args);
   1.154 +  error("Exec failed (cdrecord)");
   1.155 +}
   1.156 +
   1.157 +long atip_cdrecord(void)
   1.158 +{
   1.159 +  char *cmd;
   1.160 +  FILE *p;
   1.161 +  long size=-1;
   1.162 +  
   1.163 +  asprintf(&cmd,"%srecord 2>&1 dev=%s -atip",dvd ? "dvd":"cd",cdr_dev);
   1.164 +  DEBUG("%s: cdrecord atip command: %s\n",prg_name,cmd);
   1.165 +
   1.166 +  p=popen(cmd,"r");
   1.167 +  if(!p) fprintf(stderr,"%s: atip command failed\n",prg_name);
   1.168 +  else {
   1.169 +    char buff[256];
   1.170 +    while(fgets(buff,sizeof(buff),p)) {
   1.171 +      if(dvd && !strncmp(buff,"rzone size:",11)) size=strtol(&buff[12],NULL,10);
   1.172 +      else if(!strncmp(buff,"  ATIP start of lead out:",25)) size=strtol(&buff[26],NULL,10);
   1.173 +      }
   1.174 +    }
   1.175 +  pclose(p);
   1.176 +  free(cmd);
   1.177 +  if(size>0 && verbose) {
   1.178 +    char buff[16];
   1.179 +    fprintf(stderr,"%s: auto-detected media size %s (%ld blocks)\n",prg_name,FlexSize(buff,(long long)size*CD_FRAMESIZE),size);
   1.180 +    }
   1.181 +  return size;
   1.182  }
   1.183  
   1.184  /****************************************************************************/
   1.185 @@ -94,11 +160,24 @@
   1.186  void parse_cmdline(char argc, char *argv[]) 
   1.187  {
   1.188    int i;
   1.189 -
   1.190 -  while ((i=getopt(argc,argv,"d:r:l:s:p:a:c:mvVXD"))>0) {
   1.191 +  char *val;
   1.192 +
   1.193 +  /* get some default from the environment */
   1.194 +  val=getenv("CDR_DEVICE");
   1.195 +  if(val) {
   1.196 +    cdr_dev=strdup(val);
   1.197 +    DEBUG("cdbackup: using recording device %s from CDR_DEVICE\n",cdr_dev);
   1.198 +    }
   1.199 +  val=getenv("CDR_SPEED");
   1.200 +  if(val) {
   1.201 +    cd_speed=strtol(val,NULL,10);
   1.202 +    DEBUG("cdbackup: using speed %d from CDR_SPEED\n",cd_speed);
   1.203 +    }
   1.204 +  
   1.205 +  while ((i=getopt(argc,argv,"d:r:l:s:p:a:c:mvVXDCi:wR"))>0) {
   1.206      switch (i) {
   1.207         case 'V': fprintf(stderr,"cdbackup "VERSION" (compiled "__DATE__")\n"
   1.208 -	                        "Copyright (C) 2000-2002\n"
   1.209 +	                        "Copyright (C) 2000-2004\n"
   1.210  			        "This is free software; see the source for copying conditions.\n"
   1.211  			        "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n"
   1.212  			        "PARTICULAR PURPOSE.\n");
   1.213 @@ -110,20 +189,45 @@
   1.214         case 'd': cd_dev=optarg; break;
   1.215         case 'r': cdr_dev=optarg; break;
   1.216         case 'a': cd_label=optarg; break;
   1.217 +       case 'C': crc=0; break;
   1.218 +       case 'i': virt_name=optarg; virtual=1; break;
   1.219 +       case 'w': virt_dump=1; break;
   1.220 +       case 'R': dvd=1;
   1.221 +                 DEBUG("cdbackup: DVD mode enabled\n");
   1.222 +                 break;
   1.223         case 'D': verbose=1; debug=1; 
   1.224                   DEBUG("cdbackup: DEBUG output enabled ("VERSION")\n");
   1.225                   break;
   1.226 -       case 'l': errno=0; cd_len=strtol(optarg,NULL,10);
   1.227 -                 if(errno==ERANGE || cd_len<1) serror("Option -l: length out of range (must be >=1)\n");
   1.228 -	         cd_len = (long long)cd_len * (1024*1024) / CD_FRAMESIZE; /* convert to blocks */
   1.229 -	         break;
   1.230 +       case 'l': cd_len=(long)(FlexLen(optarg)/CD_FRAMESIZE);
   1.231 +                 break;
   1.232         case 's': errno=0; cd_speed=strtol(optarg,NULL,10);
   1.233                   if(errno==ERANGE || cd_speed<1) serror("Option -s: speed out of range (must be >=1)\n");
   1.234  	         break;
   1.235         case 'p': errno=0; padsize=strtol(optarg,NULL,10);
   1.236                   if(errno==ERANGE || padsize<15) serror("Option -p: padsize out of range (must be >=15)\n");
   1.237  	         break;
   1.238 -       default:  usage(); exit(0);
   1.239 +       default:  fprintf(stderr,
   1.240 +                         "Usage: %s [options ...] [-- cdrecord-options ...]\n"
   1.241 +                         "Reads from standard input, block formats and writes to CD-R(W).\n\n"
   1.242 +                         "  -d DEVICE      DEVICE for CD queries (default /dev/burner)\n"
   1.243 +                         "  -l N           set media size, disable auto-detect\n"
   1.244 +                         "  -r DEVICE      DEVICE for CD recording (e.g. 0,4,0)\n"
   1.245 +                         "  -s N           record CD at speed N (default 4)\n"
   1.246 +                         "  -X             enable CDROM XA2 mode in cdrecord\n"
   1.247 +                         "  -a LABEL       use LABEL as CD session title\n"
   1.248 +                         "  -p N           use a padsize of N sectors for the session (default 15)\n"
   1.249 +                         "  -m             enable multi-disk mode\n"
   1.250 +                         "  -c COMMAND     call COMMAND on disk change in multi-disk mode\n"
   1.251 +                         "  -C             disable checksum creation for datablocks\n"
   1.252 +                         "  -i IMAGE       use virtual image IMAGE for recording\n"
   1.253 +                         "  -w             dump virtual image to media\n"
   1.254 +                         "  -R             enables DVD mode\n"
   1.255 +                         "  -v             be verbose\n"
   1.256 +                         "  -D             enable DEBUG output\n"
   1.257 +                         "  -V             prints version & exits\n"
   1.258 +                         "  --             pass rest of commandline to cdrecord\n"
   1.259 +                         "\n", prg_name);
   1.260 +                 exit(0);
   1.261         }
   1.262      }
   1.263  
   1.264 @@ -132,173 +236,215 @@
   1.265      cdrec_opt=&argv[optind];
   1.266      }
   1.267      
   1.268 -  if(!cdr_dev) serror("You must specify a device for cdrecord with -r\n");
   1.269 -}
   1.270 -
   1.271 -/****************************************************************************/
   1.272 -
   1.273 -#define MARG(ptr,len,form,arg) { int l=(len);\
   1.274 -                               if(!(*ptr=(char *)malloc(l+1))) serror("No memory for cdrecord args\n");\
   1.275 -                               snprintf(*ptr++,l,form,arg);\
   1.276 -                             }
   1.277 -
   1.278 -void start_cdrecord() 
   1.279 -{
   1.280 -  char **args, **p;
   1.281 -  int l;
   1.282 -  
   1.283 -  if(!(p=args=calloc(cdrec_opt_count+8,sizeof(char *))))
   1.284 -    serror("No memory for cdrecord args\n");
   1.285 -
   1.286 -  *p++="cdrecord";
   1.287 -  *p++="-multi";
   1.288 -  MARG(p,16,"speed=%d",cd_speed);
   1.289 -  MARG(p,6+strlen(cdr_dev),"dev=%s",cdr_dev);
   1.290 -
   1.291 -  for(l=0 ; l<cdrec_opt_count ; l++) *p++=cdrec_opt[l];
   1.292 -
   1.293 -  MARG(p,20,"padsize=%ds",padsize);
   1.294 -  if(xamode2) *p++="-xa2"; else *p++="-data";
   1.295 -  *p++="-";
   1.296 -  *p++=0;
   1.297 -
   1.298 -  if(debug) {
   1.299 -    fprintf(stderr,"%s: cdrecord command:",prg_name);
   1.300 -    for(p=args ; *p ; p++) fprintf(stderr," %s",*p);
   1.301 -    fprintf(stderr,"\n");
   1.302 -    }
   1.303 -
   1.304 -  execvp("cdrecord",args);
   1.305 -  error("Unable to launch cdrecord");
   1.306 -}
   1.307 -
   1.308 -/****************************************************************************/
   1.309 -
   1.310 -int backup(char disk_set)
   1.311 -{
   1.312 -  pid_t childpid;
   1.313 -  int fd[2];
   1.314 -  int outpipe, bytes;
   1.315 +  if(cd_len<0) {
   1.316 +    auto_size=1;
   1.317 +    if(virtual && !virt_dump) serror("Can't auto-detect media size in virtual mode. Use option -l to set media size\n");
   1.318 +    }
   1.319 +  if(virtual && dvd && !virt_dump) {
   1.320 +     fprintf(stderr,"Option -R ignored in virtual mode\n");
   1.321 +     dvd=0;
   1.322 +     }
   1.323 +  if(dvd) {
   1.324 +    if(xamode2) fprintf(stderr,"Option -X ignored in DVD mode\n");
   1.325 +    padsize=0;
   1.326 +    }
   1.327 +  if(virt_dump && !virtual) serror("To dump an image you must supply the image name with -i\n");
   1.328 +  if(!cdr_dev && (!virtual || virt_dump)) serror("You must specify a device for cdrecord with -r\n");
   1.329 +}
   1.330 +
   1.331 +/****************************************************************************/
   1.332 +
   1.333 +void autosize(void)
   1.334 +{
   1.335 +  if(auto_size) {
   1.336 +    cd_len=atip_cdrecord();
   1.337 +    if(cd_len<0) serror("Media size detection failed. Use option -l to set media size\n");
   1.338 +    }
   1.339 +}
   1.340 +
   1.341 +/****************************************************************************/
   1.342 +
   1.343 +void dump(void)
   1.344 +{
   1.345 +  int n, cont;
   1.346 +  char buffer[CD_FRAMESIZE];
   1.347 +  long long grandTotal;
   1.348 +
   1.349 +  do {
   1.350 +    int change;
   1.351 +    do {
   1.352 +      autosize();
   1.353 +      virtual=1;
   1.354 +      Vopen(1); n=VreadToc(0);
   1.355 +      if(n<1) serror("It's not usefull to dump an empty image");
   1.356 +      secs=Vsize(); cont=VhasCont();
   1.357 +      if(cd_avail<secs*CD_FRAMESIZE) serror("Image doesn't fits to media");
   1.358 +      Vseek(-1); VprepareDump();
   1.359 +
   1.360 +      virtual=0; change=0;
   1.361 +      Vopen(0); n=VreadToc(0); VprintSpace();
   1.362 +      if(n!=0) {
   1.363 +        fprintf(stderr,"Can't dump to non-empty disk! Try another disk\n");
   1.364 +        change=1;
   1.365 +        }
   1.366 +
   1.367 +      if(change) {
   1.368 +        Vclose();
   1.369 +        diskchange(multicmd,cd_dev);
   1.370 +        }
   1.371 +      } while(change);
   1.372 +
   1.373 +    if(verbose)
   1.374 +      fprintf(stderr,"%s: Dumping image (%d blocks) to %s\n",prg_name,secs,VdevName());
   1.375 +    VnewTrack();
   1.376 +
   1.377 +    grandTotal=0;
   1.378 +    while(secs>0) {
   1.379 +      VvirtRead(buffer);
   1.380 +      Vwrite(buffer); grandTotal+=CD_FRAMESIZE;
   1.381 +      secs--;
   1.382 +      }
   1.383 +
   1.384 +    VcloseTrack(0);
   1.385 +
   1.386 +    totalSize+=grandTotal;
   1.387 +    if(verbose) {
   1.388 +      char str1[16], str2[16];
   1.389 +      fprintf(stderr,"%s: Dumping finished. %s written (%s on this disk)\n",
   1.390 +              prg_name,FlexSize(str1,totalSize),FlexSize(str2,grandTotal));
   1.391 +      }
   1.392 +
   1.393 +    if(multidisk==0) {
   1.394 +      if(cont) fprintf(stderr,"Multi-disk not enabled, ignoring continuation image(s)!\n");
   1.395 +      cont=0;
   1.396 +      }
   1.397 +    else {
   1.398 +      disknum++;
   1.399 +      diskchange(multicmd,cd_dev);
   1.400 +      }
   1.401 +    } while(cont);
   1.402 +}
   1.403 +
   1.404 +/****************************************************************************/
   1.405 +
   1.406 +int backup(void)
   1.407 +{
   1.408    long long grandTotal=0;
   1.409    struct header_block header;
   1.410 +  int flags, datasize, result=0;
   1.411  
   1.412    char buffer[CD_FRAMESIZE];
   1.413    struct data_block *db=(struct data_block *)&buffer[0];
   1.414  
   1.415 -  sprintf(buffer, "%04d%02d%02d%02d%02d", curtime.tm_year + 1900,
   1.416 -    curtime.tm_mon + 1, curtime.tm_mday, curtime.tm_hour, curtime.tm_min);
   1.417 +  flags=F_NONE;
   1.418 +  datasize=DATASIZE;
   1.419 +  if(crc) { flags|=F_CRC; datasize-=4; }
   1.420 +
   1.421 +  sprintf(buffer,"%04d%02d%02d%02d%02d",curtime.tm_year+1900,
   1.422 +    curtime.tm_mon+1,curtime.tm_mday,curtime.tm_hour,curtime.tm_min);
   1.423    
   1.424 -  strncpy(header.id_str,HDR_STRING,32); header.id_str[32] = 0;
   1.425 -  strncpy(header.vol_id,cd_label,32); header.vol_id[32] = 0;
   1.426 -  strncpy(header.t_stamp,buffer,12); header.t_stamp[12] = 0;
   1.427 -  header.disk_set = disk_set;
   1.428 +  strncpy(header.id_str,HDR_STRING,32); header.id_str[32]=0;
   1.429 +  strncpy(header.vol_id,cd_label,32); header.vol_id[32]=0;
   1.430 +  strncpy(header.t_stamp,buffer,12); header.t_stamp[12]=0;
   1.431 +  header.disk_set = disknum;
   1.432 +  header.flags = flags;
   1.433  
   1.434    if(verbose)
   1.435 -    fprintf(stderr,"%s: Recording to device %s, multidisk %s, disk %d\n",prg_name,cdr_dev,multidisk?"enabled":"disabled",disk_set); 
   1.436 -
   1.437 -#ifndef DEBUGOUT /* the "real" code */
   1.438 -  /* launch cdrecord */
   1.439 -  if(pipe(fd) == -1) error("Unable to create pipe handles");
   1.440 -  if((childpid=fork()) == -1) error("Fork failed");
   1.441 -  if(childpid == 0) {        /* child */
   1.442 -    close(fd[1]);
   1.443 -    close(0);		     /* stdin */
   1.444 -    dup2(fd[0], 0);
   1.445 -    start_cdrecord();        /* doesn't return */
   1.446 -    }
   1.447 -
   1.448 -  close(fd[0]); outpipe=fd[1];
   1.449 -  
   1.450 -  /* output the header block */
   1.451 +    fprintf(stderr,"%s: Recording to %s, multidisk %s, CRC %s, disk %d\n",
   1.452 +            prg_name,VdevName(),
   1.453 +            multidisk?"enabled":"disabled",
   1.454 +            crc?"enabled":"disabled",
   1.455 +            disknum); 
   1.456 +  secs=cd_len;
   1.457 +  VnewTrack();
   1.458 +
   1.459    memset(buffer,0,CD_FRAMESIZE);
   1.460    memcpy(buffer,&header,sizeof(struct header_block));
   1.461 -  if((bytes=write(outpipe, buffer, CD_FRAMESIZE)) != CD_FRAMESIZE) error("Error writing header block");
   1.462 -
   1.463 -  cd_avail-=bytes; grandTotal+=bytes;
   1.464 -  /* account for the padsize */
   1.465 -  cd_avail-=padsize*CD_FRAMESIZE;
   1.466 -#else
   1.467 -  /* debug code; send data to /dev/null.  Don't need the pipe. */
   1.468 -  fprintf(stderr, "DEBUG CODE: sending data to /dev/null!\n");
   1.469 -  outpipe = open("/dev/null", O_WRONLY);
   1.470 -  if (outpipe < 0) { perror("/dev/null"); exit(1); }
   1.471 -#endif
   1.472 -
   1.473 -  db->reserved = 0;
   1.474 +  Vwrite(buffer); grandTotal+=CD_FRAMESIZE;
   1.475  
   1.476    do {
   1.477 -    /* read a block */
   1.478 -    db->status = 0;		         /* this isn't the last block (for now) */
   1.479 -    bytes=full_read(0,&buffer[DBSIZE],DATASIZE);
   1.480 -    if (bytes < 0) error("Error reading input");
   1.481 -    if (bytes != DATASIZE) db->status=1; /* EOF, this is the last block */
   1.482 -    db->datasize = htons(bytes);
   1.483 -
   1.484 -    /* check for free space */
   1.485 -    if(cd_avail < (CD_FRAMESIZE*2)) {	/* less than 2 block free */
   1.486 -      if(db->status==0) db->status=2;   /* if not last block, mark disk as full */
   1.487 -      }
   1.488 -
   1.489 -    /* write a block */
   1.490 -    bytes = write(outpipe, buffer, CD_FRAMESIZE);
   1.491 -    if(bytes != CD_FRAMESIZE) error("Error writing data block");
   1.492 -
   1.493 -    grandTotal+=bytes; cd_avail-=bytes;
   1.494 +    int bytes;
   1.495 +
   1.496 +    db->flags=flags;
   1.497 +    db->status=0;		      /* this isn't the last block (for now) */
   1.498 +    bytes=full_read(0,&buffer[DBSIZE],datasize);
   1.499 +    if(bytes!=datasize) db->status=1; /* EOF, this is the last block */
   1.500 +    db->datasize=htons(bytes);
   1.501 +
   1.502 +    if(cd_avail<(CD_FRAMESIZE*2)) {   /* less than 2 block free */
   1.503 +      if(db->status==0) {             /* if not last block, mark disk as full */
   1.504 +        db->status=2;
   1.505 +        result=1;
   1.506 +        }
   1.507 +      }
   1.508 +    if(crc) {
   1.509 +      int l=crc32(buffer,bytes+DBSIZE);
   1.510 +      *((unsigned long *)(&buffer[CD_FRAMESIZE-4]))=l;
   1.511 +      }
   1.512 +    Vwrite(buffer); grandTotal+=CD_FRAMESIZE;
   1.513      } while(db->status==0);
   1.514  
   1.515 -  /* close pipe and wait for child termination */
   1.516 -  close(outpipe);
   1.517 -  while (wait(0) != childpid);
   1.518 +  if(dvd && cd_avail>=CD_FRAMESIZE) { /* pad up the track with zeros */
   1.519 +    memset(buffer,0,CD_FRAMESIZE);
   1.520 +    if(verbose) fprintf(stderr,"%s: padding up the track\n",prg_name);
   1.521 +    while(cd_avail>=CD_FRAMESIZE) Vwrite(buffer);
   1.522 +    }
   1.523 +
   1.524 +  VcloseTrack(result);
   1.525  
   1.526    totalSize+=grandTotal;
   1.527 -  if(verbose) fprintf(stderr,"%s: Recording finished. %lld kB written (%lld kB on this disk)\n",
   1.528 -                      prg_name,totalSize/1024,grandTotal/1024);
   1.529 -
   1.530 -  if(db->status==2) return 1; /* disk was full */
   1.531 +  if(verbose) {
   1.532 +    char str1[16], str2[16];
   1.533 +    fprintf(stderr,"%s: Recording finished. %s written (%s on this disk)\n",
   1.534 +            prg_name,FlexSize(str1,totalSize),FlexSize(str2,grandTotal));
   1.535 +    }
   1.536 +  return result;
   1.537 +}
   1.538 +
   1.539 +/****************************************************************************/
   1.540 +
   1.541 +int main(int argc, char *argv[]) 
   1.542 +{
   1.543 +  int result, loop;
   1.544 +  time_t curtime_t;
   1.545 +
   1.546 +  curtime_t=time(0); curtime=*localtime(&curtime_t);
   1.547 +  parse_cmdline(argc,argv);
   1.548 +
   1.549 +  if(virt_dump) {
   1.550 +    dump();
   1.551 +    }
   1.552 +  else {
   1.553 +    do {
   1.554 +      do {
   1.555 +        autosize();
   1.556 +        Vopen(0); result=VreadToc(0); VprintSpace();
   1.557 +        loop=1;
   1.558 +
   1.559 +        if(disknum>1 && result!=0) {
   1.560 +          Vclose();
   1.561 +          fprintf(stderr,"%s: Can't do multidisk continuation on non-empty disk! Try another disk\n", prg_name);
   1.562 +          diskchange(multicmd,cd_dev);
   1.563 +          }
   1.564 +        else if(cd_avail<(padsize+MIN_BLOCKS)*CD_FRAMESIZE) {
   1.565 +          Vclose();
   1.566 +          if(multidisk) {
   1.567 +            fprintf(stderr,"%s: Not enough free space on disk! Try another disk\n", prg_name);
   1.568 +            diskchange(multicmd,cd_dev);
   1.569 +            }
   1.570 +          else serror("Not enough free space on disk");
   1.571 +          }
   1.572 +        else loop=0;
   1.573 +        } while(loop);
   1.574 +
   1.575 +      result=backup();
   1.576 +      if(result==1) {
   1.577 +        if(multidisk==0) serror("Disk full, multi-disk not enabled. Aborting");
   1.578 +
   1.579 +        disknum++;
   1.580 +        if(!VisRegular()) diskchange(multicmd,cd_dev);
   1.581 +        }
   1.582 +      } while(result!=0);
   1.583 +    }
   1.584    return 0;
   1.585  }
   1.586 -
   1.587 -/****************************************************************************/
   1.588 -
   1.589 -int main(int argc, char *argv[]) 
   1.590 -{
   1.591 -  int cdr;
   1.592 -  int disknum, result, loop;
   1.593 -  time_t curtime_t;
   1.594 -
   1.595 -  disknum=1; totalSize=0;
   1.596 -  curtime_t=time(0); curtime=*localtime(&curtime_t);
   1.597 -
   1.598 -  parse_cmdline(argc,argv);
   1.599 -
   1.600 -  do {
   1.601 -    do {
   1.602 -      cdr=open_cdr(cd_dev); result=read_toc(cdr,0); close_cdr(cdr);
   1.603 -      print_space();
   1.604 -      loop=1;
   1.605 -  
   1.606 -      if(disknum>1 && result!=0) {
   1.607 -        fprintf(stderr,"%s: Can't do multidisk continuation on non-empty disk! Try another disk\n", prg_name);
   1.608 -        if(start_diskchange(multicmd,cd_dev)) serror("Diskchange command failed");
   1.609 -        }
   1.610 -      else if(cd_avail<(padsize+MIN_BLOCKS)*CD_FRAMESIZE) {
   1.611 -        if(multidisk) {
   1.612 -          fprintf(stderr,"%s: Not enough free space on disk! Try another disk\n", prg_name);
   1.613 -          if(start_diskchange(multicmd,cd_dev)) serror("Diskchange command failed");
   1.614 -          }
   1.615 -        else serror("Not enough free space on disk");
   1.616 -        }
   1.617 -      else loop=0;
   1.618 -      } while(loop);
   1.619 -
   1.620 -    result = backup(disknum);
   1.621 -    if(result == 1) {
   1.622 -      if(multidisk == 0) serror("Disk full, multi-disk not enabled. Aborting");
   1.623 -      
   1.624 -      disknum++;
   1.625 -      if(start_diskchange(multicmd,cd_dev)) serror("Diskchange command failed");
   1.626 -      }
   1.627 -    } while (result != 0);
   1.628 -
   1.629 -  return 0;
   1.630 -}