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