]> git.pld-linux.org Git - projects/setup.git/blame - grouprename.c
- restore
[projects/setup.git] / grouprename.c
CommitLineData
dc189fa5
JR
1/*
2 * $Id$
3 *
4 * Copyright (c) 2001 Michal Moskal <malekith@pld-linux.org>.
5 * Copyright (c) 2009 Jan Rękorajski <baggins@pld-linux.org>.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
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.
22 *
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
33 * SUCH DAMAGE.
34 *
35 *
36 *
37 * USAGE: grouprename old-name new-name
38 *
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.
43 *
44 * Written for PLD Linux (http://www.pld-linux.org/) setup package.
45 *
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
51 *
52 * Shamelss ripoff of the joinpasswd.c program
53 *
54 */
55
56#include <sys/types.h>
57#include <sys/mman.h>
58#include <sys/stat.h>
59#include <unistd.h>
60#include <fcntl.h>
61#include <stdlib.h>
62#include <stdio.h> // for rename(2)
63#include <string.h>
64#include <signal.h>
65
66#define FILE3 "/etc/group"
67#define FILE4 "/etc/gshadow"
68
69/* #define OLD_LOCK */
70
71#define LOCK_FILE "/etc/.pwd.lock"
72
73/* maybe "-" or sth? */
74#define BACKUP ".old"
75
76/* #define SILENT */
77
78void eputs(const char *msg)
79{
80 write(2, msg, strlen(msg));
81}
82
83void fatal(const char *msg)
84{
85 eputs(msg);
86 eputs("\n");
87 exit(1);
88}
89
90char *map_file(const char *name, int *sz, int *mfd)
91{
92 int fd;
93 void *ptr;
94 struct stat st;
95
96 fd = open(name, O_RDONLY);
97 if (fd == -1)
98 return NULL;
99 *mfd = fd;
100 fstat(fd, &st);
101 *sz = st.st_size;
102 ptr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
103 if (ptr == MAP_FAILED)
104 return NULL;
105
106 return ptr;
107}
108
109int exist(char *id, int id_len, char *ptr, int sz)
110{
111 int i;
112
113 for (i = 0; i < sz; ) {
114 if (sz - i > id_len && memcmp(id, ptr, id_len) == 0)
115 return 1;
116 while (i < sz && ptr[i] != '\n')
117 i++;
118 i++;
119 }
120
121 return 0;
122}
123
124void itoa(char *buf, long i)
125{
126 char tmp[32];
127 char *p;
128
129 if (i < 0) {
130 strcpy(buf, "-");
131 buf++;
132 i = -i;
133 }
134 if (i == 0) {
135 strcpy(buf, "0");
136 return;
137 }
138 for (p = tmp; i; i /= 10)
139 *p++ = (i % 10) + '0';
140 while (p > tmp)
141 *buf++ = *--p;
142 *buf = 0;
143}
144
145#ifndef OLD_LOCK
146int lock_fd = -1;
147void noop(int x)
148{
149 (void)x;
150}
151#endif
152
153int try_lock(const char *name)
154{
155#ifdef OLD_LOCK
156 char file[strlen(name) + 32], lock[strlen(name) + 32];
157 char buf[32];
158 int fd;
159 long pid;
160
161 strcpy(lock, name);
162 strcpy(file, name);
163 strcat(lock, ".lock");
164 itoa(buf, (long)getpid());
165 strcat(file, ".");
166 strcat(file, buf);
167
168 fd = open(file, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
169 if (fd < 0)
170 return -1;
171 write(fd, buf, strlen(buf));
172 close(fd);
173
174 if (link(file, lock) == 0) {
175 unlink(file);
176 return 0;
177 }
178
179 fd = open(lock, O_RDONLY);
180 if (fd < 0)
181 goto oops;
182 memset(buf, 0, sizeof(buf));
183 read(fd, buf, sizeof(buf));
184 pid = atol(buf);
185 if (pid == 0 || kill(pid, 0) != 0) {
186 /* stale lock */
187 unlink(file);
188 unlink(lock);
189 /* try again */
190 return try_lock(name);
191 }
192
193oops:
194 unlink(file);
195 return -1;
196#else
197 struct flock fl;
198
199 if (lock_fd != -1)
200 return -1;
201 lock_fd = open(LOCK_FILE, O_RDWR|O_CREAT, 0600);
202 if (lock_fd == -1)
203 return -1;
204 signal(SIGALRM, noop);
205 alarm(15);
206 memset(&fl, 0, sizeof(fl));
207 fl.l_type = F_WRLCK;
208 fl.l_whence = SEEK_SET;
209 if (fcntl(lock_fd, F_SETLKW, &fl) != 0) {
210 alarm(0);
211 close(lock_fd);
212 lock_fd = -1;
213 return -1;
214 }
215 alarm(0);
216
217 return 0;
218#endif
219}
220
221void unlock(const char *name)
222{
223#ifdef OLD_LOCK
224 char lock[strlen(name) + 32];
225
226 strcpy(lock, name);
227 strcat(lock, ".lock");
228 unlink(lock);
229#else
230 if (lock_fd != -1)
231 close(lock_fd);
232 lock_fd = -1;
233#endif
234}
235
236void lock(const char *name)
237{
238 int n;
239
240 n = 5;
241 while (n--) {
242 if (try_lock(name) == 0)
243 return;
244 eputs("waiting for lock...\n");
245 sleep(1);
246 }
247 fatal("cannot get lock");
248}
249
250int join(const char *oldgr, const char *newgr, const char *name, const char *backup)
251{
252 char *old, *id;
253 int i, fd, mfd;
254 int sz;
255
256// lock(name);
257 old = map_file(name, &sz, &mfd);
258 if (old == NULL)
259 fatal("cannot mmap old");
260
261 fd = open(backup, O_WRONLY|O_CREAT|O_TRUNC, 0600);
262 if (fd < 0)
263 fatal("cannot make backup");
264 write(fd, old, sz);
265 close(fd);
266
267 munmap(old, sz);
268 close(mfd);
269
270#ifndef SILENT
271 eputs("working on `");
272 eputs(name);
273 eputs("'\n");
274#endif /* SILENT */
275
276 old = map_file(backup, &sz, &mfd);
277 if (old == NULL)
278 fatal("cannot mmap backup");
279
280 fd = open(name, O_CREAT|O_WRONLY|O_TRUNC, 0644);
281 if (fd < 0)
282 fatal("cannot open new file");
283
284 for (i = 0; i < sz; ) {
285 id = old + i;
286 while (i < sz && old[i] != ':' && old[i] != '\n')
287 i++;
288 if (i < sz && old[i] == ':') {
289 int id_len, line_len;
290 char *rem = old + i;
291
292 id_len = i - (id - old);
293 while (i < sz && old[i] != '\n')
294 i++;
295 if (i < sz)
296 i++;
297 line_len = i - (rem - old);
298
299 if (id_len == strlen(oldgr) &&
300 memcmp(id, oldgr, id_len) == 0) {
301#ifndef SILENT
302 eputs(oldgr);
cdae1258 303 eputs(": renaming to `");
dc189fa5
JR
304 eputs(newgr);
305 eputs("'\n");
306#endif /* SILENT */
307 write(fd, newgr, strlen(newgr));
308 } else
309 write(fd, id, id_len);
310 write(fd, rem, line_len);
311 } else if (i < sz)
312 i++;
313 }
314 close(fd);
315
316 munmap(old, sz);
317 close(mfd);
318
319// unlock(name);
320
321 return 0;
322}
323
324int main(int argc, const char *argv[])
325{
326 const char *oldgr, *newgr;
327
328 if (argc != 3) {
329 eputs("Usage: grouprename old-name new-name");
330 return 1;
331 }
332 oldgr = argv[1];
333 newgr = argv[2];
334
335#if 0
336 join(oldgr, newgr, FILE3, FILE3 BACKUP);
337 join(oldgr, newgr, FILE4, FILE4 BACKUP);
338#else
339 join(oldgr, newgr, "test", "test.old");
340#endif
341 return 0;
342}
This page took 0.053963 seconds and 4 git commands to generate.