/* * lockfile.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id$"; /* * $Log$ * Revision 1.3 2008/02/15 18:16:35 james * *** empty log message *** * * Revision 1.2 2008/02/15 16:48:56 james * *** empty log message *** * * Revision 1.1 2008/02/15 15:09:17 james * *** empty log message *** * */ #define LOCK_ASCII #undef LOCK_BINARY #include #include #include #include #include #include #include #include #include #include #include #include "lockfile.h" Filelist * filelist_new (void) { Filelist *fl = (Filelist *) malloc (sizeof (Filelist)); fl->head = NULL; return fl; } void filelist_remove (Filelist * fl, Filelist_ent * fle) { Filelist_ent **ep; for (ep = &fl->head; *ep; ep = &((*ep)->next)) if (fle == *ep) break; if (!*ep) return; *ep = fle->next; free (fle); } void filelist_add (Filelist * fl, char *fn) { Filelist_ent *fle; int i = strlen (fn); if (i >= FILE_LIST_MAX_LEN) return; for (fle=fl->head;fle;fle=fle->next) if (!strcmp(fle->name,fn)) return; fle = malloc (sizeof (Filelist_ent)); strcpy (fle->name, fn); fle->next = fl->head; fl->head = fle; } void filelist_free (Filelist * fl) { while (fl->head) filelist_remove (fl, fl->head); free (fl); } void filelist_print(Filelist *fl,FILE *f) { Filelist_ent *fle; if (!fl) { fprintf(f,"(empty list)\n"); return; } for (fle=fl->head;fle;fle=fle->next) fprintf(f,"%s\n",fle->name); } static int chown_uucp (fd) int fd; { static int uuid = -1, ugid; struct passwd *pw; if (uuid < 0) { if (pw = getpwnam ("uucp")) { uuid = pw->pw_uid; ugid = pw->pw_gid; } else { return -1; } } return fchown (fd, uuid, ugid); } int lockfile_make (char *name) { char buf[1024], tmpfn[1024]; char *ptr; int fd; int i; strcpy (tmpfn, name); ptr = rindex (tmpfn, '/'); if (!ptr) return -1; ptr++; ptr += sprintf (ptr, "LTMP.%d", getpid ()); *ptr = 0; i = sprintf (buf, "%10d\n", getpid ()); unlink (tmpfn); fd = open (tmpfn, O_WRONLY | O_CREAT | O_TRUNC, 0444); if (fd < 0) { unlink (tmpfn); return -1; } write (fd, buf, i); fchmod (fd, 044); if (chown_uucp (fd)) { close (fd); unlink (tmpfn); return -1; } close (fd); if (link (tmpfn, name) < 0) { unlink (tmpfn); return -1; } unlink (tmpfn); return 0; } void lockfile_add_places (Filelist * fl, char *leaf) { char buf[1024]; struct stat stbuf; char *lock_dirs[] = { "/var/lock/uucp", "/var/spool/lock", "/var/spool/uucp", "/etc/locks", "/usr/spool/uucp", "/var/spool/locks", "/usr/spool/lock", "/usr/spool/locks", "/usr/spool/uucp/LCK" }; int i; for (i = 0; i < (sizeof (lock_dirs) / sizeof (char *)); ++i) { if (stat (lock_dirs[i], &stbuf)) continue; strcpy (buf, lock_dirs[i]); strcat (buf, "/"); strcat (buf, leaf); filelist_add (fl, buf); } } static void do_tedious_mangling (Filelist * fl, char *buf, char *ptr, char inv, int lower) { while (*ptr) { if (lower && (*ptr >= 'A') && (*ptr <= 'Z')) *ptr |= 32; if (*ptr == '/') *ptr = inv; ptr++; } lockfile_add_places (fl, buf); } void lockfile_regularize_and_add (Filelist * fl, char *leaf) { char buf[1024] = "LCK.."; char *ptr; if (*leaf == '/') leaf++; ptr = buf; while (*ptr) ptr++; strcpy (ptr, leaf); do_tedious_mangling (fl, buf, ptr, '_', 0); strcpy (ptr, leaf); do_tedious_mangling (fl, buf, ptr, '_', 1); strcpy (ptr, leaf); do_tedious_mangling (fl, buf, ptr, '.', 0); strcpy (ptr, leaf); do_tedious_mangling (fl, buf, ptr, '.', 1); } void lockfile_add_name_from_path (Filelist * fl, char *file) { char *ptr = file; if (*ptr == '/') ptr++; lockfile_regularize_and_add (fl, ptr); if (!strncmp (ptr, "dev/", 4)) { ptr += 4; lockfile_regularize_and_add (fl, ptr); } } void lockfile_add_name_from_dev (Filelist * fl, dev_t dev) { char buf[1024]; sprintf (buf, "LCK.%03d.%03d", major (dev), minor (dev)); lockfile_add_places (fl, buf); } void lockfile_check_dir_for_dev (Filelist * fl, char *dir, dev_t dev) { char buf[1024]; struct stat ent_stat; struct dirent *de; DIR *d; d = opendir (dir); if (!d) return; while ((de = readdir (d))) { strcpy (buf, dir); strcat (buf, de->d_name); if (stat (buf, &ent_stat)) continue; if (!S_ISCHR (ent_stat.st_mode)) continue; if (ent_stat.st_rdev != dev) continue; lockfile_add_name_from_path (fl, buf); } closedir (d); } Filelist * lockfile_make_list(char *device) { struct stat dev_stat; Filelist *ret = NULL; if (stat (device, &dev_stat)) return ret; if (!S_ISCHR (dev_stat.st_mode)) return ret; ret = filelist_new (); lockfile_add_name_from_dev (ret, dev_stat.st_rdev); lockfile_add_name_from_path (ret, device); lockfile_check_dir_for_dev (ret, "/dev/", dev_stat.st_rdev); lockfile_check_dir_for_dev (ret, "/dev/usb/", dev_stat.st_rdev); lockfile_check_dir_for_dev (ret, "/dev/tts/", dev_stat.st_rdev); return ret; } void lockfile_remove_stale(Filelist *fl) { } Filelist *lockfile_lock(Filelist *fl) { Filelist *ret; Filelist_ent *fle; ret=filelist_new(); lockfile_remove_stale(fl); for (fle=fl->head;fle;fle=fle->next) { if (lockfile_make(fle->name)) { fprintf(stderr,"Failed to get lockfile %s\n",fle->name); filelist_free(ret); return NULL; } filelist_add(ret,fle->name); } return ret; } #if 1 int main(int argc,char *argv[]) { Filelist *fl=lockfile_make_list("/dev/ttyS0"); Filelist *fll; Filelist_ent *fle; filelist_print(fl,stdout); fll=lockfile_lock(fl); filelist_print(fll,stdout); } #endif