/* pklock.c -- implements pklock.h */ #include "pklock.h" /* PKLOCK.C * * locking routines as modified by Petri Kutvonen */ #if (FILOCK && BSD) || SVR4 #include #include #include #include #include #ifdef SVR4 #include #else #include #endif #include #include "util.h" /* Maximum file length name 255 */ #define MAXLOCK 256 #define MAXNAME 128 #if defined(SVR4) && ! defined(__linux__) #include int gethostname(char *name, int namelen) { return sysinfo(SI_HOSTNAME, name, namelen); } #endif char *cuserid( char *retbuf) ; /* should have been declared in stdio.h */ /********************** * * if successful, returns NULL * if file locked, returns username of person locking the file * if other error, returns "LOCK ERROR: explanation" * *********************/ char *dolock( const char *fname) { int fd, n; char lname[ MAXLOCK] ; static char locker[ MAXNAME + 1] ; int mask; struct stat sbuf; mystrscpy( lname, fname, sizeof lname - 6) ; strcat( lname, ".lock~") ; /* check that we are not being cheated, qname must point to */ /* a regular file - even this code leaves a small window of */ /* vulnerability but it is rather hard to exploit it */ #if defined(S_IFLNK) if (lstat(lname, &sbuf) == 0) #else if (stat(lname, &sbuf) == 0) #endif #if defined(S_ISREG) if (!S_ISREG(sbuf.st_mode)) #else if (!(((sbuf.st_mode) & 070000) == 0)) /* SysV R2 */ #endif return "LOCK ERROR: not a regular file"; mask = umask(0); fd = open(lname, O_RDWR | O_CREAT, 0666); umask(mask); if (fd < 0) { if (errno == EACCES) return NULL; #ifdef EROFS if (errno == EROFS) return NULL; #endif return "LOCK ERROR: cannot access lock file"; } if ((n = read(fd, locker, MAXNAME)) < 1) { lseek(fd, 0, SEEK_SET); /* ** Since Ubuntu 17.04, cuserid prototype seems missing. Replacing it by ** getlogin does the trick on 64 bits but fails on 32 bits. ** So let's work around with cuserid for a while. ** logname = getlogin() ; ** strcpy( locker, logname ? logname : cuserid( NULL)) ; */ #if BSD strcpy( locker, getlogin()) ; #else strcpy( locker, cuserid( NULL)) ; #endif strcat(locker + strlen(locker), "@"); gethostname(locker + strlen(locker), 64); { int ret, locker_size ; locker_size = strlen( locker) ; ret = write( fd, locker, locker_size) ; if( ret != locker_size) { /* some error handling here */ } } close(fd); return NULL; } locker[n > MAXNAME ? MAXNAME : n] = 0; return locker; } /********************* * * undolock -- unlock the file fname * * if successful, returns NULL * if other error, returns "LOCK ERROR: explanation" * *********************/ char *undolock( const char *fname) { char lname[ MAXLOCK] ; mystrscpy( lname, fname, sizeof lname - 6) ; strcat( lname, ".lock~") ; if (unlink(lname) != 0) { if (errno == EACCES || errno == ENOENT) return NULL; #ifdef EROFS if (errno == EROFS) return NULL; #endif return "LOCK ERROR: cannot remove lock file"; } return NULL; } #else typedef void _pedantic_empty_translation_unit ; #endif /* end of pklock.c */