cdbackup.c
author nathan
Sat, 29 Dec 2007 15:31:08 +0100
branchtrunk
changeset 10 79f97a86b31a
parent 8 a306b5e43b44
child 12 6d3770b1a9e1
permissions -rw-r--r--
several fixes
nathan@0
     1
/* cdbackup.c
nathan@10
     2
Copyright (c) 2000-2006 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@0
    70
nathan@0
    71
char **cdrec_opt=0;
nathan@0
    72
int    cdrec_opt_count=0;
nathan@0
    73
nathan@4
    74
long long totalSize=0;
nathan@4
    75
int disknum=1;
nathan@4
    76
int secs;
nathan@0
    77
struct tm curtime;  /* global, so multi-disks get all the same time */
nathan@4
    78
int auto_size=0;
nathan@4
    79
nathan@4
    80
/****************************************************************************/
nathan@4
    81
nathan@4
    82
char *make_arg(const char *format, ...)
nathan@4
    83
{
nathan@4
    84
  char *ptr;
nathan@4
    85
  va_list ap;
nathan@4
    86
  va_start(ap,format);
nathan@10
    87
  if(vasprintf(&ptr,format,ap)<0) {
nathan@10
    88
    serror("No memory for cdrecord args\n");
nathan@10
    89
    ptr=0;
nathan@10
    90
    }
nathan@4
    91
  va_end(ap);
nathan@4
    92
  return ptr;
nathan@4
    93
}
nathan@4
    94
nathan@4
    95
void start_cdrecord(void)
nathan@4
    96
{
nathan@4
    97
  char **args, **p, *exname;
nathan@4
    98
  int l;
nathan@4
    99
  
nathan@10
   100
  if(!(p=args=calloc(cdrec_opt_count+32,sizeof(char *))))
nathan@4
   101
    serror("No memory for cdrecord args\n");
nathan@4
   102
nathan@4
   103
  if(dvd) exname="dvdrecord"; else exname="cdrecord";
nathan@4
   104
  *p++=exname;
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@4
   131
  execvp(exname,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@4
   141
  asprintf(&cmd,"%srecord 2>&1 dev=%s -atip",dvd ? "dvd":"cd",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@4
   186
  while ((i=getopt(argc,argv,"d:r:l:s:p:a:c:mvVXDCi:wR"))>0) {
nathan@0
   187
    switch (i) {
nathan@0
   188
       case 'V': fprintf(stderr,"cdbackup "VERSION" (compiled "__DATE__")\n"
nathan@4
   189
	                        "Copyright (C) 2000-2004\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@4
   204
       case 'R': dvd=1;
nathan@4
   205
                 DEBUG("cdbackup: DVD mode enabled\n");
nathan@4
   206
                 break;
nathan@2
   207
       case 'D': verbose=1; debug=1; 
nathan@2
   208
                 DEBUG("cdbackup: DEBUG output enabled ("VERSION")\n");
nathan@2
   209
                 break;
nathan@4
   210
       case 'l': cd_len=(long)(FlexLen(optarg)/CD_FRAMESIZE);
nathan@4
   211
                 break;
nathan@0
   212
       case 's': errno=0; cd_speed=strtol(optarg,NULL,10);
nathan@0
   213
                 if(errno==ERANGE || cd_speed<1) serror("Option -s: speed out of range (must be >=1)\n");
nathan@0
   214
	         break;
nathan@0
   215
       case 'p': errno=0; padsize=strtol(optarg,NULL,10);
nathan@0
   216
                 if(errno==ERANGE || padsize<15) serror("Option -p: padsize out of range (must be >=15)\n");
nathan@0
   217
	         break;
nathan@4
   218
       default:  fprintf(stderr,
nathan@4
   219
                         "Usage: %s [options ...] [-- cdrecord-options ...]\n"
nathan@4
   220
                         "Reads from standard input, block formats and writes to CD-R(W).\n\n"
nathan@4
   221
                         "  -d DEVICE      DEVICE for CD queries (default /dev/burner)\n"
nathan@4
   222
                         "  -l N           set media size, disable auto-detect\n"
nathan@4
   223
                         "  -r DEVICE      DEVICE for CD recording (e.g. 0,4,0)\n"
nathan@4
   224
                         "  -s N           record CD at speed N (default 4)\n"
nathan@4
   225
                         "  -X             enable CDROM XA2 mode in cdrecord\n"
nathan@4
   226
                         "  -a LABEL       use LABEL as CD session title\n"
nathan@4
   227
                         "  -p N           use a padsize of N sectors for the session (default 15)\n"
nathan@4
   228
                         "  -m             enable multi-disk mode\n"
nathan@4
   229
                         "  -c COMMAND     call COMMAND on disk change in multi-disk mode\n"
nathan@4
   230
                         "  -C             disable checksum creation for datablocks\n"
nathan@4
   231
                         "  -i IMAGE       use virtual image IMAGE for recording\n"
nathan@4
   232
                         "  -w             dump virtual image to media\n"
nathan@4
   233
                         "  -R             enables DVD mode\n"
nathan@4
   234
                         "  -v             be verbose\n"
nathan@4
   235
                         "  -D             enable DEBUG output\n"
nathan@4
   236
                         "  -V             prints version & exits\n"
nathan@4
   237
                         "  --             pass rest of commandline to cdrecord\n"
nathan@4
   238
                         "\n", prg_name);
nathan@4
   239
                 exit(0);
nathan@0
   240
       }
nathan@0
   241
    }
nathan@0
   242
nathan@0
   243
  if(optind<argc) { /* save position/count of cdrecord options */
nathan@0
   244
    cdrec_opt_count=argc-optind;
nathan@0
   245
    cdrec_opt=&argv[optind];
nathan@0
   246
    }
nathan@0
   247
    
nathan@4
   248
  if(cd_len<0) {
nathan@4
   249
    auto_size=1;
nathan@4
   250
    if(virtual && !virt_dump) serror("Can't auto-detect media size in virtual mode. Use option -l to set media size\n");
nathan@4
   251
    }
nathan@4
   252
  if(virtual && dvd && !virt_dump) {
nathan@4
   253
     fprintf(stderr,"Option -R ignored in virtual mode\n");
nathan@4
   254
     dvd=0;
nathan@4
   255
     }
nathan@4
   256
  if(dvd) {
nathan@4
   257
    if(xamode2) fprintf(stderr,"Option -X ignored in DVD mode\n");
nathan@4
   258
    padsize=0;
nathan@4
   259
    }
nathan@4
   260
  if(virt_dump && !virtual) serror("To dump an image you must supply the image name with -i\n");
nathan@4
   261
  if(!cdr_dev && (!virtual || virt_dump)) serror("You must specify a device for cdrecord with -r\n");
nathan@4
   262
}
nathan@4
   263
nathan@4
   264
/****************************************************************************/
nathan@4
   265
nathan@4
   266
void autosize(void)
nathan@4
   267
{
nathan@4
   268
  if(auto_size) {
nathan@4
   269
    cd_len=atip_cdrecord();
nathan@4
   270
    if(cd_len<0) serror("Media size detection failed. Use option -l to set media size\n");
nathan@4
   271
    }
nathan@4
   272
}
nathan@4
   273
nathan@4
   274
/****************************************************************************/
nathan@4
   275
nathan@4
   276
void dump(void)
nathan@4
   277
{
nathan@4
   278
  int n, cont;
nathan@4
   279
  char buffer[CD_FRAMESIZE];
nathan@4
   280
  long long grandTotal;
nathan@4
   281
nathan@4
   282
  do {
nathan@4
   283
    int change;
nathan@4
   284
    do {
nathan@4
   285
      autosize();
nathan@4
   286
      virtual=1;
nathan@4
   287
      Vopen(1); n=VreadToc(0);
nathan@4
   288
      if(n<1) serror("It's not usefull to dump an empty image");
nathan@4
   289
      secs=Vsize(); cont=VhasCont();
nathan@8
   290
      if(cd_len<secs) serror("Image doesn't fit to this media");
nathan@4
   291
      Vseek(-1); VprepareDump();
nathan@4
   292
nathan@4
   293
      virtual=0; change=0;
nathan@4
   294
      Vopen(0); n=VreadToc(0); VprintSpace();
nathan@4
   295
      if(n!=0) {
nathan@4
   296
        fprintf(stderr,"Can't dump to non-empty disk! Try another disk\n");
nathan@4
   297
        change=1;
nathan@4
   298
        }
nathan@4
   299
nathan@4
   300
      if(change) {
nathan@4
   301
        Vclose();
nathan@4
   302
        diskchange(multicmd,cd_dev);
nathan@4
   303
        }
nathan@4
   304
      } while(change);
nathan@4
   305
nathan@4
   306
    if(verbose)
nathan@4
   307
      fprintf(stderr,"%s: Dumping image (%d blocks) to %s\n",prg_name,secs,VdevName());
nathan@4
   308
    VnewTrack();
nathan@4
   309
nathan@4
   310
    grandTotal=0;
nathan@4
   311
    while(secs>0) {
nathan@4
   312
      VvirtRead(buffer);
nathan@4
   313
      Vwrite(buffer); grandTotal+=CD_FRAMESIZE;
nathan@4
   314
      secs--;
nathan@4
   315
      }
nathan@4
   316
nathan@4
   317
    VcloseTrack(0);
nathan@4
   318
nathan@4
   319
    totalSize+=grandTotal;
nathan@4
   320
    if(verbose) {
nathan@4
   321
      char str1[16], str2[16];
nathan@4
   322
      fprintf(stderr,"%s: Dumping finished. %s written (%s on this disk)\n",
nathan@4
   323
              prg_name,FlexSize(str1,totalSize),FlexSize(str2,grandTotal));
nathan@4
   324
      }
nathan@4
   325
nathan@4
   326
    if(multidisk==0) {
nathan@4
   327
      if(cont) fprintf(stderr,"Multi-disk not enabled, ignoring continuation image(s)!\n");
nathan@4
   328
      cont=0;
nathan@4
   329
      }
nathan@10
   330
    else if(cont) {
nathan@4
   331
      disknum++;
nathan@4
   332
      diskchange(multicmd,cd_dev);
nathan@4
   333
      }
nathan@4
   334
    } while(cont);
nathan@4
   335
}
nathan@4
   336
nathan@4
   337
/****************************************************************************/
nathan@4
   338
nathan@4
   339
int backup(void)
nathan@4
   340
{
nathan@0
   341
  long long grandTotal=0;
nathan@0
   342
  struct header_block header;
nathan@4
   343
  int flags, datasize, result=0;
nathan@0
   344
nathan@0
   345
  char buffer[CD_FRAMESIZE];
nathan@0
   346
  struct data_block *db=(struct data_block *)&buffer[0];
nathan@0
   347
nathan@4
   348
  flags=F_NONE;
nathan@4
   349
  datasize=DATASIZE;
nathan@4
   350
  if(crc) { flags|=F_CRC; datasize-=4; }
nathan@4
   351
nathan@4
   352
  sprintf(buffer,"%04d%02d%02d%02d%02d",curtime.tm_year+1900,
nathan@4
   353
    curtime.tm_mon+1,curtime.tm_mday,curtime.tm_hour,curtime.tm_min);
nathan@0
   354
  
nathan@4
   355
  strncpy(header.id_str,HDR_STRING,32); header.id_str[32]=0;
nathan@4
   356
  strncpy(header.vol_id,cd_label,32); header.vol_id[32]=0;
nathan@4
   357
  strncpy(header.t_stamp,buffer,12); header.t_stamp[12]=0;
nathan@4
   358
  header.disk_set = disknum;
nathan@4
   359
  header.flags = flags;
nathan@0
   360
nathan@0
   361
  if(verbose)
nathan@4
   362
    fprintf(stderr,"%s: Recording to %s, multidisk %s, CRC %s, disk %d\n",
nathan@4
   363
            prg_name,VdevName(),
nathan@4
   364
            multidisk?"enabled":"disabled",
nathan@4
   365
            crc?"enabled":"disabled",
nathan@4
   366
            disknum); 
nathan@4
   367
  secs=cd_len;
nathan@4
   368
  VnewTrack();
nathan@4
   369
nathan@0
   370
  memset(buffer,0,CD_FRAMESIZE);
nathan@0
   371
  memcpy(buffer,&header,sizeof(struct header_block));
nathan@4
   372
  Vwrite(buffer); grandTotal+=CD_FRAMESIZE;
nathan@0
   373
nathan@0
   374
  do {
nathan@4
   375
    int bytes;
nathan@4
   376
nathan@4
   377
    db->flags=flags;
nathan@4
   378
    db->status=0;		      /* this isn't the last block (for now) */
nathan@4
   379
    bytes=full_read(0,&buffer[DBSIZE],datasize);
nathan@4
   380
    if(bytes!=datasize) db->status=1; /* EOF, this is the last block */
nathan@4
   381
    db->datasize=htons(bytes);
nathan@4
   382
nathan@4
   383
    if(cd_avail<(CD_FRAMESIZE*2)) {   /* less than 2 block free */
nathan@4
   384
      if(db->status==0) {             /* if not last block, mark disk as full */
nathan@4
   385
        db->status=2;
nathan@4
   386
        result=1;
nathan@4
   387
        }
nathan@4
   388
      }
nathan@4
   389
    if(crc) {
nathan@4
   390
      int l=crc32(buffer,bytes+DBSIZE);
nathan@4
   391
      *((unsigned long *)(&buffer[CD_FRAMESIZE-4]))=l;
nathan@4
   392
      }
nathan@4
   393
    Vwrite(buffer); grandTotal+=CD_FRAMESIZE;
nathan@0
   394
    } while(db->status==0);
nathan@0
   395
nathan@4
   396
  if(dvd && cd_avail>=CD_FRAMESIZE) { /* pad up the track with zeros */
nathan@4
   397
    memset(buffer,0,CD_FRAMESIZE);
nathan@4
   398
    if(verbose) fprintf(stderr,"%s: padding up the track\n",prg_name);
nathan@4
   399
    while(cd_avail>=CD_FRAMESIZE) Vwrite(buffer);
nathan@4
   400
    }
nathan@4
   401
nathan@4
   402
  VcloseTrack(result);
nathan@0
   403
nathan@0
   404
  totalSize+=grandTotal;
nathan@4
   405
  if(verbose) {
nathan@4
   406
    char str1[16], str2[16];
nathan@4
   407
    fprintf(stderr,"%s: Recording finished. %s written (%s on this disk)\n",
nathan@4
   408
            prg_name,FlexSize(str1,totalSize),FlexSize(str2,grandTotal));
nathan@4
   409
    }
nathan@4
   410
  return result;
nathan@4
   411
}
nathan@4
   412
nathan@4
   413
/****************************************************************************/
nathan@4
   414
nathan@4
   415
int main(int argc, char *argv[]) 
nathan@4
   416
{
nathan@4
   417
  int result, loop;
nathan@4
   418
  time_t curtime_t;
nathan@4
   419
nathan@4
   420
  curtime_t=time(0); curtime=*localtime(&curtime_t);
nathan@4
   421
  parse_cmdline(argc,argv);
nathan@4
   422
nathan@4
   423
  if(virt_dump) {
nathan@4
   424
    dump();
nathan@4
   425
    }
nathan@4
   426
  else {
nathan@4
   427
    do {
nathan@4
   428
      do {
nathan@4
   429
        autosize();
nathan@4
   430
        Vopen(0); result=VreadToc(0); VprintSpace();
nathan@4
   431
        loop=1;
nathan@4
   432
nathan@4
   433
        if(disknum>1 && result!=0) {
nathan@4
   434
          Vclose();
nathan@4
   435
          fprintf(stderr,"%s: Can't do multidisk continuation on non-empty disk! Try another disk\n", prg_name);
nathan@4
   436
          diskchange(multicmd,cd_dev);
nathan@4
   437
          }
nathan@4
   438
        else if(cd_avail<(padsize+MIN_BLOCKS)*CD_FRAMESIZE) {
nathan@4
   439
          Vclose();
nathan@4
   440
          if(multidisk) {
nathan@4
   441
            fprintf(stderr,"%s: Not enough free space on disk! Try another disk\n", prg_name);
nathan@4
   442
            diskchange(multicmd,cd_dev);
nathan@4
   443
            }
nathan@4
   444
          else serror("Not enough free space on disk");
nathan@4
   445
          }
nathan@4
   446
        else loop=0;
nathan@4
   447
        } while(loop);
nathan@4
   448
nathan@4
   449
      result=backup();
nathan@4
   450
      if(result==1) {
nathan@4
   451
        if(multidisk==0) serror("Disk full, multi-disk not enabled. Aborting");
nathan@4
   452
nathan@4
   453
        disknum++;
nathan@4
   454
        if(!VisRegular()) diskchange(multicmd,cd_dev);
nathan@4
   455
        }
nathan@4
   456
      } while(result!=0);
nathan@4
   457
    }
nathan@0
   458
  return 0;
nathan@0
   459
}