~ubuntu-branches/ubuntu/intrepid/nethack/intrepid

« back to all changes in this revision

Viewing changes to sys/vms/vmsfiles.c

  • Committer: Bazaar Package Importer
  • Author(s): Joshua Kwan
  • Date: 2004-04-28 22:20:28 UTC
  • Revision ID: james.westby@ubuntu.com-20040428222028-xxg55fuf5dxiaogu
Tags: upstream-3.4.3
ImportĀ upstreamĀ versionĀ 3.4.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*      SCCS Id: @(#)vmsfiles.c 3.4     1999/08/29      */
 
2
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 
3
/* NetHack may be freely redistributed.  See license for details. */
 
4
 
 
5
/*
 
6
 *  VMS-specific file manipulation routines to implement some missing
 
7
 *  routines or substitute for ones where we want behavior modification.
 
8
 */
 
9
#include "config.h"
 
10
#include <ctype.h>
 
11
 
 
12
/* lint supression due to lack of extern.h */
 
13
int FDECL(vms_link, (const char *,const char *));
 
14
int FDECL(vms_unlink, (const char *));
 
15
int FDECL(vms_creat, (const char *,unsigned int));
 
16
int FDECL(vms_open, (const char *,int,unsigned int));
 
17
boolean FDECL(same_dir, (const char *,const char *));
 
18
int FDECL(c__translate, (int));
 
19
char *FDECL(vms_basename, (const char *));
 
20
 
 
21
#include <rms.h>
 
22
#if 0
 
23
#include <psldef.h>
 
24
#else
 
25
#define PSL$C_EXEC 1    /* executive mode, for priv'd logical name handling */
 
26
#endif
 
27
#include <errno.h>
 
28
#ifndef C$$TRANSLATE    /* don't rely on VAXCRTL's internal routine */
 
29
#define C$$TRANSLATE(status) (errno = EVMSERR,  vaxc$errno = (status))
 
30
#endif
 
31
extern unsigned long sys$parse(), sys$search(), sys$enter(), sys$remove();
 
32
extern int VDECL(lib$match_cond, (int,int,...));
 
33
 
 
34
#define vms_success(sts) ((sts)&1)              /* odd, */
 
35
#define vms_failure(sts) (!vms_success(sts))    /* even */
 
36
 
 
37
/* vms_link() -- create an additional directory for an existing file */
 
38
int vms_link(file, new)
 
39
const char *file, *new;
 
40
{
 
41
    struct FAB fab;
 
42
    struct NAM nam;
 
43
    unsigned short fid[3];
 
44
    char esa[NAM$C_MAXRSS];
 
45
 
 
46
    fab = cc$rms_fab;   /* set block ID and length, zero the rest */
 
47
    fab.fab$l_fop = FAB$M_OFP;
 
48
    fab.fab$l_fna = (char *) file;
 
49
    fab.fab$b_fns = strlen(file);
 
50
    fab.fab$l_nam = &nam;
 
51
    nam = cc$rms_nam;
 
52
    nam.nam$l_esa = esa;
 
53
    nam.nam$b_ess = sizeof esa;
 
54
 
 
55
    if (vms_success(sys$parse(&fab)) && vms_success(sys$search(&fab))) {
 
56
        fid[0] = nam.nam$w_fid[0];
 
57
        fid[1] = nam.nam$w_fid[1];
 
58
        fid[2] = nam.nam$w_fid[2];
 
59
        fab.fab$l_fna = (char *) new;
 
60
        fab.fab$b_fns = strlen(new);
 
61
 
 
62
        if (vms_success(sys$parse(&fab))) {
 
63
            nam.nam$w_fid[0] = fid[0];
 
64
            nam.nam$w_fid[1] = fid[1];
 
65
            nam.nam$w_fid[2] = fid[2];
 
66
            nam.nam$l_esa = nam.nam$l_name;
 
67
            nam.nam$b_esl = nam.nam$b_name + nam.nam$b_type + nam.nam$b_ver;
 
68
 
 
69
            (void) sys$enter(&fab);
 
70
        }
 
71
    }
 
72
 
 
73
    if (vms_failure(fab.fab$l_sts)) {
 
74
        C$$TRANSLATE(fab.fab$l_sts);
 
75
        return -1;
 
76
    }
 
77
    return 0;   /* success */
 
78
}
 
79
 
 
80
/*
 
81
   vms_unlink() -- remove a directory entry for a file; should only be used
 
82
   for files which have had extra directory entries added, not for deletion
 
83
   (because the file won't be deleted, just made inaccessible!).
 
84
 */
 
85
int vms_unlink(file)
 
86
const char *file;
 
87
{
 
88
    struct FAB fab;
 
89
    struct NAM nam;
 
90
    char esa[NAM$C_MAXRSS];
 
91
 
 
92
    fab = cc$rms_fab;   /* set block ID and length, zero the rest */
 
93
    fab.fab$l_fop = FAB$M_DLT;
 
94
    fab.fab$l_fna = (char *) file;
 
95
    fab.fab$b_fns = strlen(file);
 
96
    fab.fab$l_nam = &nam;
 
97
    nam = cc$rms_nam;
 
98
    nam.nam$l_esa = esa;
 
99
    nam.nam$b_ess = sizeof esa;
 
100
 
 
101
    if (vms_failure(sys$parse(&fab)) || vms_failure(sys$remove(&fab))) {
 
102
        C$$TRANSLATE(fab.fab$l_sts);
 
103
        return -1;
 
104
    }
 
105
    return 0;
 
106
}
 
107
 
 
108
/*
 
109
   Substitute creat() routine -- if trying to create a specific version,
 
110
   explicitly remove an existing file of the same name.  Since it's only
 
111
   used when we expect exclusive access, add a couple RMS options for
 
112
   optimization.  (Don't allow sharing--eliminates coordination overhead,
 
113
   and use 32 block buffer for faster throughput; ~30% speedup measured.)
 
114
 */
 
115
#undef creat
 
116
int vms_creat(file, mode)
 
117
const char *file;
 
118
unsigned int mode;
 
119
{
 
120
    if (index(file, ';')) {
 
121
        /* assumes remove or delete, not vms_unlink */
 
122
        if (!unlink(file)) {
 
123
            (void)sleep(1);
 
124
            (void)unlink(file);
 
125
        }
 
126
    }
 
127
    return creat(file, mode, "shr=nil", "mbc=32", "mbf=2", "rop=wbh");
 
128
}
 
129
 
 
130
/*
 
131
   Similar substitute for open() -- if an open attempt fails due to being
 
132
   locked by another user, retry it once (work-around for a limitation of
 
133
   at least one NFS implementation).
 
134
 */
 
135
#undef open
 
136
int vms_open(file, flags, mode)
 
137
const char *file;
 
138
int flags;
 
139
unsigned int mode;
 
140
{
 
141
    int fd = open(file, flags, mode, "mbc=32", "mbf=2", "rop=rah");
 
142
 
 
143
    if (fd < 0 && errno == EVMSERR && lib$match_cond(vaxc$errno, RMS$_FLK)) {
 
144
        (void)sleep(1);
 
145
        fd = open(file, flags, mode, "mbc=32", "mbf=2", "rop=rah");
 
146
    }
 
147
    return fd;
 
148
}
 
149
 
 
150
/*
 
151
   Determine whether two strings contain the same directory name.
 
152
   Used for deciding whether installed privileges should be disabled
 
153
   when HACKDIR is defined in the environment (or specified via -d on
 
154
   the command line).  This version doesn't handle Unix-style file specs.
 
155
 */
 
156
boolean
 
157
same_dir(d1, d2)
 
158
const char *d1, *d2;
 
159
{
 
160
    if (!d1 || !*d1 || !d2 || !*d2)
 
161
        return FALSE;
 
162
    else if (!strcmp(d1, d2))   /* strcmpi() would be better, but that leads */
 
163
        return TRUE;            /* to linking problems for the utilities */
 
164
    else {
 
165
        struct FAB f1, f2;
 
166
        struct NAM n1, n2;
 
167
 
 
168
        f1 = f2 = cc$rms_fab;   /* initialize file access block */
 
169
        n1 = n2 = cc$rms_nam;   /* initialize name block */
 
170
        f1.fab$b_acmodes = PSL$C_EXEC << FAB$V_LNM_MODE;
 
171
        f1.fab$b_fns = strlen( f1.fab$l_fna = (char *)d1 );
 
172
        f2.fab$b_fns = strlen( f2.fab$l_fna = (char *)d2 );
 
173
        f1.fab$l_nam = (genericptr_t)&n1;       /* link nam to fab */
 
174
        f2.fab$l_nam = (genericptr_t)&n2;
 
175
        n1.nam$b_nop = n2.nam$b_nop = NAM$M_NOCONCEAL; /* want true device name */
 
176
 
 
177
        return (vms_success(sys$parse(&f1)) && vms_success(sys$parse(&f2))
 
178
             && n1.nam$t_dvi[0] == n2.nam$t_dvi[0]
 
179
             && !strncmp(&n1.nam$t_dvi[1], &n2.nam$t_dvi[1], n1.nam$t_dvi[0])
 
180
             && !memcmp((genericptr_t)n1.nam$w_did,
 
181
                        (genericptr_t)n2.nam$w_did,
 
182
                        sizeof n1.nam$w_did));  /*{ short nam$w_did[3]; }*/
 
183
    }
 
184
}
 
185
 
 
186
 
 
187
/*
 
188
 * c__translate -- substitute for VAXCRTL routine C$$TRANSLATE.
 
189
 *
 
190
 *      Try to convert a VMS status code into its Unix equivalent,
 
191
 *      then set `errno' to that value; use EVMSERR if there's no
 
192
 *      appropriate translation; set `vaxc$errno' to the original
 
193
 *      status code regardless.
 
194
 *
 
195
 *      These translations match only a subset of VAXCRTL's lookup
 
196
 *      table, but work even if the severity has been adjusted or
 
197
 *      the inhibit-message bit has been set.
 
198
 */
 
199
#include <errno.h>
 
200
#include <ssdef.h>
 
201
#include <rmsdef.h>
 
202
/* #include <libdef.h> */
 
203
/* #include <mthdef.h> */
 
204
 
 
205
#define VALUE(U)        trans = U; break
 
206
#define CASE1(V)        case (V >> 3)
 
207
#define CASE2(V,W)      CASE1(V): CASE1(W)
 
208
 
 
209
int c__translate(code)
 
210
    int code;
 
211
{
 
212
    register int trans;
 
213
 
 
214
    switch ((code & 0x0FFFFFF8) >> 3) { /* strip upper 4 and bottom 3 bits */
 
215
        CASE2(RMS$_PRV,SS$_NOPRIV):
 
216
                                VALUE(EPERM);   /* not owner */
 
217
        CASE2(RMS$_DNF,RMS$_DIR):
 
218
        CASE2(RMS$_FNF,RMS$_FND):
 
219
        CASE1(SS$_NOSUCHFILE):
 
220
                                VALUE(ENOENT);  /* no such file or directory */
 
221
        CASE2(RMS$_IFI,RMS$_ISI):
 
222
                                VALUE(EIO);     /* i/o error */
 
223
        CASE1(RMS$_DEV):
 
224
        CASE2(SS$_NOSUCHDEV,SS$_DEVNOTMOUNT):
 
225
                                VALUE(ENXIO);   /* no such device or address codes */
 
226
        CASE1(RMS$_DME):
 
227
     /* CASE1(LIB$INSVIRMEM): */
 
228
        CASE2(SS$_VASFULL,SS$_INSFWSL):
 
229
                                VALUE(ENOMEM);  /* not enough core */
 
230
        CASE1(SS$_ACCVIO):
 
231
                                VALUE(EFAULT);  /* bad address */
 
232
        CASE2(RMS$_DNR,SS$_DEVASSIGN):
 
233
        CASE2(SS$_DEVALLOC,SS$_DEVALRALLOC):
 
234
        CASE2(SS$_DEVMOUNT,SS$_DEVACTIVE):
 
235
                                VALUE(EBUSY);   /* mount device busy codes to name a few */
 
236
        CASE2(RMS$_FEX,SS$_FILALRACC):
 
237
                                VALUE(EEXIST);  /* file exists */
 
238
        CASE2(RMS$_IDR,SS$_BADIRECTORY):
 
239
                                VALUE(ENOTDIR); /* not a directory */
 
240
        CASE1(SS$_NOIOCHAN):
 
241
                                VALUE(EMFILE);  /* too many open files */
 
242
        CASE1(RMS$_FUL):
 
243
        CASE2(SS$_DEVICEFULL,SS$_EXDISKQUOTA):
 
244
                                VALUE(ENOSPC);  /* no space left on disk codes */
 
245
        CASE2(RMS$_WLK,SS$_WRITLCK):
 
246
                                VALUE(EROFS);   /* read-only file system */
 
247
        default:
 
248
                                VALUE(EVMSERR);
 
249
    };
 
250
 
 
251
    errno = trans;
 
252
    vaxc$errno = code;
 
253
    return code;        /* (not very useful) */
 
254
}
 
255
 
 
256
#undef VALUE
 
257
#undef CASE1
 
258
#undef CASE2
 
259
 
 
260
static char base_name[NAM$C_MAXRSS+1];
 
261
 
 
262
/* return a copy of the 'base' portion of a filename */
 
263
char *
 
264
vms_basename(name)
 
265
const char *name;
 
266
{
 
267
    unsigned len;
 
268
    char *base, *base_p;
 
269
    register const char *name_p;
 
270
 
 
271
    /* skip directory/path */
 
272
    if ((name_p = strrchr(name, ']')) != 0) name = name_p + 1;
 
273
    if ((name_p = strrchr(name, '>')) != 0) name = name_p + 1;
 
274
    if ((name_p = strrchr(name, ':')) != 0) name = name_p + 1;
 
275
    if ((name_p = strrchr(name, '/')) != 0) name = name_p + 1;
 
276
    if (!*name) name = ".";             /* this should never happen */
 
277
 
 
278
    /* find extension/version and derive length of basename */
 
279
    if ((name_p = strchr(name, '.')) == 0 || name_p == name)
 
280
        name_p = strchr(name, ';');
 
281
    len = (name_p && name_p > name) ? name_p - name : strlen(name);
 
282
 
 
283
    /* return a lowercase copy of the name in a private static buffer */
 
284
    base = strncpy(base_name, name, len);
 
285
    base[len] = '\0';
 
286
    /* we don't use lcase() so that utilities won't need hacklib.c */
 
287
    for (base_p = base; base_p < &base[len]; base_p++)
 
288
        if (isupper(*base_p)) *base_p = tolower(*base_p);
 
289
 
 
290
    return base;
 
291
}
 
292
 
 
293
/*vmsfiles.c*/