]> git.alsa-project.org Git - alsa-utils.git/commitdiff
alsactl: Fix the file locking routines (for the state management)
authorJaroslav Kysela <perex@perex.cz>
Wed, 24 Sep 2014 08:35:53 +0000 (10:35 +0200)
committerJaroslav Kysela <perex@perex.cz>
Wed, 24 Sep 2014 08:35:53 +0000 (10:35 +0200)
alsactl/alsactl.h
alsactl/lock.c
alsactl/state.c

index 76e8c36100f9f43229270b718ce68e7eba0eef86..bd9bf23e74b314a6eb25403f24147f7ae9d95011 100644 (file)
@@ -25,7 +25,8 @@ void dbg_(const char *fcn, long line, const char *fmt, ...);
 #endif 
 
 int init(const char *file, const char *cardname);
-int state_lock(const char *file, int lock, int timeout);
+int state_lock(const char *file, int timeout);
+int state_unlock(int fd, const char *file);
 int save_state(const char *file, const char *cardname);
 int load_state(const char *file, const char *initfile, const char *cardname,
               int do_init);
index 6f85f202576dcf3e64967d84fb8698f99b850ffa..9d7efccd7ce6188c4ea09c94200106154f382070 100644 (file)
@@ -30,7 +30,7 @@
 #include <sys/stat.h>
 #include "alsactl.h"
 
-static int state_lock_(const char *file, int lock, int timeout)
+static int state_lock_(const char *file, int lock, int timeout, int _fd)
 {
        int fd = -1, err = 0;
        struct flock lck;
@@ -50,9 +50,14 @@ static int state_lock_(const char *file, int lock, int timeout)
                snprintf(lcktxt, sizeof(lcktxt), "%10li\n", (long)getpid());
        } else {
                snprintf(lcktxt, sizeof(lcktxt), "%10s\n", "");
+               fd = _fd;
        }
        while (fd < 0 && timeout-- > 0) {
                fd = open(nfile, O_RDWR);
+               if (!lock && fd < 0) {
+                       err = -EIO;
+                       goto out;
+               }
                if (fd < 0) {
                        fd = open(nfile, O_RDWR|O_CREAT|O_EXCL, 0644);
                        if (fd < 0) {
@@ -74,12 +79,12 @@ static int state_lock_(const char *file, int lock, int timeout)
                err = -errno;
                goto out;
        }
-       if (st.st_size != 11) {
+       if (st.st_size != 11 || !lock) {
                if (write(fd, lcktxt, 11) != 11) {
                        err = -EIO;
                        goto out;
                }
-               if (lseek(fd, 0, SEEK_SET)) {
+               if (lock && lseek(fd, 0, SEEK_SET)) {
                        err = -errno;
                        goto out;
                }
@@ -96,21 +101,37 @@ static int state_lock_(const char *file, int lock, int timeout)
                err = -EBUSY;
                goto out;
        }
-       if (write(fd, lcktxt, 11) != 11) {
-               err = -EIO;
-               goto out;
+       if (lock) {
+               if (write(fd, lcktxt, 11) != 11) {
+                       err = -EIO;
+                       goto out;
+               }
+               return fd;
        }
+       err = 0;
+
 out:
+       if (fd >= 0)
+               close(fd);
+       return err;
+}
+
+int state_lock(const char *file, int timeout)
+{
+       int err;
+
+       err = state_lock_(file, 1, timeout, -1);
+       if (err < 0)
+               error("file %s lock error: %s", file, strerror(-err));
        return err;
 }
 
-int state_lock(const char *file, int lock, int timeout)
+int state_unlock(int _fd, const char *file)
 {
        int err;
 
-       err = state_lock_(file, lock, timeout);
+       err = state_lock_(file, 0, 10, _fd);
        if (err < 0)
-               error("file %s %slock error: %s", file,
-                               lock ? "" : "un", strerror(-err));
+               error("file %s unlock error: %s", file, strerror(-err));
        return err;
 }
index e0c6f2e02e9bcd686ff7a7ee7480d59f4e5ce863..0c897034057c836f1186d5ee352053617ae01adf 100644 (file)
@@ -1544,6 +1544,7 @@ int save_state(const char *file, const char *cardname)
        snd_output_t *out;
        int stdio;
        char *nfile = NULL;
+       int lock_fd = -EINVAL;
 
        err = snd_config_top(&config);
        if (err < 0) {
@@ -1555,12 +1556,16 @@ int save_state(const char *file, const char *cardname)
                nfile = malloc(strlen(file) + 5);
                if (nfile == NULL) {
                        error("No enough memory...");
+                       err = -ENOMEM;
                        goto out;
                }
                strcpy(nfile, file);
                strcat(nfile, ".new");
-               if (state_lock(file, 1, 10) != 0)
+               lock_fd = state_lock(file, 10);
+               if (lock_fd < 0) {
+                       err = lock_fd;
                        goto out;
+               }
        }
        if (!stdio && (err = snd_input_stdio_open(&in, file, "r")) >= 0) {
                err = snd_config_load(config, in);
@@ -1632,8 +1637,8 @@ int save_state(const char *file, const char *cardname)
                        error("rename failed: %s (%s)", strerror(-err), file);
        }
 out:
-       if (!stdio)
-               state_lock(file, 0, 10);
+       if (!stdio && lock_fd >= 0)
+               state_unlock(lock_fd, file);
        free(nfile);
        snd_config_delete(config);
        snd_config_update_free_global();
@@ -1646,7 +1651,7 @@ int load_state(const char *file, const char *initfile, const char *cardname,
        int err, finalerr = 0;
        snd_config_t *config;
        snd_input_t *in;
-       int stdio, locked = 0;
+       int stdio, lock_fd = -EINVAL;
 
        err = snd_config_top(&config);
        if (err < 0) {
@@ -1657,15 +1662,14 @@ int load_state(const char *file, const char *initfile, const char *cardname,
        if (stdio) {
                err = snd_input_stdio_attach(&in, stdin, 0);
        } else {
-               err = state_lock(file, 1, 10);
-               locked = err >= 0;
-               err = err >= 0 ? snd_input_stdio_open(&in, file, "r") : err;
+               lock_fd = state_lock(file, 10);
+               err = lock_fd >= 0 ? snd_input_stdio_open(&in, file, "r") : lock_fd;
        }
        if (err >= 0) {
                err = snd_config_load(config, in);
                snd_input_close(in);
-               if (locked)
-                       state_lock(file, 0, 10);
+               if (lock_fd >= 0)
+                       state_unlock(lock_fd, file);
                if (err < 0) {
                        error("snd_config_load error: %s", snd_strerror(err));
                        goto out;