/* @(#)ulockf.c 1.3 */ #include "uucp.h" #include <sys/types.h> #include <sys/stat.h> #include <sys/errno.h> /* * create a lock file (file). * If one already exists, the create time is checked for * older than the age time (atime). * If it is older, an attempt will be made to unlink it * and create a new one. * return: * 0 -> success * FAIL -> failure */ ulockf(file, atime) register char *file; time_t atime; { register int ret; struct stat stbuf; static int pid = -1; static char tempfile[NAMESIZE]; time_t ptime, time(); if (pid < 0) { pid = getpid(); sprintf(tempfile, "LTMP.%d", pid); } if (onelock(pid, tempfile, file) == -1) { /* * lock file exists * get status to check age of the lock file */ ret = stat(file, &stbuf); if (ret != -1) { time(&ptime); if ((ptime - stbuf.st_ctime) < atime) { /* * file not old enough to delete */ return(FAIL); } } ret = unlink(file); ret = onelock(pid, tempfile, file); if (ret != 0) return(FAIL); } stlock(file); return(0); } #define MAXLOCKS 10 /* maximum number of lock files */ char *Lockfile[MAXLOCKS]; int Nlocks = 0; /* * put name in list of lock files * return: * none */ stlock(name) char *name; { register int i; char *p, *strcpy(), *calloc(); for (i = 0; i < Nlocks; i++) { if (Lockfile[i] == NULL) break; } ASSERT(i < MAXLOCKS, "TOO MANY LOCKS", "", i); if (i >= Nlocks) i = Nlocks++; p = calloc((unsigned) strlen(name) + 1, sizeof (char)); ASSERT(p != NULL, "CAN NOT ALLOCATE FOR", name, 0); strcpy(p, name); Lockfile[i] = p; return; } /* * remove all lock files in list * return: * none */ rmlock(name) register char *name; { register int i; void free(); for (i = 0; i < Nlocks; i++) { if (Lockfile[i] == NULL) continue; if (name == NULL || strcmp(name, Lockfile[i]) == SAME) { unlink(Lockfile[i]); free(Lockfile[i]); Lockfile[i] = NULL; } } return; } /* * return: * 0 -> if the name is a lock */ isalock(name) char *name; { struct stat xstat; if(stat(name,&xstat)<0) return(0); if(xstat.st_size!=sizeof(int)) return(0); return(1); } /* * makes lock a name on behalf of pid. * Tempfile must be in the same file system as name. */ onelock(pid,tempfile,name) char *tempfile, *name; { register int fd; char cb[100]; extern errno; fd=creat(tempfile,0444); if(fd < 0){ sprintf(cb, "%s %s %d",tempfile,name,errno); logent("ULOCKC", cb); if((errno == EMFILE) || (errno == ENFILE)) unlink(tempfile); return(-1); } write(fd,(char *) &pid,sizeof(int)); close(fd); if(link(tempfile,name)<0){ if(unlink(tempfile)< 0){ sprintf(cb, "ULK err %s %d", tempfile, errno); logent("ULOCKLNK", cb); } return(-1); } if(unlink(tempfile)<0){ sprintf(cb, "%s %d",tempfile,errno); logent("ULOCKF", cb); } return(0); } #define LOCKPRE "LCK." /* * remove a lock file * return: * 0 -> success * FAIL -> failure */ delock(s) char *s; { char ln[30]; sprintf(ln, "%s.%s", LOCKPRE, s); rmlock(ln); } /* * create system lock * return: * 0 -> success * FAIL -> failure */ mlock(sys) char *sys; { char lname[30]; sprintf(lname, "%s.%s", LOCKPRE, sys); return(ulockf(lname, (time_t) SLCKTIME ) < 0 ? FAIL : 0); } /* * update access and modify times for lock files * return: * none */ ultouch() { register int i; time_t time(); struct ut { time_t actime; time_t modtime; } ut; ut.actime = time(&ut.modtime); for (i = 0; i < Nlocks; i++) { if (Lockfile[i] == NULL) continue; utime(Lockfile[i], &ut); } return; }