#include #include #include #include #include #include #include extern const char *__progname; #include "lock.h" char lock_nohandle; char lock_errhandle; LOCK_HANDLE set_lock(const char *fn, int pid, int errfatal) { char *lfn; char *tfn; int l; int fd; int i; char pidbuf[7]; sprintf(&pidbuf[0],"%d\n",pid); l = strlen(fn); lfn = malloc(l+5+1); tfn = malloc(l+6+5+1); sprintf(lfn,"%s.LOCK",fn); sprintf(tfn,"%s.%05d",lfn,pid); unlink(tfn); fd = open(tfn,O_WRONLY|O_CREAT|O_TRUNC,0644); if (fd < 0) { if (errfatal) { fprintf(stderr,"%s: can't create %s: %s\n",__progname,tfn,strerror(errno)); exit(1); } free(lfn); free(tfn); return(LOCK_ERRHANDLE); } l = strlen(&pidbuf[0]); i = write(fd,&pidbuf[0],l); if (i != l) { if (errfatal) { if (i < 0) { fprintf(stderr,"%s: can't write pid to %s: %s\n",__progname,tfn,strerror(errno)); } else { fprintf(stderr,"%s: can't write pid to %s: wrote %d not %d\n",__progname,tfn,i,l); } unlink(tfn); exit(1); } close(fd); unlink(tfn); free(lfn); free(tfn); return(LOCK_ERRHANDLE); } close(fd); while (link(tfn,lfn) < 0) { if (errno != EEXIST) { if (errfatal) { fprintf(stderr,"%s: can't link %s to %s: %s\n",__progname,tfn,lfn,strerror(errno)); unlink(tfn); exit(1); } unlink(tfn); free(lfn); free(tfn); return(LOCK_ERRHANDLE); } fd = open(lfn,O_RDONLY,0); if (fd < 0) { if (errno != ENOENT) { if (errfatal) { fprintf(stderr,"%s: can't open %s: %s\n",__progname,lfn,strerror(errno)); unlink(tfn); exit(1); } unlink(tfn); free(lfn); free(tfn); return(LOCK_ERRHANDLE); } } else { i = read(fd,&pidbuf[0],sizeof(pidbuf)-1); if (i < 0) { if (errfatal) { fprintf(stderr,"%s: can't read from %s: %s\n",__progname,lfn,strerror(errno)); unlink(tfn); exit(1); } close(fd); unlink(tfn); free(lfn); free(tfn); return(LOCK_ERRHANDLE); } close(fd); pidbuf[i] = '\0'; i = kill(atoi(&pidbuf[0]),0); if ((i >= 0) || (errno != ESRCH)) { if (errfatal) { fprintf(stderr,"%s: %s is locked\n",__progname,fn); unlink(tfn); exit(1); } unlink(tfn); free(lfn); free(tfn); return(LOCK_NOHANDLE); } unlink(lfn); } } unlink(tfn); free(tfn); return((LOCK_HANDLE)lfn); } void unset_lock(LOCK_HANDLE h) { if (h == LOCK_NOHANDLE) return; if (h == LOCK_ERRHANDLE) abort(); unlink((char *)h); free(h); }