/** * Lock a file. * * @param lockfd The pointer to the lock file descriptor. It must be allocated * statically as its addresses is passed to a cleanup handler. * @param flags The lock flags specifying what type of locking to perform. * @param filename The name of the file to lock. * @param desc The description of the file to lock. */ void file_lock(int *lockfd, enum file_lock_flags flags, const char *filename, const char *desc) { struct flock fl; int lock_cmd; setcloexec(*lockfd, filename); file_lock_setup(&fl, F_WRLCK); if (flags == FILE_LOCK_WAIT) lock_cmd = F_SETLKW; else lock_cmd = F_SETLK; if (fcntl(*lockfd, lock_cmd, &fl) == -1) { if (errno == EACCES || errno == EAGAIN) ohshit(_("%s is locked by another process"), desc); else ohshite(_("unable to lock %s"), desc); } push_cleanup(file_unlock_cleanup, ~0, NULL, 0, 2, lockfd, desc); }
/** * Unlock a previously locked file. */ void file_unlock(int lockfd, const char *lock_desc) { struct flock fl; assert(lockfd >= 0); file_lock_setup(&fl, F_UNLCK); if (fcntl(lockfd, F_SETLK, &fl) == -1) ohshite(_("unable to unlock %s"), lock_desc); }
static void file_unlock_cleanup(int argc, void **argv) { int lockfd = *(int*)argv[0]; struct flock fl; assert(lockfd >= 0); file_lock_setup(&fl, F_UNLCK); if (fcntl(lockfd, F_SETLK, &fl) == -1) ohshite(_("unable to unlock dpkg status database")); }
/** * Check if a file has a lock acquired. * * @param lockfd The file descriptor for the lock. * @param filename The file name associated to the file descriptor. */ bool file_is_locked(int lockfd, const char *filename) { struct flock fl; file_lock_setup(&fl, F_WRLCK); if (fcntl(lockfd, F_GETLK, &fl) == -1) ohshit(_("unable to check file '%s' lock status"), filename); if (fl.l_type == F_WRLCK && fl.l_pid != getpid()) return true; else return false; }
/* lockfd must be allocated statically as its addresses is passed to * a cleanup handler. */ void file_lock(int *lockfd, const char *filename, const char *emsg, const char *emsg_eagain) { struct flock fl; setcloexec(*lockfd, filename); file_lock_setup(&fl, F_WRLCK); if (fcntl(*lockfd, emsg_eagain ? F_SETLK : F_SETLKW, &fl) == -1) { if (emsg_eagain && (errno == EACCES || errno == EAGAIN)) ohshit(emsg_eagain); ohshite(emsg); } push_cleanup(file_unlock_cleanup, ~0, NULL, 0, 1, lockfd); }