blob: 017b144c383bf802493887bac8507d234dc8230e [file] [log] [blame]
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -07001/*
sn19941094e17612006-08-22 10:36:18 -07002 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -07003 * Use is subject to license terms.
4 */
muffin8d489c72005-09-16 01:11:41 -07005
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -07006/*
7 * Copyright (c) 1983 Regents of the University of California.
8 * All rights reserved. The Berkeley software License Agreement
9 * specifies the terms and conditions for redistribution.
10 */
muffin8d489c72005-09-16 01:11:41 -070011
12#pragma ident "%Z%%M% %I% %E% SMI"
13
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -070014/*
15 * defs that come from uucp.h
16 */
17#define NAMESIZE 40
18#define FAIL -1
19#define SAME 0
20#define SLCKTIME (8*60*60) /* device timeout (LCK.. files) in seconds */
21#ifdef __STDC__
22#define ASSERT(e, f, v) if (!(e)) {\
muffin8d489c72005-09-16 01:11:41 -070023 (void) fprintf(stderr, "AERROR - (%s) ", #e); \
24 (void) fprintf(stderr, f, v); \
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -070025 finish(FAIL); \
26}
27#else
28#define ASSERT(e, f, v) if (!(e)) {\
muffin8d489c72005-09-16 01:11:41 -070029 (void) fprintf(stderr, "AERROR - (%s) ", "e"); \
30 (void) fprintf(stderr, f, v); \
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -070031 finish(FAIL); \
32}
33#endif
34#define SIZEOFPID 10 /* maximum number of digits in a pid */
35
36#define LOCKDIR "/var/spool/locks"
37#define LOCKPRE "LK"
38
39/*
40 * This code is taken almost directly from uucp and follows the same
41 * conventions. This is important since uucp and tip should
42 * respect each others locks.
43 */
44
45#include <sys/types.h>
46#include <sys/stat.h>
47#include <sys/mkdev.h>
48#include <stdio.h>
49#include <errno.h>
50#include <string.h>
muffin8d489c72005-09-16 01:11:41 -070051#include <stdlib.h>
52#include <time.h>
53#include <unistd.h>
54#include <fcntl.h>
55#include <signal.h>
56#include <utime.h>
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -070057
muffin8d489c72005-09-16 01:11:41 -070058static void stlock(char *);
59static int onelock(char *, char *, char *);
60static int checkLock(char *);
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -070061
muffin8d489c72005-09-16 01:11:41 -070062extern void finish(int);
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -070063
64/*
65 * ulockf(file, atime)
66 * char *file;
67 * time_t atime;
68 *
69 * ulockf - this routine will create a lock file (file).
70 * If one already exists, send a signal 0 to the process--if
71 * it fails, then unlink it and make a new one.
72 *
73 * input:
74 * file - name of the lock file
75 * atime - is unused, but we keep it for lint compatibility
76 * with non-ATTSVKILL
77 *
78 * return codes: 0 | FAIL
79 */
muffin8d489c72005-09-16 01:11:41 -070080/* ARGSUSED */
81static int
82ulockf(char *file, time_t atime)
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -070083{
84 static char pid[SIZEOFPID+2] = { '\0' }; /* +2 for '\n' and NULL */
85 static char tempfile[NAMESIZE];
86
87 if (pid[0] == '\0') {
sn19941094e17612006-08-22 10:36:18 -070088 (void) snprintf(pid, sizeof (pid), "%*d\n", SIZEOFPID,
89 (int)getpid());
muffin8d489c72005-09-16 01:11:41 -070090 (void) snprintf(tempfile, sizeof (tempfile),
91 "%s/LTMP.%d", LOCKDIR, getpid());
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -070092 }
93 if (onelock(pid, tempfile, file) == -1) {
94 /* lock file exists */
95 (void) unlink(tempfile);
96 if (checkLock(file))
97 return (FAIL);
98 else {
99 if (onelock(pid, tempfile, file)) {
100 (void) unlink(tempfile);
101 return (FAIL);
102 }
103 }
104 }
105 stlock(file);
106 return (0);
107}
108
109/*
110 * check to see if the lock file exists and is still active
111 * - use kill(pid, 0) - (this only works on ATTSV and some hacked
112 * BSD systems at this time)
113 * return:
114 * 0 -> success (lock file removed - no longer active)
115 * FAIL -> lock file still active
116 */
117static int
muffin8d489c72005-09-16 01:11:41 -0700118checkLock(char *file)
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -0700119{
muffin8d489c72005-09-16 01:11:41 -0700120 int ret;
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -0700121 int lpid = -1;
122 char alpid[SIZEOFPID+2]; /* +2 for '\n' and NULL */
123 int fd;
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -0700124
125 fd = open(file, 0);
126 if (fd == -1) {
127 if (errno == ENOENT) /* file does not exist -- OK */
128 return (0);
129 goto unlk;
130 }
131 ret = read(fd, (char *)alpid, SIZEOFPID+1); /* +1 for '\n' */
132 (void) close(fd);
133 if (ret != (SIZEOFPID+1))
134 goto unlk;
135 lpid = atoi(alpid);
136 if ((ret = kill(lpid, 0)) == 0 || errno == EPERM)
137 return (FAIL);
138
139unlk:
140 if (unlink(file) != 0)
141 return (FAIL);
142 return (0);
143}
144
145#define MAXLOCKS 10 /* maximum number of lock files */
146char *Lockfile[MAXLOCKS];
147int Nlocks = 0;
148
149/*
150 * stlock(name) put name in list of lock files
151 * char *name;
152 *
153 * return codes: none
154 */
155
156static void
muffin8d489c72005-09-16 01:11:41 -0700157stlock(char *name)
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -0700158{
159 char *p;
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -0700160 int i;
161
162 for (i = 0; i < Nlocks; i++) {
163 if (Lockfile[i] == NULL)
164 break;
165 }
166 ASSERT(i < MAXLOCKS, "TOO MANY LOCKS %d", i);
167 if (i >= Nlocks)
168 i = Nlocks++;
169 p = calloc(strlen(name) + 1, sizeof (char));
170 ASSERT(p != NULL, "CAN NOT ALLOCATE FOR %s", name);
muffin8d489c72005-09-16 01:11:41 -0700171 (void) strcpy(p, name);
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -0700172 Lockfile[i] = p;
173}
174
175/*
176 * rmlock(name) remove all lock files in list
177 * char *name; or name
178 *
179 * return codes: none
180 */
181
muffin8d489c72005-09-16 01:11:41 -0700182static void
183rmlock(char *name)
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -0700184{
185 int i;
186
187 for (i = 0; i < Nlocks; i++) {
188 if (Lockfile[i] == NULL)
189 continue;
190 if (name == NULL || strcmp(name, Lockfile[i]) == SAME) {
muffin8d489c72005-09-16 01:11:41 -0700191 (void) unlink(Lockfile[i]);
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -0700192 free(Lockfile[i]);
193 Lockfile[i] = NULL;
194 }
195 }
196}
197
muffin8d489c72005-09-16 01:11:41 -0700198static int
199onelock(char *pid, char *tempfile, char *name)
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -0700200{
201 int fd;
202 static int first = 1;
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -0700203
204 fd = creat(tempfile, 0444);
205 if (fd < 0) {
206 if (first) {
207 if (errno == EACCES) {
muffin8d489c72005-09-16 01:11:41 -0700208 (void) fprintf(stderr,
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -0700209 "tip: can't create files in lock file directory %s\n",
210 LOCKDIR);
211 } else if (access(LOCKDIR, 0) < 0) {
muffin8d489c72005-09-16 01:11:41 -0700212 (void) fprintf(stderr,
213 "tip: lock file directory %s: ",
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -0700214 LOCKDIR);
215 perror("");
216 }
217 first = 0;
218 }
219 if (errno == EMFILE || errno == ENFILE)
220 (void) unlink(tempfile);
221 return (-1);
222 }
223 /* +1 for '\n' */
224 if (write(fd, pid, SIZEOFPID+1) != (SIZEOFPID+1)) {
muffin8d489c72005-09-16 01:11:41 -0700225 (void) fprintf(stderr,
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -0700226 "tip: can't write to files in lock file directory %s: %s\n",
227 LOCKDIR, strerror(errno));
228 (void) unlink(tempfile);
229 return (-1);
230 }
muffin8d489c72005-09-16 01:11:41 -0700231 (void) fchmod(fd, 0444);
232 (void) close(fd);
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -0700233 if (link(tempfile, name) < 0) {
muffin8d489c72005-09-16 01:11:41 -0700234 (void) unlink(tempfile);
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -0700235 return (-1);
236 }
muffin8d489c72005-09-16 01:11:41 -0700237 (void) unlink(tempfile);
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -0700238 return (0);
239}
240
241/*
242 * delock(sys) remove a lock file
243 * char *sys;
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -0700244 */
245
muffin8d489c72005-09-16 01:11:41 -0700246void
247delock(char *sys)
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -0700248{
249 struct stat sb;
250 char lname[NAMESIZE];
251
252 if (stat(sys, &sb) < 0)
muffin8d489c72005-09-16 01:11:41 -0700253 return;
254 (void) snprintf(lname, sizeof (lname), "%s/%s.%3.3lu.%3.3lu.%3.3lu",
255 LOCKDIR, LOCKPRE,
256 (unsigned long)major(sb.st_dev),
257 (unsigned long)major(sb.st_rdev),
258 (unsigned long)minor(sb.st_rdev));
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -0700259 rmlock(lname);
260}
261
262/*
muffin8d489c72005-09-16 01:11:41 -0700263 * tip_mlock(sys) create system lock
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -0700264 * char *sys;
265 *
266 * return codes: 0 | FAIL
267 */
268
muffin8d489c72005-09-16 01:11:41 -0700269int
270tip_mlock(char *sys)
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -0700271{
272 struct stat sb;
273 char lname[NAMESIZE];
274
275 if (stat(sys, &sb) < 0)
276 return (FAIL);
muffin8d489c72005-09-16 01:11:41 -0700277 (void) snprintf(lname, sizeof (lname), "%s/%s.%3.3lu.%3.3lu.%3.3lu",
278 LOCKDIR, LOCKPRE,
279 (unsigned long)major(sb.st_dev),
280 (unsigned long)major(sb.st_rdev),
281 (unsigned long)minor(sb.st_rdev));
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -0700282 return (ulockf(lname, (time_t)SLCKTIME) < 0 ? FAIL : 0);
283}