4 * Copyright (c) 2001 Michal Moskal <malekith@pld-linux.org>.
5 * Copyright (c) 2009 Jan Rękorajski <baggins@pld-linux.org>.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Michal Moskal.
19 * 4. Neither the name of the author nor the names of any co-contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY MICHAL MOSKAL AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * USAGE: grouprename old-name new-name
39 * Change the name of a group from old-name to new-name,
40 * It is usable as part of setup package, during upgrade in case a group name
41 * has to change. If new-name is already found in system database or old-name
42 * is not found, nothing changes,. UIDs/GIDs are *not* checked anyhow.
44 * Written for PLD Linux (http://www.pld-linux.org/) setup package.
46 * Compilation against uClibc:
47 * UCROOT=/usr/lib/bootdisk/usr
48 * gcc -I$UCROOT/include -nostdlib -O2 grouprename.c $UCROOT/lib/crt0.o \
49 * $UCROOT/lib/libc.a -lgcc -o grouprename
50 * strip -R .comment -R .note grouprename
52 * Shamelss ripoff of the joinpasswd.c program
56 #include <sys/types.h>
62 #include <stdio.h> // for rename(2)
66 #define FILE3 "/etc/group"
67 #define FILE4 "/etc/gshadow"
69 /* #define OLD_LOCK */
71 #define LOCK_FILE "/etc/.pwd.lock"
73 /* maybe "-" or sth? */
78 void eputs(const char *msg)
80 write(2, msg, strlen(msg));
83 void fatal(const char *msg)
90 char *map_file(const char *name, int *sz, int *mfd)
96 fd = open(name, O_RDONLY);
102 ptr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
103 if (ptr == MAP_FAILED)
109 int exist(char *id, int id_len, char *ptr, int sz)
113 for (i = 0; i < sz; ) {
114 if (sz - i > id_len && memcmp(id, ptr, id_len) == 0)
116 while (i < sz && ptr[i] != '\n')
124 void itoa(char *buf, long i)
138 for (p = tmp; i; i /= 10)
139 *p++ = (i % 10) + '0';
153 int try_lock(const char *name)
156 char file[strlen(name) + 32], lock[strlen(name) + 32];
163 strcat(lock, ".lock");
164 itoa(buf, (long)getpid());
168 fd = open(file, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
171 write(fd, buf, strlen(buf));
174 if (link(file, lock) == 0) {
179 fd = open(lock, O_RDONLY);
182 memset(buf, 0, sizeof(buf));
183 read(fd, buf, sizeof(buf));
185 if (pid == 0 || kill(pid, 0) != 0) {
190 return try_lock(name);
201 lock_fd = open(LOCK_FILE, O_RDWR|O_CREAT, 0600);
204 signal(SIGALRM, noop);
206 memset(&fl, 0, sizeof(fl));
208 fl.l_whence = SEEK_SET;
209 if (fcntl(lock_fd, F_SETLKW, &fl) != 0) {
221 void unlock(const char *name)
224 char lock[strlen(name) + 32];
227 strcat(lock, ".lock");
236 void lock(const char *name)
242 if (try_lock(name) == 0)
244 eputs("waiting for lock...\n");
247 fatal("cannot get lock");
250 int join(const char *oldgr, const char *newgr, const char *name, const char *backup)
257 old = map_file(name, &sz, &mfd);
259 fatal("cannot mmap old");
261 fd = open(backup, O_WRONLY|O_CREAT|O_TRUNC, 0600);
263 fatal("cannot make backup");
271 eputs("working on `");
276 old = map_file(backup, &sz, &mfd);
278 fatal("cannot mmap backup");
280 fd = open(name, O_CREAT|O_WRONLY|O_TRUNC, 0644);
282 fatal("cannot open new file");
284 for (i = 0; i < sz; ) {
286 while (i < sz && old[i] != ':' && old[i] != '\n')
288 if (i < sz && old[i] == ':') {
289 int id_len, line_len;
292 id_len = i - (id - old);
293 while (i < sz && old[i] != '\n')
297 line_len = i - (rem - old);
299 if (id_len == strlen(oldgr) &&
300 memcmp(id, oldgr, id_len) == 0) {
303 eputs(": renaming to `");
307 write(fd, newgr, strlen(newgr));
309 write(fd, id, id_len);
310 write(fd, rem, line_len);
324 int main(int argc, const char *argv[])
326 const char *oldgr, *newgr;
329 eputs("Usage: grouprename old-name new-name");
336 join(oldgr, newgr, FILE3, FILE3 BACKUP);
337 join(oldgr, newgr, FILE4, FILE4 BACKUP);
339 join(oldgr, newgr, "test", "test.old");