1 Index: src/stored/faketape.c
2 ===================================================================
3 --- src/stored/faketape.c (révision 7092)
4 +++ src/stored/faketape.c (copie de travail)
6 int faketape::tape_op(struct mtop *mt_com)
9 + int count = mt_com->mt_count;
16 case MTFSF: /* Forward space over mt_count filemarks. */
17 - result = fsf(mt_com->mt_count);
20 + } while (--count > 0 && result == 0);
23 case MTBSF: /* Backward space over mt_count filemarks. */
24 - result = bsf(mt_com->mt_count);
27 + } while (--count > 0 && result == 0);
30 case MTFSR: /* Forward space over mt_count records (tape blocks). */
34 case MTWEOF: /* Write mt_count filemarks. */
35 - result = weof(mt_com->mt_count);
38 + } while (result == 0 && --count > 0);
41 case MTREW: /* Rewind. */
42 Dmsg0(dbglevel, "rewind faketape\n");
44 atEOF = atEOD = false;
49 + lseek(fd, 0, SEEK_SET);
53 case MTOFFL: /* put tape offline */
57 case MTEOM:/* Go to the end of the recorded media (for appending files). */
59 + lseek(fd, next_FM, SEEK_SET);
63 + while (::read(fd, &l, sizeof(l)) > 0) {
65 + lseek(fd, l, SEEK_CUR);
69 + Dmsg0(dbglevel, "skip 1 block\n");
85 - current_file = last_file;
90 case MTERASE: /* not used by bacula */
96 + lseek(fd, 0, SEEK_SET);
117 if (!atEOD) { /* if not at the end of the data */
122 needEOF = true; /* next operation need EOF mark */
124 -// if ((count + file_size) > max_size) {
126 -// "EOT writing only %i of %i requested\n",
127 -// max_size - file_size, count);
128 -// count = max_size - file_size;
132 uint32_t size = count;
133 ::write(fd, &size, sizeof(uint32_t));
134 nb = ::write(fd, buffer, count);
135 @@ -484,43 +493,68 @@
139 -int faketape::weof(int count)
141 + * +---+---------+---+------------------+---+-------------------+
142 + * |00N| DATA |0LN| DATA |0LC| DATA |
143 + * +---+---------+---+------------------+---+-------------------+
146 + * L : Last FileMark offset
147 + * N : Next FileMark offset
148 + * C : Current FileMark Offset
150 +int faketape::weof()
153 ASSERT(current_file >= 0);
154 Dmsg3(dbglevel, "Writing EOF %i:%i last=%i\n",
155 current_file, current_block,last_file);
167 - truncate_file(); /* nothing after this point */
169 + truncate_file(); /* nothing after this point */
172 + cur_FM = lseek(fd, 0, SEEK_CUR); // current position
174 + /* update previous next_FM */
175 + lseek(fd, last_FM + sizeof(uint32_t)+sizeof(off_t), SEEK_SET);
176 + ::write(fd, &cur_FM, sizeof(off_t));
177 + lseek(fd, cur_FM, SEEK_SET);
184 - ::write(fd, &c, sizeof(uint32_t));
185 + ::write(fd, &c, sizeof(uint32_t)); // EOF
186 + ::write(fd, &last_FM, sizeof(last_FM)); // F-1
187 + ::write(fd, &next_FM, sizeof(next_FM)); // F (will be updated next time)
189 - current_file += count;
195 - ::write(fd, &c, sizeof(uint32_t));
196 - lseek(fd, lseek(fd, 0, SEEK_CUR) - sizeof(uint32_t), SEEK_SET);
204 + last_file = MAX(current_file, last_file);
209 -int faketape::fsf(int count)
216 ASSERT(current_file >= 0);
217 @@ -528,24 +562,33 @@
219 * 1 0 -> fsf -> 2 0 -> fsf -> 2 -1
226 if (atEOT || atEOD) {
232 - atBOT = atEOF = false;
233 - Dmsg3(dbglevel+1, "fsf %i+%i <= %i\n", current_file, count, last_file);
235 + Dmsg2(dbglevel+1, "fsf %i <= %i\n", current_file, last_file);
237 - if ((current_file + count) <= last_file) {
238 - current_file += count;
240 + if (next_FM > last_FM) { /* not the last file */
241 + lseek(fd, next_FM, SEEK_SET);
242 + read_next_fm(true);
248 + } else if (atEOF) { /* last file mark */
254 + } else { /* last file, but no at the end */
257 Dmsg0(dbglevel, "Try to FSF after EOT\n");
259 current_file = last_file ;
260 @@ -553,10 +596,44 @@
268 +/* /------------\ /---------------\
269 + * +---+------+---+---------------+-+
271 + * +---+------+---+---------------+-+
273 +bool faketape::read_next_fm(bool read_all /* read the 0 byte */)
276 + return read_fm(read_all);
279 +bool faketape::read_fm(bool read_all /* read the 0 byte */)
284 + ::read(fd, &c, sizeof(c));
286 + lseek(fd, lseek(fd, 0, SEEK_CUR) - sizeof(c), SEEK_SET);
290 + ::read(fd, &last_FM, sizeof(last_FM));
291 + ret = ::read(fd, &next_FM, sizeof(next_FM));
295 + Dmsg1(dbglevel, "Read FM next=%lli\n", next_FM);
297 + return (ret == sizeof(next_FM));
301 + * TODO: Check fsr with EOF
303 int faketape::fsr(int count)
308 Dmsg3(dbglevel, "fsr %i:%i count=%i\n", current_file,current_block, count);
314 @@ -595,20 +671,23 @@
315 current_file, current_block, nb,s);
318 - if (current_file < last_file) {
324 + read_next_fm(false);
326 atEOF = true; /* stop the loop */
330 - find_maxfile(); /* refresh stats */
336 + * BSR + EOF => begin of EOF + EIO
337 + * BSR + BSR + EOF => last block
338 + * current_block = -1
340 int faketape::bsr(int count)
342 Dmsg2(dbglevel, "bsr current_block=%i count=%i\n",
351 @@ -641,22 +719,21 @@
355 + /* at EOF 0:-1 BOT=0 EOD=0 EOF=0 ERR: Input/output error */
357 - if (!current_block) {
358 - if (current_file > 0) {
368 + lseek(fd, last_FM, SEEK_CUR);
378 + * First, go to last_FM and read all blocks to find the good one
381 + lseek(fd, last_FM, SEEK_CUR);
386 @@ -700,31 +777,35 @@
390 -int faketape::bsf(int count)
391 +/* BSF => just before last EOF
392 + * EOF + BSF => just before EOF
393 + * file 0 + BSF => BOT + errno
398 ASSERT(current_file >= 0);
399 - Dmsg3(dbglevel, "bsf %i:%i count=%i\n", current_file, current_block, count);
400 + Dmsg2(dbglevel, "bsf %i:%i count=%i\n", current_file, current_block);
406 atBOT = atEOF = atEOT = atEOD = false;
408 - if (current_file - count < 0) {
409 + if (current_file == 0) {/* BOT + errno */
410 + lseek(fd, 0, SEEK_SET);
419 - current_file = current_file - count + 1;
420 - current_block = -1;
422 + Dmsg1(dbglevel, "bfs last=%lli\n", last_FM);
423 + lseek(fd, last_FM, SEEK_SET);
425 - /* go just before last EOF */
426 - lseek(fd, lseek(fd, 0, SEEK_CUR) - sizeof(uint32_t), SEEK_SET);
435 +/* A filemark is automatically written to tape if the last tape operation
436 + * before close was a write.
438 int faketape::close()
441 @@ -756,18 +840,15 @@
449 - * EOF Bacula status: file=2 block=0
450 - * Device status: EOF ONLINE IM_REP_EN file=2 block=0
453 - * EOD EOF Bacula status: file=2 block=0
454 - * Device status: EOD ONLINE IM_REP_EN file=2 block=-1
456 + * When a filemark is encountered while reading, the following happens. If
457 + * there are data remaining in the buffer when the filemark is found, the
458 + * buffered data is returned. The next read returns zero bytes. The following
459 + * read returns data from the next file. The end of recorded data is sig‐
460 + * naled by returning zero bytes for two consecutive read calls. The third
461 + * read returns an error.
464 int faketape::read(void *buffer, unsigned int count)
468 Dmsg2(dbglevel, "read %i:%i\n", current_file, current_block);
470 if (atEOT || atEOD) {
471 + if (eot_count < 2) { // first two reads return 0, after EIO
478 @@ -792,10 +877,10 @@
485 atEOD = atBOT = false;
488 /* reading size of data */
489 nb = ::read(fd, &s, sizeof(uint32_t));
490 @@ -813,11 +898,10 @@
494 - if (current_file < last_file) { /* move to next file if possible */
498 + if (read_next_fm(false)) {
506 nb = ::read(fd, buffer, s);
507 if (s != nb) { /* read error */
512 Dmsg0(dbglevel, "EOT during reading\n");
514 @@ -860,36 +944,25 @@
518 - /* open volume descriptor and get this->fd */
524 + prev_FM = next_FM = last_FM = 0;
529 atEOT = atEOD = false;
535 - * read volume to get the last file number
537 -int faketape::find_maxfile()
540 - if (fstat(fd, &statp) != 0) {
543 + if (!read_fm(true)) {
545 + last_file = current_file=0;
547 - last_file = statp.st_size>>FILE_OFFSET;
549 - Dmsg1(dbglevel+1, "last_file=%i\n", last_file);
555 +/* use this to track file usage */
556 void faketape::update_pos()
559 @@ -901,32 +974,12 @@
560 Dmsg1(dbglevel+1, "update_pos=%i\n", file_block);
562 if (file_block > max_block) {
570 -int faketape::seek_file()
573 - ASSERT(current_file >= 0);
574 - Dmsg2(dbglevel, "seek_file %i:%i\n", current_file, current_block);
577 - off_t pos = ((off_t)current_file)<<FILE_OFFSET;
578 - if(lseek(fd, pos, SEEK_SET) == -1) {
582 - last_file = MAX(last_file, current_file);
583 - if (current_block > 0) {
584 - fsr(current_block);
590 void faketape::dump()
592 Dmsg0(dbglevel+1, "===================\n");
593 Index: src/stored/faketape.h
594 ===================================================================
595 --- src/stored/faketape.h (révision 7084)
596 +++ src/stored/faketape.h (copie de travail)
599 int fd; /* Our file descriptor */
601 - off_t file_block; /* size */
602 + off_t file_block; /* size */
605 + off_t prev_FM; /* previous file mark */
606 + off_t last_FM; /* last file mark (current file) */
609 bool atEOF; /* End of file */
610 bool atEOT; /* End of media */
611 bool atEOD; /* End of data */
612 bool atBOT; /* Begin of tape */
613 bool online; /* volume online */
614 - bool inplace; /* have to seek before writing ? */
615 bool needEOF; /* check if last operation need eof */
617 int32_t last_file; /* last file of the volume */
618 int32_t current_file; /* current position */
619 int32_t current_block; /* current position */
620 + int eot_count; /* count eot reads */
623 - int find_maxfile();
627 - void check_eof() { if(needEOF) weof(1);};
628 - void check_inplace() { if (!inplace) seek_file();};
629 + void check_eof() { if(needEOF) weof();};
631 + bool read_fm(bool readfirst);
632 + bool read_next_fm(bool readfirst);
633 + void set_eot() { eot_count=0; atEOT=true;};
636 - int fsf(int count);
639 - int weof(int count);
640 - int bsf(int count);