]> git.pld-linux.org Git - projects/setup.git/blobdiff - joinpasswd.c
- ChangeLog update by changelog.sh
[projects/setup.git] / joinpasswd.c
index 42258857d366d91693998b6626114c06e38b7a80..75fb9ebcd7bede96398b32378beefb61a1c5e5c1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * $Id$
  * 
- * Copyright (c) 2001 Michal Moskal <malekith@pld.org.pl>.
+ * Copyright (c) 2001 Michal Moskal <malekith@pld-linux.org>.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * Add entries from freshly created {passwd,shadow,group}.rpmnew to existing
  * {passwd,shadow,group}. It is usable as part of setup package, during upgrade
  * where new system user/group is to be added. If entry is already found in 
- * system database, it is left, otherwise it is added. UIDs/GIDs are *not* checked
- * anyhow. 
+ * system database, it is left, otherwise it is added. UIDs/GIDs are *not* 
+ * checked anyhow. 
  *
  * For typical sizes of files in setup package, it takes about 1 second per
  * 20000 users in system database on Pentium class machine. After static link
  * against uClibc it is under 2k on x86. Stdio hasn't been used intentionally.
  * 
- * Written for PLD GNU/Linux (http://www.pld.org.pl) setup package.
+ * Written for PLD Linux (http://www.pld-linux.org/) setup package.
  *
  * Compilation against uClibc:
  * UCROOT=/usr/lib/bootdisk/usr
@@ -53,7 +53,7 @@
  *             $UCROOT/lib/libc.a -lgcc -o joinpasswd
  * strip -R .comment -R .note joinpasswd
  *
- * The idea of this program comes from Lukasz Dobrek <dobrek@pld.org.pl>.
+ * The idea of this program comes from Lukasz Dobrek <dobrek@pld-linux.org>.
  * 
  */
 
 #include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
+#include <signal.h>
 
 #define FILE1 "/etc/passwd"
 #define FILE2 "/etc/shadow"
 #define FILE3 "/etc/group"
+#define FILE4 "/etc/gshadow"
+
+/* #define OLD_LOCK */
+
+#define LOCK_FILE "/etc/.pwd.lock"
 
 #define SUFFIX ".rpmnew"
+/* maybe "-" or sth? */
+#define BACKUP ".old"
 
 /* #define SILENT */
 
@@ -118,7 +126,133 @@ int exist(char *id, int id_len, char *ptr, int sz)
        return 0;
 }
 
-int join(const char *old_name, const char *new_name)
+void itoa(char *buf, long i)
+{
+       char tmp[32];
+       char *p;
+
+       if (i < 0) {
+               strcpy(buf, "-");
+               buf++;
+               i = -i;
+       }
+       if (i == 0) {
+               strcpy(buf, "0"); 
+               return;
+       }
+       for (p = tmp; i; i /= 10)
+               *p++ = (i % 10) + '0';
+       while (p > tmp)
+               *buf++ = *--p;
+       *buf = 0;
+}
+
+#ifndef OLD_LOCK
+int lock_fd = -1;
+void noop(int x)
+{
+       (void)x;
+}
+#endif
+
+int try_lock(const char *name)
+{
+#ifdef OLD_LOCK
+       char file[strlen(name) + 32], lock[strlen(name) + 32];
+       char buf[32];
+       int fd;
+       long pid;
+
+       strcpy(lock, name);
+       strcpy(file, name);
+       strcat(lock, ".lock");
+       itoa(buf, (long)getpid());
+       strcat(file, ".");
+       strcat(file, buf);
+       
+       fd = open(file, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
+       if (fd < 0)
+               return -1;
+       write(fd, buf, strlen(buf));
+       close(fd);
+
+       if (link(file, lock) == 0) {
+               unlink(file);
+               return 0;
+       }
+
+       fd = open(lock, O_RDONLY);
+       if (fd < 0)
+               goto oops;
+       memset(buf, 0, sizeof(buf));
+       read(fd, buf, sizeof(buf));
+       pid = atol(buf);
+       if (pid == 0 || kill(pid, 0) != 0) {
+               /* stale lock */
+               unlink(file);
+               unlink(lock);
+               /* try again */
+               return try_lock(name);
+       }
+
+oops:
+       unlink(file);
+       return -1;
+#else
+       struct flock fl;
+       
+       if (lock_fd != -1)
+               return -1;
+       lock_fd = open(LOCK_FILE, O_RDWR|O_CREAT, 0600);
+       if (lock_fd == -1)
+               return -1;
+       signal(SIGALRM, noop);
+       alarm(15);
+       memset(&fl, 0, sizeof(fl));
+       fl.l_type = F_WRLCK;
+       fl.l_whence = SEEK_SET;
+       if (fcntl(lock_fd, F_SETLKW, &fl) != 0) {
+               alarm(0);
+               close(lock_fd);
+               lock_fd = -1;
+               return -1;
+       }
+       alarm(0);
+       
+       return 0;
+#endif
+}
+
+void unlock(const char *name)
+{
+#ifdef OLD_LOCK
+       char lock[strlen(name) + 32];
+
+       strcpy(lock, name);
+       strcat(lock, ".lock");
+       unlink(lock);
+#else
+       if (lock_fd != -1)
+               close(lock_fd);
+       lock_fd = -1;
+#endif
+}
+
+void lock(const char *name)
+{
+       int n;
+
+       n = 5;
+       while (n--) {
+               if (try_lock(name) == 0)
+                       return;
+               eputs("waiting for lock...\n");
+               sleep(1);
+       }
+       fatal("cannot get lock");
+}
+
+int join(const char *old_name, const char *new_name, const char *backup_name)
 {
        char *old, *new, *id;
        int i, fd;
@@ -127,13 +261,20 @@ int join(const char *old_name, const char *new_name)
        new = map_file(new_name, &new_sz);
        if (new == NULL)
                return -1;
-               
+       
+       lock(old_name);
        old = map_file(old_name, &old_sz);
        if (old == NULL)
                fatal("cannot mmap old");
-
+       
+       fd = open(backup_name, O_WRONLY|O_CREAT|O_TRUNC, 0600);
+       if (fd < 0)
+               fatal("cannot make backup");
+       write(fd, old, old_sz);
+       close(fd);
+       
 #ifndef SILENT
-       eputs("marging contest of `");
+       eputs("merging content of `");
        eputs(old_name);
        eputs("' with `");
        eputs(new_name);
@@ -173,6 +314,7 @@ int join(const char *old_name, const char *new_name)
        /* user may want to exime this file... */
        unlink(new_name);
 #endif
+       unlock(old_name);
 
        return 0;
 }
@@ -180,11 +322,12 @@ int join(const char *old_name, const char *new_name)
 int main()
 {
 #if 1
-       join(FILE1, FILE1 SUFFIX);
-       join(FILE2, FILE2 SUFFIX);
-       join(FILE3, FILE3 SUFFIX);
+       join(FILE1, FILE1 SUFFIX, FILE1 BACKUP);
+       join(FILE2, FILE2 SUFFIX, FILE2 BACKUP);
+       join(FILE3, FILE3 SUFFIX, FILE3 BACKUP);
+       join(FILE4, FILE4 SUFFIX, FILE4 BACKUP);
 #else
-       join("test", "test.new");
+       join("test", "test.new", "test.old");
 #endif
        return 0;
 }
This page took 0.082637 seconds and 4 git commands to generate.