/************************************************************************ * secure exclusive creat/lock v1.6 1995/05/05 * * (works even across NFS, which O_EXCL does *not*) * * * * Created 1990-1995, S.R. van den Berg, The Netherlands * * berg@pool.informatik.rwth-aachen.de * * berg@physik.tu-muenchen.de * * * * This file is donated to the public domain. * * * * Usage: int xcreat(const char*filename,mode_t mode) * * * * returns 0:success -1:lock busy * * -2:parameter error or out of memory * * * * sets errno on failure * * * * To remove a `lockfile', simply unlink it. * * * ************************************************************************/ #define HOSTNAMElen 9 /* significant characters for hostname */ /*#define NOuname /* uncomment if uname is not available */ /*#define NOstrpbrk /* uncomment if strpbrk is not available */ /*#define strchr(s,c) index(s,c) /* uncomment if strchr is not available */ #define const /* can be undefined for ANSI compilers */ static const char dirsep[]="/"; /* directory separators */ #include /* open() close() link() unlink() getpid() */ #include /* O_WRONLY O_CREAT O_EXCL */ #include /* malloc() free() */ #include /* strncpy() strcat() strpbrk() */ #include /* stat() struct stat */ #ifndef NOuname #include /* uname() struct utsname */ #endif #include /************************************************************************ * Only edit below this line if you *think* you know what you are doing * ************************************************************************/ #ifndef O_SYNC #define O_SYNC 0 #endif #ifndef O_CREAT #define copen(path,type,mode) creat(path,mode) #else #define copen(path,type,mode) open(path,type,mode) #endif #define log(string) /* should log string to stderr */ #define UNIQ_PREFIX '_' #define charsSERIAL 4 #define UNIQnamelen (1+charsSERIAL+HOSTNAMElen+1) #define bitsSERIAL (6*charsSERIAL) #define maskSERIAL ((1L<>=6); *dest='\0'; } static unique(full,p,mode)const char*const full;char*const p;const mode_t mode; { unsigned long retry=mrotbSERIAL;int i; /* create unique file name */ do { ultoan(maskSERIAL&(retry-=irotbSERIAL)+(long)getpid(),p+1);*p=UNIQ_PREFIX; strcat(p,hostname()); } while(0>(i=copen(full,O_WRONLY|O_CREAT|O_EXCL|O_SYNC,mode))&&errno==EEXIST&& retry); /* casually check if it already exists (highly unlikely) */ if(i<0) { log("Error while writing to \"");log(full);log("\"\n");return 0; } close(i);return 1; } /* rename MUST fail if already existent */ static myrename(old,newn)const char*const old,*const newn; { int i,serrno;struct stat stbuf; if(!link(old,newn)) { unlink(old); return 0; } serrno=errno;i=stat(old,&stbuf);unlink(old);errno=serrno; return stbuf.st_nlink==2?i:-1; } /* an NFS secure exclusive file open */ xcreat(name,mode)char*name;const mode_t mode; { char*p,*q;int j= -2,i; for(q=name;p=strpbrk(q,dirsep);q=p+1); /* find last DIRSEP */ if(!(p=malloc((i=q-name)+UNIQnamelen))) /* out of memory */ return j; strncpy(p,name,i); if(unique(p,p+i,mode)) j=myrename(p,name); /* try and rename it, fails if nonexclusive */ free(p);return j; } .