X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fpatches%2Ftesting%2Ffaketape.c;h=9284680b6635f8e531595253ef423a4023fdba3d;hb=4c89411092df8f48c412994c0a68bfd8a823067a;hp=17591c26fe9fea1edb6fccdb0758ba3b3ba640d7;hpb=ac68dc7645e9a24aaf438ac5ba533411c8d650a5;p=bacula%2Fbacula diff --git a/bacula/patches/testing/faketape.c b/bacula/patches/testing/faketape.c index 17591c26fe..9284680b66 100644 --- a/bacula/patches/testing/faketape.c +++ b/bacula/patches/testing/faketape.c @@ -26,13 +26,43 @@ Switzerland, email:ftf@fsfeurope.org. */ -#include "faketape.h" -#include -#include -#include +/* + +Device { + Name = Drive-1 # + Maximum File Size = 800M + Maximum Volume Size = 3G + Device Type = TAPE + Archive Device = /tmp/fake + Media Type = DLT-8000 + AutomaticMount = yes; # when device opened, read it + AlwaysOpen = yes; + RemovableMedia = yes; + RandomAccess = no; +} + + Block description : + + block { + int32 size; + void *data; + } -static int dbglevel = 0; + EOF description : + + EOF { + int32 size=0; + } + + + */ + +#include "bacula.h" /* define 64bit file usage */ +#include "stored.h" +#include "faketape.h" +static int dbglevel = 10; +#define FILE_OFFSET 30 faketape *ftape_list[FTAPE_MAX_DRIVE]; static faketape *get_tape(int fd) @@ -60,17 +90,22 @@ static bool put_tape(faketape *ftape) return true; } +void faketape_debug(int level) +{ + dbglevel = level; +} + /****************************************************************/ /* theses function will replace open/read/write/close/ioctl * in bacula core */ -int faketape_open(const char *pathname, int flags, int mode) +int faketape_open(const char *pathname, int flags) { ASSERT(pathname != NULL); int fd; faketape *tape = new faketape(); - fd = tape->open(pathname, flags, mode); + fd = tape->open(pathname, flags); if (fd > 0) { put_tape(tape); } @@ -117,13 +152,9 @@ int faketape_ioctl(int fd, unsigned long int request, ...) result = t->tape_op(va_arg(argp, mtop *)); } else if (request == MTIOCGET) { result = t->tape_get(va_arg(argp, mtget *)); - } -// -// case MTIOCPOS: -// result = tape_pos(fd, va_arg(argp, mtpos *)); -// break; -// - else { + } else if (request == MTIOCPOS) { + result = t->tape_pos(va_arg(argp, mtpos *)); + } else { errno = ENOTTY; result = -1; } @@ -159,16 +190,7 @@ int faketape::tape_op(struct mtop *mt_com) break; case MTBSF: /* Backward space over mt_count filemarks. */ - current_file = current_file - mt_com->mt_count; - if (current_file < 0) { - current_file = 0; - errno = EIO; - result = -1; - } - atEOD = false; - atEOF = false; - atBOT = false; - seek_file(); + result = bsf(mt_com->mt_count); break; case MTFSR: /* Forward space over mt_count records (tape blocks). */ @@ -179,7 +201,7 @@ int faketape::tape_op(struct mtop *mt_com) file number = 1 block number = 1 - mt: /dev/lto2: Erreur d'entrée/sortie + mt: /dev/lto2: Erreur d'entree/sortie file number = 2 block number = 0 @@ -189,14 +211,15 @@ int faketape::tape_op(struct mtop *mt_com) break; case MTBSR: /* Backward space over mt_count records (tape blocks). */ - result = -1; + result = bsr(mt_com->mt_count); break; case MTWEOF: /* Write mt_count filemarks. */ - weof(mt_com->mt_count); + result = weof(mt_com->mt_count); break; case MTREW: /* Rewind. */ + Dmsg0(dbglevel, "rewind faketape\n"); atEOF = atEOD = false; atBOT = true; current_file = 0; @@ -229,19 +252,20 @@ int faketape::tape_op(struct mtop *mt_com) */ /* Can be at EOM */ atBOT = false; - atEOF = true; + atEOF = false; atEOD = true; - current_file = last_file+1; + atEOT = false; + + current_file = last_file; current_block = -1; seek_file(); - /* Ne pas creer le fichier si on est a la fin */ - break; case MTERASE: /* not used by bacula */ atEOD = true; atEOF = false; atEOT = false; + current_file = 0; current_block = -1; seek_file(); @@ -287,36 +311,7 @@ int faketape::tape_op(struct mtop *mt_com) case MTMKPART: break; } -// -// switch (result) { -// case NO_ERROR: -// case -1: /* Error has already been translated into errno */ -// break; -// -// default: -// case ERROR_FILEMARK_DETECTED: -// errno = EIO; -// break; -// -// case ERROR_END_OF_MEDIA: -// errno = EIO; -// break; -// -// case ERROR_NO_DATA_DETECTED: -// errno = EIO; -// break; -// -// case ERROR_NO_MEDIA_IN_DRIVE: -// errno = ENOMEDIUM; -// break; -// -// case ERROR_INVALID_HANDLE: -// case ERROR_ACCESS_DENIED: -// case ERROR_LOCK_VIOLATION: -// errno = EBADF; -// break; -// } -// + return result == 0 ? 0 : -1; } @@ -371,7 +366,12 @@ int faketape::tape_get(struct mtget *mt_get) int faketape::tape_pos(struct mtpos *mt_pos) { - return 0; + if (current_block >= 0) { + mt_pos->mt_blkno = current_block; + return 0; + } + + return -1; } /* @@ -381,7 +381,10 @@ int faketape::tape_pos(struct mtpos *mt_pos) */ int faketape::truncate_file() { + Dmsg2(dbglevel, "truncate %i:%i\n", current_file, current_block); ftruncate(fd, lseek(fd, 0, SEEK_CUR)); + last_file = current_file; + atEOD=true; return 0; } @@ -394,7 +397,9 @@ faketape::faketape() atEOT = false; atEOD = false; online = false; - + inplace = false; + needEOF = false; + file_size = 0; last_file = 0; current_file = 0; @@ -403,12 +408,10 @@ faketape::faketape() max_block = 1024*1024*1024*1024*8; - volume = get_pool_memory(PM_NAME); } faketape::~faketape() { - free_pool_memory(volume); } int faketape::get_fd() @@ -416,31 +419,41 @@ int faketape::get_fd() return this->fd; } +/* + * TODO: check if after a write op, and other tape op put a EOF + */ int faketape::write(const void *buffer, unsigned int count) { - ASSERT(count >= 0); + ASSERT(current_file >= 0); + ASSERT(count > 0); ASSERT(buffer); unsigned int nb; - Dmsg2(dbglevel, "write len=%i blocks=%i\n", count, current_block); + Dmsg3(dbglevel, "write len=%i %i:%i\n", count, current_file,current_block); if (atEOT) { Dmsg0(dbglevel, "write nothing, EOT !\n"); - return 0; + errno = ENOSPC; + return -1; + } + + if (!inplace) { + seek_file(); } if (!atEOD) { /* if not at the end of the data */ truncate_file(); - weof(1); - - } else { /* already writing something */ - if (current_block != -1) { - current_block++; - } + } + + if (current_block != -1) { + current_block++; } atBOT = false; - atEOD = true; + atEOF = false; + atEOD = true; /* End of data */ + + needEOF = true; /* next operation need EOF mark */ // if ((count + file_size) > max_size) { // Dmsg2(dbglevel, @@ -450,10 +463,11 @@ int faketape::write(const void *buffer, unsigned int count) // atEOT = true; // } - ::write(fd, &count, sizeof(count)); + uint32_t size = count; + ::write(fd, &size, sizeof(uint32_t)); nb = ::write(fd, buffer, count); - file_size += sizeof(count) + nb; + file_size += sizeof(uint32_t) + nb; if (nb != count) { atEOT = true; @@ -467,42 +481,49 @@ int faketape::write(const void *buffer, unsigned int count) int faketape::weof(int count) { - Dmsg2(dbglevel, "Writing EOF %i:%i\n", current_file, current_block); + ASSERT(current_file >= 0); + Dmsg3(dbglevel, "Writing EOF %i:%i last=%i\n", + current_file, current_block,last_file); if (atEOT) { + errno = ENOSPC; current_block = -1; return -1; } - - count--; /* end this file */ + needEOF = false; truncate_file(); /* nothing after this point */ - current_file++; - atEOF = true; - atEOD = false; + /* TODO: check this */ + current_file += count; + current_block = 0; - if (count > 0) { - current_block = -1; - return -1; - } else { - current_block = 0; - } + uint32_t c=0; + seek_file(); + ::write(fd, &c, sizeof(uint32_t)); seek_file(); + atEOD = false; + atBOT = false; + atEOF = true; + return 0; } int faketape::fsf(int count) { + ASSERT(current_file >= 0); + ASSERT(fd >= 0); /* * 1 0 -> fsf -> 2 0 -> fsf -> 2 -1 */ + check_eof(); + int ret; if (atEOT) { current_block = -1; return -1; } - atEOF=1; + atBOT = atEOF = false; Dmsg3(dbglevel+1, "fsf %i+%i <= %i\n", current_file, count, last_file); if ((current_file + count) <= last_file) { @@ -516,65 +537,152 @@ int faketape::fsf(int count) atEOD=true; ret = -1; } - seek_file(); return ret; } int faketape::fsr(int count) { - int i,nb; - off_t where=0, s; - Dmsg2(dbglevel, "fsr current_block=%i count=%i\n", current_block, count); + ASSERT(current_file >= 0); + ASSERT(fd >= 0); + + int i,nb, ret=0; + off_t where=0; + uint32_t s; + Dmsg3(dbglevel, "fsr %i:%i count=%i\n", current_file,current_block, count); + + check_eof(); if (atEOT) { + errno = EIO; current_block = -1; return -1; } + if (atEOD) { + errno = EIO; + return -1; + } + + atBOT = atEOF = false; + /* check all block record */ - for(i=0; (i < count) && (where != -1) ; i++) { - nb = ::read(fd, &s, sizeof(s)); /* get size of block */ - if (nb == sizeof(s)) { + for(i=0; (i < count) && !atEOF ; i++) { + nb = ::read(fd, &s, sizeof(uint32_t)); /* get size of next block */ + if (nb == sizeof(uint32_t) && s) { current_block++; - where = lseek(fd, s, SEEK_CUR); /* seek after this block */ - if (where == -1) { - errno = EIO; - return -1; - } + where = lseek(fd, s, SEEK_CUR); /* seek after this block */ } else { + Dmsg4(dbglevel, "read EOF %i:%i nb=%i s=%i\n", + current_file, current_block, nb,s); errno = EIO; - return -1; + ret = -1; + if (current_file < last_file) { + current_block = 0; + current_file++; + seek_file(); + } + atEOF = true; /* stop the loop */ } } + find_maxfile(); /* refresh stats */ if (where == file_size) { - atBOT = false; atEOD = true; } + return ret; +} + +int faketape::bsr(int count) +{ + Dmsg2(dbglevel, "bsr current_block=%i count=%i\n", + current_block, count); + + ASSERT(current_file >= 0); + ASSERT(count == 1); + ASSERT(fd >= 0); + + check_eof(); + + if (!count) { + return 0; + } + + int ret=0; + int last_f=0; + int last_b=0; + + off_t last=-1, last2=-1; + off_t orig = lseek(fd, 0, SEEK_CUR); + int orig_f = current_file; + int orig_b = current_block; + + current_block=0; + seek_file(); + + do { + if (!atEOF) { + last2 = last; + last = lseek(fd, 0, SEEK_CUR); + last_f = current_file; + last_b = current_block; + Dmsg5(dbglevel, "EOF=%i last=%lli orig=%lli %i:%i\n", + atEOF, last, orig, current_file, current_block); + } + ret = fsr(1); + } while ((lseek(fd, 0, SEEK_CUR) < orig) && (ret == 0)); + + if (last2 > 0 && atEOF) { /* we take the previous position */ + lseek(fd, last2, SEEK_SET); + current_file = last_f; + current_block = last_b - 1; + Dmsg3(dbglevel, "set offset2=%lli %i:%i\n", + last, current_file, current_block); + + } else if (last > 0) { + lseek(fd, last, SEEK_SET); + current_file = last_f; + current_block = last_b; + Dmsg3(dbglevel, "set offset=%lli %i:%i\n", + last, current_file, current_block); + } else { + lseek(fd, orig, SEEK_SET); + current_file = orig_f; + current_block = orig_b; + return -1; + } + + Dmsg2(dbglevel, "bsr %i:%i\n", current_file, current_block); + atEOT = atEOF = atEOD = false; + return 0; } int faketape::bsf(int count) { - int ret = 1; - atEOT = atEOD = false; + ASSERT(current_file >= 0); + Dmsg3(dbglevel, "bsf %i:%i count=%i\n", current_file, current_block, count); + int ret = 0; + + check_eof(); + atBOT = atEOF = atEOT = atEOD = false; if (current_file - count < 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(); + current_file--; + /* go just before last EOF */ + lseek(fd, lseek(fd, 0, SEEK_CUR) - sizeof(uint32_t), SEEK_SET); } - - current_file = current_file - count; - current_block = 0; - if (!current_file) { - atBOT = true; - } - seek_file(); - return 0; + return ret; } /* @@ -584,10 +692,10 @@ int faketape::offline() { close(); - atEOF = false; - atEOT = false; - atEOD = false; - atBOT = false; + atEOF = false; /* End of file */ + atEOT = false; /* End of tape */ + atEOD = false; /* End of data */ + atBOT = false; /* Begin of tape */ current_file = -1; current_block = -1; @@ -597,6 +705,7 @@ int faketape::offline() int faketape::close() { + check_eof(); ::close(fd); fd = -1; return 0; @@ -615,21 +724,46 @@ int faketape::close() int faketape::read(void *buffer, unsigned int count) { - unsigned int nb, s; + ASSERT(current_file >= 0); + unsigned int nb; + uint32_t s; + + Dmsg2(dbglevel, "read %i:%i\n", current_file, current_block); if (atEOT || atEOD) { return 0; } - atBOT = false; + if (atEOF) { + current_file++; + current_block=0; + inplace = false; + atEOF = false; + } + + if (!inplace) { + seek_file(); + } + + atEOD = atBOT = false; current_block++; - nb = ::read(fd, &s, sizeof(s)); - if (s > count) { + nb = ::read(fd, &s, sizeof(uint32_t)); + if (nb <= 0) { + atEOF = true; + return 0; + } + if (s > count) { /* not enough buffer to read block */ + Dmsg2(dbglevel, "Need more buffer to read next block %i > %i\n",s,count); lseek(fd, s, SEEK_CUR); errno = ENOMEM; return -1; } + if (!s) { /* EOF */ + atEOF = true; + lseek(fd, lseek(fd, 0, SEEK_CUR) - sizeof(uint32_t), SEEK_SET); + return 0; + } nb = ::read(fd, buffer, s); if (s != nb) { atEOF = true; @@ -642,18 +776,17 @@ int faketape::read(void *buffer, unsigned int count) return nb; } -int faketape::open(const char *pathname, int uflags, int umode) +int faketape::open(const char *pathname, int uflags) { - Dmsg3(dbglevel, "faketape::open(%s, %i, %i)\n", pathname, uflags, umode); - pm_strcpy(volume, pathname); + Dmsg2(dbglevel, "faketape::open(%s, %i)\n", pathname, uflags); struct stat statp; - if (stat(volume, &statp) != 0) { - Dmsg1(dbglevel, "Can't stat on %s\n", volume); + if (stat(pathname, &statp) != 0) { + Dmsg1(dbglevel, "Can't stat on %s\n", pathname); return -1; } - fd = ::open(pathname, O_CREAT | O_RDWR, 0700); + fd = ::open(pathname, O_CREAT | O_RDWR | O_LARGEFILE, 0700); if (fd < 0) { return -1; } @@ -663,7 +796,12 @@ int faketape::open(const char *pathname, int uflags, int umode) return -1; } - current_block=-1; + current_block = 0; + current_file = 0; + needEOF = false; + online = inplace = true; + atBOT = true; + atEOT = atEOD = false; return fd; } @@ -674,25 +812,34 @@ int faketape::open(const char *pathname, int uflags, int umode) int faketape::find_maxfile() { struct stat statp; - fstat(fd, &statp); - last_file = statp.st_size % ((off_t)1<<32); + if (fstat(fd, &statp) != 0) { + return 0; + } + last_file = statp.st_size>>FILE_OFFSET; file_size = statp.st_size; current_pos = lseek(fd, 0, SEEK_CUR); /* get current position */ + Dmsg3(dbglevel+1, "last_file=%i file_size=%u current_pos=%i\n", + last_file, file_size, current_pos); return last_file; } int faketape::seek_file() { + ASSERT(current_file >= 0); Dmsg2(dbglevel, "seek_file %i:%i\n", current_file, current_block); - off_t pos = ((off_t)current_file)<<32; + off_t pos = ((off_t)current_file)< current_file)?last_file:current_file; + if (current_block > 0) { + fsr(current_block); + } + inplace = true; + return 0; } @@ -701,115 +848,7 @@ void faketape::dump() Dmsg0(dbglevel+1, "===================\n"); Dmsg2(dbglevel, "file:block = %i:%i\n", current_file, current_block); Dmsg1(dbglevel+1, "last_file=%i\n", last_file); - Dmsg1(dbglevel+1, "volume=%s\n", volume); Dmsg1(dbglevel+1, "file_size=%i\n", file_size); - Dmsg1(dbglevel+1, "EOF=%i\n", atEOF); - Dmsg1(dbglevel+1, "EOT=%i\n", atEOT); - Dmsg1(dbglevel+1, "EOD=%i\n", atEOD); -} - -/**************************************************************** - -#define GMT_EOF(x) ((x) & 0x80000000) -#define GMT_BOT(x) ((x) & 0x40000000) -#define GMT_EOT(x) ((x) & 0x20000000) -#define GMT_SM(x) ((x) & 0x10000000) -#define GMT_EOD(x) ((x) & 0x08000000) - - - GMT_EOF(x) : La bande est positionnée juste après une filemark (toujours faux - après une opération MTSEEK). - - GMT_BOT(x) : La bande est positionnée juste au début du premier fichier - (toujours faux après une opération MTSEEK). - - GMT_EOT(x) : Une opération a atteint la fin physique de la bande (End Of - Tape). - - GMT_SM(x) : La bande est positionnée sur une setmark (toujours faux après une - opération MTSEEK). - - GMT_EOD(x) : La bande est positionnée à la fin des données enregistrées. - - -blkno = -1 (after MTBSF MTBSS or MTSEEK) -fileno = -1 (after MTBSS or MTSEEK) - -*** mtx load -drive type = Generic SCSI-2 tape -drive status = 0 -sense key error = 0 -residue count = 0 -file number = 0 -block number = 0 -Tape block size 0 bytes. Density code 0x0 (default). -Soft error count since last status=0 -General status bits on (41010000): - BOT ONLINE IM_REP_EN - -*** read empty block -dd if=/dev/lto2 of=/tmp/toto count=1 -dd: lecture de `/dev/lto2': Ne peut allouer de la mémoire -0+0 enregistrements lus -0+0 enregistrements écrits -1 octet (1B) copié, 4,82219 seconde, 0,0 kB/s - -file number = 0 -block number = 1 - -*** read file mark -dd if=/dev/lto2 of=/tmp/toto count=1 -0+0 enregistrements lus -0+0 enregistrements écrits -1 octet (1B) copié, 0,167274 seconde, 0,0 kB/s - -file number = 1 -block number = 0 - - *** write 2 blocks after rewind -dd if=/dev/zero of=/dev/lto2 count=2 -2+0 enregistrements lus -2+0 enregistrements écrits -1024 octets (1,0 kB) copiés, 6,57402 seconde, 0,2 kB/s - -file number = 1 -block number = 0 - -*** write 2 blocks -file number = 2 -block number = 0 - -*** rewind and fsr -file number = 0 -block number = 1 - -*** rewind and 2x fsr (we have just 2 blocks) -file number = 0 -block number = 2 - -*** fsr -mt: /dev/lto2: Erreur -file number = 1 -block number = 0 - - - ****************************************************************/ - - -#ifdef TEST - -int main() -{ - int fd; - char buf[500]; - printf("Starting FakeTape\n"); - - mkdir("/tmp/fake", 0700); - - - - - return 0; + Dmsg4(dbglevel+1, "EOF=%i EOT=%i EOD=%i BOT=%i\n", + atEOF, atEOT, atEOD, atBOT); } - -#endif