cdbackup.c
author nathan
Sun, 23 May 2010 08:39:19 +0200
branchtrunk
changeset 13 6ef9b2adca64
parent 12 6d3770b1a9e1
child 14 ae01b419e8f9
permissions -rw-r--r--
fix gcc warnings (asprintf)
nathan@0
     1
/* cdbackup.c
nathan@12
     2
Copyright (c) 2000-2010 Craig Condit, Stefan Hülswitt.
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@0
    78
struct tm curtime;  /* global, so multi-disks get all the same time */
nathan@4
    79
int auto_size=0;
nathan@4
    80
nathan@4
    81
/****************************************************************************/
nathan@4
    82
nathan@4
    83
char *make_arg(const char *format, ...)
nathan@4
    84
{
nathan@4
    85
  char *ptr;
nathan@4
    86
  va_list ap;
nathan@4
    87
  va_start(ap,format);
nathan@10
    88
  if(vasprintf(&ptr,format,ap)<0) {
nathan@10
    89
    serror("No memory for cdrecord args\n");
nathan@10
    90
    ptr=0;
nathan@10
    91
    }
nathan@4
    92
  va_end(ap);
nathan@4
    93
  return ptr;
nathan@4
    94
}
nathan@4
    95
nathan@4
    96
void start_cdrecord(void)
nathan@4
    97
{
nathan@12
    98
  char **args, **p;
nathan@4
    99
  int l;
nathan@4
   100
  
nathan@10
   101
  if(!(p=args=calloc(cdrec_opt_count+32,sizeof(char *))))
nathan@4
   102
    serror("No memory for cdrecord args\n");
nathan@4
   103
nathan@12
   104
  *p++=exename;
nathan@4
   105
nathan@4
   106
  if(virt_dump || dvd) {
nathan@4
   107
    *p++="-dao";
nathan@4
   108
    *p++=make_arg("tsize=%ds",secs);
nathan@4
   109
    }
nathan@4
   110
  else {
nathan@4
   111
    *p++="-multi";
nathan@10
   112
    *p++="-tao";
nathan@4
   113
    *p++=make_arg("padsize=%ds",padsize);
nathan@4
   114
    }
nathan@4
   115
nathan@4
   116
  *p++=make_arg("speed=%d",cd_speed);
nathan@4
   117
  *p++=make_arg("dev=%s",cdr_dev);
nathan@4
   118
nathan@4
   119
  for(l=0 ; l<cdrec_opt_count ; l++) *p++=cdrec_opt[l];
nathan@4
   120
nathan@4
   121
  if(xamode2 && !dvd) *p++="-xa2"; else *p++="-data";
nathan@4
   122
  *p++="-";
nathan@4
   123
  *p++=0;
nathan@4
   124
nathan@4
   125
  if(debug) {
nathan@4
   126
    fprintf(stderr,"%s: cdrecord command:",prg_name);
nathan@4
   127
    for(p=args ; *p ; p++) fprintf(stderr," %s",*p);
nathan@4
   128
    fprintf(stderr,"\n");
nathan@4
   129
    }
nathan@4
   130
nathan@12
   131
  execvp(exename,args);
nathan@4
   132
  error("Exec failed (cdrecord)");
nathan@4
   133
}
nathan@4
   134
nathan@4
   135
long atip_cdrecord(void)
nathan@4
   136
{
nathan@4
   137
  char *cmd;
nathan@4
   138
  FILE *p;
nathan@4
   139
  long size=-1;
nathan@4
   140
  
nathan@13
   141
  if(asprintf(&cmd,"%s 2>&1 dev=%s -atip",exename,cdr_dev)<0) {
nathan@13
   142
    fprintf(stderr,"%s: error making atip command: %s\n",prg_name,strerror(errno));
nathan@13
   143
    return -1;
nathan@13
   144
    }
nathan@4
   145
  DEBUG("%s: cdrecord atip command: %s\n",prg_name,cmd);
nathan@4
   146
nathan@4
   147
  p=popen(cmd,"r");
nathan@4
   148
  if(!p) fprintf(stderr,"%s: atip command failed\n",prg_name);
nathan@4
   149
  else {
nathan@4
   150
    char buff[256];
nathan@4
   151
    while(fgets(buff,sizeof(buff),p)) {
nathan@6
   152
      if(dvd) {
nathan@6
   153
         /* DVD-R */
nathan@6
   154
	 if(!strncmp(buff,"rzone size:",11)) size=strtol(&buff[11],NULL,10);
nathan@6
   155
	 /* DVD+R */
nathan@6
   156
	 else if(!strncmp(buff,"phys size:...",13)) size=strtol(&buff[13],NULL,10);
nathan@6
   157
	 }
nathan@6
   158
      else if(!strncmp(buff,"  ATIP start of lead out:",25)) size=strtol(&buff[25],NULL,10);
nathan@4
   159
      }
nathan@4
   160
    }
nathan@4
   161
  pclose(p);
nathan@4
   162
  free(cmd);
nathan@4
   163
  if(size>0 && verbose) {
nathan@4
   164
    char buff[16];
nathan@4
   165
    fprintf(stderr,"%s: auto-detected media size %s (%ld blocks)\n",prg_name,FlexSize(buff,(long long)size*CD_FRAMESIZE),size);
nathan@4
   166
    }
nathan@4
   167
  return size;
nathan@0
   168
}
nathan@0
   169
nathan@0
   170
/****************************************************************************/
nathan@0
   171
nathan@0
   172
void parse_cmdline(char argc, char *argv[]) 
nathan@0
   173
{
nathan@0
   174
  int i;
nathan@4
   175
  char *val;
nathan@4
   176
nathan@4
   177
  /* get some default from the environment */
nathan@4
   178
  val=getenv("CDR_DEVICE");
nathan@4
   179
  if(val) {
nathan@4
   180
    cdr_dev=strdup(val);
nathan@4
   181
    DEBUG("cdbackup: using recording device %s from CDR_DEVICE\n",cdr_dev);
nathan@4
   182
    }
nathan@4
   183
  val=getenv("CDR_SPEED");
nathan@4
   184
  if(val) {
nathan@4
   185
    cd_speed=strtol(val,NULL,10);
nathan@4
   186
    DEBUG("cdbackup: using speed %d from CDR_SPEED\n",cd_speed);
nathan@4
   187
    }
nathan@4
   188
  
nathan@12
   189
  while ((i=getopt(argc,argv,"d:r:l:s:p:a:c:mvVXDCi:wRE:"))>0) {
nathan@0
   190
    switch (i) {
nathan@0
   191
       case 'V': fprintf(stderr,"cdbackup "VERSION" (compiled "__DATE__")\n"
nathan@12
   192
	                        "Copyright (C) 2000-2010\n"
nathan@0
   193
			        "This is free software; see the source for copying conditions.\n"
nathan@0
   194
			        "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n"
nathan@0
   195
			        "PARTICULAR PURPOSE.\n");
nathan@0
   196
                 exit(0);
nathan@0
   197
       case 'v': verbose=1; break;
nathan@0
   198
       case 'm': multidisk=1; break;
nathan@0
   199
       case 'X': xamode2=1; break;
nathan@0
   200
       case 'c': multicmd=optarg; break;
nathan@0
   201
       case 'd': cd_dev=optarg; break;
nathan@0
   202
       case 'r': cdr_dev=optarg; break;
nathan@0
   203
       case 'a': cd_label=optarg; break;
nathan@4
   204
       case 'C': crc=0; break;
nathan@4
   205
       case 'i': virt_name=optarg; virtual=1; break;
nathan@4
   206
       case 'w': virt_dump=1; break;
nathan@12
   207
       case 'E': exename=optarg; break;
nathan@4
   208
       case 'R': dvd=1;
nathan@4
   209
                 DEBUG("cdbackup: DVD mode enabled\n");
nathan@4
   210
                 break;
nathan@2
   211
       case 'D': verbose=1; debug=1; 
nathan@2
   212
                 DEBUG("cdbackup: DEBUG output enabled ("VERSION")\n");
nathan@2
   213
                 break;
nathan@4
   214
       case 'l': cd_len=(long)(FlexLen(optarg)/CD_FRAMESIZE);
nathan@4
   215
                 break;
nathan@0
   216
       case 's': errno=0; cd_speed=strtol(optarg,NULL,10);
nathan@0
   217
                 if(errno==ERANGE || cd_speed<1) serror("Option -s: speed out of range (must be >=1)\n");
nathan@0
   218
	         break;
nathan@0
   219
       case 'p': errno=0; padsize=strtol(optarg,NULL,10);
nathan@0
   220
                 if(errno==ERANGE || padsize<15) serror("Option -p: padsize out of range (must be >=15)\n");
nathan@0
   221
	         break;
nathan@4
   222
       default:  fprintf(stderr,
nathan@4
   223
                         "Usage: %s [options ...] [-- cdrecord-options ...]\n"
nathan@4
   224
                         "Reads from standard input, block formats and writes to CD-R(W).\n\n"
nathan@4
   225
                         "  -d DEVICE      DEVICE for CD queries (default /dev/burner)\n"
nathan@4
   226
                         "  -l N           set media size, disable auto-detect\n"
nathan@4
   227
                         "  -r DEVICE      DEVICE for CD recording (e.g. 0,4,0)\n"
nathan@4
   228
                         "  -s N           record CD at speed N (default 4)\n"
nathan@4
   229
                         "  -X             enable CDROM XA2 mode in cdrecord\n"
nathan@4
   230
                         "  -a LABEL       use LABEL as CD session title\n"
nathan@4
   231
                         "  -p N           use a padsize of N sectors for the session (default 15)\n"
nathan@4
   232
                         "  -m             enable multi-disk mode\n"
nathan@4
   233
                         "  -c COMMAND     call COMMAND on disk change in multi-disk mode\n"
nathan@4
   234
                         "  -C             disable checksum creation for datablocks\n"
nathan@4
   235
                         "  -i IMAGE       use virtual image IMAGE for recording\n"
nathan@4
   236
                         "  -w             dump virtual image to media\n"
nathan@4
   237
                         "  -R             enables DVD mode\n"
nathan@12
   238
                         "  -E EXE         set alternative cdrecord executable\n"
nathan@4
   239
                         "  -v             be verbose\n"
nathan@4
   240
                         "  -D             enable DEBUG output\n"
nathan@4
   241
                         "  -V             prints version & exits\n"
nathan@4
   242
                         "  --             pass rest of commandline to cdrecord\n"
nathan@4
   243
                         "\n", prg_name);
nathan@4
   244
                 exit(0);
nathan@0
   245
       }
nathan@0
   246
    }
nathan@0
   247
nathan@0
   248
  if(optind<argc) { /* save position/count of cdrecord options */
nathan@0
   249
    cdrec_opt_count=argc-optind;
nathan@0
   250
    cdrec_opt=&argv[optind];
nathan@0
   251
    }
nathan@0
   252
    
nathan@4
   253
  if(cd_len<0) {
nathan@4
   254
    auto_size=1;
nathan@4
   255
    if(virtual && !virt_dump) serror("Can't auto-detect media size in virtual mode. Use option -l to set media size\n");
nathan@4
   256
    }
nathan@4
   257
  if(virtual && dvd && !virt_dump) {
nathan@4
   258
     fprintf(stderr,"Option -R ignored in virtual mode\n");
nathan@4
   259
     dvd=0;
nathan@4
   260
     }
nathan@4
   261
  if(dvd) {
nathan@4
   262
    if(xamode2) fprintf(stderr,"Option -X ignored in DVD mode\n");
nathan@4
   263
    padsize=0;
nathan@4
   264
    }
nathan@4
   265
  if(virt_dump && !virtual) serror("To dump an image you must supply the image name with -i\n");
nathan@4
   266
  if(!cdr_dev && (!virtual || virt_dump)) serror("You must specify a device for cdrecord with -r\n");
nathan@4
   267
}
nathan@4
   268
nathan@4
   269
/****************************************************************************/
nathan@4
   270
nathan@4
   271
void autosize(void)
nathan@4
   272
{
nathan@4
   273
  if(auto_size) {
nathan@4
   274
    cd_len=atip_cdrecord();
nathan@4
   275
    if(cd_len<0) serror("Media size detection failed. Use option -l to set media size\n");
nathan@4
   276
    }
nathan@4
   277
}
nathan@4
   278
nathan@4
   279
/****************************************************************************/
nathan@4
   280
nathan@4
   281
void dump(void)
nathan@4
   282
{
nathan@4
   283
  int n, cont;
nathan@4
   284
  char buffer[CD_FRAMESIZE];
nathan@4
   285
  long long grandTotal;
nathan@4
   286
nathan@4
   287
  do {
nathan@4
   288
    int change;
nathan@4
   289
    do {
nathan@4
   290
      autosize();
nathan@4
   291
      virtual=1;
nathan@4
   292
      Vopen(1); n=VreadToc(0);
nathan@4
   293
      if(n<1) serror("It's not usefull to dump an empty image");
nathan@4
   294
      secs=Vsize(); cont=VhasCont();
nathan@8
   295
      if(cd_len<secs) serror("Image doesn't fit to this media");
nathan@4
   296
      Vseek(-1); VprepareDump();
nathan@4
   297
nathan@4
   298
      virtual=0; change=0;
nathan@4
   299
      Vopen(0); n=VreadToc(0); VprintSpace();
nathan@4
   300
      if(n!=0) {
nathan@4
   301
        fprintf(stderr,"Can't dump to non-empty disk! Try another disk\n");
nathan@4
   302
        change=1;
nathan@4
   303
        }
nathan@4
   304
nathan@4
   305
      if(change) {
nathan@4
   306
        Vclose();
nathan@4
   307
        diskchange(multicmd,cd_dev);
nathan@4
   308
        }
nathan@4
   309
      } while(change);
nathan@4
   310
nathan@4
   311
    if(verbose)
nathan@4
   312
      fprintf(stderr,"%s: Dumping image (%d blocks) to %s\n",prg_name,secs,VdevName());
nathan@4
   313
    VnewTrack();
nathan@4
   314
nathan@4
   315
    grandTotal=0;
nathan@4
   316
    while(secs>0) {
nathan@4
   317
      VvirtRead(buffer);
nathan@4
   318
      Vwrite(buffer); grandTotal+=CD_FRAMESIZE;
nathan@4
   319
      secs--;
nathan@4
   320
      }
nathan@4
   321
nathan@4
   322
    VcloseTrack(0);
nathan@4
   323
nathan@4
   324
    totalSize+=grandTotal;
nathan@4
   325
    if(verbose) {
nathan@4
   326
      char str1[16], str2[16];
nathan@4
   327
      fprintf(stderr,"%s: Dumping finished. %s written (%s on this disk)\n",
nathan@4
   328
              prg_name,FlexSize(str1,totalSize),FlexSize(str2,grandTotal));
nathan@4
   329
      }
nathan@4
   330
nathan@4
   331
    if(multidisk==0) {
nathan@4
   332
      if(cont) fprintf(stderr,"Multi-disk not enabled, ignoring continuation image(s)!\n");
nathan@4
   333
      cont=0;
nathan@4
   334
      }
nathan@10
   335
    else if(cont) {
nathan@4
   336
      disknum++;
nathan@4
   337
      diskchange(multicmd,cd_dev);
nathan@4
   338
      }
nathan@4
   339
    } while(cont);
nathan@4
   340
}
nathan@4
   341
nathan@4
   342
/****************************************************************************/
nathan@4
   343
nathan@4
   344
int backup(void)
nathan@4
   345
{
nathan@0
   346
  long long grandTotal=0;
nathan@0
   347
  struct header_block header;
nathan@4
   348
  int flags, datasize, result=0;
nathan@0
   349
nathan@0
   350
  char buffer[CD_FRAMESIZE];
nathan@0
   351
  struct data_block *db=(struct data_block *)&buffer[0];
nathan@0
   352
nathan@4
   353
  flags=F_NONE;
nathan@4
   354
  datasize=DATASIZE;
nathan@4
   355
  if(crc) { flags|=F_CRC; datasize-=4; }
nathan@4
   356
nathan@4
   357
  sprintf(buffer,"%04d%02d%02d%02d%02d",curtime.tm_year+1900,
nathan@4
   358
    curtime.tm_mon+1,curtime.tm_mday,curtime.tm_hour,curtime.tm_min);
nathan@0
   359
  
nathan@4
   360
  strncpy(header.id_str,HDR_STRING,32); header.id_str[32]=0;
nathan@4
   361
  strncpy(header.vol_id,cd_label,32); header.vol_id[32]=0;
nathan@4
   362
  strncpy(header.t_stamp,buffer,12); header.t_stamp[12]=0;
nathan@4
   363
  header.disk_set = disknum;
nathan@4
   364
  header.flags = flags;
nathan@0
   365
nathan@0
   366
  if(verbose)
nathan@4
   367
    fprintf(stderr,"%s: Recording to %s, multidisk %s, CRC %s, disk %d\n",
nathan@4
   368
            prg_name,VdevName(),
nathan@4
   369
            multidisk?"enabled":"disabled",
nathan@4
   370
            crc?"enabled":"disabled",
nathan@4
   371
            disknum); 
nathan@4
   372
  secs=cd_len;
nathan@4
   373
  VnewTrack();
nathan@4
   374
nathan@0
   375
  memset(buffer,0,CD_FRAMESIZE);
nathan@0
   376
  memcpy(buffer,&header,sizeof(struct header_block));
nathan@4
   377
  Vwrite(buffer); grandTotal+=CD_FRAMESIZE;
nathan@0
   378
nathan@0
   379
  do {
nathan@4
   380
    int bytes;
nathan@4
   381
nathan@4
   382
    db->flags=flags;
nathan@4
   383
    db->status=0;		      /* this isn't the last block (for now) */
nathan@4
   384
    bytes=full_read(0,&buffer[DBSIZE],datasize);
nathan@4
   385
    if(bytes!=datasize) db->status=1; /* EOF, this is the last block */
nathan@4
   386
    db->datasize=htons(bytes);
nathan@4
   387
nathan@4
   388
    if(cd_avail<(CD_FRAMESIZE*2)) {   /* less than 2 block free */
nathan@4
   389
      if(db->status==0) {             /* if not last block, mark disk as full */
nathan@4
   390
        db->status=2;
nathan@4
   391
        result=1;
nathan@4
   392
        }
nathan@4
   393
      }
nathan@4
   394
    if(crc) {
nathan@4
   395
      int l=crc32(buffer,bytes+DBSIZE);
nathan@4
   396
      *((unsigned long *)(&buffer[CD_FRAMESIZE-4]))=l;
nathan@4
   397
      }
nathan@4
   398
    Vwrite(buffer); grandTotal+=CD_FRAMESIZE;
nathan@0
   399
    } while(db->status==0);
nathan@0
   400
nathan@4
   401
  if(dvd && cd_avail>=CD_FRAMESIZE) { /* pad up the track with zeros */
nathan@4
   402
    memset(buffer,0,CD_FRAMESIZE);
nathan@4
   403
    if(verbose) fprintf(stderr,"%s: padding up the track\n",prg_name);
nathan@4
   404
    while(cd_avail>=CD_FRAMESIZE) Vwrite(buffer);
nathan@4
   405
    }
nathan@4
   406
nathan@4
   407
  VcloseTrack(result);
nathan@0
   408
nathan@0
   409
  totalSize+=grandTotal;
nathan@4
   410
  if(verbose) {
nathan@4
   411
    char str1[16], str2[16];
nathan@4
   412
    fprintf(stderr,"%s: Recording finished. %s written (%s on this disk)\n",
nathan@4
   413
            prg_name,FlexSize(str1,totalSize),FlexSize(str2,grandTotal));
nathan@4
   414
    }
nathan@4
   415
  return result;
nathan@4
   416
}
nathan@4
   417
nathan@4
   418
/****************************************************************************/
nathan@4
   419
nathan@4
   420
int main(int argc, char *argv[]) 
nathan@4
   421
{
nathan@4
   422
  int result, loop;
nathan@4
   423
  time_t curtime_t;
nathan@4
   424
nathan@4
   425
  curtime_t=time(0); curtime=*localtime(&curtime_t);
nathan@4
   426
  parse_cmdline(argc,argv);
nathan@4
   427
nathan@4
   428
  if(virt_dump) {
nathan@4
   429
    dump();
nathan@4
   430
    }
nathan@4
   431
  else {
nathan@4
   432
    do {
nathan@4
   433
      do {
nathan@4
   434
        autosize();
nathan@4
   435
        Vopen(0); result=VreadToc(0); VprintSpace();
nathan@4
   436
        loop=1;
nathan@4
   437
nathan@4
   438
        if(disknum>1 && result!=0) {
nathan@4
   439
          Vclose();
nathan@4
   440
          fprintf(stderr,"%s: Can't do multidisk continuation on non-empty disk! Try another disk\n", prg_name);
nathan@4
   441
          diskchange(multicmd,cd_dev);
nathan@4
   442
          }
nathan@4
   443
        else if(cd_avail<(padsize+MIN_BLOCKS)*CD_FRAMESIZE) {
nathan@4
   444
          Vclose();
nathan@4
   445
          if(multidisk) {
nathan@4
   446
            fprintf(stderr,"%s: Not enough free space on disk! Try another disk\n", prg_name);
nathan@4
   447
            diskchange(multicmd,cd_dev);
nathan@4
   448
            }
nathan@4
   449
          else serror("Not enough free space on disk");
nathan@4
   450
          }
nathan@4
   451
        else loop=0;
nathan@4
   452
        } while(loop);
nathan@4
   453
nathan@4
   454
      result=backup();
nathan@4
   455
      if(result==1) {
nathan@4
   456
        if(multidisk==0) serror("Disk full, multi-disk not enabled. Aborting");
nathan@4
   457
nathan@4
   458
        disknum++;
nathan@4
   459
        if(!VisRegular()) diskchange(multicmd,cd_dev);
nathan@4
   460
        }
nathan@4
   461
      } while(result!=0);
nathan@4
   462
    }
nathan@0
   463
  return 0;
nathan@0
   464
}