Imported Upstream version 2.5.1
[debian/amanda] / tape-src / amdd.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 #define tape_open       rait_open
13 #define tapefd_read     rait_read
14 #define tapefd_write    rait_write
15 #define tapefd_setinfo_length(outfd, length)
16 #define tapefd_close    rait_close
17
18 #else
19 #include "amanda.h"
20 #include "tapeio.h"
21 #endif
22
23 extern int optind;
24
25 static int debug_amdd = 0;
26 static char *pgm = NULL;
27
28 static void usage(void);
29
30 static void
31 usage(void)
32 {
33     fprintf(stderr, "usage: %s ", pgm);
34     fprintf(stderr, " [-d]");
35     fprintf(stderr, " [-l length]");
36     fprintf(stderr, " [if=input]");
37     fprintf(stderr, " [of=output]");
38     fprintf(stderr, " [bs=blocksize]");
39     fprintf(stderr, " [count=count]");
40     fprintf(stderr, " [skip=count]");
41     fprintf(stderr, "\n");
42     exit(1);
43 }
44
45 static ssize_t (*read_func)(int, void *, size_t);
46 static ssize_t (*write_func)(int, const void *, size_t);
47
48 int
49 main(
50     int         argc,
51     char **     argv)
52 {
53     int infd = 0;                               /* stdin */
54     int outfd = 1;                              /* stdout */
55     size_t blocksize = 512;
56     off_t skip = (off_t)0;
57     ssize_t len;
58     int pread, fread, pwrite, fwrite;
59     int res = 0;
60     char *buf;
61     off_t count = (off_t)0;
62     int have_count = 0;
63     int save_errno;
64     int ch;
65     char *eq;
66     off_t length = (off_t)0;
67     int have_length = 0;
68
69     if((pgm = strrchr(argv[0], '/')) != NULL) {
70         pgm++;
71     } else {
72         pgm = argv[0];
73     }
74     while(-1 != (ch = getopt(argc, argv, "hdl:"))) {
75         switch(ch) {
76         case 'd':
77             debug_amdd = 1;
78             fprintf(stderr, "debug mode!\n");
79             break;
80
81 #ifndef __lint
82         case 'l':
83             have_length = 1;
84             length = OFF_T_ATOI(optarg);
85             len = (ssize_t)strlen(optarg);
86             if(len > 0) {
87                 switch(optarg[len-1] ) {
88                 case 'k':                               break;
89                 case 'b': length /= (off_t)2;           break;
90                 case 'M': length *= (off_t)1024;        break;
91                 default:  length /= (off_t)1024;        break;
92                 }
93             } else {
94                 length /= (off_t)1024;
95             }
96             break;
97 #endif
98         case 'h':
99         default:
100             usage();
101             /*NOTREACHED*/
102         }
103     }
104
105     /*@ignore@*/
106     read_func = read;
107     write_func = write;
108     /*@end@*/
109     for( ; optind < argc; optind++) {
110         if(0 == (eq = strchr(argv[optind], '='))) {
111             usage();
112             /*NOTREACHED*/
113         }
114         len = (ssize_t)(eq - argv[optind]);
115         if(0 == strncmp("if", argv[optind], (size_t)len)) {
116             if((infd = tape_open(eq + 1, O_RDONLY, 0)) < 0) {
117                 save_errno = errno;
118                 fprintf(stderr, "%s: %s: ", pgm, eq + 1);
119                 errno = save_errno;
120                 perror("open");
121                 return 1;
122             }
123             read_func = tapefd_read;
124             if(debug_amdd) {
125                 fprintf(stderr, "input opened \"%s\", got fd %d\n",
126                                 eq + 1, infd);
127             }
128         } else if(0 == strncmp("of", argv[optind], (size_t)len)) {
129             if((outfd = tape_open(eq + 1, O_RDWR|O_CREAT|O_TRUNC, 0644)) < 0) {
130                 save_errno = errno;
131                 fprintf(stderr, "%s: %s: ", pgm, eq + 1);
132                 errno = save_errno;
133                 perror("open");
134                 return 1;
135             }
136             write_func = tapefd_write;
137             if(debug_amdd) {
138                 fprintf(stderr, "output opened \"%s\", got fd %d\n",
139                                 eq + 1, outfd);
140             }
141             if(have_length) {
142                 if(debug_amdd) {
143                     fprintf(stderr, "length set to " OFF_T_FMT "\n",
144                         (OFF_T_FMT_TYPE)length);
145                 }
146                 tapefd_setinfo_length(outfd, length);
147             }
148         } else if(0 == strncmp("bs", argv[optind], (size_t)len)) {
149             blocksize = SIZE_T_ATOI(eq + 1);
150             len = (ssize_t)strlen(argv[optind]);
151             if(len > 0) {
152                 switch(argv[optind][len-1] ) {
153                 case 'k': blocksize *= 1024;            break;
154                 case 'b': blocksize *= 512;             break;
155                 case 'M': blocksize *= 1024 * 1024;     break;
156                 }
157             }
158             if(debug_amdd) {
159                 fprintf(stderr, "blocksize set to " SIZE_T_FMT "\n",
160                         (SIZE_T_FMT_TYPE)blocksize);
161             }
162         } else if(0 == strncmp("count", argv[optind], (size_t)len)) {
163             count = OFF_T_ATOI(eq + 1);
164             have_count = 1;
165             if(debug_amdd) {
166                 fprintf(stderr, "count set to " OFF_T_FMT "\n",
167                         (OFF_T_FMT_TYPE)count);
168             }
169         } else if(0 == strncmp("skip", argv[optind], (size_t)len)) {
170             skip = OFF_T_ATOI(eq + 1);
171             if(debug_amdd) {
172                 fprintf(stderr, "skip set to " OFF_T_FMT "\n",
173                         (OFF_T_FMT_TYPE)skip);
174             }
175         } else {
176             fprintf(stderr, "%s: bad argument: \"%s\"\n", pgm, argv[optind]);
177             return 1;
178         }
179     }
180
181     if(0 == (buf = malloc(blocksize))) {
182         save_errno = errno;
183         fprintf(stderr, "%s: ", pgm);
184         errno = save_errno;
185         perror("malloc error");
186         return 1;
187     }
188
189     eq = "read error";
190     pread = fread = pwrite = fwrite = 0;
191     while(0 < (len = (*read_func)(infd, buf, blocksize))) {
192         if((skip -= (off_t)1) > (off_t)0) {
193             continue;
194         }
195         if((size_t)len == blocksize) {
196             fread++;
197         } else if(len > 0) {
198             pread++;
199         }
200         len = (*write_func)(outfd, buf, (size_t)len);
201         if(len < 0) {
202             eq = "write error";
203             break;
204         } else if((size_t)len == blocksize) {
205             fwrite++;
206         } else if(len > 0) {
207             pwrite++;
208         }
209         if(have_count) {
210             if((count -= (off_t)1) <= (off_t)0) {
211                 len = 0;
212                 break;
213             }
214         }
215     }
216     if(len < 0) {
217         save_errno = errno;
218         fprintf(stderr, "%s: ", pgm);
219         errno = save_errno;
220         perror(eq);
221         res = 1;
222     }
223     fprintf(stderr, "%d+%d in\n%d+%d out\n", fread, pread, fwrite, pwrite);
224     if(read_func == tapefd_read) {
225         if(0 != tapefd_close(infd)) {
226             save_errno = errno;
227             fprintf(stderr, "%s: ", pgm);
228             errno = save_errno;
229             perror("input close");
230             res = 1;
231         }
232     }
233     if(write_func == tapefd_write) {
234         if(0 != tapefd_close(outfd)) {
235             save_errno = errno;
236             fprintf(stderr, "%s: ", pgm);
237             errno = save_errno;
238             perror("output close");
239             res = 1;
240         }
241     }
242     return res;
243 }