4 * Copyright (c) 2008 James McKenzie <james@fishsoup.dhs.org>,
10 "$Id: lockfile.c,v 1.17 2010/07/16 11:04:10 james Exp $";
13 * $Log: lockfile.c,v $
14 * Revision 1.17 2010/07/16 11:04:10 james
15 * ignore tedious return values
17 * Revision 1.16 2008/05/09 12:56:11 james
18 * *** empty log message ***
20 * Revision 1.15 2008/03/07 14:13:40 james
21 * *** empty log message ***
23 * Revision 1.14 2008/03/07 13:16:02 james
24 * *** empty log message ***
26 * Revision 1.13 2008/03/07 12:37:04 james
27 * *** empty log message ***
29 * Revision 1.12 2008/03/03 06:04:42 james
30 * *** empty log message ***
32 * Revision 1.11 2008/03/02 10:38:18 james
33 * *** empty log message ***
35 * Revision 1.10 2008/03/02 10:37:56 james
36 * *** empty log message ***
38 * Revision 1.9 2008/02/15 23:52:12 james
39 * *** empty log message ***
41 * Revision 1.8 2008/02/15 20:52:36 james
42 * *** empty log message ***
44 * Revision 1.7 2008/02/15 19:51:30 james
45 * *** empty log message ***
47 * Revision 1.6 2008/02/15 19:09:00 james
48 * *** empty log message ***
50 * Revision 1.5 2008/02/15 18:26:49 james
51 * *** empty log message ***
53 * Revision 1.4 2008/02/15 18:16:48 james
54 * *** empty log message ***
56 * Revision 1.3 2008/02/15 18:16:35 james
57 * *** empty log message ***
59 * Revision 1.2 2008/02/15 16:48:56 james
60 * *** empty log message ***
62 * Revision 1.1 2008/02/15 15:09:17 james
63 * *** empty log message ***
70 #define STALE_CHECK_INTERVAL 10
73 #include <sys/types.h>
89 extern void *xmalloc (size_t);
94 Filelist *fl = (Filelist *) xmalloc (sizeof (Filelist));
102 filelist_remove (Filelist * fl, Filelist_ent * fle)
106 for (ep = &fl->head; *ep; ep = &((*ep)->next))
120 filelist_add (Filelist * fl, char *fn)
125 if (i >= FILE_LIST_MAX_LEN)
128 for (fle = fl->head; fle; fle = fle->next)
129 if (!strcmp (fle->name, fn))
132 fle = xmalloc (sizeof (Filelist_ent));
134 strcpy (fle->name, fn);
136 fle->next = fl->head;
141 filelist_free (Filelist * fl)
144 filelist_remove (fl, fl->head);
149 filelist_print (Filelist * fl, FILE * f)
153 fprintf (f, "(empty list)\n");
156 for (fle = fl->head; fle; fle = fle->next)
157 fprintf (f, "%s\n", fle->name);
167 static int uuid = -1, ugid;
171 if (pw = getpwnam ("uucp")) {
178 return fchown (fd, uuid, ugid);
182 lockfile_make (char *name)
184 char buf[1024], tmpfn[1024];
189 strcpy (tmpfn, name);
191 ptr = rindex (tmpfn, '/');
197 ptr += sprintf (ptr, "LTMP.%d", getpid ());
200 i = sprintf (buf, "%10d\n", getpid ());
203 fd = open (tmpfn, O_WRONLY | O_CREAT | O_TRUNC, 0444);
210 result = write (fd, buf, i);
213 if (chown_uucp (fd)) {
224 if (link (tmpfn, name) < 0) {
235 lockfile_add_places (Filelist * fl, char *leaf)
240 { "/var/lock/uucp", "/var/spool/lock", "/var/spool/uucp", "/etc/locks",
241 "/usr/spool/uucp", "/var/spool/locks", "/usr/spool/lock",
242 "/usr/spool/locks", "/usr/spool/uucp/LCK", "/var/lock"
246 for (i = 0; i < (sizeof (lock_dirs) / sizeof (char *)); ++i) {
247 if (stat (lock_dirs[i], &stbuf))
249 strcpy (buf, lock_dirs[i]);
252 filelist_add (fl, buf);
258 do_tedious_mangling (Filelist * fl, char *buf, char *ptr, char inv, int lower)
261 if (lower && (*ptr >= 'A') && (*ptr <= 'Z'))
268 lockfile_add_places (fl, buf);
273 lockfile_regularize_and_add (Filelist * fl, char *leaf)
275 char buf[1024] = "LCK..";
286 do_tedious_mangling (fl, buf, ptr, '_', 0);
288 do_tedious_mangling (fl, buf, ptr, '_', 1);
290 do_tedious_mangling (fl, buf, ptr, '.', 0);
292 do_tedious_mangling (fl, buf, ptr, '.', 1);
296 lockfile_add_name_from_path (Filelist * fl, char *file)
303 lockfile_regularize_and_add (fl, ptr);
305 if (!strncmp (ptr, "dev/", 4)) {
307 lockfile_regularize_and_add (fl, ptr);
313 lockfile_add_name_from_dev (Filelist * fl, dev_t dev)
316 sprintf (buf, "LCK.%03d.%03d", major (dev), minor (dev));
317 lockfile_add_places (fl, buf);
321 lockfile_check_dir_for_dev (Filelist * fl, char *dir, dev_t dev)
324 struct stat ent_stat;
333 while ((de = readdir (d))) {
335 strcat (buf, de->d_name);
337 if (stat (buf, &ent_stat))
339 if (!S_ISCHR (ent_stat.st_mode))
341 if (ent_stat.st_rdev != dev)
344 lockfile_add_name_from_path (fl, buf);
351 lockfile_make_list (char *device)
353 struct stat dev_stat;
354 Filelist *ret = NULL;
357 if (stat (device, &dev_stat))
359 if (!S_ISCHR (dev_stat.st_mode))
362 ret = filelist_new ();
365 lockfile_add_name_from_dev (ret, dev_stat.st_rdev);
367 lockfile_add_name_from_path (ret, device);
369 lockfile_check_dir_for_dev (ret, "/dev/", dev_stat.st_rdev);
370 lockfile_check_dir_for_dev (ret, "/dev/usb/", dev_stat.st_rdev);
371 lockfile_check_dir_for_dev (ret, "/dev/tts/", dev_stat.st_rdev);
378 remove_stale_lock (char *path)
385 fd = open (path, O_RDONLY);
389 length = read (fd, apid, sizeof (apid) - 1);
395 if (length == sizeof (pid) || sscanf (apid, "%d", &pid) != 1 || pid == 0) {
396 pid = *((int *) apid);
399 "compiled with ascii locks, found binary lock file (length=%d, pid=%d)!",
406 "compiled with binary locks, found ascii lock file (length=%d, pid=%d)!",
413 if ((kill (pid, 0) < 0) && (errno == ESRCH)) {
414 fprintf (stderr, "removing stale lock file %s\n", path);
421 lockfile_remove_stale (Filelist * fl)
426 for (fle = fl->head; fle; fle = fle->next) {
427 if (stat (fle->name, &buf))
429 remove_stale_lock (fle->name);
437 lockfile_lock (Filelist * fl)
442 ret = filelist_new ();
445 lockfile_remove_stale (fl);
447 for (fle = fl->head; fle; fle = fle->next) {
448 if (lockfile_make (fle->name)) {
449 fprintf (stderr, "Failed to get lockfile %s\n", fle->name);
453 filelist_add (ret, fle->name);
461 lockfile_unlock (Filelist * fl)
465 unlink (fl->head->name);
466 filelist_remove (fl, fl->head);
471 /* If we have a passive lock, check noone has an */
472 /* active one, returns 1 if he does, 0 if he doesnt */
474 serial_lock_check (Serial_lock * l)
479 struct timeval now, dif;
481 if (l->mode == SERIAL_LOCK_ACTIVE)
484 for (fle = l->locks_to_check->head; fle; fle = fle->next) {
485 if (!stat (fle->name, &buf))
492 gettimeofday (&now, NULL);
493 timersub (&now, &l->last_stale_purge, &dif);
495 if (dif.tv_sec > STALE_CHECK_INTERVAL) {
496 lockfile_remove_stale (l->locks_to_check);
497 l->last_stale_purge = now;
504 serial_lock_free (Serial_lock * l)
510 lockfile_unlock (l->locks_held);
511 filelist_free (l->locks_held);
514 if (l->locks_to_check) {
515 filelist_free (l->locks_to_check);
523 serial_lock_new (char *dev, int mode)
525 Filelist *fl = lockfile_make_list (dev);
531 l = (Serial_lock *) xmalloc (sizeof (Serial_lock));
534 l->locks_to_check = fl;
535 l->locks_held = NULL;
536 memset (&l->last_stale_purge, 0, sizeof (l->last_stale_purge));
538 if (mode == SERIAL_LOCK_PASSIVE)
541 l->locks_held = lockfile_lock (l->locks_to_check);
542 if (!l->locks_held) {
543 serial_lock_free (l);
553 main (int argc, char *argv[])
555 Filelist *fl = lockfile_make_list ("/dev/ttyS0");
559 filelist_print (fl, stdout);
561 fll = lockfile_lock (fl);
563 filelist_print (fll, stdout);