home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / nethack-3.1 / sys / vms / vmsfiles.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-24  |  6.9 KB  |  241 lines

  1. /*    SCCS Id: @(#)vmsfiles.c    3.1    93/01/20    */
  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.  
  11. #include <rms.h>
  12. #if 0
  13. #include <psldef.h>
  14. #else
  15. #define PSL$C_EXEC 1    /* executive mode, for priv'd logical name handling */
  16. #endif
  17. #ifndef C$$TRANSLATE    /* don't rely on VAXCRTL's internal routine */
  18. #include <errno.h>
  19. #define C$$TRANSLATE(status) (errno = EVMSERR,  vaxc$errno = (status))
  20. #else
  21. int FDECL(c__translate, (int));
  22. #endif
  23. extern unsigned long SYS$PARSE(), SYS$SEARCH(), SYS$ENTER(), SYS$REMOVE();
  24.  
  25. #define vms_success(sts) ((sts)&1)        /* odd, */
  26. #define vms_failure(sts) (!vms_success(sts))    /* even */
  27.  
  28. /* vms_link() -- create an additional directory for an existing file */
  29. int vms_link(file, new)
  30. const char *file, *new;
  31. {
  32.     struct FAB fab;
  33.     struct NAM nam;
  34.     unsigned short fid[3];
  35.     char esa[NAM$C_MAXRSS];
  36.  
  37.     fab = cc$rms_fab;    /* set block ID and length, zero the rest */
  38.     fab.fab$l_fop = FAB$M_OFP;
  39.     fab.fab$l_fna = (char *) file;
  40.     fab.fab$b_fns = strlen(file);
  41.     fab.fab$l_nam = &nam;
  42.     nam = cc$rms_nam;
  43.     nam.nam$l_esa = esa;
  44.     nam.nam$b_ess = sizeof esa;
  45.  
  46.     if (vms_success(SYS$PARSE(&fab)) && vms_success(SYS$SEARCH(&fab))) {
  47.     fid[0] = nam.nam$w_fid[0];
  48.     fid[1] = nam.nam$w_fid[1];
  49.     fid[2] = nam.nam$w_fid[2];
  50.     fab.fab$l_fna = (char *) new;
  51.     fab.fab$b_fns = strlen(new);
  52.  
  53.     if (vms_success(SYS$PARSE(&fab))) {
  54.         nam.nam$w_fid[0] = fid[0];
  55.         nam.nam$w_fid[1] = fid[1];
  56.         nam.nam$w_fid[2] = fid[2];
  57.         nam.nam$l_esa = nam.nam$l_name;
  58.         nam.nam$b_esl = nam.nam$b_name + nam.nam$b_type + nam.nam$b_ver;
  59.  
  60.         (void) SYS$ENTER(&fab);
  61.     }
  62.     }
  63.  
  64.     if (vms_failure(fab.fab$l_sts)) {
  65.     C$$TRANSLATE(fab.fab$l_sts);
  66.     return -1;
  67.     }
  68.     return 0;    /* success */
  69. }
  70.  
  71. /*
  72.    vms_unlink() -- remove a directory entry for a file; should only be used
  73.    for files which have had extra directory entries added, not for deletion
  74.    (because the file won't be deleted, just made inaccessible!).
  75.  */
  76. int vms_unlink(file)
  77. const char *file;
  78. {
  79.     struct FAB fab;
  80.     struct NAM nam;
  81.     char esa[NAM$C_MAXRSS];
  82.  
  83.     fab = cc$rms_fab;    /* set block ID and length, zero the rest */
  84.     fab.fab$l_fop = FAB$M_DLT;
  85.     fab.fab$l_fna = (char *) file;
  86.     fab.fab$b_fns = strlen(file);
  87.     fab.fab$l_nam = &nam;
  88.     nam = cc$rms_nam;
  89.     nam.nam$l_esa = esa;
  90.     nam.nam$b_ess = sizeof esa;
  91.  
  92.     if (vms_failure(SYS$PARSE(&fab)) || vms_failure(SYS$REMOVE(&fab))) {
  93.     C$$TRANSLATE(fab.fab$l_sts);
  94.     return -1;
  95.     }
  96.     return 0;
  97. }
  98.  
  99. /*
  100.    Substitute creat() routine -- if trying to create a specific version,
  101.    explicitly remove an existing file of the same name.  Since it's only
  102.    used when we expect exclusive access, add a couple RMS options for
  103.    optimization.  (Don't allow sharing--eliminates coordination overhead,
  104.    and use 32 block buffer for faster throughput; ~30% speedup measured.)
  105.  */
  106. #undef creat
  107. int vms_creat(file, mode)
  108. const char *file;
  109. unsigned int mode;
  110. {
  111.     if (index(file, ';'))
  112.     (void) unlink(file);    /* assumes remove or delete, not vms_unlink */
  113.     return creat(file, mode, "shr=nil", "mbc=32");
  114. }
  115.  
  116. /*
  117.    Similar substitute for open() -- can't disallow sharing, because we're
  118.    relying on deleting a file that we've got open, so must share it with
  119.    ourself!
  120.  */
  121. #undef open
  122. int vms_open(file, flags, mode)
  123. const char *file;
  124. int flags;
  125. unsigned int mode;
  126. {
  127.     return open(file, flags, mode, "mbc=32");
  128. }
  129.  
  130. /*
  131.    Determine whether two strings contain the same directory name.
  132.    Used for deciding whether installed privileges should be disabled
  133.    when HACKDIR is defined in the environment (or specified via -d on
  134.    the command line).  This version doesn't handle Unix-style file specs.
  135.  */
  136. boolean
  137. same_dir(d1, d2)
  138. const char *d1, *d2;
  139. {
  140.     if (!d1 || !*d1 || !d2 || !*d2)
  141.     return FALSE;
  142.     else if (!strcmp(d1, d2))    /* strcmpi() would be better, but that leads */
  143.     return TRUE;        /* to linking problems for the utilities */
  144.     else {
  145.     struct FAB f1, f2;
  146.     struct NAM n1, n2;
  147.  
  148.     f1 = f2 = cc$rms_fab;    /* initialize file access block */
  149.     n1 = n2 = cc$rms_nam;    /* initialize name block */
  150.     f1.fab$b_acmodes = PSL$C_EXEC << FAB$V_LNM_MODE;
  151.     f1.fab$b_fns = strlen( f1.fab$l_fna = (char *)d1 );
  152.     f2.fab$b_fns = strlen( f2.fab$l_fna = (char *)d2 );
  153.     f1.fab$l_nam = (genericptr_t)&n1;    /* link nam to fab */
  154.     f2.fab$l_nam = (genericptr_t)&n2;
  155.     n1.nam$b_nop = n2.nam$b_nop = NAM$M_NOCONCEAL; /* want true device name */
  156.  
  157.     return (vms_success(SYS$PARSE(&f1)) && vms_success(SYS$PARSE(&f2))
  158.          && n1.nam$t_dvi[0] == n2.nam$t_dvi[0]
  159.          && !strncmp(&n1.nam$t_dvi[1], &n2.nam$t_dvi[1], n1.nam$t_dvi[0])
  160.          && !memcmp((genericptr_t)n1.nam$w_did,
  161.             (genericptr_t)n2.nam$w_did,
  162.             sizeof n1.nam$w_did));    /*{ short nam$w_did[3]; }*/
  163.     }
  164. }
  165.  
  166.  
  167. /*
  168.  * c__translate -- substitute for VAXCRTL routine C$$TRANSLATE.
  169.  *
  170.  *    Try to convert a VMS status code into its Unix equivalent,
  171.  *    then set `errno' to that value; use EVMSERR if there's no
  172.  *    appropriate translation; set `vaxc$errno' to the original
  173.  *    status code regardless.
  174.  *
  175.  *    These translations match only a subset of VAXCRTL's lookup
  176.  *    table, but work even if the severity has been adjusted or
  177.  *    the inhibit-message bit has been set.
  178.  */
  179. #include <errno.h>
  180. #include <ssdef.h>
  181. #include <rmsdef.h>
  182. /* #include <libdef.h> */
  183. /* #include <mthdef.h> */
  184.  
  185. #define VALUE(U)    trans = U; break
  186. #define CASE1(V)    case (V >> 3)
  187. #define CASE2(V,W)    CASE1(V): CASE1(W)
  188.  
  189. int c__translate(code)
  190.     int code;
  191. {
  192.     register int trans;
  193.  
  194.     switch ((code & 0x0FFFFFF8) >> 3) {    /* strip upper 4 and bottom 3 bits */
  195.     CASE2(RMS$_PRV,SS$_NOPRIV):
  196.                 VALUE(EPERM);    /* not owner */
  197.     CASE2(RMS$_DNF,RMS$_DIR):
  198.     CASE2(RMS$_FNF,RMS$_FND):
  199.     CASE1(SS$_NOSUCHFILE):
  200.                 VALUE(ENOENT);    /* no such file or directory */
  201.     CASE2(RMS$_IFI,RMS$_ISI):
  202.                 VALUE(EIO);    /* i/o error */
  203.     CASE1(RMS$_DEV):
  204.     CASE2(SS$_NOSUCHDEV,SS$_DEVNOTMOUNT):
  205.                 VALUE(ENXIO);    /* no such device or address codes */
  206.     CASE1(RMS$_DME):
  207.      /* CASE1(LIB$INSVIRMEM): */
  208.     CASE2(SS$_VASFULL,SS$_INSFWSL):
  209.                 VALUE(ENOMEM);    /* not enough core */
  210.     CASE1(SS$_ACCVIO):
  211.                 VALUE(EFAULT);    /* bad address */
  212.     CASE2(RMS$_DNR,SS$_DEVASSIGN):
  213.     CASE2(SS$_DEVALLOC,SS$_DEVALRALLOC):
  214.     CASE2(SS$_DEVMOUNT,SS$_DEVACTIVE):
  215.                 VALUE(EBUSY);    /* mount device busy codes to name a few */
  216.     CASE2(RMS$_FEX,SS$_FILALRACC):
  217.                 VALUE(EEXIST);    /* file exists */
  218.     CASE2(RMS$_IDR,SS$_BADIRECTORY):
  219.                 VALUE(ENOTDIR);    /* not a directory */
  220.     CASE1(SS$_NOIOCHAN):
  221.                 VALUE(EMFILE);    /* too many open files */
  222.     CASE1(RMS$_FUL):
  223.     CASE2(SS$_DEVICEFULL,SS$_EXDISKQUOTA):
  224.                 VALUE(ENOSPC);    /* no space left on disk codes */
  225.     CASE2(RMS$_WLK,SS$_WRITLCK):
  226.                 VALUE(EROFS);    /* read-only file system */
  227.     default:
  228.                 VALUE(EVMSERR);
  229.     };
  230.  
  231.     errno = trans;
  232.     vaxc$errno = code;
  233.     return code;    /* (not very useful) */
  234. }
  235.  
  236. #undef VALUE
  237. #undef CASE1
  238. #undef CASE2
  239.  
  240. /*vmsfiles.c*/
  241.