]> git.pld-linux.org Git - projects/setup.git/blob - grouprename.c
- spelling
[projects/setup.git] / grouprename.c
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
78 void eputs(const char *msg)
79 {
80         write(2, msg, strlen(msg));
81 }
82
83 void fatal(const char *msg)
84 {
85         eputs(msg);
86         eputs("\n");
87         exit(1);
88 }
89
90 char *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
109 int 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
124 void 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
146 int lock_fd = -1;
147 void noop(int x)
148 {
149         (void)x;
150 }
151 #endif
152
153 int 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
193 oops:
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
221 void 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
236 void 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
250 int 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);
303                                 eputs(": renaming to `");
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
324 int 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.063798 seconds and 4 git commands to generate.