home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume28 / yapp / part01 / files.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-29  |  6.5 KB  |  234 lines

  1. /* MOPEN.C */
  2. static char sccsid[]="@(#)files.c 1.4 93/05/11 Copyright (c)1993 thalerd";
  3. #include <stdio.h>
  4. #include <sys/types.h> 
  5. #include <sys/file.h> 
  6. #include <sys/stat.h> 
  7. #include <fcntl.h> /* to get O_CREAT, etc */
  8. #include <errno.h>
  9. #include <string.h>
  10. #include "config.h"
  11. #include "struct.h"
  12. #include "globals.h"
  13. #include "files.h"
  14. #include "xalloc.h"
  15. #include "system.h" /* to get SL_OWNER */
  16.  
  17. /* Information about each open file */
  18. typedef struct fd_tt {
  19.    char         *filename;
  20.    short         flg;
  21.    int           fd;
  22.    struct fd_tt *next;
  23. } fd_t;
  24. static fd_t *first_fd=0;
  25.  
  26. #ifdef FLOCKF
  27. /******************************************************************************/
  28. /* FLOCK FOR SYSTEMS WITH LOCKF() ONLY                                        */
  29. /******************************************************************************/
  30. #include <unistd.h>
  31. #define LOCK_EX 2
  32. #define LOCK_NB 4
  33. int 
  34. flock(fd, operation)
  35. int fd, operation;
  36. {
  37.    return lockf(fd,(operation & LOCK_NB)? F_TLOCK : F_LOCK,0L);
  38. }
  39. #endif
  40.  
  41. /******************************************************************************/
  42. /* DUMP ALL FILES CURRENTLY OPEN                                              */
  43. /******************************************************************************/
  44. void    /* RETURNS: (nothing) */
  45. mdump() /* ARGUMENTS: (none)  */
  46. {
  47.    fd_t *this;
  48.  
  49.    for (this=first_fd; this; this = this->next) {
  50.       printf("mdump: fd=%d filename='%s' flg=%x\n",this->fd,
  51.        this->filename, this->flg);
  52.    }
  53. }
  54.  
  55. /******************************************************************************/
  56. /* ADD AN OPEN FD TO THE DATABASE (FROM SPOPEN/MOPEN)                         */
  57. /******************************************************************************/
  58. void
  59. madd(fd,file,flg)
  60. int   fd;
  61. char *file;
  62. short flg;
  63. {
  64.    fd_t       *this;
  65.  
  66.    /* Save info for debugging */
  67.    this           = (fd_t *)malloc(sizeof(fd_t));
  68.    this->fd       = fd;
  69.    this->filename = xstrdup(file);
  70.    this->flg      = flg;
  71.    this->next     = first_fd;
  72.    first_fd       = this;
  73. }
  74.  
  75. /******************************************************************************/
  76. /* OPEN A FILE AND LOCK IT FOR EXCLUSIVE ACCESS                               */
  77. /******************************************************************************/
  78. FILE *         /* RETURNS: Open file pointer, or NULL on error */
  79. mopen(file,flg) /* ARGUMENTS: */
  80. char *file;    /*    Filename to open */
  81. long  flg;     /*    Flag: 0=append only, 1=create new (only) */
  82. {
  83.    struct stat st;
  84.    short       err;
  85.    int         fd,
  86.                perm;
  87.    char        modestr[3];
  88.    FILE       *fp;
  89.    char        buff[MAX_LINE_LENGTH];
  90. #ifdef NOFLOCK
  91.    short       timeout=0;
  92. #endif
  93.  
  94.    if (flags & O_DEBUG)
  95.       printf("mopen: flags=%x\n",flg);
  96.  
  97.    /* Process flags */
  98.    if (flg & (O_EXCL|O_NOCREATE))  err=stat(file,&st);
  99.    if ( err && (flg & O_NOCREATE)) {
  100.       if (!(flg & O_SILENT)) error("opening ",file);
  101.       return NULL; /* append: doesn't exist  */
  102.    } else if (!err && (flg & O_CREAT) && (flg & O_EXCL))    {
  103.       error("creating ",file);
  104.       return NULL; /* create: already exists */
  105.    }
  106.    perm=umask(0);
  107.  
  108. #ifdef NOFLOCK
  109.    /* For auxilary file locking */
  110.    if (flg & O_LOCK) {
  111.       sprintf(buff,"%s.lock",file);
  112.       while ((fd=open(buff,O_WRONLY|O_CREAT|O_EXCL,0400))<0
  113.        && errno==EEXIST && timeout<10 && !(status & S_INT)) {
  114.             if (flg & O_NOBLOCK)
  115.                 return NULL; /* can't lock */
  116.          timeout++;
  117.          sleep(1);
  118.       }
  119.       if (fd>=0) close(fd);
  120.  
  121.    /* Currently overrides lock after timeout
  122.     *
  123.     * if (timeout>=10 || (status & S_INT)) {
  124.     *    error("locking ",buff);
  125.     *    umask(perm);
  126.     *    return NULL;
  127.     * }
  128.     */
  129.       if (timeout>=10) printf("Warning: overriding lock on %s\n",file);
  130.    }
  131. #endif
  132.  
  133.     /* Open file */
  134.    fd=open(file,flg & O_PASSTHRU,(flg & O_PRIVATE)? 0600 : 0644);
  135.    if (fd < 0) {
  136.       error("opening ",file);
  137. #ifdef NOFLOCK
  138.       if (flg & O_LOCK)
  139.             rm(buff,SL_OWNER);      /* unlock */
  140. #endif
  141.       umask(perm);
  142.       return NULL;
  143.    }
  144.  
  145. #ifndef NOFLOCK
  146.     /* Lock it */
  147.    if (flg & O_LOCK) {
  148.         if (flock(fd,(flg & O_NOBLOCK)? LOCK_EX|LOCK_NB : LOCK_EX)) {
  149.          umask(perm);
  150.          return NULL;
  151.         }
  152.    }
  153. #endif
  154.  
  155.    umask(perm);
  156.    if (flg & O_APPEND) lseek(fd,0L,2);
  157.  
  158.    /* Determine mode string */
  159.    if      ((flg & O_WPLUS)==O_WPLUS) strcpy(modestr,"w+");
  160.    else if ((flg & O_W    )==O_W    ) strcpy(modestr,"w"); 
  161.    else if ((flg & O_APLUS)==O_APLUS) strcpy(modestr,"a+");
  162.    else if ((flg & O_A    )==O_A    ) strcpy(modestr,"a");
  163.    else if ((flg & O_RPLUS)==O_RPLUS) strcpy(modestr,"r+");  /* should be next to last */
  164.    else if ((flg & O_R    )==O_R    ) strcpy(modestr,"r");   /* MUST be last */
  165.    else printf("KKK Invalid mopen mode\n"); 
  166.  
  167.    /* Save info for debugging */
  168.    madd(fd,file,flg);
  169.  
  170.    if ((fp = fdopen(fd,modestr))==NULL) {
  171.       sprintf(buff,"%s for %s after mode %x\n",file,modestr,flg);
  172.       error("reopening ",buff);
  173.    }
  174.    return fp;
  175. }
  176.  
  177. /******************************************************************************/
  178. /* CLOSE AND UNLOCK A FILE                                                    */
  179. /******************************************************************************/
  180. int         /* RETURNS: non-zero on error */
  181. mclose(fp)  /* ARGUMENTS:               */
  182. FILE *fp;   /*    File pointer to close */
  183. {
  184.    fd_t *this,*prev=0;
  185.    int   ret;
  186. #ifdef NOFLOCK
  187.    char buff[MAX_LINE_LENGTH];
  188. #endif
  189.  
  190.    fflush(fp);
  191.    for (this=first_fd; this && this->fd != fileno(fp); prev=this, this = this->next);
  192.    if (!this) {
  193.       (void)printf("Tried to close unopened file\n");
  194.       return 1; /* not found */
  195.    }
  196.    if (!fp) {
  197.       (void)printf("Tried to close null file\n");
  198.       return 1; 
  199.    }
  200.  
  201.    ret=fclose(fp); /* flock automatically closes */
  202.  
  203. #ifdef NOFLOCK
  204.    /* For auxilary file locking */
  205.    if (this->flg & O_LOCK) {
  206.       sprintf(buff,"%s.lock",this->filename);
  207.       rm(buff,SL_OWNER);
  208.    }
  209. #endif
  210.  
  211.    /* Remove from debugging database */
  212.    if (!prev) first_fd   = this->next;
  213.    else       prev->next = this->next;
  214.    xfree(this->filename);
  215.    free((char *)this);
  216.  
  217.    return ret;
  218. }
  219.  
  220. /******************************************************************************/
  221. /* VERIFY THAT ALL FILES HAVE BEEN CLOSED                                     */
  222. /******************************************************************************/
  223. void
  224. mcheck()
  225. {
  226.    if (!first_fd) {
  227.       if (flags & O_DEBUG)
  228.          puts("mcheck: Everything closed.\n");
  229.    } else {
  230.       printf("mcheck: Error, failed to close the following:\n");
  231.       mdump();
  232.    }
  233. }
  234.