1
/******************************************************************************
2
(c) 2005 P.J. Caulfield patrick@tykepenguin.cix.co.uk
4
This program is free software; you can redistribute it and/or modify
5
it under the terms of the GNU General Public License as published by
6
the Free Software Foundation; either version 2 of the License, or
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
13
******************************************************************************
16
/* This code is lifted from FAL. */
17
#include <sys/socket.h>
19
#include <sys/param.h>
34
#include <netdnet/dn.h>
35
#include <netdnet/dnetdb.h>
36
#include "filenames.h"
41
const char *sysdisk_name = "SYS$SYSDEVICE";
43
// A couple of general utility methods:
44
static void makelower(char *s)
47
for (i=0; i<strlen(s); i++) s[i] = tolower(s[i]);
50
static void makeupper(char *s)
53
for (i=0; i<strlen(s); i++) s[i] = toupper(s[i]);
56
// Convert a Unix-style filename to a VMS-style name
57
// No return code because this routine cannot fail :-)
58
void make_vms_filespec(const char *unixname, char *vmsname, int isdir)
60
char fullname[PATH_MAX];
65
// Take a copy wwe can muck about with
66
strcpy(fullname, unixname);
68
// Find the last slash in the name
69
lastslash = fullname + strlen(fullname);
70
while (*(--lastslash) != '/') ;
72
// If the filename has no extension then add one. VMS seems to
73
// expect one as does dapfs.
74
if (!strchr(lastslash, '.' && !isdir))
75
strcat(fullname, ".");
79
// Oh, also make it all upper case for VMS's benefit.
80
for (i=0; i<(int)strlen(fullname); i++)
82
if (islower(fullname[i])) fullname[i] = toupper(fullname[i]);
83
if (fullname[i] == '/')
91
sprintf(vmsname, "[]%s", unixname+1);
97
for (i=0; i<=(int)strlen(fullname); i++)
107
if (fullname[i] == '/')
110
if (thisslash == slashes)
116
vmsname[v++] = fullname[i];
121
// Split out the volume, directory and file portions of a VMS file spec
122
// We assume that the VMS name is (quite) well formed.
123
static void parse_vms_filespec(char *volume, char *directory, char *file)
125
char *colon = strchr(file, ':');
131
if (colon) // We have a volume name
133
char saved = *(colon+1);
135
strcpy(volume, file);
140
char *enddir = strchr(ptr, ']');
142
// Don't get caught out by concatenated filespecs
143
// like dua0:[home.patrick.][test]
144
if (enddir && enddir[1] == '[')
145
enddir=strchr(enddir+1, ']');
147
if (*ptr == '[' && enddir) // we have a directory
149
char saved = *(enddir+1);
152
strcpy(directory, ptr);
157
// Copy the rest of the filename using memmove 'cos it might overlap
159
memmove(file, ptr, strlen(ptr)+1);
163
// Convert a VMS filespec into a Unix filespec
164
// volume names are turned into directories in the root directory
165
// (unless they are SYSDISK which is our pseudo name)
166
void make_unix_filespec(char *unixname, char *vmsname)
168
char volume[PATH_MAX];
174
strcpy(file, vmsname);
176
// Remove the trailing version number
177
char *semi = strchr(file, ';');
178
if (semi) *semi = '\0';
180
// If the filename has a trailing dot them remove that too
181
if (file[strlen(file)-1] == '.')
182
file[strlen(file)-1] = '\0';
186
// Split it into its component parts
187
parse_vms_filespec(volume, dir, file);
189
// Remove the trailing colon from the volume name
190
if (volume[strlen(volume)-1] == ':')
191
volume[strlen(volume)-1] = '\0';
193
// If the filename has the dummy SYSDISK volume then start from the
195
if (strcasecmp(volume, sysdisk_name) == 0)
197
strcpy(unixname, "/");
201
if (volume[0] != '\0')
203
strcpy(unixname, "/");
204
strcat(unixname, volume);
207
ptr = strlen(unixname);
209
// Copy the directory
210
for (i=0; i< (int)strlen(dir); i++)
212
// If the directory name starts [. then it is relative to the
213
// user's home directory and we lose the starting slash
214
// If there is also a volume name present then it all falls
215
// to bits but then it's pretty dodgy on VMS too.
228
unixname[ptr++] = '/';
232
// Skip root directory specs
233
if (dir[i] == '0' && (strncmp(&dir[i], "000000", 6) == 0))
238
if (dir[i] == '0' && (strncmp(&dir[i], "0,0", 3) == 0))
243
unixname[ptr++] = dir[i];
246
unixname[ptr++] = '\0'; // so that strcat will work properly
248
// A special case (ugh!), if VMS sent us '*.*' (maybe as part of *.*;*)
249
// then change it to just '*' so we get all the files.
250
if (strcmp(file, "*.*") == 0) strcpy(file, "*");
252
strcat(unixname, file);
254
// Finally convert it all to lower case. This is not the greatest way to
255
// cope with it but because VMS will upper-case everything anyway we
256
// can't really distinguish case. I know samba does fancy stuff with
257
// matching various combinations of case but I really can't be bothered.
260
// If the name ends in .dir and there is a directory of that name without
261
// the .dir then remove it (the .dir, not the directory!)
262
if (strstr(unixname, ".dir") == unixname+strlen(unixname)-4)
264
char dirname[strlen(unixname)+1];
267
strcpy(dirname, unixname);
268
char *ext = strstr(dirname, ".dir");
269
if (ext) *ext = '\0';
270
if (stat(dirname, &st) == 0 &&
273
char *ext = strstr(unixname, ".dir");
274
if (ext) *ext = '\0';