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)
70 ASSERT(pathname != NULL);
73 faketape *tape = new faketape();
74 fd = tape->open(pathname, flags, mode);
81 int faketape_read(int fd, void *buffer, unsigned int count)
83 faketape *tape = get_tape(fd);
85 return tape->read(buffer, count);
88 int faketape_write(int fd, const void *buffer, unsigned int count)
90 faketape *tape = get_tape(fd);
92 return tape->write(buffer, count);
95 int faketape_close(int fd)
97 faketape *tape = get_tape(fd);
104 int faketape_ioctl(int fd, unsigned long int request, ...)
109 faketape *t = get_tape(fd);
115 va_start(argp, request);
117 // switch (request) {
119 result = t->tape_op(va_arg(argp, mtop *));
123 // result = tape_get(fd, va_arg(argp, mtget *));
127 // result = tape_pos(fd, va_arg(argp, mtpos *));
141 int faketape::tape_op(struct mtop *mt_com)
145 switch (mt_com->mt_op)
161 case MTFSF: /* Forward space over mt_count filemarks. */
164 case MTBSF: /* Backward space over mt_count filemarks. */
165 current_file = current_file - mt_com->mt_count;
166 if (current_file < 0) {
177 case MTFSR: /* Forward space over mt_count records (tape blocks). */
185 mt: /dev/lto2: Erreur d'entrée/sortie
190 /* tester si on se trouve a la fin du fichier */
191 lseek(cur_fd, SEEK_CUR, tape_info.block_size*mt_com->mt_count);
194 case MTBSR: /* Backward space over mt_count records (tape blocks). */
198 case MTWEOF: /* Write mt_count filemarks. */
199 weof(mt_com->mt_count);
202 case MTREW: /* Rewind. */
204 atEOF = atEOD = false;
210 case MTOFFL: /* put tape offline */
214 case MTRETEN: /* Re-tension tape. */
218 case MTBSFM: /* not used by bacula */
223 case MTFSFM: /* not used by bacula */
228 case MTEOM:/* Go to the end of the recorded media (for appending files). */
236 /* Ne pas creer le fichier si on est a la fin */
246 delete_files(current_file);
291 // case -1: /* Error has already been translated into errno */
295 // case ERROR_FILEMARK_DETECTED:
299 // case ERROR_END_OF_MEDIA:
303 // case ERROR_NO_DATA_DETECTED:
307 // case ERROR_NO_MEDIA_IN_DRIVE:
308 // errno = ENOMEDIUM;
311 // case ERROR_INVALID_HANDLE:
312 // case ERROR_ACCESS_DENIED:
313 // case ERROR_LOCK_VIOLATION:
318 return result == 0 ? 0 : -1;
321 int faketape::tape_get(struct mtget *mt_get)
326 int faketape::tape_pos(struct mtpos *mt_pos)
331 int faketape::delete_files(int startfile)
340 Dmsg1(dbglevel, "delete_files %i\n", startfile);
342 fp_dir = opendir(this->volume);
351 /* search for all digit files
352 * and we remove all ones that are greater than
355 while ((dir = readdir (fp_dir)) != NULL)
357 Mmsg(tmp, "%s/%s", this->volume, dir->d_name);
359 /* check if d_name contains only digits */
360 for(p = dir->d_name; *p && isdigit(*p); p++)
365 if (!*p && cur > 0) {
366 if (cur >= startfile) { /* remove it */
369 if (lstat(tmp.c_str(), &statp) == 0) {
370 this->size += statp.st_size;
372 max = (max > cur)?max:cur;
378 this->last_file = max;
399 volume = get_pool_memory(PM_NAME);
400 cur_file = get_pool_memory(PM_NAME);
401 cur_info = get_pool_memory(PM_NAME);
404 faketape::~faketape()
406 free_pool_memory(volume);
407 free_pool_memory(cur_file);
408 free_pool_memory(cur_info);
411 int faketape::get_fd()
416 int faketape::write(const void *buffer, unsigned int count)
429 /* TODO: remove all files > current_file and
430 * remove blocks > current_block
432 if (count + size > max_size) {
434 "EOT writing only %i of %i requested\n",
435 max_size - size, count);
436 count = max_size - size;
440 nb = ::write(cur_fd, buffer, count);
445 "Not enough space writing only %i of %i requested\n",
452 int faketape::weof(int count)
459 count--; /* end this file */
460 ftruncate(cur_fd, lseek(cur_fd, 0, SEEK_CUR));
464 /* we erase all previous information */
465 if (last_file > current_file) {
466 delete_files(current_file);
469 for (; count>0 ; count--) {
479 int faketape::fsf(int count)
483 * 1 0 -> fsf -> 2 0 -> fsf -> 2 -1
493 if (current_file + count <= last_file) {
494 current_file += count;
498 current_file = last_file;
505 int faketape::bsf(int count)
509 * 1 0 -> fsf -> 2 0 -> fsf -> 2 -1
512 atEOT = atEOD = false;
514 if (current_file - count < 0) {
521 current_file = current_file - count;
531 * Put faketape in offline mode
533 int faketape::offline()
551 int faketape::close_file()
560 int faketape::close()
570 * EOF Bacula status: file=2 block=0
571 * Device status: EOF ONLINE IM_REP_EN file=2 block=0
574 * EOD EOF Bacula status: file=2 block=0
575 * Device status: EOD ONLINE IM_REP_EN file=2 block=-1
579 int faketape::read(void *buffer, unsigned int count)
584 if (atEOT || atEOD) {
590 nb = ::read(cur_fd, buffer, count);
593 if (current_file == last_file) {
597 Dmsg0(dbglevel, "EOF during reading\n");
602 int faketape::read_volinfo()
605 memset(&tape_info, 0, sizeof(FTAPE_FORMAT));
607 Dmsg2(0, "read_volinfo %p %p\n", cur_info, volume);
608 Mmsg(cur_info, "%s/info", volume);
609 fd = ::open(cur_info, O_CREAT | O_RDWR | O_BINARY, 0640);
617 /* read volume info */
618 int nb = ::read(fd, &tape_info, sizeof(FTAPE_FORMAT));
619 if (nb != sizeof(FTAPE_FORMAT)) { /* new tape ? */
620 Dmsg1(dbglevel, "Initialize %s\n", volume);
621 tape_info.version = 1;
622 tape_info.block_max = 2000000;
623 tape_info.block_size = statp.st_blksize;
624 tape_info.max_file_mark = 2000;
626 lseek(fd, SEEK_SET, 0);
627 nb = ::write(fd, &tape_info, sizeof(FTAPE_FORMAT));
629 if (nb != sizeof(FTAPE_FORMAT)) {
635 Dmsg0(dbglevel, "read_volinfo OK\n");
641 int faketape::open(const char *pathname, int uflags, int umode)
643 Dmsg3(dbglevel, "faketape::open(%s, %i, %i)\n", pathname, uflags, umode);
644 pm_strcpy(volume, pathname);
647 if (lstat(volume, &statp) != 0) {
648 Dmsg1(dbglevel, "Can't stat on %s\n", volume);
652 if (!S_ISDIR(statp.st_mode)) {
653 Dmsg1(dbglevel, "%s is not a directory\n", volume);
658 /* open volume descriptor and get this->fd */
659 if (read_volinfo() < 0) {
668 int faketape::find_maxfile()
678 fp_dir = opendir(this->volume);
686 /* search for all digit file */
687 while ((dir = readdir (fp_dir)) != NULL)
689 Mmsg(tmp, "%s/%s", this->volume, dir->d_name);
690 if (lstat(tmp.c_str(), &statp) == 0) {
691 this->size += statp.st_size;
693 Dmsg1(dbglevel, "Can't stat %s\n", tmp.c_str());
696 /* TODO: compute size */
697 for(p = dir->d_name; *p && isdigit(*p); p++)
703 max = (max > cur)?max:cur;
708 this->last_file = max;
712 int faketape::open_file()
714 ASSERT(current_file >= 0);
719 Mmsg(cur_file, "%s/%i", volume, current_file);
720 cur_fd = ::open(cur_file, O_CREAT | O_RDWR | O_BINARY, 0640);
725 last_file = (last_file > current_file)?last_file:current_file;
727 Dmsg1(dbglevel, "open_file %s %i\n", cur_file);
733 void faketape::dump()
735 Dmsg0(dbglevel, "===================\n");
736 Dmsg1(dbglevel, "last_file=%i\n", last_file);
737 Dmsg1(dbglevel, "current_file=%i\n", current_file);
738 Dmsg1(dbglevel, "volume=%s\n", volume);
739 Dmsg1(dbglevel, "cur_file=%s\n", cur_file);
740 Dmsg1(dbglevel, "size=%i\n", size);
741 Dmsg1(dbglevel, "EOF=%i\n", atEOF);
742 Dmsg1(dbglevel, "EOT=%i\n", atEOT);
743 Dmsg1(dbglevel, "EOD=%i\n", atEOD);
746 /****************************************************************
748 #define GMT_EOF(x) ((x) & 0x80000000)
749 #define GMT_BOT(x) ((x) & 0x40000000)
750 #define GMT_EOT(x) ((x) & 0x20000000)
751 #define GMT_SM(x) ((x) & 0x10000000)
752 #define GMT_EOD(x) ((x) & 0x08000000)
755 GMT_EOF(x) : La bande est positionnée juste après une filemark (toujours faux
756 après une opération MTSEEK).
758 GMT_BOT(x) : La bande est positionnée juste au début du premier fichier
759 (toujours faux après une opération MTSEEK).
761 GMT_EOT(x) : Une opération a atteint la fin physique de la bande (End Of
764 GMT_SM(x) : La bande est positionnée sur une setmark (toujours faux après une
767 GMT_EOD(x) : La bande est positionnée à la fin des données enregistrées.
770 blkno = -1 (after MTBSF MTBSS or MTSEEK)
771 fileno = -1 (after MTBSS or MTSEEK)
774 drive type = Generic SCSI-2 tape
780 Tape block size 0 bytes. Density code 0x0 (default).
781 Soft error count since last status=0
782 General status bits on (41010000):
786 dd if=/dev/lto2 of=/tmp/toto count=1
787 dd: lecture de `/dev/lto2': Ne peut allouer de la mémoire
788 0+0 enregistrements lus
789 0+0 enregistrements écrits
790 1 octet (1B) copié, 4,82219 seconde, 0,0 kB/s
796 dd if=/dev/lto2 of=/tmp/toto count=1
797 0+0 enregistrements lus
798 0+0 enregistrements écrits
799 1 octet (1B) copié, 0,167274 seconde, 0,0 kB/s
804 *** write 2 blocks after rewind
805 dd if=/dev/zero of=/dev/lto2 count=2
806 2+0 enregistrements lus
807 2+0 enregistrements écrits
808 1024 octets (1,0 kB) copiés, 6,57402 seconde, 0,2 kB/s
821 *** rewind and 2x fsr (we have just 2 blocks)
826 mt: /dev/lto2: Erreur
831 ****************************************************************/
839 printf("Starting FakeTape\n");
841 mkdir("/tmp/fake", 0777);
842 fd = faketape_open("/tmp/fake", O_CREAT | O_RDWR | O_BINARY, 0666);
848 faketape *tape = get_tape(fd);
849 tape->write("test", strlen("test")+1);
850 tape->write("test", strlen("test")+1);
854 tape->write("test", strlen("test")+1);
855 tape->write("test", strlen("test")+1);