4 Module for vms <-> unix file name conversion
6 Written by Klaus Kämpf (kkaempf@progis.de)
7 of proGIS Software, Aachen, Germany
23 #include <lib$routines.h>
24 /* Initialize a string descriptor (struct dsc$descriptor_s) for an
25 arbitrary string. ADDR is a pointer to the first character
26 of the string, and LEN is the length of the string. */
28 #define INIT_DSC_S(dsc, addr, len) do { \
29 (dsc).dsc$b_dtype = DSC$K_DTYPE_T; \
30 (dsc).dsc$b_class = DSC$K_CLASS_S; \
31 (dsc).dsc$w_length = (len); \
32 (dsc).dsc$a_pointer = (addr); \
35 /* Initialize a string descriptor (struct dsc$descriptor_s) for a
36 NUL-terminated string. S is a pointer to the string; the length
37 is determined by calling strlen(). */
39 #define INIT_DSC_CSTRING(dsc, s) INIT_DSC_S(dsc, s, strlen(s))
43 copy 'from' to 'to' up to but not including 'upto'
44 return 0 if eos on from
45 return 1 if upto found
47 return 'to' at last char + 1
48 return 'from' at match + 1 or eos if no match
50 if as_dir == 1, change all '.' to '_'
51 else change all '.' but the last to '_'
55 copyto (char **to
, char **from
, char upto
, int as_dir
)
59 s
= strrchr (*from
, '.');
69 while (**from
== upto
);
82 if (isupper ((unsigned char)**from
))
83 **to
= tolower ((unsigned char)**from
);
96 get translation of logical name
104 static char reslt
[1024];
105 $
DESCRIPTOR (reslt_dsc
, reslt
);
107 struct dsc$descriptor_s name_dsc
;
110 INIT_DSC_CSTRING (name_dsc
, name
);
112 stat
= lib$
sys_trnlog (&name_dsc
, &resltlen
, &reslt_dsc
);
118 if (stat
== SS$_NOTRAN
)
122 reslt
[resltlen
] = '\0';
124 s
= (char *)malloc (resltlen
+1);
138 if (strchr (s
, '\\') == 0)
152 enum namestate
{ N_START
, N_DEVICE
, N_OPEN
, N_DOT
, N_CLOSED
, N_DONE
};
155 convert unix style name to vms style
156 type = 0 -> name is a full name (directory and filename part)
157 type = 1 -> name is a directory
158 type = 2 -> name is a filename without directory
160 The following conversions are applied
162 input full name dir name file name
164 1 ./ <cwd> [] <current directory>.dir
165 2 ../ <home of cwd> <home of cwd> <home of cwd>.dir
167 3 // <dev of cwd>: <dev of cwd>:[000000] <dev of cwd>:000000.dir
169 5 //a/ a: a: a:000000.dir
171 9 / [000000] [000000] 000000.dir
172 10 /a [000000]a [a] [000000]a
173 11 /a/ [a] [a] [000000]a.dir
174 12 /a/b [a]b [a.b] [a]b
175 13 /a/b/ [a.b] [a.b] [a]b.dir
176 14 /a/b/c [a.b]c [a.b.c] [a.b]c
177 15 /a/b/c/ [a.b.c] [a.b.c] [a.b]c.dir
180 17 a/ [.a] [.a] a.dir
181 18 a/b [.a]b [.a.b] [.a]b
182 19 a/b/ [.a.b] [.a.b] [.a]b.dir
183 20 a/b/c [.a.b]c [.a.b.c] [.a.b]c
184 21 a/b/c/ [.a.b.c] [.a.b.c] [.a.b]c.dir
186 22 a.b.c a_b.c [.a_b_c] a_b_c.dir
188 23 [x][y]z [x.y]z [x.y]z [x.y]z
189 24 [x][.y]z [x.y]z [x.y]z [x.y]z
191 25 filenames with '$' are left unchanged if they contain no '/'
192 25 filenames with ':' are left unchanged
193 26 filenames with a single pair of '[' ']' are left unchanged
195 the input string is not written to
199 vmsify (char *name
, int type
)
207 #define MAXPATHLEN 512
209 enum namestate nstate
;
210 static char vmsname
[MAXPATHLEN
+1];
225 s
= strpbrk (name
, "$:");
233 s1
= strchr (s
+1, '[');
234 s2
= strchr (s
+1, ']');
239 if (strchr (name
, '/') == 0)
241 if ((type
== 1) && (s1
!= 0) && (s2
== 0))
243 strcpy (vmsname
, name
);
244 strcat (vmsname
, "]");
253 if ((type
== 1) && (s1
!= 0) && (s2
== 0))
255 strcpy (vmsname
, name
);
256 strcat (vmsname
, "]");
266 s
= strchr (name
, '[');
270 s1
= strchr (s
+1, '[');
274 && (strchr (s
+1, ']') == 0))
276 strcpy (vmsname
, name
);
277 strcat (vmsname
, "]");
281 return name
; /* single [, keep unchanged */
286 return name
; /* not ][, keep unchanged */
293 /* s -> starting char
298 strncpy (vptr
, s
, s1
-s
); /* copy up to but not including ']' */
302 s
= s1
+ 1; /* s -> char behind ']' */
303 if (*s
!= '[') /* was '][' ? */
304 break; /* no, last ] found, exit */
308 s1
= strchr (s
, ']');
309 if (s1
== 0) /* no closing ] */
320 else /* no [ in name */
325 int rooted
= 1; /* flag if logical is rooted, else insert [000000] */
334 case 0: /* start of loop */
340 else if (*fptr
== '.')
349 case 1: /* '/' at start */
359 case 2: /* no '/' at start */
360 s
= strchr (fptr
, '/');
361 if (s
== 0) /* no '/' (16) */
368 copyto (&vptr
, &fptr
, 0, (type
==1));
373 else /* found '/' (17..21) */
376 && (*(s
+1) == 0)) /* 17(2) */
378 copyto (&vptr
, &fptr
, '/', 1);
385 copyto (&vptr
, &fptr
, '/', 1);
392 case 3: /* '//' at start */
393 while (*fptr
== '/') /* collapse all '/' */
395 if (*fptr
== 0) /* just // */
397 char cwdbuf
[MAXPATHLEN
+1];
399 s1
= getcwd(cwdbuf
, MAXPATHLEN
);
402 return ""; /* FIXME, err getcwd */
404 s
= strchr (s1
, ':');
407 return ""; /* FIXME, err no device */
409 strncpy (vptr
, s1
, s
-s1
+1);
417 if (copyto (&vptr
, &fptr
, '/', 1) == 0) /* copy device part */
425 if (*fptr
== 0) /* just '//a/' */
427 strcpy (vptr
+1, "[000000]");
433 /* check logical for [000000] insertion */
436 { /* found translation */
438 for (;;) /* loop over all nested logicals */
440 s2
= s1
+ strlen (s1
) - 1;
441 if (*s2
== ':') /* translation ends in ':' */
451 continue; /* next iteration */
453 if (*s2
== ']') /* translation ends in ']' */
455 if (*(s2
-1) == '.') /* ends in '.]' */
457 if (strncmp (fptr
, "000000", 6) != 0)
462 strcpy (vmsname
, s1
);
463 s
= strchr (vmsname
, ']');
486 strcpy (vptr
, "[000000.");
494 /* s1-> '.' after 000000 or NULL */
496 s
= strchr (fptr
, '/');
499 if (*(vptr
-1) == '.')
501 else if (rooted
== 0)
503 copyto (&vptr
, &fptr
, 0, (type
== 1));
509 while (*(s
+1) == '/') /* skip multiple '/' */
514 && (*(vptr
-1) != '.'))
520 if ((nstate
== N_DOT
)
533 case 4: /* single '/' at start (9..15) */
540 case 5: /* just '/' at start (9) */
546 strcpy (vptr
, "000000");
554 case 6: /* chars following '/' at start 10..15 */
557 s
= strchr (fptr
, '/');
562 strcpy (vptr
, "000000]");
565 copyto (&vptr
, &fptr
, 0, (type
== 1));
575 && (*(s
+1) == 0)) /* 11(2) */
577 strcpy (vptr
, "000000]");
581 copyto (&vptr
, &fptr
, '/', (*(vptr
-1) != ']'));
586 case 7: /* add '.dir' and exit */
587 if ((nstate
== N_OPEN
)
588 || (nstate
== N_DOT
))
605 strcpy (vptr
, ".dir");
610 case 8: /* add ']' and exit */
615 case 9: /* 17..21, fptr -> 1st '/' + 1 */
626 s
= strchr (fptr
, '/');
631 if (nstate
== N_OPEN
)
640 if (nstate
== N_OPEN
)
650 while (*(s
+1) == '/')
653 && (*(s
+1) == 0)) /* 19(2), 21(2)*/
655 if (nstate
!= N_CLOSED
)
664 if (nstate
== N_OPEN
)
672 if ( (*fptr
== '.') /* check for '..' or '../' */
673 && (*(fptr
+1) == '.')
674 && ((*(fptr
+2) == '/')
675 || (*(fptr
+2) == 0)) )
684 while (*fptr
== '/');
688 vptr
--; /* vptr -> '.' or ']' */
693 if (*s1
== '.') /* one back */
699 if (*s1
== '[') /* top level reached */
703 strcpy (s1
, "[000000]");
720 copyto (&vptr
, &fptr
, '/', as_dir
);
734 if (type
== 2) /* 19,21 */
747 case 10: /* 1,2 first is '.' */
757 case 11: /* 2, '..' at start */
761 if (*fptr
!= '/') /* got ..xxx */
768 while (*fptr
== '/') fptr
++;
771 if (*(fptr
+1) != '.')
778 while (*fptr
== '/');
780 { /* got '..' or '../' */
781 char cwdbuf
[MAXPATHLEN
+1];
783 s1
= getcwd(cwdbuf
, MAXPATHLEN
);
786 return ""; /* FIXME, err getcwd */
789 s
= strchr (vptr
, ']');
799 strcpy (s
, "000000]");
807 if (*fptr
== 0) /* had '..' or '../' */
812 else /* had '../xxx' */
822 vptr
+= strlen (vptr
);
826 case 12: /* 1, '.' at start */
838 char cwdbuf
[MAXPATHLEN
+1];
840 s1
= getcwd(cwdbuf
, MAXPATHLEN
);
843 return ""; /*FIXME, err getcwd */
853 s
= strchr (vptr
, ']');
861 vptr
+= strlen (vptr
);
875 /* directory conversion done
876 fptr -> filename part of input string
877 vptr -> free space in vmsname
888 convert from vms-style to unix-style
890 dev:[dir1.dir2] //dev/dir1/dir2/
896 static char piece
[512];
899 if (strchr (name
, '/') != 0) /* already in unix style */
907 s
= strchr (name
, ':');
922 s
= strchr (name
, '[');
936 strcat (p
, "./"); /* [. */
956 if (*s
!= 0) /* more after ']' ?? */
960 strcpy (p
, s
); /* copy it anyway */
964 else /* no '[' anywhere */
970 /* force end with '/' */