X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fpatches%2Ftesting%2Ffaketape2.patch;h=3b09dd94341f61b6ca96a4dfeb1538176b703d88;hb=8fc14a69f0caa1820e4f24b1e7fb4d822759a60d;hp=34ebb519a3aa86e859a454eca1af69dad2f28b91;hpb=8ada8695eff71254813038ad31d47d5f295ac053;p=bacula%2Fbacula diff --git a/bacula/patches/testing/faketape2.patch b/bacula/patches/testing/faketape2.patch index 34ebb519a3..3b09dd9434 100644 --- a/bacula/patches/testing/faketape2.patch +++ b/bacula/patches/testing/faketape2.patch @@ -1,645 +1,588 @@ -Index: src/stored/faketape.c +Index: src/baconfig.h =================================================================== ---- src/stored/faketape.c (révision 7092) -+++ src/stored/faketape.c (copie de travail) -@@ -170,6 +170,7 @@ - int faketape::tape_op(struct mtop *mt_com) - { - int result=0; -+ int count = mt_com->mt_count; - - if (!online) { - errno = ENOMEDIUM; -@@ -193,11 +194,15 @@ - break; - - case MTFSF: /* Forward space over mt_count filemarks. */ -- result = fsf(mt_com->mt_count); -+ do { -+ result = fsf(); -+ } while (--count > 0 && result == 0); - break; - - case MTBSF: /* Backward space over mt_count filemarks. */ -- result = bsf(mt_com->mt_count); -+ do { -+ result = bsf(); -+ } while (--count > 0 && result == 0); - break; - - case MTFSR: /* Forward space over mt_count records (tape blocks). */ -@@ -222,16 +227,20 @@ - break; - - case MTWEOF: /* Write mt_count filemarks. */ -- result = weof(mt_com->mt_count); -+ do { -+ result = weof(); -+ } while (result == 0 && --count > 0); - break; - - case MTREW: /* Rewind. */ - Dmsg0(dbglevel, "rewind faketape\n"); -+ check_eof(); - atEOF = atEOD = false; - atBOT = true; - current_file = 0; - current_block = 0; -- seek_file(); -+ lseek(fd, 0, SEEK_SET); -+ read_next_fm(true); - break; - - case MTOFFL: /* put tape offline */ -@@ -253,19 +262,28 @@ - break; - - case MTEOM:/* Go to the end of the recorded media (for appending files). */ -+ while (next_FM) { -+ lseek(fd, next_FM, SEEK_SET); -+ read_next_fm(true); -+ } -+ off_t l; -+ while (::read(fd, &l, sizeof(l)) > 0) { -+ if (l) { -+ lseek(fd, l, SEEK_CUR); -+ } else { -+ ASSERT(0); -+ } -+ Dmsg0(dbglevel, "skip 1 block\n"); -+ } -+ current_block = -1; -+ atEOF = false; -+ atEOD = true; -+ - /* - file number = 3 - block number = -1 - */ - /* Can be at EOM */ -- atBOT = false; -- atEOF = false; -- atEOD = true; -- atEOT = false; -- -- current_file = last_file; -- current_block = -1; -- seek_file(); - break; - - case MTERASE: /* not used by bacula */ -@@ -275,7 +293,8 @@ - - current_file = 0; - current_block = -1; -- seek_file(); -+ lseek(fd, 0, SEEK_SET); -+ read_next_fm(true); - truncate_file(); - break; - -@@ -405,8 +424,8 @@ - atEOT = false; - atEOD = false; - online = false; -- inplace = false; - needEOF = false; -+ eot_count = 0; - - file_block = 0; - last_file = 0; -@@ -444,8 +463,6 @@ - return -1; - } - -- check_inplace(); -- - if (!atEOD) { /* if not at the end of the data */ - truncate_file(); - } -@@ -460,14 +477,6 @@ - - needEOF = true; /* next operation need EOF mark */ - --// if ((count + file_size) > max_size) { --// Dmsg2(dbglevel, --// "EOT writing only %i of %i requested\n", --// max_size - file_size, count); --// count = max_size - file_size; --// atEOT = true; --// } -- - uint32_t size = count; - ::write(fd, &size, sizeof(uint32_t)); - nb = ::write(fd, buffer, count); -@@ -484,43 +493,68 @@ - return nb; - } - --int faketape::weof(int count) -+/* -+ * +---+---------+---+------------------+---+-------------------+ -+ * |00N| DATA |0LN| DATA |0LC| DATA | -+ * +---+---------+---+------------------+---+-------------------+ -+ * -+ * 0 : zero -+ * L : Last FileMark offset -+ * N : Next FileMark offset -+ * C : Current FileMark Offset -+ */ -+int faketape::weof() - { - ASSERT(online); - ASSERT(current_file >= 0); - Dmsg3(dbglevel, "Writing EOF %i:%i last=%i\n", - current_file, current_block,last_file); -+ -+ off_t cur_FM; -+ - if (atEOT) { - errno = ENOSPC; - current_block = -1; - return -1; - } -- needEOF = false; - -- check_inplace(); -- truncate_file(); /* nothing after this point */ -+ if (!atEOD) { -+ truncate_file(); /* nothing after this point */ -+ } -+ -+ cur_FM = lseek(fd, 0, SEEK_CUR); // current position - -+ /* update previous next_FM */ -+ lseek(fd, last_FM + sizeof(uint32_t)+sizeof(off_t), SEEK_SET); -+ ::write(fd, &cur_FM, sizeof(off_t)); -+ lseek(fd, cur_FM, SEEK_SET); -+ -+ prev_FM = last_FM; -+ last_FM = cur_FM; -+ next_FM = 0; -+ - uint32_t c=0; -- ::write(fd, &c, sizeof(uint32_t)); -+ ::write(fd, &c, sizeof(uint32_t)); // EOF -+ ::write(fd, &last_FM, sizeof(last_FM)); // F-1 -+ ::write(fd, &next_FM, sizeof(next_FM)); // F (will be updated next time) - -- current_file += count; -+ current_file++; - current_block = 0; -- seek_file(); - -- c=0; -- ::write(fd, &c, sizeof(uint32_t)); -- lseek(fd, lseek(fd, 0, SEEK_CUR) - sizeof(uint32_t), SEEK_SET); +--- src/baconfig.h (revision 7116) ++++ src/baconfig.h (working copy) +@@ -86,12 +86,6 @@ + void InitWinAPIWrapper(); + + #define OSDependentInit() InitWinAPIWrapper() +-#define tape_open win32_tape_open +-#define tape_ioctl win32_tape_ioctl +-#define tape_read win32_tape_read +-#define tape_write win32_tape_write +-#define tape_close win32_tape_close +-#define IS_TAPE(x) S_ISCHR(x) + + #define sbrk(x) 0 + +@@ -117,22 +111,6 @@ + + #define OSDependentInit() + +-#if defined(USE_FAKETAPE) +-# define tape_open faketape_open +-# define tape_ioctl faketape_ioctl +-# define tape_read faketape_read +-# define tape_write faketape_write +-# define tape_close faketape_close +-# define IS_TAPE(x) S_ISREG(x) +-#else /* UNIX && !FAKETAPE */ +-# define tape_open ::open +-# define tape_ioctl ::ioctl +-# define tape_read ::read +-# define tape_write ::write +-# define tape_close ::close +-# define IS_TAPE(x) S_ISCHR(x) +-#endif - -+ needEOF = false; - atEOD = false; - atBOT = false; - atEOF = true; + #endif /* HAVE_WIN32 */ -- update_pos(); -+ last_file = MAX(current_file, last_file); - return 0; - } +Index: src/stored/stored.h +=================================================================== +--- src/stored/stored.h (revision 7116) ++++ src/stored/stored.h (working copy) +@@ -78,10 +78,9 @@ + int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result); + #endif --int faketape::fsf(int count) -+/* -+ * Go to next FM -+ */ -+int faketape::fsf() - { - ASSERT(online); - ASSERT(current_file >= 0); -@@ -528,24 +562,33 @@ - /* - * 1 0 -> fsf -> 2 0 -> fsf -> 2 -1 - */ -- check_inplace(); -- check_eof(); - -- int ret; -+ int ret=0; - if (atEOT || atEOD) { - errno = EIO; - current_block = -1; - return -1; - } +-#ifdef USE_FAKETAPE +-# include "faketape.h" +-#endif ++#include "faketape.h" -- atBOT = atEOF = false; -- Dmsg3(dbglevel+1, "fsf %i+%i <= %i\n", current_file, count, last_file); -+ atBOT = false; -+ Dmsg2(dbglevel+1, "fsf %i <= %i\n", current_file, last_file); - -- if ((current_file + count) <= last_file) { -- current_file += count; -- current_block = 0; -+ if (next_FM > last_FM) { /* not the last file */ -+ lseek(fd, next_FM, SEEK_SET); -+ read_next_fm(true); -+ current_file++; -+ atEOF = true; - ret = 0; -- } else { -+ -+ } else if (atEOF) { /* last file mark */ -+ current_block=-1; -+ errno = EIO; -+ atEOF = false; -+ atEOD = true; + -+ } else { /* last file, but no at the end */ -+ fsr(100000); -+ - Dmsg0(dbglevel, "Try to FSF after EOT\n"); - errno = EIO; - current_file = last_file ; -@@ -553,10 +596,44 @@ - atEOD=true; - ret = -1; - } -- seek_file(); - return ret; + /* Daemon globals from stored.c */ + extern STORES *me; /* "Global" daemon resource */ + extern bool forge_on; /* proceed inspite of I/O errors */ +Index: src/stored/stored_conf.c +=================================================================== +--- src/stored/stored_conf.c (revision 7116) ++++ src/stored/stored_conf.c (working copy) +@@ -213,6 +213,7 @@ + {"dvd", B_DVD_DEV}, + {"fifo", B_FIFO_DEV}, + {"vtl", B_VTL_DEV}, ++ {"faketape", B_FAKETAPE_DEV}, + {NULL, 0} + }; + +Index: src/stored/btape.c +=================================================================== +--- src/stored/btape.c (revision 7116) ++++ src/stored/btape.c (working copy) +@@ -2504,11 +2504,7 @@ + Pmsg1(0, _("Begin writing raw blocks of %u bytes.\n"), block->buf_len); + for ( ;; ) { + *p = block_num; +- if (dev->is_tape()) { +- stat = tape_write(dev->fd(), block->buf, block->buf_len); +- } else { +- stat = write(dev->fd(), block->buf, block->buf_len); +- } ++ stat = dev->d_write(dev->fd(), block->buf, block->buf_len); + if (stat == (int)block->buf_len) { + if ((block_num++ % 100) == 0) { + printf("+"); +Index: src/stored/dev.c +=================================================================== +--- src/stored/dev.c (revision 7116) ++++ src/stored/dev.c (working copy) +@@ -123,10 +123,17 @@ + } + if (S_ISDIR(statp.st_mode)) { + device->dev_type = B_FILE_DEV; +- } else if (IS_TAPE(statp.st_mode)) { /* char device or fake tape */ ++ } else if (S_ISCHR(statp.st_mode)) { + device->dev_type = B_TAPE_DEV; + } else if (S_ISFIFO(statp.st_mode)) { + device->dev_type = B_FIFO_DEV; ++#ifdef USE_FAKETAPE ++ /* must set DeviceType = Faketape ++ * in normal mode, autodetection is disabled ++ */ ++ } else if (S_ISREG(statp.st_mode)) { ++ device->dev_type = B_FAKETAPE_DEV; ++#endif + } else if (!(device->cap_bits & CAP_REQMOUNT)) { + Jmsg2(jcr, M_ERROR, 0, _("%s is an unknown device type. Must be tape or directory\n" + " or have RequiresMount=yes for DVD. st_mode=%x\n"), +@@ -162,6 +169,7 @@ + dev->drive_index = device->drive_index; + dev->autoselect = device->autoselect; + dev->dev_type = device->dev_type; ++ dev->init_backend(); + if (dev->is_tape()) { /* No parts on tapes */ + dev->max_part_size = 0; + } else { +@@ -264,6 +272,34 @@ + return dev; } -+/* /------------\ /---------------\ -+ * +---+------+---+---------------+-+ -+ * |OLN| |0LN| | | -+ * +---+------+---+---------------+-+ -+ */ -+bool faketape::read_next_fm(bool read_all /* read the 0 byte */) ++/* Choose the right backend */ ++void DEVICE::init_backend() +{ -+ prev_FM = last_FM; -+ return read_fm(read_all); -+} ++ if (is_faketape()) { ++ d_open = faketape_open; ++ d_write = faketape_write; ++ d_close = faketape_close; ++ d_ioctl = faketape_ioctl; ++ d_read = faketape_read; + -+bool faketape::read_fm(bool read_all /* read the 0 byte */) -+{ -+ int ret; -+ uint32_t c; -+ if (read_all) { -+ ::read(fd, &c, sizeof(c)); -+ if (c != 0) { -+ lseek(fd, lseek(fd, 0, SEEK_CUR) - sizeof(c), SEEK_SET); -+ return false; -+ } -+ } -+ ::read(fd, &last_FM, sizeof(last_FM)); -+ ret = ::read(fd, &next_FM, sizeof(next_FM)); ++#ifdef HAVE_WIN32 ++ } else if (is_tape()) { ++ d_open = win32_tape_open; ++ d_write = win32_tape_write; ++ d_close = win32_tape_close; ++ d_ioctl = win32_tape_ioctl; ++ d_read = win32_tape_read; ++#endif + -+ current_block=0; -+ -+ Dmsg1(dbglevel, "Read FM next=%lli\n", next_FM); -+ -+ return (ret == sizeof(next_FM)); ++ } else { ++ d_open = ::open; ++ d_write = ::write; ++ d_close = ::close; ++ d_ioctl = ::ioctl; ++ d_read = ::read; ++ } +} + -+/* -+ * TODO: Check fsr with EOF -+ */ - int faketape::fsr(int count) - { - ASSERT(online); -@@ -568,7 +645,6 @@ - uint32_t s; - Dmsg3(dbglevel, "fsr %i:%i count=%i\n", current_file,current_block, count); - -- check_inplace(); - check_eof(); - - if (atEOT) { -@@ -595,20 +671,23 @@ - current_file, current_block, nb,s); - errno = EIO; - ret = -1; -- if (current_file < last_file) { -+ if (next_FM) { - current_block = 0; - current_file++; -- seek_file(); + /* + * Open the device with the operating system and + * initialize buffer pointers. +@@ -285,11 +321,7 @@ + if (openmode == omode) { + return m_fd; + } else { +- if (is_tape()) { +- tape_close(m_fd); +- } else { +- ::close(m_fd); - } -+ read_next_fm(false); -+ } - atEOF = true; /* stop the loop */ - } ++ d_close(m_fd); + clear_opened(); + Dmsg0(100, "Close fd for mode change.\n"); + preserve = state & (ST_LABEL|ST_APPEND|ST_READ); +@@ -368,7 +400,7 @@ + #if defined(HAVE_WIN32) + + /* Windows Code */ +- if ((m_fd = tape_open(dev_name, mode)) < 0) { ++ if ((m_fd = d_open(dev_name, mode)) < 0) { + dev_errno = errno; } -- find_maxfile(); /* refresh stats */ -- - return ret; - } - -+/* -+ * BSR + EOF => begin of EOF + EIO -+ * BSR + BSR + EOF => last block -+ * current_block = -1 -+ */ - int faketape::bsr(int count) - { - Dmsg2(dbglevel, "bsr current_block=%i count=%i\n", -@@ -619,7 +698,6 @@ - ASSERT(count == 1); - ASSERT(fd >= 0); - -- check_inplace(); - check_eof(); - - if (!count) { -@@ -641,22 +719,21 @@ - return -1; - } +@@ -378,7 +410,7 @@ + /* If busy retry each second for max_open_wait seconds */ + for ( ;; ) { + /* Try non-blocking open */ +- m_fd = tape_open(dev_name, mode+O_NONBLOCK); ++ m_fd = d_open(dev_name, mode+O_NONBLOCK); + if (m_fd < 0) { + berrno be; + dev_errno = errno; +@@ -390,10 +422,10 @@ + mt_com.mt_op = MTREW; + mt_com.mt_count = 1; + /* rewind only if dev is a tape */ +- if (is_tape() && (tape_ioctl(m_fd, MTIOCTOP, (char *)&mt_com) < 0)) { ++ if (is_tape() && (d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com) < 0)) { + berrno be; + dev_errno = errno; /* set error status from rewind */ +- tape_close(m_fd); ++ d_close(m_fd); + clear_opened(); + Dmsg2(100, "Rewind error on %s close: ERR=%s\n", print_name(), + be.bstrerror(dev_errno)); +@@ -403,8 +435,8 @@ + } + } else { + /* Got fd and rewind worked, so we must have medium in drive */ +- tape_close(m_fd); +- m_fd = tape_open(dev_name, mode); /* open normally */ ++ d_close(m_fd); ++ m_fd = d_open(dev_name, mode); /* open normally */ + if (m_fd < 0) { + berrno be; + dev_errno = errno; +@@ -688,7 +720,7 @@ + be.bstrerror()); + Dmsg1(100, "open failed: %s", errmsg); + /* Use system close() */ +- ::close(m_fd); ++ d_close(m_fd); + clear_opened(); + } else { + part_size = filestat.st_size; +@@ -732,7 +764,7 @@ + * retrying every 5 seconds. + */ + for (i=max_rewind_wait; ; i -= 5) { +- if (tape_ioctl(m_fd, MTIOCTOP, (char *)&mt_com) < 0) { ++ if (d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com) < 0) { + berrno be; + clrerror(MTREW); + if (i == max_rewind_wait) { +@@ -746,7 +778,7 @@ + */ + if (first && dcr) { + int open_mode = openmode; +- tape_close(m_fd); ++ d_close(m_fd); + clear_opened(); + open(dcr, open_mode); + if (m_fd < 0) { +@@ -886,7 +918,7 @@ + mt_com.mt_count = 1; + } -+ /* at EOF 0:-1 BOT=0 EOD=0 EOF=0 ERR: Input/output error */ - if (atEOF) { -- if (!current_block) { -- if (current_file > 0) { -- current_file--; -- } -- current_block=-1; -- errno = EIO; -- return -1; -- -- } else { -- atEOF=false; -- } -+ lseek(fd, last_FM, SEEK_CUR); -+ atEOF = false; -+ current_block=-1; -+ errno = EIO; -+ return -1; - } +- if (tape_ioctl(m_fd, MTIOCTOP, (char *)&mt_com) < 0) { ++ if (d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com) < 0) { + berrno be; + clrerror(mt_com.mt_op); + Dmsg1(50, "ioctl error: %s\n", be.bstrerror()); +@@ -1030,7 +1062,7 @@ + stat |= BMT_TAPE; + Pmsg0(-20,_(" Bacula status:")); + Pmsg2(-20,_(" file=%d block=%d\n"), dev->file, dev->block_num); +- if (tape_ioctl(dev->fd(), MTIOCGET, (char *)&mt_stat) < 0) { ++ if (dev->d_ioctl(dev->fd(), MTIOCGET, (char *)&mt_stat) < 0) { + berrno be; + dev->dev_errno = errno; + Mmsg2(dev->errmsg, _("ioctl MTIOCGET error on %s. ERR=%s.\n"), +@@ -1157,7 +1189,7 @@ + dev->file_addr = 0; + mt_com.mt_op = MTLOAD; + mt_com.mt_count = 1; +- if (tape_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) { ++ if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) { + berrno be; + dev->dev_errno = errno; + Mmsg2(dev->errmsg, _("ioctl MTLOAD error on %s. ERR=%s.\n"), +@@ -1188,7 +1220,7 @@ + unlock_door(); + mt_com.mt_op = MTOFFL; + mt_com.mt_count = 1; +- if (tape_ioctl(m_fd, MTIOCTOP, (char *)&mt_com) < 0) { ++ if (d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com) < 0) { + berrno be; + dev_errno = errno; + Mmsg2(errmsg, _("ioctl MTOFFL error on %s. ERR=%s.\n"), +@@ -1263,7 +1295,7 @@ + int my_errno = 0; + mt_com.mt_op = MTFSF; + mt_com.mt_count = num; +- stat = tape_ioctl(m_fd, MTIOCTOP, (char *)&mt_com); ++ stat = d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com); + if (stat < 0) { + my_errno = errno; /* save errno */ + } else if ((os_file=get_os_tape_file()) < 0) { +@@ -1344,7 +1376,7 @@ + } + + Dmsg0(100, "Doing MTFSF\n"); +- stat = tape_ioctl(m_fd, MTIOCTOP, (char *)&mt_com); ++ stat = d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com); + if (stat < 0) { /* error => EOT */ + berrno be; + set_eot(); +@@ -1418,7 +1450,7 @@ + file_size = 0; + mt_com.mt_op = MTBSF; + mt_com.mt_count = num; +- stat = tape_ioctl(m_fd, MTIOCTOP, (char *)&mt_com); ++ stat = d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com); + if (stat < 0) { + berrno be; + clrerror(MTBSF); +@@ -1458,7 +1490,7 @@ + Dmsg1(100, "fsr %d\n", num); + mt_com.mt_op = MTFSR; + mt_com.mt_count = num; +- stat = tape_ioctl(m_fd, MTIOCTOP, (char *)&mt_com); ++ stat = d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com); + if (stat == 0) { + clear_eof(); + block_num += num; +@@ -1517,7 +1549,7 @@ + clear_eot(); + mt_com.mt_op = MTBSR; + mt_com.mt_count = num; +- stat = tape_ioctl(m_fd, MTIOCTOP, (char *)&mt_com); ++ stat = d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com); + if (stat < 0) { + berrno be; + clrerror(MTBSR); +@@ -1533,7 +1565,7 @@ + struct mtop mt_com; + mt_com.mt_op = MTLOCK; + mt_com.mt_count = 1; +- tape_ioctl(m_fd, MTIOCTOP, (char *)&mt_com); ++ d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com); + #endif + } -- current_block=0; -- seek_file(); -+ /* -+ * First, go to last_FM and read all blocks to find the good one -+ */ -+ -+ lseek(fd, last_FM, SEEK_CUR); -+ read_fm(true); - - do { - if (!atEOF) { -@@ -700,31 +777,35 @@ - return 0; +@@ -1543,7 +1575,7 @@ + struct mtop mt_com; + mt_com.mt_op = MTUNLOCK; + mt_com.mt_count = 1; +- tape_ioctl(m_fd, MTIOCTOP, (char *)&mt_com); ++ d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com); + #endif } --int faketape::bsf(int count) -+/* BSF => just before last EOF -+ * EOF + BSF => just before EOF -+ * file 0 + BSF => BOT + errno -+ */ -+int faketape::bsf() +@@ -1668,7 +1700,7 @@ + clear_eot(); + mt_com.mt_op = MTWEOF; + mt_com.mt_count = num; +- stat = tape_ioctl(m_fd, MTIOCTOP, (char *)&mt_com); ++ stat = d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com); + if (stat == 0) { + block_num = 0; + file += num; +@@ -1799,7 +1831,7 @@ + /* Found on Solaris */ + #ifdef MTIOCLRERR { - ASSERT(online); - ASSERT(current_file >= 0); -- Dmsg3(dbglevel, "bsf %i:%i count=%i\n", current_file, current_block, count); -+ Dmsg2(dbglevel, "bsf %i:%i count=%i\n", current_file, current_block); - int ret = 0; - -- check_inplace(); - check_eof(); - - atBOT = atEOF = atEOT = atEOD = false; - -- if (current_file - count < 0) { -+ if (current_file == 0) {/* BOT + errno */ -+ lseek(fd, 0, SEEK_SET); -+ read_fm(true); -+ prev_FM = 0; - current_file = 0; - current_block = 0; - atBOT = true; - errno = EIO; - ret = -1; - } else { -- current_file = current_file - count + 1; -- current_block = -1; -- seek_file(); -+ Dmsg1(dbglevel, "bfs last=%lli\n", last_FM); -+ lseek(fd, last_FM, SEEK_SET); - current_file--; -- /* go just before last EOF */ -- lseek(fd, lseek(fd, 0, SEEK_CUR) - sizeof(uint32_t), SEEK_SET); -+ current_block=-1; - } - return ret; +- tape_ioctl(m_fd, MTIOCLRERR); ++ d_ioctl(m_fd, MTIOCLRERR); + Dmsg0(200, "Did MTIOCLRERR\n"); } -@@ -749,6 +830,9 @@ - return 0; + #endif +@@ -1812,7 +1844,7 @@ + union mterrstat mt_errstat; + Dmsg2(200, "Doing MTIOCERRSTAT errno=%d ERR=%s\n", dev_errno, + be.bstrerror(dev_errno)); +- tape_ioctl(m_fd, MTIOCERRSTAT, (char *)&mt_errstat); ++ d_ioctl(m_fd, MTIOCERRSTAT, (char *)&mt_errstat); } - -+/* A filemark is automatically written to tape if the last tape operation -+ * before close was a write. -+ */ - int faketape::close() - { - check_eof(); -@@ -756,18 +840,15 @@ - fd = -1; - return 0; + #endif + +@@ -1823,7 +1855,7 @@ + mt_com.mt_op = MTCSE; + mt_com.mt_count = 1; + /* Clear any error condition on the tape */ +- tape_ioctl(m_fd, MTIOCTOP, (char *)&mt_com); ++ d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com); + Dmsg0(200, "Did MTCSE\n"); } -+ - /* -- **rb -- **status -- * EOF Bacula status: file=2 block=0 -- * Device status: EOF ONLINE IM_REP_EN file=2 block=0 -- **rb -- **status -- * EOD EOF Bacula status: file=2 block=0 -- * Device status: EOD ONLINE IM_REP_EN file=2 block=-1 -- * -+ * When a filemark is encountered while reading, the following happens. If -+ * there are data remaining in the buffer when the filemark is found, the -+ * buffered data is returned. The next read returns zero bytes. The following -+ * read returns data from the next file. The end of recorded data is sig‐ -+ * naled by returning zero bytes for two consecutive read calls. The third -+ * read returns an error. - */ -- - int faketape::read(void *buffer, unsigned int count) - { - ASSERT(online); -@@ -778,6 +859,10 @@ - Dmsg2(dbglevel, "read %i:%i\n", current_file, current_block); - - if (atEOT || atEOD) { -+ if (eot_count < 2) { // first two reads return 0, after EIO -+ eot_count++; -+ return 0; -+ } - errno = EIO; - return -1; - } -@@ -792,10 +877,10 @@ - atEOF=false; + #endif +@@ -1860,10 +1892,8 @@ + case B_VTL_DEV: + case B_TAPE_DEV: + unlock_door(); +- tape_close(m_fd); +- break; + default: +- ::close(m_fd); ++ d_close(m_fd); } -- check_inplace(); - check_eof(); + /* Clean up device packet so it can be reused */ +@@ -2262,11 +2292,7 @@ - atEOD = atBOT = false; -+ eot_count = 0; + get_timer_count(); - /* reading size of data */ - nb = ::read(fd, &s, sizeof(uint32_t)); -@@ -813,11 +898,10 @@ +- if (this->is_tape()) { +- read_len = tape_read(m_fd, buf, len); +- } else { +- read_len = ::read(m_fd, buf, len); +- } ++ read_len = d_read(m_fd, buf, len); - if (!s) { /* EOF */ - atEOF = true; -- if (current_file < last_file) { /* move to next file if possible */ -- current_file++; -- current_block = 0; -- inplace=false; -+ if (read_next_fm(false)) { -+ current_file++; - } -+ - return 0; - } + last_tick = get_timer_count(); -@@ -825,7 +909,7 @@ - nb = ::read(fd, buffer, s); - if (s != nb) { /* read error */ - errno=EIO; -- atEOT = true; -+ set_eot(); - current_block = -1; - Dmsg0(dbglevel, "EOT during reading\n"); - return -1; -@@ -860,36 +944,25 @@ - return -1; - } +@@ -2287,11 +2313,7 @@ -- /* open volume descriptor and get this->fd */ -- find_maxfile(); -- - file_block = 0; - current_block = 0; - current_file = 0; -+ prev_FM = next_FM = last_FM = 0; -+ eot_count = 0; - needEOF = false; -- inplace = true; - atBOT = true; - atEOT = atEOD = false; - -- return fd; --} -- --/* -- * read volume to get the last file number -- */ --int faketape::find_maxfile() --{ -- struct stat statp; -- if (fstat(fd, &statp) != 0) { -- return 0; -+ -+ if (!read_fm(true)) { -+ weof(); -+ last_file = current_file=0; - } -- last_file = statp.st_size>>FILE_OFFSET; -- -- Dmsg1(dbglevel+1, "last_file=%i\n", last_file); + get_timer_count(); -- return last_file; -+ return fd; - } +- if (this->is_tape()) { +- write_len = tape_write(m_fd, buf, len); +- } else { +- write_len = ::write(m_fd, buf, len); +- } ++ write_len = d_write(m_fd, buf, len); -+/* use this to track file usage */ - void faketape::update_pos() - { - ASSERT(online); -@@ -901,32 +974,12 @@ - Dmsg1(dbglevel+1, "update_pos=%i\n", file_block); + last_tick = get_timer_count(); + +@@ -2317,7 +2339,7 @@ + struct mtget mt_stat; - if (file_block > max_block) { -- atEOT = true; -+ set_eot(); + if (has_cap(CAP_MTIOCGET) && +- tape_ioctl(m_fd, MTIOCGET, (char *)&mt_stat) == 0) { ++ d_ioctl(m_fd, MTIOCGET, (char *)&mt_stat) == 0) { + return mt_stat.mt_fileno; + } + return -1; +@@ -2442,7 +2464,7 @@ + mt_com.mt_op = MTSETBLK; + mt_com.mt_count = 0; + Dmsg0(100, "Set block size to zero\n"); +- if (tape_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) { ++ if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) { + dev->clrerror(MTSETBLK); + } + } +@@ -2458,7 +2480,7 @@ + mt_com.mt_count |= MT_ST_FAST_MTEOM; + } + Dmsg0(100, "MTSETDRVBUFFER\n"); +- if (tape_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) { ++ if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) { + dev->clrerror(MTSETDRVBUFFER); + } + } +@@ -2472,13 +2494,13 @@ + dev->min_block_size == 0) { /* variable block mode */ + mt_com.mt_op = MTSETBSIZ; + mt_com.mt_count = 0; +- if (tape_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) { ++ if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) { + dev->clrerror(MTSETBSIZ); + } + /* Get notified at logical end of tape */ + mt_com.mt_op = MTEWARN; + mt_com.mt_count = 1; +- if (tape_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) { ++ if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) { + dev->clrerror(MTEWARN); + } + } +@@ -2491,7 +2513,7 @@ + dev->min_block_size == 0) { /* variable block mode */ + mt_com.mt_op = MTSETBSIZ; + mt_com.mt_count = 0; +- if (tape_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) { ++ if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) { + dev->clrerror(MTSETBSIZ); + } + } +@@ -2502,7 +2524,7 @@ } else { - atEOT = false; + neof = 1; + } +- if (tape_ioctl(dev->fd(), MTIOCSETEOTMODEL, (caddr_t)&neof) < 0) { ++ if (dev->d_ioctl(dev->fd(), MTIOCSETEOTMODEL, (caddr_t)&neof) < 0) { + berrno be; + dev->dev_errno = errno; /* save errno */ + Mmsg2(dev->errmsg, _("Unable to set eotmodel on device %s: ERR=%s\n"), +@@ -2519,7 +2541,7 @@ + dev->min_block_size == 0) { /* variable block mode */ + mt_com.mt_op = MTSRSZ; + mt_com.mt_count = 0; +- if (tape_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) { ++ if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) { + dev->clrerror(MTSRSZ); + } } +@@ -2531,7 +2553,7 @@ + { + Dmsg0(100, "dev_get_os_pos\n"); + return dev->has_cap(CAP_MTIOCGET) && +- tape_ioctl(dev->fd(), MTIOCGET, (char *)mt_stat) == 0 && ++ dev->d_ioctl(dev->fd(), MTIOCGET, (char *)mt_stat) == 0 && + mt_stat->mt_fileno >= 0; } --int faketape::seek_file() --{ -- ASSERT(online); -- ASSERT(current_file >= 0); -- Dmsg2(dbglevel, "seek_file %i:%i\n", current_file, current_block); -- inplace = true; -- -- off_t pos = ((off_t)current_file)< 0) { -- fsr(current_block); -- } -- -- return 0; --} -- - void faketape::dump() - { - Dmsg0(dbglevel+1, "===================\n"); -Index: src/stored/faketape.h +Index: src/stored/faketape.c =================================================================== ---- src/stored/faketape.h (révision 7084) -+++ src/stored/faketape.h (copie de travail) -@@ -56,35 +56,39 @@ - private: - int fd; /* Our file descriptor */ - -- off_t file_block; /* size */ -+ off_t file_block; /* size */ - off_t max_block; - -+ off_t prev_FM; /* previous file mark */ -+ off_t last_FM; /* last file mark (current file) */ -+ off_t next_FM; +--- src/stored/faketape.c (revision 7116) ++++ src/stored/faketape.c (working copy) +@@ -60,7 +60,6 @@ + #include "bacula.h" /* define 64bit file usage */ + #include "stored.h" + +-#ifdef USE_FAKETAPE + #include "faketape.h" + + static int dbglevel = 100; +@@ -992,4 +991,3 @@ + atEOF, atEOT, atEOD, atBOT); + } + +-#endif /* USE_FAKETAPE */ +Index: src/stored/dev.h +=================================================================== +--- src/stored/dev.h (revision 7116) ++++ src/stored/dev.h (working copy) +@@ -95,7 +95,8 @@ + B_TAPE_DEV, + B_DVD_DEV, + B_FIFO_DEV, +- B_VTL_DEV ++ B_FAKETAPE_DEV, /* change to B_TAPE_DEV after init */ ++ B_VTL_DEV + }; + + /* Generic status bits returned from status_dev() */ +@@ -307,11 +308,13 @@ + int is_autochanger() const { return capabilities & CAP_AUTOCHANGER; } + int requires_mount() const { return capabilities & CAP_REQMOUNT; } + int is_removable() const { return capabilities & CAP_REM; } +- int is_tape() const { return dev_type == B_TAPE_DEV; } ++ int is_tape() const { return (dev_type == B_TAPE_DEV || ++ dev_type == B_FAKETAPE_DEV); } + int is_file() const { return dev_type == B_FILE_DEV; } + int is_fifo() const { return dev_type == B_FIFO_DEV; } + int is_dvd() const { return dev_type == B_DVD_DEV; } + int is_vtl() const { return dev_type == B_VTL_DEV; } ++ int is_faketape() const { return dev_type == B_FAKETAPE_DEV; } + int is_open() const { return m_fd >= 0; } + int is_offline() const { return state & ST_OFFLINE; } + int is_labeled() const { return state & ST_LABEL; } +@@ -426,6 +429,14 @@ + uint32_t get_block_num() const { return block_num; }; + int fd() const { return m_fd; }; + ++ /* low level operations */ ++ void init_backend(); ++ int (*d_open)(const char *pathname, int flags, ...); ++ int (*d_read)(int fd, void *buffer, unsigned int count); ++ int (*d_write)(int fd, const void *buffer, unsigned int count); ++ int (*d_close)(int fd); ++ int (*d_ioctl)(int fd, unsigned long int request, ...); + - bool atEOF; /* End of file */ - bool atEOT; /* End of media */ - bool atEOD; /* End of data */ - bool atBOT; /* Begin of tape */ - bool online; /* volume online */ -- bool inplace; /* have to seek before writing ? */ - bool needEOF; /* check if last operation need eof */ - - int32_t last_file; /* last file of the volume */ - int32_t current_file; /* current position */ - int32_t current_block; /* current position */ -+ int eot_count; /* count eot reads */ - - void destroy(); -- int find_maxfile(); - int offline(); - int truncate_file(); -- int seek_file(); -- void check_eof() { if(needEOF) weof(1);}; -- void check_inplace() { if (!inplace) seek_file();}; -+ void check_eof() { if(needEOF) weof();}; + /* + * Locking and blocking calls + */ +Index: src/stored/faketape.h +=================================================================== +--- src/stored/faketape.h (revision 7116) ++++ src/stored/faketape.h (working copy) +@@ -38,8 +38,6 @@ + #include + #include "bacula.h" + +-#ifdef USE_FAKETAPE +- + #define FTAPE_MAX_DRIVE 50 + + /* +@@ -85,7 +83,7 @@ + void check_eof() { if(needEOF) weof();}; void update_pos(); -+ bool read_fm(bool readfirst); -+ bool read_next_fm(bool readfirst); -+ void set_eot() { eot_count=0; atEOT=true;}; + bool read_fm(FT_READ_FM_MODE readfirst); +- void set_eot() { eot_count=0; atEOT=true;}; ++ void set_eot() { atEOT=true;}; public: -- int fsf(int count); -+ int fsf(); - int fsr(int count); -- int weof(int count); -- int bsf(int count); -+ int weof(); -+ int bsf(); - int bsr(int count); - - faketape(); + int fsf(); +@@ -109,5 +107,4 @@ + int tape_pos(struct mtpos *mt_com); + }; + +-#endif /* USE_FAKETAPE */ + #endif /* !FAKETAPE_H */ +Index: src/version.h +=================================================================== +--- src/version.h (revision 7116) ++++ src/version.h (working copy) +@@ -62,7 +62,7 @@ + * run regress test. + */ + #ifdef DEVELOPER +-//#define USE_FAKETAPE ++#define USE_FAKETAPE + #endif + + /*