4
Module for vms <-> unix file name conversion
6
Written by Klaus Kļæ½mpf (kkaempf@progis.de)
7
of proGIS Software, Aachen, Germany
22
#include <lib$routines.h>
23
/* Initialize a string descriptor (struct dsc$descriptor_s) for an
24
arbitrary string. ADDR is a pointer to the first character
25
of the string, and LEN is the length of the string. */
27
#define INIT_DSC_S(dsc, addr, len) do { \
28
(dsc).dsc$b_dtype = DSC$K_DTYPE_T; \
29
(dsc).dsc$b_class = DSC$K_CLASS_S; \
30
(dsc).dsc$w_length = (len); \
31
(dsc).dsc$a_pointer = (addr); \
34
/* Initialize a string descriptor (struct dsc$descriptor_s) for a
35
NUL-terminated string. S is a pointer to the string; the length
36
is determined by calling strlen(). */
38
#define INIT_DSC_CSTRING(dsc, s) INIT_DSC_S(dsc, s, strlen(s))
42
copy 'from' to 'to' up to but not including 'upto'
43
return 0 if eos on from
44
return 1 if upto found
46
return 'to' at last char + 1
47
return 'from' at match + 1 or eos if no match
49
if as_dir == 1, change all '.' to '_'
50
else change all '.' but the last to '_'
54
copyto (char **to, char **from, char upto, int as_dir)
58
s = strrchr (*from, '.');
68
while (**from == upto);
82
**to = toupper (**from);
95
get translation of logical name
103
static char reslt[1024];
104
$DESCRIPTOR (reslt_dsc, reslt);
106
struct dsc$descriptor_s name_dsc;
109
INIT_DSC_CSTRING (name_dsc, name);
111
stat = lib$sys_trnlog (&name_dsc, &resltlen, &reslt_dsc);
117
if (stat == SS$_NOTRAN)
121
reslt[resltlen] = '\0';
123
s = (char *)malloc (resltlen+1);
130
enum namestate { N_START, N_DEVICE, N_OPEN, N_DOT, N_CLOSED, N_DONE };
133
convert unix style name to vms style
134
type = 0 -> name is a full name (directory and filename part)
135
type = 1 -> name is a directory
136
type = 2 -> name is a filename without directory
138
The following conversions are applied
140
input full name dir name file name
142
1 ./ <cwd> [] <current directory>.dir
143
2 ../ <home of cwd> <home of cwd> <home of cwd>.dir
145
3 // <dev of cwd>: <dev of cwd>:[000000] <dev of cwd>:000000.dir
147
5 //a/ a: a: a:000000.dir
149
9 / [000000] [000000] 000000.dir
150
10 /a [000000]a [a] [000000]a
151
11 /a/ [a] [a] [000000]a.dir
152
12 /a/b [a]b [a.b] [a]b
153
13 /a/b/ [a.b] [a.b] [a]b.dir
154
14 /a/b/c [a.b]c [a.b.c] [a.b]c
155
15 /a/b/c/ [a.b.c] [a.b.c] [a.b]c.dir
158
17 a/ [.a] [.a] a.dir
159
18 a/b [.a]b [.a.b] [.a]b
160
19 a/b/ [.a.b] [.a.b] [.a]b.dir
161
20 a/b/c [.a.b]c [.a.b.c] [.a.b]c
162
21 a/b/c/ [.a.b.c] [.a.b.c] [.a.b]c.dir
164
22 a.b.c a_b.c [.a_b_c] a_b_c.dir
166
23 [x][y]z [x.y]z [x.y]z [x.y]z
167
24 [x][.y]z [x.y]z [x.y]z [x.y]z
169
25 filenames with '$' are left unchanged if they contain no '/'
170
25 filenames with ':' are left unchanged
171
26 filenames with a single pair of '[' ']' are left unchanged
173
the input string is not written to
187
#define MAXPATHLEN 512
189
enum namestate nstate;
190
static char vmsname[MAXPATHLEN+1];
205
s = strpbrk (name, "$:");
210
if (strchr (name, '/') == 0)
223
s = strchr (name, '[');
227
s1 = strchr (s+1, '[');
230
return name; /* single [, keep unchanged */
235
return name; /* not ][, keep unchanged */
242
/* s -> starting char
247
strncpy (vptr, s, s1-s); /* copy up to but not including ']' */
251
s = s1 + 1; /* s -> char behind ']' */
252
if (*s != '[') /* was '][' ? */
253
break; /* no, last ] found, exit */
257
s1 = strchr (s, ']');
258
if (s1 == 0) /* no closing ] */
269
else /* no [ in name */
274
int rooted = 1; /* flag if logical is rooted, else insert [000000] */
283
case 0: /* start of loop */
289
else if (*fptr == '.')
298
case 1: /* '/' at start */
308
case 2: /* no '/' at start */
309
s = strchr (fptr, '/');
310
if (s == 0) /* no '/' (16) */
317
copyto (&vptr, &fptr, 0, (type==1));
322
else /* found '/' (17..21) */
325
&& (*(s+1) == 0)) /* 17(2) */
327
copyto (&vptr, &fptr, '/', 1);
334
copyto (&vptr, &fptr, '/', 1);
341
case 3: /* '//' at start */
342
while (*fptr == '/') /* collapse all '/' */
344
if (*fptr == 0) /* just // */
346
char cwdbuf[MAXPATHLEN+1];
348
s1 = getcwd(cwdbuf, MAXPATHLEN);
351
return ""; /* FIXME, err getcwd */
353
s = strchr (s1, ':');
356
return ""; /* FIXME, err no device */
358
strncpy (vptr, s1, s-s1+1);
366
if (copyto (&vptr, &fptr, '/', 1) == 0) /* copy device part */
374
if (*fptr == 0) /* just '//a/' */
376
strcpy (vptr+1, "[000000]");
382
/* check logical for [000000] insertion */
385
{ /* found translation */
387
for (;;) /* loop over all nested logicals */
389
s2 = s1 + strlen (s1) - 1;
390
if (*s2 == ':') /* translation ends in ':' */
400
continue; /* next iteration */
402
if (*s2 == ']') /* translation ends in ']' */
404
if (*(s2-1) == '.') /* ends in '.]' */
406
if (!strneq (fptr, "000000", 6))
411
strcpy (vmsname, s1);
412
s = strchr (vmsname, ']');
435
strcpy (vptr, "[000000.");
443
/* s1-> '.' after 000000 or NULL */
445
s = strchr (fptr, '/');
448
if (*(vptr-1) == '.')
450
else if (rooted == 0)
452
copyto (&vptr, &fptr, 0, (type == 1));
458
while (*(s+1) == '/') /* skip multiple '/' */
463
&& (*(vptr-1) != '.'))
469
if ((nstate == N_DOT)
482
case 4: /* single '/' at start (9..15) */
489
case 5: /* just '/' at start (9) */
495
strcpy (vptr, "000000");
503
case 6: /* chars following '/' at start 10..15 */
506
s = strchr (fptr, '/');
511
strcpy (vptr, "000000]");
514
copyto (&vptr, &fptr, 0, (type == 1));
524
&& (*(s+1) == 0)) /* 11(2) */
526
strcpy (vptr, "000000]");
530
copyto (&vptr, &fptr, '/', (*(vptr-1) != ']'));
535
case 7: /* add '.dir' and exit */
536
if ((nstate == N_OPEN)
537
|| (nstate == N_DOT))
554
strcpy (vptr, ".dir");
559
case 8: /* add ']' and exit */
564
case 9: /* 17..21, fptr -> 1st '/' + 1 */
575
s = strchr (fptr, '/');
580
if (nstate == N_OPEN)
589
if (nstate == N_OPEN)
599
while (*(s+1) == '/')
602
&& (*(s+1) == 0)) /* 19(2), 21(2)*/
604
if (nstate != N_CLOSED)
613
if (nstate == N_OPEN)
621
if ( (*fptr == '.') /* check for '..' or '../' */
622
&& (*(fptr+1) == '.')
623
&& ((*(fptr+2) == '/')
624
|| (*(fptr+2) == 0)) )
633
while (*fptr == '/');
637
vptr--; /* vptr -> '.' or ']' */
642
if (*s1 == '.') /* one back */
648
if (*s1 == '[') /* top level reached */
652
strcpy (s1, "[000000]");
669
copyto (&vptr, &fptr, '/', as_dir);
683
if (type == 2) /* 19,21 */
696
case 10: /* 1,2 first is '.' */
706
case 11: /* 2, '..' at start */
710
if (*fptr != '/') /* got ..xxx */
717
while (*fptr == '/') fptr++;
720
if (*(fptr+1) != '.')
727
while (*fptr == '/');
729
{ /* got '..' or '../' */
735
if (*fptr == 0) /* had '..' or '../' */
740
else /* had '../xxx' */
748
case 12: /* 1, '.' at start */
790
char cwdbuf[MAXPATHLEN+1];
792
s1 = getcwd(cwdbuf, MAXPATHLEN);
795
return "foo"; /*FIXME, err getcwd */
798
vptr += strlen (vptr);
822
for (i = 0; i < 6; i++)
831
strcpy (vptr, ".dir");
848
/* directory conversion done
849
fptr -> filename part of input string
850
vptr -> free space in vmsname
861
convert from vms-style to unix-style
863
dev:[dir1.dir2] //dev/dir1/dir2/
869
static char piece[512];
872
if (strchr (name, '/') != 0) /* already in unix style */
880
s = strchr (name, ':');
895
s = strchr (name, '[');
909
strcat (p, "./"); /* [. */
929
if (*s != 0) /* more after ']' ?? */
933
strcpy (p, s); /* copy it anyway */
937
else /* no '[' anywhere */
943
/* force end with '/' */