* 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
return 0;
}
+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;
+}
+
+int try_lock(const char *name)
+{
+ 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;
+}
+
+void unlock(const char *name)
+{
+ char lock[strlen(name) + 32];
+
+ strcpy(lock, name);
+ strcat(lock, ".lock");
+ unlink(lock);
+}
+
+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;
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");
/* user may want to exime this file... */
unlink(new_name);
#endif
+ unlock(old_name);
return 0;
}
int main()
{
-#if 1
- join(FILE1, FILE1 SUFFIX);
- join(FILE2, FILE2 SUFFIX);
- join(FILE3, FILE3 SUFFIX);
+#if 0
+ join(FILE1, FILE1 SUFFIX, FILE1 BACKUP);
+ join(FILE2, FILE2 SUFFIX, FILE2 BACKUP);
+ join(FILE3, FILE3 SUFFIX, FILE3 BACKUP);
#else
- join("test", "test.new");
+ join("test", "test.new", "test.old");
#endif
return 0;
}