lock.c (2880B)
1 /* 2 * Advanced Linux Sound Architecture Control Program 3 * Copyright (c) by Jaroslav Kysela <perex@perex.cz> 4 * 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * 20 */ 21 22 #include "aconfig.h" 23 #include "version.h" 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <unistd.h> 27 #include <fcntl.h> 28 #include <errno.h> 29 #include <string.h> 30 #include <sys/stat.h> 31 #include "alsactl.h" 32 33 static int state_lock_(const char *file, int lock, int timeout, int _fd) 34 { 35 int fd = -1, err = 0; 36 struct flock lck; 37 struct stat st; 38 char lcktxt[12]; 39 char *nfile = lockfile; 40 41 if (do_lock <= 0) 42 return 0; 43 44 lck.l_type = lock ? F_WRLCK : F_UNLCK; 45 lck.l_whence = SEEK_SET; 46 lck.l_start = 0; 47 lck.l_len = 11; 48 lck.l_pid = 0; 49 if (lock) { 50 snprintf(lcktxt, sizeof(lcktxt), "%10li\n", (long)getpid()); 51 } else { 52 snprintf(lcktxt, sizeof(lcktxt), "%10s\n", ""); 53 fd = _fd; 54 } 55 while (fd < 0 && timeout-- > 0) { 56 fd = open(nfile, O_RDWR); 57 if (!lock && fd < 0) { 58 err = -EIO; 59 goto out; 60 } 61 if (fd < 0) { 62 fd = open(nfile, O_RDWR|O_CREAT|O_EXCL, 0644); 63 if (fd < 0) { 64 if (errno == EBUSY || errno == EAGAIN) { 65 sleep(1); 66 timeout--; 67 } else { 68 err = -errno; 69 goto out; 70 } 71 } 72 } 73 } 74 if (fd < 0 && timeout <= 0) { 75 err = -EBUSY; 76 goto out; 77 } 78 if (fstat(fd, &st) < 0) { 79 err = -errno; 80 goto out; 81 } 82 if (st.st_size != 11 || !lock) { 83 if (write(fd, lcktxt, 11) != 11) { 84 err = -EIO; 85 goto out; 86 } 87 if (lock && lseek(fd, 0, SEEK_SET)) { 88 err = -errno; 89 goto out; 90 } 91 } 92 while (timeout > 0) { 93 if (fcntl(fd, F_SETLK, &lck) < 0) { 94 sleep(1); 95 timeout--; 96 } else { 97 break; 98 } 99 } 100 if (timeout <= 0) { 101 err = -EBUSY; 102 goto out; 103 } 104 if (lock) { 105 if (write(fd, lcktxt, 11) != 11) { 106 err = -EIO; 107 goto out; 108 } 109 return fd; 110 } 111 err = 0; 112 113 out: 114 if (fd >= 0) 115 close(fd); 116 return err; 117 } 118 119 int state_lock(const char *file, int timeout) 120 { 121 int err; 122 123 err = state_lock_(file, 1, timeout, -1); 124 if (err < 0) 125 error("file %s lock error: %s", file, strerror(-err)); 126 return err; 127 } 128 129 int state_unlock(int _fd, const char *file) 130 { 131 int err; 132 133 err = state_lock_(file, 0, 10, _fd); 134 if (err < 0) 135 error("file %s unlock error: %s", file, strerror(-err)); 136 return err; 137 }