home *** CD-ROM | disk | FTP | other *** search
- /* MOPEN.C */
- static char sccsid[]="@(#)files.c 1.4 93/05/11 Copyright (c)1993 thalerd";
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/file.h>
- #include <sys/stat.h>
- #include <fcntl.h> /* to get O_CREAT, etc */
- #include <errno.h>
- #include <string.h>
- #include "config.h"
- #include "struct.h"
- #include "globals.h"
- #include "files.h"
- #include "xalloc.h"
- #include "system.h" /* to get SL_OWNER */
-
- /* Information about each open file */
- typedef struct fd_tt {
- char *filename;
- short flg;
- int fd;
- struct fd_tt *next;
- } fd_t;
- static fd_t *first_fd=0;
-
- #ifdef FLOCKF
- /******************************************************************************/
- /* FLOCK FOR SYSTEMS WITH LOCKF() ONLY */
- /******************************************************************************/
- #include <unistd.h>
- #define LOCK_EX 2
- #define LOCK_NB 4
- int
- flock(fd, operation)
- int fd, operation;
- {
- return lockf(fd,(operation & LOCK_NB)? F_TLOCK : F_LOCK,0L);
- }
- #endif
-
- /******************************************************************************/
- /* DUMP ALL FILES CURRENTLY OPEN */
- /******************************************************************************/
- void /* RETURNS: (nothing) */
- mdump() /* ARGUMENTS: (none) */
- {
- fd_t *this;
-
- for (this=first_fd; this; this = this->next) {
- printf("mdump: fd=%d filename='%s' flg=%x\n",this->fd,
- this->filename, this->flg);
- }
- }
-
- /******************************************************************************/
- /* ADD AN OPEN FD TO THE DATABASE (FROM SPOPEN/MOPEN) */
- /******************************************************************************/
- void
- madd(fd,file,flg)
- int fd;
- char *file;
- short flg;
- {
- fd_t *this;
-
- /* Save info for debugging */
- this = (fd_t *)malloc(sizeof(fd_t));
- this->fd = fd;
- this->filename = xstrdup(file);
- this->flg = flg;
- this->next = first_fd;
- first_fd = this;
- }
-
- /******************************************************************************/
- /* OPEN A FILE AND LOCK IT FOR EXCLUSIVE ACCESS */
- /******************************************************************************/
- FILE * /* RETURNS: Open file pointer, or NULL on error */
- mopen(file,flg) /* ARGUMENTS: */
- char *file; /* Filename to open */
- long flg; /* Flag: 0=append only, 1=create new (only) */
- {
- struct stat st;
- short err;
- int fd,
- perm;
- char modestr[3];
- FILE *fp;
- char buff[MAX_LINE_LENGTH];
- #ifdef NOFLOCK
- short timeout=0;
- #endif
-
- if (flags & O_DEBUG)
- printf("mopen: flags=%x\n",flg);
-
- /* Process flags */
- if (flg & (O_EXCL|O_NOCREATE)) err=stat(file,&st);
- if ( err && (flg & O_NOCREATE)) {
- if (!(flg & O_SILENT)) error("opening ",file);
- return NULL; /* append: doesn't exist */
- } else if (!err && (flg & O_CREAT) && (flg & O_EXCL)) {
- error("creating ",file);
- return NULL; /* create: already exists */
- }
- perm=umask(0);
-
- #ifdef NOFLOCK
- /* For auxilary file locking */
- if (flg & O_LOCK) {
- sprintf(buff,"%s.lock",file);
- while ((fd=open(buff,O_WRONLY|O_CREAT|O_EXCL,0400))<0
- && errno==EEXIST && timeout<10 && !(status & S_INT)) {
- if (flg & O_NOBLOCK)
- return NULL; /* can't lock */
- timeout++;
- sleep(1);
- }
- if (fd>=0) close(fd);
-
- /* Currently overrides lock after timeout
- *
- * if (timeout>=10 || (status & S_INT)) {
- * error("locking ",buff);
- * umask(perm);
- * return NULL;
- * }
- */
- if (timeout>=10) printf("Warning: overriding lock on %s\n",file);
- }
- #endif
-
- /* Open file */
- fd=open(file,flg & O_PASSTHRU,(flg & O_PRIVATE)? 0600 : 0644);
- if (fd < 0) {
- error("opening ",file);
- #ifdef NOFLOCK
- if (flg & O_LOCK)
- rm(buff,SL_OWNER); /* unlock */
- #endif
- umask(perm);
- return NULL;
- }
-
- #ifndef NOFLOCK
- /* Lock it */
- if (flg & O_LOCK) {
- if (flock(fd,(flg & O_NOBLOCK)? LOCK_EX|LOCK_NB : LOCK_EX)) {
- umask(perm);
- return NULL;
- }
- }
- #endif
-
- umask(perm);
- if (flg & O_APPEND) lseek(fd,0L,2);
-
- /* Determine mode string */
- if ((flg & O_WPLUS)==O_WPLUS) strcpy(modestr,"w+");
- else if ((flg & O_W )==O_W ) strcpy(modestr,"w");
- else if ((flg & O_APLUS)==O_APLUS) strcpy(modestr,"a+");
- else if ((flg & O_A )==O_A ) strcpy(modestr,"a");
- else if ((flg & O_RPLUS)==O_RPLUS) strcpy(modestr,"r+"); /* should be next to last */
- else if ((flg & O_R )==O_R ) strcpy(modestr,"r"); /* MUST be last */
- else printf("KKK Invalid mopen mode\n");
-
- /* Save info for debugging */
- madd(fd,file,flg);
-
- if ((fp = fdopen(fd,modestr))==NULL) {
- sprintf(buff,"%s for %s after mode %x\n",file,modestr,flg);
- error("reopening ",buff);
- }
- return fp;
- }
-
- /******************************************************************************/
- /* CLOSE AND UNLOCK A FILE */
- /******************************************************************************/
- int /* RETURNS: non-zero on error */
- mclose(fp) /* ARGUMENTS: */
- FILE *fp; /* File pointer to close */
- {
- fd_t *this,*prev=0;
- int ret;
- #ifdef NOFLOCK
- char buff[MAX_LINE_LENGTH];
- #endif
-
- fflush(fp);
- for (this=first_fd; this && this->fd != fileno(fp); prev=this, this = this->next);
- if (!this) {
- (void)printf("Tried to close unopened file\n");
- return 1; /* not found */
- }
- if (!fp) {
- (void)printf("Tried to close null file\n");
- return 1;
- }
-
- ret=fclose(fp); /* flock automatically closes */
-
- #ifdef NOFLOCK
- /* For auxilary file locking */
- if (this->flg & O_LOCK) {
- sprintf(buff,"%s.lock",this->filename);
- rm(buff,SL_OWNER);
- }
- #endif
-
- /* Remove from debugging database */
- if (!prev) first_fd = this->next;
- else prev->next = this->next;
- xfree(this->filename);
- free((char *)this);
-
- return ret;
- }
-
- /******************************************************************************/
- /* VERIFY THAT ALL FILES HAVE BEEN CLOSED */
- /******************************************************************************/
- void
- mcheck()
- {
- if (!first_fd) {
- if (flags & O_DEBUG)
- puts("mcheck: Everything closed.\n");
- } else {
- printf("mcheck: Error, failed to close the following:\n");
- mdump();
- }
- }
-