patch genisoimage multi extent
[platform/upstream/cdrkit.git] / genisoimage / vms.c
1 /*
2  * This file has been modified for the cdrkit suite.
3  *
4  * The behaviour and appearence of the program code below can differ to a major
5  * extent from the version distributed by the original author(s).
6  *
7  * For details, see Changelog file distributed with the cdrkit package. If you
8  * received this file from another source then ask the distributing person for
9  * a log of modifications.
10  *
11  */
12
13 /* @(#)vms.c    1.9 04/03/04 joerg */
14 /*
15  * File vms.c - assorted bletcherous hacks for VMS.
16  *
17  * Written by Eric Youngdale (1993).
18  *
19  */
20
21 #include <mconfig.h>
22 #ifdef VMS
23 #define opendir fake_opendir
24 #include "genisoimage.h"
25 #undef opendir
26 #include <rms.h>
27 #include <descrip.h>
28 #include <ssdef.h>
29
30 static struct RAB       *rab;           /* used for external mailfiles */
31 static int              rms_status;
32
33 static
34 error_exit(char *text)
35 {
36         fprintf(stderr, "%s\n", text);
37         exit(33);
38 }
39
40
41 char *strrchr(const char *, char);
42
43 int
44 VMS_stat(char *path, struct stat * spnt)
45 {
46         char            *spath;
47         char            sbuffer[255];
48         char            *pnt,
49                         *ppnt;
50         char            *pnt1;
51
52         ppnt = strrchr(path, ']');
53         if (ppnt)
54                 ppnt++;
55         else
56                 ppnt = path;
57
58         spath = path;
59
60         if (strcmp(ppnt, ".") == 0 || strcmp(ppnt, "..") == 0) {
61                 strcpy(sbuffer, path);
62
63                 /* Find end of actual name */
64                 pnt = strrchr(sbuffer, ']');
65                 if (!pnt)
66                         return (0);
67
68                 pnt1 = pnt;
69                 while (*pnt1 != '[' && *pnt1 != '.')
70                         pnt1--;
71
72                 if (*pnt1 != '[' && strcmp(ppnt, "..") == 0) {
73                         pnt1--;
74                         while (*pnt1 != '[' && *pnt1 != '.')
75                                 pnt1--;
76                 };
77
78                 if (*pnt1 == '.') {
79                         *pnt1 = ']';
80                         pnt = pnt1;
81                         while (*pnt != '.' && *pnt != ']')
82                                 pnt++;
83                         *pnt++ = ']';
84                         while (*pnt != '.' && *pnt != ']')
85                                 pnt++;
86                         *pnt = 0;
87                         strcat(sbuffer, ".DIR;1");
88                 };
89
90                 if (*pnt1 == '[') {
91                         pnt1++;
92                         *pnt1 = 0;
93                         strcat(pnt1, "000000]");
94                         pnt1 = strrchr(path, '[') + 1;
95                         pnt = sbuffer + strlen(sbuffer);
96                         while (*pnt1 && *pnt1 != '.' && *pnt1 != ']')
97                                 *pnt++ = *pnt1++;
98                         *pnt = 0;
99                         strcat(sbuffer, ".DIR;1");
100                 };
101
102                 spath = sbuffer;
103         };
104         return (stat_filter(spath, spnt));
105 }
106
107 static int              dircontext[32] = {0, };
108 static char             *searchpath[32];
109 static struct direct    d_entry[32];
110
111 int                     optind = 0;
112 char                    *optarg;
113
114 int
115 getopt(int argc, char *argv[], char *flags)
116 {
117         char            *pnt;
118         char            c;
119
120         optind++;
121         if (*argv[optind] != '-')
122                 return (EOF);
123         optarg = 0;
124
125         c = *(argv[optind] + 1);
126         pnt = (char *) strchr(flags, c);
127         if (!pnt)
128                 return (c);     /* Not found */
129         if (pnt[1] == ':') {
130                 optind++;
131                 optarg = argv[optind];
132         };
133         return (c);
134 }
135
136 void
137 vms_path_fixup(char *name)
138 {
139         char            *pnt1;
140
141         pnt1 = name + strlen(name) - 6;
142
143         /* First strip the .DIR;1 */
144         if (strcmp(pnt1, ".DIR;1") == 0)
145                 *pnt1 = 0;
146
147         pnt1 = (char *) strrchr(name, ']');
148         if (pnt1) {
149                 if (pnt1[1] == 0)
150                         return;
151                 *pnt1 = '.';
152                 strcat(name, "]");
153                 return;
154         };
155         pnt1 = (char *) strrchr(name, '>');
156         if (pnt1) {
157                 if (pnt1[1] == 0)
158                         return;
159                 *pnt1 = '.';
160                 strcat(name, ">");
161                 return;
162         };
163 }
164
165 int
166 opendir(char *path)
167 {
168         int             i;
169
170         for (i = 1; i < 32; i++) {
171                 if (dircontext[i] == 0) {
172                         dircontext[i] = -1;
173                         searchpath[i] = (char *) e_malloc(strlen(path) + 6);
174                         strcpy(searchpath[i], path);
175                         vms_path_fixup(searchpath[i]);
176                         strcat(searchpath[i], "*.*.*");
177                         return (i);
178                 };
179         };
180         exit(0);
181 }
182
183 struct direct  *
184 readdir(int context)
185 {
186         int             i;
187         char            cresult[100];
188         char            *pnt;
189         int             status;
190
191         $DESCRIPTOR(dpath, searchpath[context]);
192         $DESCRIPTOR(result, cresult);
193
194         if (dircontext[context] == -1) {
195                 dircontext[context] = -2;
196                 strcpy(d_entry[context].d_name, ".");
197                 return (&d_entry[context]);
198         };
199
200         if (dircontext[context] == -2) {
201                 dircontext[context] = -3;
202                 strcpy(d_entry[context].d_name, "..");
203                 return (&d_entry[context]);
204         };
205
206         if (dircontext[context] == -3)
207                 dircontext[context] = 0;
208
209         dpath.dsc$w_length = strlen(searchpath[context]);
210         lib$find_file(&dpath, &result, &dircontext[context],
211                 0, 0, &status, 0);
212
213         if (status == SS$_NOMOREFILES)
214                 return (0);
215
216         /* Now trim trailing spaces from the name */
217         i = result.dsc$w_length - 1;
218         while (i && cresult[i] == ' ')
219                 i--;
220         cresult[i + 1] = 0;
221
222         /* Now locate the actual portion of the file we want */
223
224         pnt = (char *) strrchr(cresult, ']');
225         if (pnt)
226                 pnt++;
227         else
228                 pnt = cresult;
229
230         strcpy(d_entry[context].d_name, pnt);
231         return (&d_entry[context]);
232 }
233
234 void
235 closedir(int context)
236 {
237         lib$find_file_end(&dircontext[context]);
238         free(searchpath[context]);
239         searchpath[context] = (char *) 0;
240         dircontext[context] = 0;
241 }
242
243 static
244 open_file(char *fn)
245 {
246         /*
247          * this routine initializes a rab and  fab required to get the
248          * correct definition of the external data file used by mail
249          */
250         struct FAB      *fab;
251
252         rab = (struct RAB *) e_malloc(sizeof (struct RAB));
253         fab = (struct FAB *) e_malloc(sizeof (struct FAB));
254
255         *rab = cc$rms_rab;      /* initialize RAB */
256         rab->rab$l_fab = fab;
257
258         *fab = cc$rms_fab;      /* initialize FAB */
259         fab->fab$l_fna = fn;
260         fab->fab$b_fns = strlen(fn);
261         fab->fab$w_mrs = 512;
262         fab->fab$b_fac = FAB$M_BIO | FAB$M_GET;
263         fab->fab$b_org = FAB$C_SEQ;
264         fab->fab$b_rfm = FAB$C_FIX;
265         fab->fab$l_xab = (char *) 0;
266
267         rms_status = sys$open(rab->rab$l_fab);
268         if (rms_status != RMS$_NORMAL && rms_status != RMS$_CREATED)
269                 error_exit("$OPEN");
270         rms_status = sys$connect(rab);
271         if (rms_status != RMS$_NORMAL)
272                 error_exit("$CONNECT");
273         return (1);
274 }
275
276 static
277 close_file(struct RAB * prab)
278 {
279         rms_status = sys$close(prab->rab$l_fab);
280         free(prab->rab$l_fab);
281         free(prab);
282         if (rms_status != RMS$_NORMAL)
283                 error_exit("$CLOSE");
284 }
285
286 #define NSECT 16
287 extern unsigned int last_extent_written;
288
289 int
290 vms_write_one_file(char *filename, off_t size, FILE * outfile)
291 {
292         int             status,
293                         i;
294         char            buffer[SECTOR_SIZE * NSECT];
295         int             count;
296         int             use;
297         off_t           remain;
298
299         open_file(filename);
300
301         remain = size;
302
303         while (remain > 0) {
304                 use = (remain > SECTOR_SIZE * NSECT - 1 ? NSECT * SECTOR_SIZE : remain);
305                 use = ROUND_UP(use);    /* Round up to nearest sector boundary */
306                 memset(buffer, 0, use);
307                 rab->rab$l_ubf = buffer;
308                 rab->rab$w_usz = sizeof (buffer);
309                 status = sys$read(rab);
310                 fwrite(buffer, 1, use, outfile);
311                 last_extent_written += use / SECTOR_SIZE;
312                 if ((last_extent_written % 1000) < use / SECTOR_SIZE)
313                         fprintf(stderr, "%d..", last_extent_written);
314                 remain -= use;
315         };
316
317         close_file(rab);
318 }
319
320 #endif