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