/*--------------------------------------------------------*/ /* file.c 02-mar-1999/bets */ /*--------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include "file.h" int errno; extern char *progname; /*--------------------------------------------------------*/ /* file_exists */ /* */ /* returns TRUE if file exists */ /* returns FALSE if file does not exist */ /*--------------------------------------------------------*/ int file_exists( char *filename ) { if ( access( filename,F_OK ) == 0 ) { return( TRUE ); } else { fprintf( stderr,"[%s] can't access %s: %s\n", progname,filename,strerror( errno )); return( FALSE ); } } /* end of file_exists() */ /*--------------------------------------------------------*/ /* file_delete */ /* */ /* removes a file */ /* */ /* returns TRUE if file is deleted successfully */ /* returns FALSE if not */ /*--------------------------------------------------------*/ int file_delete( char *filename ) { if ( unlink( filename ) == 0 ) { return( TRUE ); } else { fprintf( stderr,"[%s] can't unlink %s: %s\n", progname,filename,strerror( errno )); return( FALSE ); } } /* end of file_delete() */ /*--------------------------------------------------------*/ /* file_lock */ /* */ /* this routine "locks" a file by creating a file named */ /* "lockname" and locking that file with either an */ /* exclusive or a shared lock. the idea is that the */ /* "lockfile" is associated with a file (or set of files) */ /* that are the one(s) really being locked. the lockfile */ /* contains the pid of the process that creates it. */ /* */ /* file_unlock must be called to unlock the file. */ /* */ /* if the process locking the lockfile exits abnormally */ /* (i.e. without unlocking the lockfile), then the lock */ /* is removed automatically by the system. */ /* */ /* the routine returns NULL if the lockfile is currently */ /* locked by another process (in exclusive mode); */ /* otherwise, the routine returns a file pointer to the */ /* lockfile */ /* */ /* arguments: */ /* lockname (input) = the name of the lockfile */ /* mode (input) = mode for file locking: */ /* 'x' -> exclusive */ /* 's' -> shared */ /* which means that only ONE process */ /* can have the file locked in */ /* exclusive mode, but multiple */ /* processes can have the file locked */ /* in shared mode; this prevents */ /* multiple processes from writing to */ /* the lockfile at the same time or */ /* processes reading the lockfile at */ /* the same time that a process is */ /* writing to the lockfile */ /*--------------------------------------------------------*/ FILE *file_lock( char *lockname, char mode ) { int e; FILE *fl; switch ( mode ) { case 'x': fl = fopen( lockname,"w" ); if ( fl == NULL ) { fprintf( stderr,"[%s] can't open %s: %s\n", progname,lockname,strerror( errno )); return( NULL ); } e = flock( fileno( fl ),LOCK_EX|LOCK_NB ); fprintf( fl,"%ld",getpid() ); break; case 's': fl = fopen( lockname,"r" ); if ( fl == NULL ) { /* check that failure on open didn't occur because file didn't exist -- in which case, create file, write pid, close file and then we should be able to open it for reading */ if (( fl = fopen( lockname,"w" )) == NULL ) { fprintf( stderr,"[%s] can't open %s: %s\n", progname,lockname,strerror( errno )); return( NULL ); } fprintf( fl,"%ld",getpid() ); fclose( fl ); if (( fl = fopen( lockname,"r" )) == NULL ) { fprintf( stderr,"[%s] can't open %s: %s\n", progname,lockname,strerror( errno )); return( NULL ); } } e = flock( fileno( fl ),LOCK_SH|LOCK_NB ); break; } if ( e == -1 ) { fprintf( stderr,"[%s] can't lock %s: %s\n", progname,lockname,strerror( errno )); fclose( fl ); return( NULL ); } return( fl ); } /* end of file_lock() */ /*--------------------------------------------------------*/ /* file_unlock */ /* */ /* this routine "unlocks" a file by removing the lock on */ /* it that was created by file_lock (see this routine for */ /* details of the locking procedure). */ /* */ /* returns FALSE if it can't unlock the file and */ /* returns TRUE if it can */ /* */ /* argument: */ /* fl (input) = file pointer to lockfile */ /*--------------------------------------------------------*/ int file_unlock( FILE *fl,char *filename ) { if ( flock( fileno( fl ),LOCK_UN ) == -1 ) { fprintf( stderr,"[%s] can't unlock %s: %s\n", progname,filename,strerror( errno )); fclose( fl ); return( FALSE ); } fclose( fl ); file_delete( filename ); return( TRUE ); } /* end of file_unlock() */ /*--------------------------------------------------------*/ /* file_locked */ /* */ /* this routine checks to see if the file named "lockname"*/ /* is locked. */ /* */ /* see the routine "file_lock" for details of the locking */ /* procedure. */ /* */ /* the routine returns TRUE if the lockfile is "locked" */ /* and FALSE if the lockfile is not locked */ /* */ /* argument: */ /* lockname (input) = the name of the file to check */ /*--------------------------------------------------------*/ int file_locked( char *lockname ) { int fn; FILE *fp = fopen( lockname,"r" ); if ( fp == NULL ) { /* if lock file doesn't exist, then it's not locked! */ return( 0 ); } fn = fileno( fp ); return( flock( fn,LOCK_EX|LOCK_NB ) == -1 ); } /* end of file_locked() */ /*--------------------------------------------------------*/ /* file_lock_name */ /* */ /* this routine creates the name of the lock file */ /* associated with "filename", which is ".lock" appended */ /* to "filename" */ /* */ /* returns a string that is the lockfile name */ /* */ /* arguments: */ /* filename (input) = the name of the file with which to */ /* associate the lock file name */ /*--------------------------------------------------------*/ char *file_lock_name( char *filename ) { char *fln = (char *)malloc( (strlen(filename)+6)*sizeof(char) ); if ( (fln) == NULL ) { fprintf( stderr, "[%s] out of memory setting file lock name %s\n", progname,filename ); return( NULL ); } sprintf( fln,"%s.lock",filename ); return( fln ); } /* end of file_lock_name() */