* lock handler
*/
struct _mnt_lock {
- pid_t id; /* getpid() or so (see linkfile)... */
char *lockfile; /* path to lock file (e.g. /etc/mtab~) */
char *linkfile; /* path to link file (e.g. /etc/mtab~.<id>) */
int lockfile_fd; /* lock file descriptor */
/**
* mnt_new_lock:
- * @lockfile: path to lockfile or NULL (default is _PATH_MOUNTED_LOCK)
+ * @dataname: the file that should be covered by the lock
* @id: unique linkfile identifier or 0 (default is getpid())
*
* Returns: newly allocated lock handler or NULL on case of error.
*/
-mnt_lock *mnt_new_lock(const char *lockfile, pid_t id)
+mnt_lock *mnt_new_lock(const char *datafile, pid_t id)
{
- mnt_lock *ml = calloc(1, sizeof(struct _mnt_lock));
+ mnt_lock *ml = NULL;
+ char *lo = NULL, *ln = NULL;
- if (!ml)
+ /* lockfile */
+ if (!datafile)
return NULL;
- ml->lockfile_fd = -1;
- ml->id = id;
- if (lockfile) {
- ml->lockfile = strdup(lockfile);
- if (!ml->lockfile) {
- free(ml);
- return NULL;
- }
+ if (asprintf(&lo, "%s~", datafile) == -1) {
+ lo = NULL;
+ goto err;
+ }
+ if (asprintf(&ln, "%s~.%d", datafile, id ? : getpid()) == -1) {
+ ln = NULL;
+ goto err;
}
+ ml = calloc(1, sizeof(struct _mnt_lock) );
+ if (!ml)
+ goto err;
+
+ ml->lockfile_fd = -1;
+ ml->linkfile = ln;
+ ml->lockfile = lo;
return ml;
+err:
+ free(lo);
+ free(ln);
+ free(ml);
+ return NULL;
}
+
/**
* mnt_free_lock:
* @ml: mnt_lock handler
*/
const char *mnt_lock_get_lockfile(mnt_lock *ml)
{
- if (!ml)
- return NULL;
- if (ml->lockfile)
- return ml->lockfile;
- return _PATH_MOUNTED_LOCK;
+ return ml ? ml->lockfile : NULL;
}
/**
* mnt_lock_get_linkfile:
* @ml: mnt_lock handler
*
- * Returns: unique (per process) path to linkfile.
+ * Note that the filename is generated by mnt_new_lock() and depends on
+ * getpid() or 'id' argument of the mnt_new_lock() function.
+ *
+ * Returns: unique (per process/thread) path to linkfile.
*/
const char *mnt_lock_get_linkfile(mnt_lock *ml)
{
- if (!ml)
- return NULL;
-
- if (!ml->linkfile) {
- const char *lf = mnt_lock_get_lockfile(ml);
- size_t sz;
-
- if (!lf)
- return NULL;
- sz = strlen(lf) + 32;
-
- ml->linkfile = malloc(sz);
- if (ml->linkfile)
- snprintf(ml->linkfile, sz, "%s.%d",
- lf, ml->id ? ml->id : getpid());
- }
- return ml->linkfile;
+ return ml ? ml->linkfile : NULL;
}
static void mnt_lockalrm_handler(int sig)
*
* This mtab locking code has been refactored and moved to libmount. The mtab
* locking is really not perfect (e.g. SIGALRM), but it's stable, reliable and
- * backwardly compatible code. Don't forget that this code has to be compatible
- * with 3rd party mounts (/sbin/mount.<foo>) and has to work with NFS.
+ * backwardly compatible code.
+ *
+ * Don't forget that this code has to be compatible with 3rd party mounts
+ * (/sbin/mount.<foo>) and has to work with NFS.
* -- kzak@redhat.com [May-2009]
*/
/* sleep time (in microseconds, max=999999) between attempts */
#define MOUNTLOCK_WAITTIME 5000
-/* Remove lock file. */
+/**
+ * mnt_unlock_file:
+ * @ml: lock struct
+ *
+ * Unlocks the file. The function could be called independently on the
+ * lock status (for example from exit(3)).
+ */
void mnt_unlock_file(mnt_lock *ml)
{
if (!ml)
return;
- DBG(DEBUG_LOCKS, fprintf(stderr, "LOCK: (%d) unlocking/cleaning.\n", getpid()));
+ DBG(DEBUG_LOCKS, fprintf(stderr,
+ "LOCK: (%d) unlocking/cleaning.\n", getpid()));
if (ml->locked == 0 && ml->lockfile && ml->linkfile)
{
* int update_mtab()
* {
* int sig = 0;
+ * const char *mtab;
*
- * atexit(unlock_fallback);
+ * if (!(mtab = mnt_get_writable_mtab_path()))
+ * return 0; // system without mtab
+ * if (!(ml = mnt_new_lock(mtab, 0)))
+ * return -1; // error
*
- * ml = mnt_new_lock(NULL, 0);
+ * atexit(unlock_fallback);
*
* if (mnt_lock_file(ml) != 0) {
* printf(stderr, "cannot create %s lockfile\n",
}
DBG(DEBUG_LOCKS, fprintf(stderr,
"LOCK: %s: (%d) successfully locked\n",
- ml->lockfile, getpid()));
+ lockfile, getpid()));
unlink(linkfile);
return 0;
int test_lock(struct mtest *ts, int argc, char *argv[])
{
- const char *lockfile, *datafile;
+ const char *datafile;
int verbose = 0, loops, l;
- if (argc < 4)
+ if (argc < 3)
return -1;
- lockfile = argv[1];
- datafile = argv[2];
- loops = atoi(argv[3]);
+ datafile = argv[1];
+ loops = atoi(argv[2]);
if (argc == 5 && strcmp(argv[4], "--verbose") == 0)
verbose = 1;
}
for (l = 0; l < loops; l++) {
- lock = mnt_new_lock(lockfile, 0);
+ lock = mnt_new_lock(datafile, 0);
+ if (!lock)
+ return -1;
if (mnt_lock_file(lock) == -1) {
- fprintf(stderr, "%d: failed to create lock file: %s\n",
- getpid(), lockfile);
+ fprintf(stderr, "%d: failed to lock %s file\n",
+ getpid(), datafile);
return -1;
}
int main(int argc, char *argv[])
{
struct mtest tss[] = {
- { "--lock", test_lock, " <lockfile> <datafile> <loops> [--verbose] increment number in datafile" },
+ { "--lock", test_lock, " <datafile> <loops> [--verbose] increment number in datafile" },
{ NULL }
};