cdbackup.c
author nathan
Sun, 22 Dec 2013 11:59:05 +0100
branchtrunk
changeset 18 b00641305fed
parent 17 4879fdaac574
permissions -rw-r--r--
rework layerbreak workaround
nathan@0
     1
/* cdbackup.c
nathan@18
     2
Copyright (c) 2000-2013 Craig Condit, Stefan Huelswitt.
nathan@0
     3
nathan@0
     4
Redistribution and use in source and binary forms, with or without
nathan@0
     5
modification, are permitted provided that the following conditions are met: 
nathan@0
     6
nathan@0
     7
1. Redistributions of source code must retain the above copyright notice,
nathan@0
     8
   this list of conditions and the following disclaimer. 
nathan@0
     9
2. Redistributions in binary form must reproduce the above copyright notice,
nathan@0
    10
   this list of conditions and the following disclaimer in the documentation
nathan@0
    11
   and/or other materials provided with the distribution. 
nathan@0
    12
nathan@0
    13
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
nathan@0
    14
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
nathan@0
    15
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
nathan@0
    16
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
nathan@0
    17
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
nathan@0
    18
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
nathan@0
    19
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
nathan@0
    20
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
nathan@0
    21
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
nathan@0
    22
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
nathan@0
    23
SUCH DAMAGE.
nathan@0
    24
*/
nathan@0
    25
nathan@0
    26
#define _LARGEFILE64_SOURCE
nathan@4
    27
#define _GNU_SOURCE
nathan@0
    28
nathan@0
    29
#include <stdlib.h>
nathan@0
    30
#include <stdio.h>
nathan@4
    31
#include <stdarg.h>
nathan@0
    32
#include <unistd.h>
nathan@0
    33
#include <fcntl.h>
nathan@0
    34
#include <string.h>
nathan@0
    35
#include <time.h>
nathan@0
    36
#include <errno.h>
nathan@0
    37
#include <sys/wait.h>
nathan@0
    38
#include <sys/ioctl.h>
nathan@0
    39
#include <netinet/in.h>
nathan@4
    40
nathan@4
    41
#ifndef sun
nathan@4
    42
#include <getopt.h>
nathan@4
    43
#endif
nathan@0
    44
nathan@0
    45
#include "cdbackup.h"
nathan@0
    46
#include "cdrom.h"
nathan@4
    47
#include "virtual.h"
nathan@0
    48
#include "misc.h"
nathan@2
    49
#include "debug.h"
nathan@0
    50
#include "version.h"
nathan@0
    51
nathan@0
    52
/* defaults */
nathan@4
    53
char *prg_name ="cdbackup";
nathan@4
    54
char *cd_dev   ="/dev/burner";
nathan@4
    55
char *cdr_dev  =0;                     /* no default here, too dangerous */
nathan@4
    56
char *cd_label ="CDBackup Track";
nathan@4
    57
int   cd_speed =4;
nathan@4
    58
long  cd_len   =-1;                    /* blocks */
nathan@4
    59
int   padsize  =15;                    /* blocks */
nathan@4
    60
int   multidisk=0;
nathan@4
    61
char *multicmd =0;
nathan@4
    62
int   verbose  =0;
nathan@4
    63
int   xamode2  =0;
nathan@4
    64
int   crc      =1;
nathan@4
    65
int   debug    =0;
nathan@4
    66
int   virtual  =0;
nathan@4
    67
char *virt_name=0;
nathan@4
    68
int   virt_dump=0;
nathan@4
    69
int   dvd      =0;
nathan@12
    70
char *exename  ="cdrecord";
nathan@0
    71
nathan@0
    72
char **cdrec_opt=0;
nathan@0
    73
int    cdrec_opt_count=0;
nathan@0
    74
nathan@4
    75
long long totalSize=0;
nathan@4
    76
int disknum=1;
nathan@4
    77
int secs;
nathan@17
    78
long layerbreak=0;
nathan@0
    79
struct tm curtime;  /* global, so multi-disks get all the same time */
nathan@4
    80
int auto_size=0;
nathan@4
    81
nathan@4
    82
/****************************************************************************/
nathan@4
    83
nathan@4
    84
char *make_arg(const char *format, ...)
nathan@4
    85
{
nathan@4
    86
  char *ptr;
nathan@4
    87
  va_list ap;
nathan@4
    88
  va_start(ap,format);
nathan@10
    89
  if(vasprintf(&ptr,format,ap)<0) {
nathan@10
    90
    serror("No memory for cdrecord args\n");
nathan@10
    91
    ptr=0;
nathan@10
    92
    }
nathan@4
    93
  va_end(ap);
nathan@4
    94
  return ptr;
nathan@4
    95
}
nathan@4
    96
nathan@4
    97
void start_cdrecord(void)
nathan@4
    98
{
nathan@12
    99
  char **args, **p;
nathan@4
   100
  int l;
nathan@4
   101
  
nathan@10
   102
  if(!(p=args=calloc(cdrec_opt_count+32,sizeof(char *))))
nathan@4
   103
    serror("No memory for cdrecord args\n");
nathan@4
   104
nathan@12
   105
  *p++=exename;
nathan@4
   106
nathan@4
   107
  if(virt_dump || dvd) {
nathan@4
   108
    *p++="-dao";
nathan@4
   109
    *p++=make_arg("tsize=%ds",secs);
nathan@17
   110
    /* work around the oddidity that cdrecord refuses to burn the disk, if
nathan@17
   111
       the tracksize is less than the first layer size on dual-layer disks */
nathan@17
   112
    if(layerbreak>0 && secs<layerbreak)
nathan@18
   113
      *p++=make_arg("padsize=%lds",layerbreak-secs+1);
nathan@4
   114
    }
nathan@4
   115
  else {
nathan@4
   116
    *p++="-multi";
nathan@10
   117
    *p++="-tao";
nathan@4
   118
    *p++=make_arg("padsize=%ds",padsize);
nathan@4
   119
    }
nathan@4
   120
nathan@4
   121
  *p++=make_arg("speed=%d",cd_speed);
nathan@4
   122
  *p++=make_arg("dev=%s",cdr_dev);
nathan@4
   123
nathan@4
   124
  for(l=0 ; l<cdrec_opt_count ; l++) *p++=cdrec_opt[l];
nathan@4
   125
nathan@4
   126
  if(xamode2 && !dvd) *p++="-xa2"; else *p++="-data";
nathan@4
   127
  *p++="-";
nathan@4
   128
  *p++=0;
nathan@4
   129
nathan@4
   130
  if(debug) {
nathan@4
   131
    fprintf(stderr,"%s: cdrecord command:",prg_name);
nathan@4
   132
    for(p=args ; *p ; p++) fprintf(stderr," %s",*p);
nathan@4
   133
    fprintf(stderr,"\n");
nathan@4
   134
    }
nathan@4
   135
nathan@12
   136
  execvp(exename,args);
nathan@4
   137
  error("Exec failed (cdrecord)");
nathan@4
   138
}
nathan@4
   139
nathan@4
   140
long atip_cdrecord(void)
nathan@4
   141
{
nathan@4
   142
  char *cmd;
nathan@4
   143
  FILE *p;
nathan@4
   144
  long size=-1;
nathan@4
   145
  
nathan@13
   146
  if(asprintf(&cmd,"%s 2>&1 dev=%s -atip",exename,cdr_dev)<0) {
nathan@13
   147
    fprintf(stderr,"%s: error making atip command: %s\n",prg_name,strerror(errno));
nathan@13
   148
    return -1;
nathan@13
   149
    }
nathan@4
   150
  DEBUG("%s: cdrecord atip command: %s\n",prg_name,cmd);
nathan@4
   151
nathan@4
   152
  p=popen(cmd,"r");
nathan@4
   153
  if(!p) fprintf(stderr,"%s: atip command failed\n",prg_name);
nathan@4
   154
  else {
nathan@4
   155
    char buff[256];
nathan@4
   156
    while(fgets(buff,sizeof(buff),p)) {
nathan@6
   157
      if(dvd) {
nathan@17
   158
         /* get layerbreak position */
nathan@17
   159
         if(!strncmp(buff,"layer break at:",15)) layerbreak=strtol(&buff[15],NULL,10);
nathan@6
   160
         /* DVD-R */
nathan@6
   161
	 if(!strncmp(buff,"rzone size:",11)) size=strtol(&buff[11],NULL,10);
nathan@6
   162
	 /* DVD+R */
nathan@6
   163
	 else if(!strncmp(buff,"phys size:...",13)) size=strtol(&buff[13],NULL,10);
nathan@6
   164
	 }
nathan@6
   165
      else if(!strncmp(buff,"  ATIP start of lead out:",25)) size=strtol(&buff[25],NULL,10);
nathan@4
   166
      }
nathan@4
   167
    }
nathan@4
   168
  pclose(p);
nathan@4
   169
  free(cmd);
nathan@4
   170
  if(size>0 && verbose) {
nathan@4
   171
    char buff[16];
nathan@17
   172
    fprintf(stderr,"%s: auto-detected media size %s (%ld blocks, layerbreak at %ld)\n",prg_name,FlexSize(buff,(long long)size*CD_FRAMESIZE),size,layerbreak);
nathan@4
   173
    }
nathan@4
   174
  return size;
nathan@0
   175
}
nathan@0
   176
nathan@0
   177
/****************************************************************************/
nathan@0
   178
nathan@0
   179
void parse_cmdline(char argc, char *argv[]) 
nathan@0
   180
{
nathan@0
   181
  int i;
nathan@4
   182
  char *val;
nathan@4
   183
nathan@4
   184
  /* get some default from the environment */
nathan@4
   185
  val=getenv("CDR_DEVICE");
nathan@4
   186
  if(val) {
nathan@4
   187
    cdr_dev=strdup(val);
nathan@4
   188
    DEBUG("cdbackup: using recording device %s from CDR_DEVICE\n",cdr_dev);
nathan@4
   189
    }
nathan@4
   190
  val=getenv("CDR_SPEED");
nathan@4
   191
  if(val) {
nathan@4
   192
    cd_speed=strtol(val,NULL,10);
nathan@4
   193
    DEBUG("cdbackup: using speed %d from CDR_SPEED\n",cd_speed);
nathan@4
   194
    }
nathan@4
   195
  
nathan@12
   196
  while ((i=getopt(argc,argv,"d:r:l:s:p:a:c:mvVXDCi:wRE:"))>0) {
nathan@0
   197
    switch (i) {
nathan@0
   198
       case 'V': fprintf(stderr,"cdbackup "VERSION" (compiled "__DATE__")\n"
nathan@18
   199
	                        "Copyright (C) 2000-2013\n"
nathan@0
   200
			        "This is free software; see the source for copying conditions.\n"
nathan@0
   201
			        "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n"
nathan@0
   202
			        "PARTICULAR PURPOSE.\n");
nathan@0
   203
                 exit(0);
nathan@0
   204
       case 'v': verbose=1; break;
nathan@0
   205
       case 'm': multidisk=1; break;
nathan@0
   206
       case 'X': xamode2=1; break;
nathan@0
   207
       case 'c': multicmd=optarg; break;
nathan@0
   208
       case 'd': cd_dev=optarg; break;
nathan@0
   209
       case 'r': cdr_dev=optarg; break;
nathan@0
   210
       case 'a': cd_label=optarg; break;
nathan@4
   211
       case 'C': crc=0; break;
nathan@4
   212
       case 'i': virt_name=optarg; virtual=1; break;
nathan@4
   213
       case 'w': virt_dump=1; break;
nathan@12
   214
       case 'E': exename=optarg; break;
nathan@4
   215
       case 'R': dvd=1;
nathan@4
   216
                 DEBUG("cdbackup: DVD mode enabled\n");
nathan@4
   217
                 break;
nathan@2
   218
       case 'D': verbose=1; debug=1; 
nathan@2
   219
                 DEBUG("cdbackup: DEBUG output enabled ("VERSION")\n");
nathan@2
   220
                 break;
nathan@4
   221
       case 'l': cd_len=(long)(FlexLen(optarg)/CD_FRAMESIZE);
nathan@4
   222
                 break;
nathan@0
   223
       case 's': errno=0; cd_speed=strtol(optarg,NULL,10);
nathan@0
   224
                 if(errno==ERANGE || cd_speed<1) serror("Option -s: speed out of range (must be >=1)\n");
nathan@0
   225
	         break;
nathan@0
   226
       case 'p': errno=0; padsize=strtol(optarg,NULL,10);
nathan@0
   227
                 if(errno==ERANGE || padsize<15) serror("Option -p: padsize out of range (must be >=15)\n");
nathan@0
   228
	         break;
nathan@4
   229
       default:  fprintf(stderr,
nathan@4
   230
                         "Usage: %s [options ...] [-- cdrecord-options ...]\n"
nathan@4
   231
                         "Reads from standard input, block formats and writes to CD-R(W).\n\n"
nathan@4
   232
                         "  -d DEVICE      DEVICE for CD queries (default /dev/burner)\n"
nathan@4
   233
                         "  -l N           set media size, disable auto-detect\n"
nathan@4
   234
                         "  -r DEVICE      DEVICE for CD recording (e.g. 0,4,0)\n"
nathan@4
   235
                         "  -s N           record CD at speed N (default 4)\n"
nathan@4
   236
                         "  -X             enable CDROM XA2 mode in cdrecord\n"
nathan@4
   237
                         "  -a LABEL       use LABEL as CD session title\n"
nathan@4
   238
                         "  -p N           use a padsize of N sectors for the session (default 15)\n"
nathan@4
   239
                         "  -m             enable multi-disk mode\n"
nathan@4
   240
                         "  -c COMMAND     call COMMAND on disk change in multi-disk mode\n"
nathan@4
   241
                         "  -C             disable checksum creation for datablocks\n"
nathan@4
   242
                         "  -i IMAGE       use virtual image IMAGE for recording\n"
nathan@4
   243
                         "  -w             dump virtual image to media\n"
nathan@4
   244
                         "  -R             enables DVD mode\n"
nathan@12
   245
                         "  -E EXE         set alternative cdrecord executable\n"
nathan@4
   246
                         "  -v             be verbose\n"
nathan@4
   247
                         "  -D             enable DEBUG output\n"
nathan@4
   248
                         "  -V             prints version & exits\n"
nathan@4
   249
                         "  --             pass rest of commandline to cdrecord\n"
nathan@4
   250
                         "\n", prg_name);
nathan@4
   251
                 exit(0);
nathan@0
   252
       }
nathan@0
   253
    }
nathan@0
   254
nathan@0
   255
  if(optind<argc) { /* save position/count of cdrecord options */
nathan@0
   256
    cdrec_opt_count=argc-optind;
nathan@0
   257
    cdrec_opt=&argv[optind];
nathan@0
   258
    }
nathan@0
   259
    
nathan@4
   260
  if(cd_len<0) {
nathan@4
   261
    auto_size=1;
nathan@4
   262
    if(virtual && !virt_dump) serror("Can't auto-detect media size in virtual mode. Use option -l to set media size\n");
nathan@4
   263
    }
nathan@4
   264
  if(virtual && dvd && !virt_dump) {
nathan@4
   265
     fprintf(stderr,"Option -R ignored in virtual mode\n");
nathan@4
   266
     dvd=0;
nathan@4
   267
     }
nathan@4
   268
  if(dvd) {
nathan@4
   269
    if(xamode2) fprintf(stderr,"Option -X ignored in DVD mode\n");
nathan@4
   270
    padsize=0;
nathan@4
   271
    }
nathan@4
   272
  if(virt_dump && !virtual) serror("To dump an image you must supply the image name with -i\n");
nathan@4
   273
  if(!cdr_dev && (!virtual || virt_dump)) serror("You must specify a device for cdrecord with -r\n");
nathan@4
   274
}
nathan@4
   275
nathan@4
   276
/****************************************************************************/
nathan@4
   277
nathan@4
   278
void autosize(void)
nathan@4
   279
{
nathan@4
   280
  if(auto_size) {
nathan@4
   281
    cd_len=atip_cdrecord();
nathan@4
   282
    if(cd_len<0) serror("Media size detection failed. Use option -l to set media size\n");
nathan@4
   283
    }
nathan@4
   284
}
nathan@4
   285
nathan@4
   286
/****************************************************************************/
nathan@4
   287
nathan@4
   288
void dump(void)
nathan@4
   289
{
nathan@4
   290
  int n, cont;
nathan@4
   291
  char buffer[CD_FRAMESIZE];
nathan@4
   292
  long long grandTotal;
nathan@4
   293
nathan@4
   294
  do {
nathan@4
   295
    int change;
nathan@4
   296
    do {
nathan@4
   297
      autosize();
nathan@4
   298
      virtual=1;
nathan@4
   299
      Vopen(1); n=VreadToc(0);
nathan@4
   300
      if(n<1) serror("It's not usefull to dump an empty image");
nathan@4
   301
      secs=Vsize(); cont=VhasCont();
nathan@8
   302
      if(cd_len<secs) serror("Image doesn't fit to this media");
nathan@4
   303
      Vseek(-1); VprepareDump();
nathan@4
   304
nathan@4
   305
      virtual=0; change=0;
nathan@4
   306
      Vopen(0); n=VreadToc(0); VprintSpace();
nathan@4
   307
      if(n!=0) {
nathan@4
   308
        fprintf(stderr,"Can't dump to non-empty disk! Try another disk\n");
nathan@4
   309
        change=1;
nathan@4
   310
        }
nathan@4
   311
nathan@4
   312
      if(change) {
nathan@4
   313
        Vclose();
nathan@4
   314
        diskchange(multicmd,cd_dev);
nathan@4
   315
        }
nathan@4
   316
      } while(change);
nathan@4
   317
nathan@4
   318
    if(verbose)
nathan@4
   319
      fprintf(stderr,"%s: Dumping image (%d blocks) to %s\n",prg_name,secs,VdevName());
nathan@4
   320
    VnewTrack();
nathan@4
   321
nathan@4
   322
    grandTotal=0;
nathan@4
   323
    while(secs>0) {
nathan@4
   324
      VvirtRead(buffer);
nathan@4
   325
      Vwrite(buffer); grandTotal+=CD_FRAMESIZE;
nathan@4
   326
      secs--;
nathan@4
   327
      }
nathan@4
   328
nathan@4
   329
    VcloseTrack(0);
nathan@4
   330
nathan@4
   331
    totalSize+=grandTotal;
nathan@4
   332
    if(verbose) {
nathan@4
   333
      char str1[16], str2[16];
nathan@4
   334
      fprintf(stderr,"%s: Dumping finished. %s written (%s on this disk)\n",
nathan@4
   335
              prg_name,FlexSize(str1,totalSize),FlexSize(str2,grandTotal));
nathan@4
   336
      }
nathan@4
   337
nathan@4
   338
    if(multidisk==0) {
nathan@4
   339
      if(cont) fprintf(stderr,"Multi-disk not enabled, ignoring continuation image(s)!\n");
nathan@4
   340
      cont=0;
nathan@4
   341
      }
nathan@10
   342
    else if(cont) {
nathan@4
   343
      disknum++;
nathan@4
   344
      diskchange(multicmd,cd_dev);
nathan@4
   345
      }
nathan@4
   346
    } while(cont);
nathan@4
   347
}
nathan@4
   348
nathan@4
   349
/****************************************************************************/
nathan@4
   350
nathan@4
   351
int backup(void)
nathan@4
   352
{
nathan@0
   353
  long long grandTotal=0;
nathan@0
   354
  struct header_block header;
nathan@4
   355
  int flags, datasize, result=0;
nathan@0
   356
nathan@0
   357
  char buffer[CD_FRAMESIZE];
nathan@0
   358
  struct data_block *db=(struct data_block *)&buffer[0];
nathan@0
   359
nathan@4
   360
  flags=F_NONE;
nathan@4
   361
  datasize=DATASIZE;
nathan@4
   362
  if(crc) { flags|=F_CRC; datasize-=4; }
nathan@4
   363
nathan@4
   364
  sprintf(buffer,"%04d%02d%02d%02d%02d",curtime.tm_year+1900,
nathan@4
   365
    curtime.tm_mon+1,curtime.tm_mday,curtime.tm_hour,curtime.tm_min);
nathan@0
   366
  
nathan@4
   367
  strncpy(header.id_str,HDR_STRING,32); header.id_str[32]=0;
nathan@4
   368
  strncpy(header.vol_id,cd_label,32); header.vol_id[32]=0;
nathan@4
   369
  strncpy(header.t_stamp,buffer,12); header.t_stamp[12]=0;
nathan@4
   370
  header.disk_set = disknum;
nathan@4
   371
  header.flags = flags;
nathan@0
   372
nathan@0
   373
  if(verbose)
nathan@4
   374
    fprintf(stderr,"%s: Recording to %s, multidisk %s, CRC %s, disk %d\n",
nathan@4
   375
            prg_name,VdevName(),
nathan@4
   376
            multidisk?"enabled":"disabled",
nathan@4
   377
            crc?"enabled":"disabled",
nathan@4
   378
            disknum); 
nathan@4
   379
  secs=cd_len;
nathan@4
   380
  VnewTrack();
nathan@4
   381
nathan@0
   382
  memset(buffer,0,CD_FRAMESIZE);
nathan@0
   383
  memcpy(buffer,&header,sizeof(struct header_block));
nathan@4
   384
  Vwrite(buffer); grandTotal+=CD_FRAMESIZE;
nathan@0
   385
nathan@0
   386
  do {
nathan@4
   387
    int bytes;
nathan@4
   388
nathan@4
   389
    db->flags=flags;
nathan@4
   390
    db->status=0;		      /* this isn't the last block (for now) */
nathan@4
   391
    bytes=full_read(0,&buffer[DBSIZE],datasize);
nathan@4
   392
    if(bytes!=datasize) db->status=1; /* EOF, this is the last block */
nathan@4
   393
    db->datasize=htons(bytes);
nathan@4
   394
nathan@4
   395
    if(cd_avail<(CD_FRAMESIZE*2)) {   /* less than 2 block free */
nathan@4
   396
      if(db->status==0) {             /* if not last block, mark disk as full */
nathan@4
   397
        db->status=2;
nathan@4
   398
        result=1;
nathan@4
   399
        }
nathan@4
   400
      }
nathan@4
   401
    if(crc) {
nathan@4
   402
      int l=crc32(buffer,bytes+DBSIZE);
nathan@4
   403
      *((unsigned long *)(&buffer[CD_FRAMESIZE-4]))=l;
nathan@4
   404
      }
nathan@4
   405
    Vwrite(buffer); grandTotal+=CD_FRAMESIZE;
nathan@0
   406
    } while(db->status==0);
nathan@0
   407
nathan@4
   408
  if(dvd && cd_avail>=CD_FRAMESIZE) { /* pad up the track with zeros */
nathan@4
   409
    memset(buffer,0,CD_FRAMESIZE);
nathan@4
   410
    if(verbose) fprintf(stderr,"%s: padding up the track\n",prg_name);
nathan@4
   411
    while(cd_avail>=CD_FRAMESIZE) Vwrite(buffer);
nathan@4
   412
    }
nathan@4
   413
nathan@14
   414
  VcloseTrack(multidisk==0 ? 0 : result);
nathan@0
   415
nathan@0
   416
  totalSize+=grandTotal;
nathan@4
   417
  if(verbose) {
nathan@4
   418
    char str1[16], str2[16];
nathan@4
   419
    fprintf(stderr,"%s: Recording finished. %s written (%s on this disk)\n",
nathan@4
   420
            prg_name,FlexSize(str1,totalSize),FlexSize(str2,grandTotal));
nathan@4
   421
    }
nathan@4
   422
  return result;
nathan@4
   423
}
nathan@4
   424
nathan@4
   425
/****************************************************************************/
nathan@4
   426
nathan@4
   427
int main(int argc, char *argv[]) 
nathan@4
   428
{
nathan@4
   429
  int result, loop;
nathan@4
   430
  time_t curtime_t;
nathan@4
   431
nathan@4
   432
  curtime_t=time(0); curtime=*localtime(&curtime_t);
nathan@4
   433
  parse_cmdline(argc,argv);
nathan@4
   434
nathan@4
   435
  if(virt_dump) {
nathan@4
   436
    dump();
nathan@4
   437
    }
nathan@4
   438
  else {
nathan@4
   439
    do {
nathan@4
   440
      do {
nathan@4
   441
        autosize();
nathan@4
   442
        Vopen(0); result=VreadToc(0); VprintSpace();
nathan@4
   443
        loop=1;
nathan@4
   444
nathan@4
   445
        if(disknum>1 && result!=0) {
nathan@4
   446
          Vclose();
nathan@4
   447
          fprintf(stderr,"%s: Can't do multidisk continuation on non-empty disk! Try another disk\n", prg_name);
nathan@4
   448
          diskchange(multicmd,cd_dev);
nathan@4
   449
          }
nathan@4
   450
        else if(cd_avail<(padsize+MIN_BLOCKS)*CD_FRAMESIZE) {
nathan@4
   451
          Vclose();
nathan@4
   452
          if(multidisk) {
nathan@4
   453
            fprintf(stderr,"%s: Not enough free space on disk! Try another disk\n", prg_name);
nathan@4
   454
            diskchange(multicmd,cd_dev);
nathan@4
   455
            }
nathan@4
   456
          else serror("Not enough free space on disk");
nathan@4
   457
          }
nathan@4
   458
        else loop=0;
nathan@4
   459
        } while(loop);
nathan@4
   460
nathan@4
   461
      result=backup();
nathan@4
   462
      if(result==1) {
nathan@4
   463
        if(multidisk==0) serror("Disk full, multi-disk not enabled. Aborting");
nathan@4
   464
nathan@4
   465
        disknum++;
nathan@4
   466
        if(!VisRegular()) diskchange(multicmd,cd_dev);
nathan@4
   467
        }
nathan@4
   468
      } while(result!=0);
nathan@4
   469
    }
nathan@0
   470
  return 0;
nathan@0
   471
}