Imported Upstream version 2.5.1
[debian/amanda] / tape-src / ammt.c
1 #ifdef NO_AMANDA
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <string.h>
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <sys/stat.h>
9
10 #include "output-rait.h"
11
12 extern char *getenv();
13
14 #define tape_open       rait_open
15 #define tapefd_read     rait_read
16 #define tapefd_write    rait_write
17 #define tapefd_fsf      rait_tapefd_fsf
18 #define tapefd_rewind   rait_tapefd_rewind
19 #define tapefd_status   rait_tapefd_status
20 #define tapefd_unload   rait_tapefd_unload
21 #define tapefd_weof     rait_tapefd_weof
22 #define tapefd_setinfo_length(outfd, length)
23 #define tapefd_close    rait_close
24
25 #else
26 #include "amanda.h"
27 #include "tapeio.h"
28 #endif
29
30 extern int optind;
31
32 static int do_asf(int fd, off_t count);
33 static int do_bsf(int fd, off_t count);
34 static int do_status(int fd, off_t count);
35 static void usage(void);
36
37 struct cmd {
38     char *name;
39     size_t min_chars;
40     int count;
41     int (*func)(int, off_t);
42     int flags;
43 } cmd[] = {
44     { "eof",            0,      1,      tapefd_weof,    O_RDWR },
45     { "weof",           0,      1,      tapefd_weof,    O_RDWR },
46     { "fsf",            0,      1,      tapefd_fsf,     O_RDONLY },
47     { "asf",            0,      0,      do_asf,         O_RDONLY },
48     { "bsf",            0,      1,      do_bsf,         O_RDONLY },
49     { "rewind",         0,      0,      (int (*)(int, off_t))tapefd_rewind,
50                                                         O_RDONLY },
51     { "offline",        0,      0,      (int (*)(int, off_t))tapefd_unload,
52                                                         O_RDONLY },
53     { "rewoffl",        0,      0,      (int (*)(int, off_t))tapefd_unload,
54                                                         O_RDONLY },
55     { "status",         0,      0,      do_status,      O_RDONLY },
56     { NULL,             0,      0,      NULL,           0 }
57 };
58
59 static char *pgm;
60 static int debug_ammt = 0;
61
62 static char *tapename;
63
64 static int
65 do_asf(
66     int         fd,
67     off_t       count)
68 {
69     int r;
70
71     if(debug_ammt) {
72         fprintf(stderr, "calling tapefd_rewind()\n");
73     }
74     if(0 != (r = tapefd_rewind(fd))) {
75         return r;
76     }
77     if(debug_ammt) {
78         fprintf(stderr, "calling tapefd_fsf(" OFF_T_FMT ")\n",
79                 (OFF_T_FMT_TYPE)count);
80     }
81     return tapefd_fsf(fd, count);
82 }
83
84 static int
85 do_bsf(
86     int         fd,
87     off_t       count)
88 {
89     if(debug_ammt) {
90         fprintf(stderr, "calling tapefd_fsf(" OFF_T_FMT ")\n", 
91                 (OFF_T_FMT_TYPE)-count);
92     }
93     return tapefd_fsf(fd, -count);
94 }
95
96 static int
97 do_status(
98     int         fd,
99     off_t       count)
100 {
101     int ret;
102     struct am_mt_status stat;
103
104     (void)count;        /* Quiet unused parameter warning */
105
106     if(debug_ammt) {
107         fprintf(stderr, "calling tapefd_status()\n");
108     }
109     if((ret = tapefd_status(fd, &stat)) != 0) {
110         return ret;
111     }
112     printf("%s status:", tapename);
113     if(stat.online_valid) {
114         if(stat.online) {
115             fputs(" ONLINE", stdout);
116         } else {
117             fputs(" OFFLINE", stdout);
118         }
119     }
120     if(stat.bot_valid && stat.bot) {
121         fputs(" BOT", stdout);
122     }
123     if(stat.eot_valid && stat.eot) {
124         fputs(" EOT", stdout);
125     }
126     if(stat.protected_valid && stat.protected) {
127         fputs(" PROTECTED", stdout);
128     }
129     if(stat.device_status_valid) {
130         printf(" ds == 0x%0*lx",
131                stat.device_status_size * 2,
132                (unsigned long)stat.device_status);
133     }
134     if(stat.error_status_valid) {
135         printf(" er == 0x%0*lx",
136                stat.error_status_size * 2,
137                (unsigned long)stat.error_status);
138     }
139     if(stat.fileno_valid) {
140         printf(" fileno == %ld", stat.fileno);
141     }
142     if(stat.blkno_valid) {
143         printf(" blkno == %ld", stat.blkno);
144     }
145
146     putchar('\n');
147     return 0;
148 }
149
150 static void
151 usage(void)
152 {
153     fprintf(stderr, "usage: %s [-d] [-f|-t device] command [count]\n", pgm);
154     exit(1);
155 }
156
157 int
158 main(
159     int         argc,
160     char **     argv)
161 {
162     int ch;
163     off_t count;
164     size_t i;
165     size_t j;
166     int fd;
167     int save_errno;
168     char *s;
169
170     /* Don't die when child closes pipe */
171     signal(SIGPIPE, SIG_IGN);
172
173     if((pgm = strrchr(argv[0], '/')) != NULL) {
174         pgm++;
175     } else {
176         pgm = argv[0];
177     }
178     tapename = getenv("TAPE");
179     while(-1 != (ch = getopt(argc, argv, "df:t:"))) {
180         switch(ch) {
181         case 'd':
182             debug_ammt = 1;
183             fprintf(stderr, "debug mode!\n");
184             break;
185         case 'f':
186         case 't':
187             tapename = stralloc(optarg);
188             break;
189         default:
190             usage();
191             /*NOTREACHED*/
192         }
193     }
194     if(optind >= argc) {
195         usage();
196         /*NOTREACHED*/
197     }
198
199     /*
200      * Compute the minimum abbreviation for each command.
201      */
202     for(i = 0; cmd[i].name; i++) {
203         cmd[i].min_chars = (size_t)1;
204         while (1) {
205             for(j = 0; cmd[j].name; j++) {
206                 if(i == j) {
207                     continue;
208                 }
209                 if(0 == strncmp(cmd[i].name, cmd[j].name,
210                                 cmd[i].min_chars)) {
211                     break;
212                 }
213             }
214             if(0 == cmd[j].name) {
215                 break;
216             }
217             cmd[i].min_chars++;
218         }
219         if(debug_ammt) {
220             fprintf(stderr, "syntax: %-20s -> %*.*s\n",
221                             cmd[i].name,
222                             (int)cmd[i].min_chars,
223                             (int)cmd[i].min_chars,
224                             cmd[i].name);
225         }
226     }
227
228     /*
229      * Process the command.
230      */
231     s = "unknown";
232     j = strlen(argv[optind]);
233     for(i = 0; cmd[i].name; i++) {
234         if(0 == strncmp(cmd[i].name, argv[optind], j)) {
235             if(j >= cmd[i].min_chars) {
236                 break;
237             }
238             s = "ambiguous";
239         }
240     }
241     if(0 == cmd[i].name) {
242         fprintf(stderr, "%s: %s command: %s\n", pgm, s, argv[optind]);
243         exit(1);
244     }
245     optind++;
246     if(0 == tapename) {
247         fprintf(stderr, "%s: -f device or -t device is required\n", pgm);
248         exit(1);
249     }
250     if(debug_ammt) {
251         fprintf(stderr, "tapename is \"%s\"\n", tapename);
252     }
253
254     count = (off_t)1;
255     if(optind < argc && cmd[i].count) {
256         count = OFF_T_ATOI(argv[optind]);
257     }
258
259     if(debug_ammt) {
260         fprintf(stderr, "calling tape_open(\"%s\",%d)\n", tapename, cmd[i].flags);
261     }
262     if((fd = tape_open(tapename, cmd[i].flags, 0)) < 0) {
263         goto report_error;
264     }
265
266     if(debug_ammt) {
267         fprintf(stderr, "processing %s(" OFF_T_FMT ")\n",
268                 cmd[i].name, (OFF_T_FMT_TYPE)count);
269     }
270     if(0 != (*cmd[i].func)(fd, count)) {
271         goto report_error;
272     }
273
274     (void)tapefd_close(fd);
275
276     exit(0);
277
278 report_error:
279
280     save_errno = errno;
281     fprintf(stderr, "%s %s", tapename, cmd[i].name);
282     if(cmd[i].count) {
283         fprintf(stderr, " " OFF_T_FMT, (OFF_T_FMT_TYPE)count);
284     }
285     errno = save_errno;
286     perror(" failed");
287     return (1); /* exit */
288 }