2 * Copyright (C) 2001 Yan "Warrior" Gurtovoy (ymg@azstarnet.com)
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 int dev_getstat(char *dev, devrec *dptr) {
22 /* validates device name, retreives stat structure for it,
23 * and generates names for the lock files.
24 * input: device name in *dev,
25 * pointer to the devrec structure in *dptr
26 * returns: 0 on success, -1 on error.
33 /* check if device name looks good */
34 if (!(ptr = strrchr(dev, '/')) || ptr - dev >= strlen(dev)) {
35 fprintf(stderr, "\n%s %s\n", DINVNAME, dev);
38 /* check if device exists and get major and minor numbers */
39 if (stat(dev, &(dptr->strec)) == -1) {
40 sprintf(buffer, "%s %s", DACCFAIL, dev);
44 /* generate FSSTND-1.2 lock file name */
45 sprintf(dptr->fsstnd, "%s/LCK..%s", LOCK_PATH, ++ptr);
46 /* generate SVr4 lock file name */
47 if ((dptr->strec).st_rdev >= TTYAUX_MAJOR * 256 + 64 &&
48 (dptr->strec).st_rdev <= TTYAUX_MAJOR * 256 + 127) {
49 tmp = (TTY_MAJOR - TTYAUX_MAJOR) * 256;
51 sprintf(dptr->svr4, "%s/LCK.%03d.%03d", LOCK_PATH,
52 (int) MAJOR(tmp + (dptr->strec).st_rdev),
53 (int) MINOR(tmp + (dptr->strec).st_rdev));
57 pid_t dev_readpid(const char *fname) {
58 /* reads pid from a specified lock file
59 * input: name of the file in fname
60 * returns: pid on success, -1 on error
66 if (!(fd = fopen(fname, "r"))) {
69 /* get owner's pid from the file */
70 tmp = fscanf(fd, "%d", &pid);
73 return tmp == 1 ? pid : -1;
76 pid_t dev_checklock(char *dev, devrec *drec) {
77 /* performs actual check of the locks, called
78 * internally from dev_getlock() and dev_unlock
79 * returns: 0 if device is not locked, -1 on error,
80 * pid of the process that owns device otherwise.
87 for (j = 0; j < 2; j++) {
89 /* check for FSSTND-1.2 lock */
90 lckname = drec->fsstnd;
92 /* check for a SVr4 style lock */
94 /* try to open the lock file */
95 if ((pid = dev_readpid(lckname)) == -1) {
96 /* don't bail out if file doesn't exist */
97 if (errno != ENOENT) {
98 sprintf(buffer, "Failed to open lock file %s", lckname);
103 /* check if we got a valid pid */
107 /* it's a stale lock, let's remove it */
108 if (unlink(lckname) == -1) {
109 sprintf(buffer, "Failed to remove stale lock %s", lckname);
115 return 0; /* no valid lock found */
118 pid_t dev_getlock(char *dev) {
120 * checks if device is locked
121 * input: device name in *dev, i.e. "/dev/ttyS0"
122 * returns: 0 if device is not locked, -1 on error,
123 * pid of the process that owns device otherwise.
129 /* allocate memory for drec */
130 if (!(drec = malloc(sizeof(devrec)))) {
131 fprintf(stderr, "\nMemory allocation failed! \n");
134 /* get drec for the device */
135 if (dev_getstat(dev, drec) == -1) {
139 pid = dev_checklock(dev, drec);
144 pid_t dev_setlock(char *dev) {
145 /* locks specified device
146 * input: device name in *dev, i.e. "/dev/ttyS0"
147 * returns: lock owner's pid on success, -1 on error
152 pid_t ourpid, pid1, pid2 = 0;
157 /* allocate memory for drec */
158 if (!(drec = malloc(sizeof(devrec)))) {
159 fprintf(stderr, "\nMemory allocation failed! \n");
162 /* give rw permissions to lock files created */
164 /* get drec for the device */
165 if (dev_getstat(dev, drec) == -1) {
169 /* get our own pid */
171 /* check if device is already locked */
172 if ((pid1 = dev_checklock(dev, drec)) == -1) {
173 /* something went wrong while checking the lock - bail out */
177 /* it's locked already */
178 if (pid1 == ourpid) {
179 /* we own this device, do nothing */
183 /* it's locked by someone else */
184 fprintf(stderr, "Unable to obtain lock. Device %s is locked by pid %li\n",
185 dev, (long int) pid1);
190 /* create a file with our pid in the name - should be unique */
191 sprintf(lckname, "%s/LCK...%d", LOCK_PATH, (int) ourpid);
192 if (!(fd = fopen(lckname, "w"))) {
193 sprintf(buffer, "Failed to create lock file %s", lckname);
198 fprintf(fd, "%d\n", (int) ourpid);
201 /* create SVr4 lock */
202 if (link(lckname, drec->svr4) == -1) {
203 sprintf(buffer, "Failed to create lock file %s", drec->svr4);
209 /* create FSSTND-1.2 lock */
210 if (link(lckname, drec->fsstnd) == -1) {
211 sprintf(buffer, "Failed to create lock file %s", drec->fsstnd);
218 /* both locks created succesfully, let's make sure nothing went wrong */
219 if ((pid1 = dev_readpid(drec->fsstnd)) != ourpid ||
220 (pid2 = dev_readpid(drec->svr4)) != ourpid) {
221 /* something went wrong, we don't own at least one of the locks */
222 /* unlink files we own and bail out */
225 unlink(drec->fsstnd);
226 else if (pid2 == ourpid)
228 if (pid1 != ourpid) {
229 sprintf(buffer,"%s %li", RACECOND, (long int) pid1);
232 if (pid2 != ourpid && pid2 != pid1) {
233 sprintf(buffer, "%s %li", RACECOND, (long int) pid2);
239 /* we own the lock */
246 int dev_unlock(char *dev) {
247 /* unlocks specified device
248 * input: device name in *dev, i.e. "/dev/ttyS0"
249 * returns: 0 on success, -1 on error
256 /* allocate memory for drec */
257 if (!(drec = malloc(sizeof(devrec)))) {
258 fprintf(stderr, "\nMemory allocation failed! \n");
261 /* get drec for the device */
262 if (dev_getstat(dev, drec) == -1) {
266 /* get our own pid */
268 /* check if device is already locked */
269 if ((pid1 = dev_checklock(dev, drec)) == -1) {
270 /* something went wrong while checking the lock - bail out */
274 /* it's not locked, so we have nothing to do */
279 if (pid1 == ourpid) {
280 /* we own this device, remove lock */
281 if (unlink(drec->fsstnd) == -1) {
282 sprintf(buffer, "%s %s", REMFAIL, drec->fsstnd);
285 if (unlink(drec->svr4) == -1) {
286 sprintf(buffer, "%s %s", REMFAIL, drec->svr4);
292 /* it's locked by someone else */
293 fprintf(stderr, "Unable to remove lock. Device %s is locked by pid %li\n",
294 dev, (long int) pid1);