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