2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation, which is
11 listed in the file LICENSE.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of John Walker.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
34 static int tape_get(int fd, struct mtget *mt_get);
35 static int tape_op(int fd, struct mtop *mt_com);
36 static int tape_pos(int fd, struct mtpos *mt_pos);
38 static int dbglevel = 0;
41 faketape *ftape_list[FTAPE_MAX_DRIVE];
43 static faketape *get_tape(int fd)
47 if (fd >= FTAPE_MAX_DRIVE) {
52 return ftape_list[fd];
55 static bool put_tape(faketape *ftape)
57 ASSERT(ftape != NULL);
59 int fd = ftape->get_fd();
60 if (fd >= FTAPE_MAX_DRIVE) {
64 ftape_list[fd] = ftape;
68 int faketape_open(const char *pathname, int flags, int mode)
71 faketape *tape = new faketape();
72 fd = tape->open(pathname, flags, mode);
79 int faketape_read(int fd, void *buffer, unsigned int count)
81 faketape *tape = get_tape(fd);
83 return tape->read(buffer, count);
86 int faketape_write(int fd, const void *buffer, unsigned int count)
88 faketape *tape = get_tape(fd);
90 return tape->write(buffer, count);
93 int faketape_close(int fd)
95 faketape *tape = get_tape(fd);
102 int faketape_ioctl(int fd, unsigned long int request, ...)
107 faketape *t = get_tape(fd);
113 va_start(argp, request);
115 // switch (request) {
117 result = t->tape_op(va_arg(argp, mtop *));
121 // result = tape_get(fd, va_arg(argp, mtget *));
125 // result = tape_pos(fd, va_arg(argp, mtpos *));
139 int faketape::tape_op(struct mtop *mt_com)
144 switch (mt_com->mt_op)
160 case MTFSF: /* Forward space over mt_count filemarks. */
161 /* we are already at EOT */
162 if (current_file > max_file) {
168 /* we are at the last file */
169 if (current_file == max_file) {
176 case MTBSF: /* Backward space over mt_count filemarks. */
177 current_file = current_file - mt_op->mt_count;
178 if (current_file < 0) {
189 case MTFSR: /* Forward space over mt_count records (tape blocks). */
197 mt: /dev/lto2: Erreur d'entrée/sortie
202 /* tester si on se trouve a la fin du fichier */
203 fseek(cur_fd, SEEK_CUR, tape_info.block_size*mt_op->mt_count);
206 case MTBSR: /* Backward space over mt_count records (tape blocks). */
212 mt: /dev/lto2: Erreur d'entrée/sortie
218 fstat(cur_file, &statp);
219 off_t cur_pos = lseek(cur_fd, 0, SEEK_CUR);
221 fseek(cur_fd, SEEK_CUR, tape_info.block_size*mt_op->mt_count);
224 case MTWEOF: /* Write mt_count filemarks. */
227 case MTREW: /* Rewind. */
228 atEOF = atEOD = atEOM = false;
233 case MTOFFL: /* put tape offline */
234 // check if can_read/can_write
238 case MTRETEN: /* Re-tension tape. */
242 case MTBSFM: /* not used by bacula */
247 case MTFSFM: /* not used by bacula */
252 case MTEOM:/* Go to the end of the recorded media (for appending files). */
260 /* Ne pas creer le fichier si on est a la fin */
270 delete_files(current_file);
315 // case -1: /* Error has already been translated into errno */
319 // case ERROR_FILEMARK_DETECTED:
323 // case ERROR_END_OF_MEDIA:
327 // case ERROR_NO_DATA_DETECTED:
331 // case ERROR_NO_MEDIA_IN_DRIVE:
332 // errno = ENOMEDIUM;
335 // case ERROR_INVALID_HANDLE:
336 // case ERROR_ACCESS_DENIED:
337 // case ERROR_LOCK_VIOLATION:
342 return result == 0 ? 0 : -1;
345 int faketape::tape_get(struct mtget *mt_get)
350 int faketape::tape_pos(struct mtpos *mt_pos)
355 int faketape::delete_files(int startfile)
364 fp_dir = opendir(this->volume);
373 /* search for all digit file */
374 while ((dir = readdir (fp_dir)) != NULL)
376 Mmsg(tmp, "%s/%s", this->volume, dir->d_name);
378 /* check if d_name contains only digits */
379 for(p = dir->d_name; *p && isdigit(*p); p++)
385 if (cur >= startfile) { /* remove it */
388 if (lstat(tmp.c_str(), &statp) == 0) {
389 this->size += statp.st_size;
391 max = (max > cur)?max:cur;
397 this->max_file = max;
410 volume = get_pool_memory(PM_NAME);
411 cur_file = get_pool_memory(PM_NAME);
412 cur_info = get_pool_memory(PM_NAME);
415 faketape::~faketape()
417 free_pool_memory(volume);
418 free_pool_memory(cur_file);
419 free_pool_memory(cur_info);
422 int faketape::get_fd()
427 int faketape::write(const void *buffer, unsigned int count)
430 if (current_block == -1) {
433 /* remove all file > current_file */
434 return ::write(cur_fd, buffer, count);
437 int faketape::close()
446 int faketape::read(void *buffer, unsigned int count)
449 if (current_block == -1) {
452 return ::read(cur_fd, buffer, count);
455 int faketape::read_volinfo()
458 memset(&tape_info, 0, sizeof(FTAPE_FORMAT));
460 Dmsg2(0, "Info %p %p\n", cur_info, volume);
461 Mmsg(cur_info, "%s/info", volume);
462 fd = ::open(cur_info, O_CREAT | O_RDWR | O_BINARY, 0640);
468 fstat(cur_info, &statp);
470 /* read volume info */
471 int nb = ::read(fd, &tape_info, sizeof(FTAPE_FORMAT));
472 if (nb != sizeof(FTAPE_FORMAT)) { /* new tape ? */
473 Dmsg1(dbglevel, "Initialize %s\n", volume);
474 tape_info.version = 1;
475 tape_info.block_max = 2000000;
476 tape_info.block_size = statp.st_blksize;
477 tape_info.max_file_mark = 2000;
479 lseek(fd, SEEK_SET, 0);
480 nb = ::write(fd, &tape_info, sizeof(FTAPE_FORMAT));
482 if (nb != sizeof(FTAPE_FORMAT)) {
488 Dmsg0(dbglevel, "read_volinfo OK\n");
494 int faketape::open(const char *pathname, int uflags, int umode)
496 Dmsg3(dbglevel, "faketape::open(%s, %i, %i)\n", pathname, uflags, umode);
497 pm_strcpy(volume, pathname);
500 if (lstat(volume, &statp) != 0) {
501 Dmsg1(dbglevel, "Can't stat on %s\n", volume);
505 if (!S_ISDIR(statp.st_mode)) {
506 Dmsg1(dbglevel, "%s is not a directory\n", volume);
511 /* open volume descriptor and get this->fd */
512 if (read_volinfo() < 0) {
521 int faketape::find_maxfile()
531 fp_dir = opendir(this->volume);
539 /* search for all digit file */
540 while ((dir = readdir (fp_dir)) != NULL)
542 Mmsg(tmp, "%s/%s", this->volume, dir->d_name);
543 if (lstat(tmp.c_str(), &statp) == 0) {
544 this->size += statp.st_size;
546 Dmsg1(dbglevel, "Can't stat %s\n", tmp.c_str());
549 /* TODO: compute size */
550 for(p = dir->d_name; *p && isdigit(*p); p++)
556 max = (max > cur)?max:cur;
561 this->max_file = max;
565 int faketape::open_file()
571 Mmsg(cur_file, "%s/%i", volume, current_file);
572 cur_fd = ::open(cur_file, O_CREAT | O_RDWR | O_BINARY, 0640);
577 max_file = (max_file > current_file)?max_file:current_file;
583 void faketape::dump()
585 Dmsg1(dbglevel, "max_file=%i\n", max_file);
586 Dmsg1(dbglevel, "current_file=%i\n", current_file);
587 Dmsg1(dbglevel, "volume=%s\n", volume);
588 Dmsg1(dbglevel, "cur_info=%s\n", cur_info);
589 Dmsg1(dbglevel, "cur_file=%s\n", cur_file);
590 Dmsg1(dbglevel, "size=%i\n", size);
598 printf("Starting FakeTape\n");
600 mkdir("/tmp/fake", 0777);
601 fd = faketape_open("/tmp/fake", O_CREAT | O_RDWR | O_BINARY, 0666);
607 faketape *tape = get_tape(fd);