1 /*
2 Copyright Ⓒ 1997, 1998, 1999, 2000, 2001 joost witteveen
3 Copyright Ⓒ 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Clint Adams
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 title : fakeroot
16 description : create a "fake" root shell, by wrapping
17 functions like chown, stat, etc. Useful for debian
18 packaging mechanism
19 */
20
21 /*
22 upon startup, the fakeroot script (/usr/bin/fakeroot)
23 forks faked (this program), and the shell or user program that
24 will run with the libtricks.so.0.0 wrapper.
25
26 These tree running programs have the following tasks:
27
28 fakeroot script
29 starts the other two processes, waits for the user process to
30 die, and then send a SIGTERM signal to faked, causing
31 Faked to clear the ipc message queues.
32
33 faked
34 the ``main'' daemon, creates ipc message queues, and later
35 receives ipc messages from the user program, maintains
36 fake inode<->ownership database (actually just a
37 lot of struct stat entries). Will clear ipc message ques
38 upon receipt of a SIGTERM. Will show debug output upon
39 receipt of a SIGUSR1 (if started with -d debug option)
40
41 user program
42 Any shell or other programme, run with
43 LD_PRELOAD=libtricks.so.0.0, and FAKEROOT_DBKEY=ipc-key,
44 thus the executed commands will communicate with
45 faked. libtricks will wrap all file ownership etc modification
46 calls, and send the info to faked. Also the stat() function
47 is wrapped, it will first ask the database kept by faked
48 and report the `fake' data if available.
49
50 The following functions are currently wrapped:
51 getuid(), geteuid(), getgid(), getegid(),
52 mknod()
53 chown(), fchown() lchown()
54 chmod(), fchmod()
55 mkdir(),
56 lstat(), fstat(), stat() (actually, __xlstat, ...)
57 unlink(), remove(), rmdir(), rename()
58
59 comments:
60 I need to wrap unlink because of the following:
61 install -o admin foo bar
62 rm bar
63 touch bar //bar now may have the same inode:dev as old bar,
64 //but unless the rm was caught,
65 //fakeroot still has the old entry.
66 ls -al bar
67 Same goes for all other ways to remove inodes form the filesystem,
68 like rename(existing_file, any_file).
69
70 The communication between client (user progamme) and faked happens
71 with inode/dev information, not filenames. This is
72 needed, as the client is the only one who knows what cwd is,
73 so it's much easier to stat in the client. Otherwise, the daemon
74 needs to keep a list of client pids vs cwd, and I'd have to wrap
75 fork e.d., as they inherit their parent's cwd. Very compilcated.
76
77 */
78 /* ipc documentation bugs: msgsnd(2): MSGMAX=4056, not 4080
79 (def in ./linux/msg.h, couldn't find other def in /usr/include/
80 */
81
82 #ifdef __APPLE__
83 /*
84 In this file, we want 'struct stat' to have a 32-bit 'ino_t'.
85 We use 'struct stat64' when we need a 64-bit 'ino_t'.
86 */
87 #define _DARWIN_NO_64_BIT_INODE
88 #endif
89
90 #include "config.h"
91 #include "communicate.h"
92 #ifndef FAKEROOT_FAKENET
93 # include <sys/ipc.h>
94 # include <sys/msg.h>
95 # include <sys/sem.h>
96 #else /* FAKEROOT_FAKENET */
97 # include <sys/socket.h>
98 # include <sys/param.h>
99 # include <netinet/in.h>
100 # include <netinet/tcp.h>
101 # include <arpa/inet.h>
102 # include <netdb.h>
103 #endif /* FAKEROOT_FAKENET */
104 #include <sys/stat.h>
105 #include <sys/wait.h>
106 #include <sys/types.h>
107 #ifdef HAVE_SYS_XATTR_H
108 #include <sys/xattr.h>
109 #endif
110 #include <fcntl.h>
111 #include <ctype.h>
112 #include <stdio.h>
113 #include <time.h>
114 #include <errno.h>
115 #include <unistd.h>
116 #include <stdlib.h>
117 #include <string.h>
118 #include <signal.h>
119 #ifdef HAVE_STDINT_H
120 # include <stdint.h>
121 #endif
122 #ifdef HAVE_SYS_SYSMACROS_H
123 # include <sys/sysmacros.h>
124 #endif
125 #ifdef FAKEROOT_DB_PATH
126 # include <dirent.h>
127 #endif
128
129 #ifndef FAKEROOT_FAKENET
130 # define FAKE_KEY msg_key
131 #else /* FAKEROOT_FAKENET */
132 # define FAKE_KEY port
133 #endif /* FAKEROOT_FAKENET */
134
135 #ifndef SOL_TCP
136 # define SOL_TCP 6 /* this should probably be done with getprotoent */
137 #endif
138
139 #define fakestat_equal(a, b) ((a)->dev == (b)->dev && (a)->ino == (b)->ino)
140
141 #ifndef FAKEROOT_FAKENET
142 # if HAVE_SEMUN_DEF == 0
143 union semun {
144 int val;
145 struct semid_ds *buf;
146 u_short *array;
147 };
148 # endif
149 #endif /* ! FAKEROOT_FAKENET */
150
151 void process_chown(struct fake_msg *buf);
152 void process_chmod(struct fake_msg *buf);
153 void process_mknod(struct fake_msg *buf);
154 void process_stat(struct fake_msg *buf);
155 void process_unlink(struct fake_msg *buf);
156 void process_listxattr(struct fake_msg *buf);
157 void process_setxattr(struct fake_msg *buf);
158 void process_getxattr(struct fake_msg *buf);
159 void process_removexattr(struct fake_msg *buf);
160
161 #ifdef FAKEROOT_FAKENET
162 static int get_fakem(struct fake_msg *buf);
163 #endif
164
165 typedef void (*process_func)(struct fake_msg *);
166
167 process_func func_arr[]={process_chown,
168 process_chmod,
169 process_mknod,
170 process_stat,
171 process_unlink,
172 NULL, /* debugdata */
173 NULL, /* reqoptions */
174 process_listxattr,
175 process_getxattr,
176 process_setxattr,
177 process_removexattr,
178 };
179
180 unsigned int highest_funcid = sizeof(func_arr)/sizeof(func_arr[0]);
181
182 #ifndef FAKEROOT_FAKENET
183 key_t msg_key=0;
184 #else /* FAKEROOT_FAKENET */
185 static int comm_sd = -1;
186 static volatile int detached = 0;
187 #endif /* FAKEROOT_FAKENET */
188
189 int debug = 0, unknown_is_real = 0;
190 char *save_file = NULL;
191
192 void cleanup(int);
193
194 #ifdef FAKEROOT_FAKENET
fail(const char * msg)195 static void fail(const char *msg)
196 {
197 if (errno > 0)
198 fprintf(stderr, "fakeroot daemon: %s (%s)\n", msg, strerror(errno));
199 else
200 fprintf(stderr, "fakeroot daemon: %s\n", msg);
201
202 exit(1);
203 }
204 #endif
205
206 struct xattr_node_s;
207 typedef struct xattr_node_s {
208 struct xattr_node_s *next;
209 char *key;
210 char *value;
211 size_t value_size;
212 } xattr_node_t;
213
214 struct data_node_s;
215 typedef struct data_node_s {
216 struct data_node_s *next;
217 struct fakestat buf;
218 uint32_t remote;
219 xattr_node_t *xattr;
220 } data_node_t;
221
xattr_find(xattr_node_t * node,char * key)222 static xattr_node_t *xattr_find(xattr_node_t *node, char *key)
223 {
224 while (node) {
225 if (node->key && (!strcmp(node->key, key)))
226 break;
227 node = node->next;
228 }
229 return node;
230 }
231
xattr_erase(xattr_node_t ** head,char * key)232 static int xattr_erase(xattr_node_t **head, char *key)
233 {
234 xattr_node_t *cur_node, *prev_node = NULL;
235
236 for (cur_node = *head; cur_node; prev_node = cur_node, cur_node = cur_node->next) {
237 if (cur_node->key && (!strcmp(cur_node->key, key))) {
238 if (prev_node == NULL) {
239 *head = cur_node->next;
240 } else {
241 prev_node->next = cur_node->next;
242 }
243 free(cur_node->key);
244 if (cur_node->value)
245 free(cur_node->value);
246 free(cur_node);
247 return 1;
248 }
249 }
250 return 0;
251 }
252
xattr_clear(xattr_node_t ** head)253 static int xattr_clear(xattr_node_t **head)
254 {
255 xattr_node_t *cur_node, *next_node;
256 cur_node = *head;
257 *head = NULL;
258 while (cur_node) {
259 next_node = cur_node->next;
260 if (cur_node->key)
261 free(cur_node->key);
262 if (cur_node->value)
263 free(cur_node->value);
264 free(cur_node);
265 cur_node = next_node;
266 }
267 return 0;
268 }
269
xattr_insert(xattr_node_t ** head)270 static xattr_node_t *xattr_insert(xattr_node_t **head)
271 {
272 xattr_node_t *new_node;
273 new_node = calloc(1, sizeof(xattr_node_t));
274 new_node->next = *head;
275 *head = new_node;
276 return new_node;
277 }
278
xattr_fill(xattr_node_t * node,char * key,char * value,size_t value_size)279 static void xattr_fill(xattr_node_t *node, char *key, char *value, size_t value_size)
280 {
281 if (node->key)
282 free(node->key);
283 node->key = strdup(key);
284 if (node->value)
285 free(node->value);
286 node->value = malloc(value_size);
287 memcpy(node->value, value, value_size);
288 node->value_size = value_size;
289 }
290
291 #define data_node_get(n) ((struct fakestat *) &(n)->buf)
292
293 #define HASH_TABLE_SIZE 10009
294 #define HASH_DEV_MULTIPLIER 8328 /* = 2^64 % HASH_TABLE_SIZE */
295
data_hash_val(const struct fakestat * key)296 static int data_hash_val(const struct fakestat *key) {
297 return (key->dev * HASH_DEV_MULTIPLIER + key->ino) % HASH_TABLE_SIZE;
298 }
299
300 static data_node_t *data_hash_table[HASH_TABLE_SIZE];
301
init_hash_table()302 static void init_hash_table() {
303 int table_pos;
304
305 for (table_pos = 0; table_pos < HASH_TABLE_SIZE; table_pos++)
306 data_hash_table[table_pos] = NULL;
307 }
308
data_find(const struct fakestat * key,const uint32_t remote)309 static data_node_t *data_find(const struct fakestat *key,
310 const uint32_t remote)
311 {
312 data_node_t *n;
313
314 for (n = data_hash_table[data_hash_val(key)]; n; n = n->next) {
315 if (fakestat_equal(&n->buf, key) && n->remote == remote)
316 break;
317 }
318
319 return n;
320 }
321
data_insert(const struct fakestat * buf,const uint32_t remote)322 static void data_insert(const struct fakestat *buf,
323 const uint32_t remote)
324 {
325 data_node_t *n, *last = NULL;
326
327 for (n = data_hash_table[data_hash_val(buf)]; n; last = n, n = n->next)
328 if (fakestat_equal(&n->buf, buf) && n->remote == remote)
329 break;
330
331 if (n == NULL) {
332 n = calloc(1, sizeof (data_node_t));
333
334 if (last)
335 last->next = n;
336 else
337 data_hash_table[data_hash_val(buf)] = n;
338 }
339
340 memcpy(&n->buf, buf, sizeof (struct fakestat));
341 n->xattr = NULL;
342 n->remote = (uint32_t) remote;
343 }
344
data_erase(data_node_t * pos)345 static data_node_t *data_erase(data_node_t *pos)
346 {
347 data_node_t *n, *prev = NULL, *next;
348
349 for (n = data_hash_table[data_hash_val(&pos->buf)]; n;
350 prev = n, n = n->next)
351 if (n == pos)
352 break;
353
354 next = n->next;
355
356 if (n == data_hash_table[data_hash_val(&pos->buf)])
357 data_hash_table[data_hash_val(&pos->buf)] = next;
358 else
359 prev->next = next;
360
361 xattr_clear(&n->xattr);
362 free(n);
363
364 return next;
365 }
366
data_node_next(data_node_t * n)367 static data_node_t *data_node_next(data_node_t *n) {
368 int table_pos;
369
370 if (n != NULL && n->next != NULL)
371 return n->next;
372
373 if (n == NULL)
374 table_pos = 0;
375 else
376 table_pos = data_hash_val(&n->buf) + 1;
377 while (table_pos < HASH_TABLE_SIZE && data_hash_table[table_pos] == NULL)
378 table_pos++;
379 if (table_pos < HASH_TABLE_SIZE)
380 return data_hash_table[table_pos];
381 else
382 return NULL;
383 }
384
data_size(void)385 static unsigned int data_size(void)
386 {
387 unsigned int size = 0;
388 int table_pos;
389 data_node_t *n;
390
391 for (table_pos = 0; table_pos < HASH_TABLE_SIZE; table_pos++)
392 for (n = data_hash_table[table_pos]; n; n = n->next)
393 size++;
394
395 return size;
396
397 }
398
399 #define data_begin() (data_node_next(NULL))
400 #define data_end() (NULL)
401
402
403 #ifdef FAKEROOT_FAKENET
404 static struct {
405 unsigned int capacity;
406 unsigned int size;
407 int *array;
408 } sd_list = {
409 0, 0, NULL
410 };
411
sd_list_add(int sd)412 static void sd_list_add(int sd)
413 {
414 if (sd_list.capacity == sd_list.size) {
415 sd_list.capacity += 16;
416
417 if (sd_list.array == NULL) {
418
419 sd_list.array = malloc(sd_list.capacity * sizeof (int));
420 if (!sd_list.array)
421 fail("malloc");
422 } else {
423 sd_list.array = realloc(sd_list.array, sd_list.capacity * sizeof (int));
424 if (!sd_list.array)
425 fail("realloc");
426
427 }
428 }
429
430 sd_list.array[sd_list.size] = sd;
431 sd_list.size++;
432 }
433
sd_list_remove(unsigned int i)434 static void sd_list_remove(unsigned int i)
435 {
436 for (i++; i < sd_list.size; i++)
437 sd_list.array[i - 1] = sd_list.array[i];
438 sd_list.size--;
439 }
440
441 #define sd_list_size() (sd_list.size)
442 #define sd_list_index(i) (sd_list.array[(i)])
443
faked_send_fakem(const struct fake_msg * buf)444 static void faked_send_fakem(const struct fake_msg *buf)
445 {
446 struct fake_msg fm;
447
448 fm.id = htonl(buf->id);
449 fm.st.uid = htonl(buf->st.uid);
450 fm.st.gid = htonl(buf->st.gid);
451 fm.st.ino = htonll(buf->st.ino);
452 fm.st.dev = htonll(buf->st.dev);
453 fm.st.rdev = htonll(buf->st.rdev);
454 fm.st.mode = htonl(buf->st.mode);
455 fm.st.nlink = htonl(buf->st.nlink);
456 fm.remote = htonl(buf->remote);
457 fm.xattr.buffersize = htonl(buf->xattr.buffersize);
458 fm.xattr.flags_rc = htonl(buf->xattr.flags_rc);
459 memcpy(fm.xattr.buf, buf->xattr.buf, MAX_IPC_BUFFER_SIZE);
460
461 while (1) {
462 ssize_t len;
463
464 len = write(comm_sd, &fm, sizeof (fm));
465 if (len > 0)
466 break;
467
468 if (errno == EINTR)
469 continue;
470
471 fail("write");
472 }
473 }
474 #else
475
476 # define faked_send_fakem send_fakem
477
478 #endif /* FAKEROOT_FAKENET */
479
480 #ifdef FAKEROOT_DB_PATH
481 # define DB_PATH_LEN 4095
482 # define DB_PATH_SCAN "%4095s"
483
484 /*
485 * IN: 'path' contains the dir to scan recursively
486 * OUT: 'path' contains the matching file if 1 is returned
487 */
scan_dir(const fake_dev_t dev,const fake_ino_t ino,char * const path)488 static int scan_dir(const fake_dev_t dev, const fake_ino_t ino,
489 char *const path)
490 {
491 const size_t pathlen = strlen(path) + strlen("/");
492 if (pathlen >= DB_PATH_LEN)
493 return 0;
494 strcat(path, "/");
495
496 DIR *const dir = opendir(path);
497 if (!dir)
498 return 0;
499
500 struct dirent *ent;
501 while ((ent = readdir(dir))) {
502 if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
503 continue;
504
505 if (ent->d_ino == ino) {
506 struct stat buf;
507 strncpy(path + pathlen, ent->d_name, DB_PATH_LEN - pathlen);
508 if (lstat(path, &buf) == 0 && buf.st_dev == dev)
509 break;
510 } else if (ent->d_type == DT_DIR) {
511 strncpy(path + pathlen, ent->d_name, DB_PATH_LEN - pathlen);
512 if (scan_dir(dev, ino, path))
513 break;
514 }
515 }
516
517 closedir(dir);
518 return ent != 0;
519 }
520
521 /*
522 * Finds a path for inode/device pair--there can be several if bind mounts
523 * are used. This should not be a problem if the bind mount configuration
524 * is the same when loading the database.
525 *
526 * IN: 'roots' contains the dirs to scan recursively (separated by colons)
527 * OUT: 'path' contains the matching file if 1 is returned
528 */
find_path(const fake_dev_t dev,const fake_ino_t ino,const char * const roots,char * const path)529 static int find_path(const fake_dev_t dev, const fake_ino_t ino,
530 const char *const roots, char *const path)
531 {
532 unsigned int end = 0;
533
534 do {
535 unsigned int len, start = end;
536
537 while (roots[end] != '\0' && roots[end] != ':')
538 end++;
539
540 len = end - start;
541 if (len == 0)
542 continue;
543
544 if (roots[end - 1] == '/')
545 len--;
546
547 if (len > DB_PATH_LEN)
548 len = DB_PATH_LEN;
549
550 strncpy(path, roots + start, len);
551 path[len] = '\0';
552
553 if (scan_dir(dev, ino, path))
554 return 1;
555 } while (roots[end++] != '\0');
556
557 return 0;
558 }
559
560 #endif
561
save_database(const uint32_t remote)562 int save_database(const uint32_t remote)
563 {
564 #ifdef FAKEROOT_DB_PATH
565 char path[DB_PATH_LEN + 1];
566 const char *roots;
567 #endif
568 data_node_t *i;
569 FILE *f;
570
571 if(!save_file)
572 return 0;
573
574 #ifdef FAKEROOT_DB_PATH
575 path[DB_PATH_LEN] = '\0';
576
577 roots = getenv(DB_SEARCH_PATHS_ENV);
578 if (!roots)
579 roots = "/";
580 #endif
581
582 do {
583 int r,fd=0;
584 struct stat s;
585 r=stat(save_file,&s);
586 if (r<0) {
587 if (errno == ENOENT)
588 break;
589 else
590 return EOF;
591 }
592 if (!(s.st_mode&S_IFIFO)) break;
593 fd=open(save_file,O_WRONLY|O_NONBLOCK);
594 if (fd<0) {
595 sleep(1);
596 continue;
597 }
598 close(fd);
599 break;
600 } while (1);
601
602
603 f=fopen(save_file, "w");
604 if(!f)
605 return EOF;
606
607 for (i = data_begin(); i != data_end(); i = data_node_next(i)) {
608 if (i->remote != remote)
609 continue;
610
611 #ifdef FAKEROOT_DB_PATH
612 if (find_path(i->buf.dev, i->buf.ino, roots, path))
613 fprintf(f,"mode=%llo,uid=%llu,gid=%llu,nlink=%llu,rdev=%llu %s\n",
614 (uint64_t) i->buf.mode,(uint64_t) i->buf.uid,(uint64_t) i->buf.gid,
615 (uint64_t) i->buf.nlink,(uint64_t) i->buf.rdev,path);
616 #else
617 fprintf(f,"dev=%llx,ino=%llu,mode=%llo,uid=%llu,gid=%llu,nlink=%llu,rdev=%llu\n",
618 (uint64_t) i->buf.dev,(uint64_t) i->buf.ino,(uint64_t) i->buf.mode,
619 (uint64_t) i->buf.uid,(uint64_t) i->buf.gid,(uint64_t) i->buf.nlink,
620 (uint64_t) i->buf.rdev);
621 #endif
622 }
623
624 return fclose(f);
625 }
626
load_database(const uint32_t remote)627 int load_database(const uint32_t remote)
628 {
629 int r;
630
631 uint64_t stdev, stino, stmode, stuid, stgid, stnlink, strdev;
632 struct fakestat st;
633
634 #ifdef FAKEROOT_DB_PATH
635 char path[DB_PATH_LEN + 1];
636 struct stat path_st;
637
638 path[DB_PATH_LEN] = '\0';
639 #endif
640
641 while(1){
642 #ifdef FAKEROOT_DB_PATH
643 r=scanf("mode=%llo,uid=%llu,gid=%llu,nlink=%llu,rdev=%llu "DB_PATH_SCAN"\n",
644 &stmode, &stuid, &stgid, &stnlink, &strdev, &path);
645 if (r != 6)
646 break;
647
648 if (stat(path, &path_st) < 0) {
649 fprintf(stderr, "%s: %s\n", path, strerror(errno));
650 if (errno == ENOENT || errno == EACCES)
651 continue;
652 else
653 break;
654 }
655 stdev = path_st.st_dev;
656 stino = path_st.st_ino;
657 #else
658 r=scanf("dev=%llx,ino=%llu,mode=%llo,uid=%llu,gid=%llu,nlink=%llu,rdev=%llu\n",
659 &stdev, &stino, &stmode, &stuid, &stgid, &stnlink, &strdev);
660 if (r != 7)
661 break;
662 #endif
663
664 st.dev = stdev;
665 st.ino = stino;
666 st.mode = stmode;
667 st.uid = stuid;
668 st.gid = stgid;
669 st.nlink = stnlink;
670 st.rdev = strdev;
671 data_insert(&st, remote);
672 }
673 if(!r||r==EOF)
674 return 1;
675 else
676 return 0;
677 }
678
679 /*********************************/
680 /* */
681 /* data base maintainance */
682 /* */
683 /*********************************/
debug_stat(const struct fakestat * st)684 void debug_stat(const struct fakestat *st){
685 fprintf(stderr,"dev:ino=(%llx:%lli), mode=0%lo, own=(%li,%li), nlink=%li, rdev=%lli\n",
686 st->dev,
687 st->ino,
688 (long)st->mode,
689 (long)st->uid,
690 (long)st->gid,
691 (long)st->nlink,
692 st->rdev);
693 }
694
insert_or_overwrite(struct fakestat * st,const uint32_t remote)695 void insert_or_overwrite(struct fakestat *st,
696 const uint32_t remote){
697 data_node_t *i;
698
699 i = data_find(st, remote);
700 if (i == data_end()) {
701 if(debug){
702 fprintf(stderr,"FAKEROOT: insert_or_overwrite unknown stat:\n");
703 debug_stat(st);
704 }
705 data_insert(st, remote);
706 }
707 else
708 memcpy(data_node_get(i), st, sizeof (struct fakestat));
709 }
710
711 /*******************************************/
712 /* */
713 /* process requests from wrapper functions */
714 /* */
715 /*******************************************/
716
717
process_chown(struct fake_msg * buf)718 void process_chown(struct fake_msg *buf){
719 struct fakestat *stptr;
720 struct fakestat st;
721 data_node_t *i;
722
723 if(debug){
724 fprintf(stderr,"FAKEROOT: chown ");
725 debug_stat(&buf->st);
726 }
727 i = data_find(&buf->st, buf->remote);
728 if (i != data_end()) {
729 stptr = data_node_get(i);
730 /* From chown(2): If the owner or group is specified as -1,
731 then that ID is not changed.
732 Cannot put that test in libtricks, as at that point it isn't
733 known what the fake user/group is (so cannot specify `unchanged')
734
735 I typecast to (uint32_t), as st.uid may be bigger than uid_t.
736 In that case, the msb in st.uid should be discarded.
737 I don't typecaset to (uid_t), as the size of uid_t may vary
738 depending on what libc (headers) were used to compile. So,
739 different clients might actually use different uid_t's
740 concurrently. Yes, this does seem farfeched, but was
741 actually the case with the libc5/6 transition.
742 */
743 if ((uint32_t)buf->st.uid != (uint32_t)-1)
744 stptr->uid=buf->st.uid;
745 if ((uint32_t)buf->st.gid != (uint32_t)-1)
746 stptr->gid=buf->st.gid;
747 }
748 else{
749 st=buf->st;
750 /* See comment above. We pretend that unknown files are owned
751 by root.root, so we have to maintain that pretense when the
752 caller asks to leave an id unchanged. */
753 if ((uint32_t)st.uid == (uint32_t)-1)
754 st.uid = 0;
755 if ((uint32_t)st.gid == (uint32_t)-1)
756 st.gid = 0;
757 insert_or_overwrite(&st, buf->remote);
758 }
759 }
760
process_chmod(struct fake_msg * buf)761 void process_chmod(struct fake_msg *buf){
762 struct fakestat *st;
763 data_node_t *i;
764
765 if(debug)
766 fprintf(stderr,"FAKEROOT: chmod, mode=%lo\n",
767 (long)buf->st.mode);
768
769 i = data_find(&buf->st, buf->remote);
770 if (i != data_end()) {
771 st = data_node_get(i);
772 /* Statically linked binaries can remove inodes without us knowing.
773 ldconfig is a prime offender. Also, some packages run tests without
774 LD_PRELOAD.
775
776 While those cases can be fixed in other ways, we shouldn't continue to
777 cache stale file information.
778
779 mknod() creates a regular file, everything else should have the same
780 file type on disk and in our database. Therefore, we check the file's
781 type first. If we have something in our database as a device node and
782 we get a request to change it to regular file, it might be a chmod of
783 a device node that was created from within fakeroot, which is a device
784 file on disk - there's no way to distinguish. For anything else, we
785 trust the new type and assume the inode got unlinked from something that
786 wasn't using the LD_PRELOAD library.
787 */
788
789 if ((buf->st.mode&S_IFMT) != (st->mode&S_IFMT) &&
790 ((buf->st.mode&S_IFMT) != S_IFREG || (!st->mode&(S_IFBLK|S_IFCHR)))) {
791 fprintf(stderr,"FAKEROOT: chmod mode=%lo incompatible with "
792 "existing mode=%lo\n", (unsigned long)buf->st.mode, (unsigned long)st->mode);
793 st->mode = buf->st.mode;
794 }
795 else{
796 st->mode = (buf->st.mode&~S_IFMT) | (st->mode&S_IFMT);
797 }
798 }
799 else{
800 st=&buf->st;
801 st->uid=0;
802 st->gid=0;
803 }
804 insert_or_overwrite(st, buf->remote);
805 }
806
process_mknod(struct fake_msg * buf)807 void process_mknod(struct fake_msg *buf){
808 struct fakestat *st;
809 data_node_t *i;
810
811 if(debug)
812 fprintf(stderr,"FAKEROOT: mknod, mode=%lo\n",
813 (long)buf->st.mode);
814
815 i = data_find(&buf->st, buf->remote);
816 if (i != data_end()) {
817 st = data_node_get(i);
818 st->mode = buf->st.mode;
819 st->rdev = buf->st.rdev;
820 }
821 else{
822 st=&buf->st;
823 st->uid=0;
824 st->gid=0;
825 }
826 insert_or_overwrite(st, buf->remote);
827 }
828
process_stat(struct fake_msg * buf)829 void process_stat(struct fake_msg *buf){
830 data_node_t *i;
831
832 i = data_find(&buf->st, buf->remote);
833 if(debug){
834 fprintf(stderr,"FAKEROOT: process stat oldstate=");
835 debug_stat(&buf->st);
836 }
837 if (i == data_end()) {
838 if (debug)
839 fprintf(stderr,"FAKEROOT: (previously unknown)\n");
840 if (!unknown_is_real) {
841 buf->st.uid=0;
842 buf->st.gid=0;
843 }
844 }
845 else{
846 cpyfakefake(&buf->st, data_node_get(i));
847 if(debug){
848 fprintf(stderr,"FAKEROOT: (previously known): fake=");
849 debug_stat(&buf->st);
850 }
851
852 }
853 faked_send_fakem(buf);
854 }
855 //void process_fstat(struct fake_msg *buf){
856 // process_stat(buf);
857 //}
858
process_unlink(struct fake_msg * buf)859 void process_unlink(struct fake_msg *buf){
860
861 if((buf->st.nlink==1)||
862 (S_ISDIR(buf->st.mode)&&(buf->st.nlink==2))){
863 data_node_t *i;
864 i = data_find(&buf->st, buf->remote);
865 if (i != data_end()) {
866 if(debug){
867 fprintf(stderr,"FAKEROOT: unlink known file, old stat=");
868 debug_stat(data_node_get(i));
869 }
870 data_erase(i);
871 }
872 if (data_find(&buf->st, buf->remote) != data_end()) {
873 fprintf(stderr,"FAKEROOT************************************************* cannot remove stat (a \"cannot happen\")\n");
874 }
875 }
876 }
877
process_listxattr(struct fake_msg * buf)878 void process_listxattr(struct fake_msg *buf)
879 {
880 #if defined(HAVE_LISTXATTR) || defined(HAVE_LLISTXATTR) || defined(HAVE_FLISTXATTR)
881 data_node_t *i;
882 xattr_node_t *x = NULL;
883
884 buf->xattr.flags_rc = 0;
885 i = data_find(&buf->st, buf->remote);
886 if(debug){
887 fprintf(stderr,"FAKEROOT: process listxattr\n");
888 }
889 if (i != data_end()) {
890 x = i->xattr;
891 }
892 if (!x) {
893 if (debug) {
894 fprintf(stderr,"FAKEROOT: (previously unknown)\n");
895 }
896 buf->xattr.buffersize = 0;
897 } else {
898 int bsize = 0;
899 while (x) {
900 int keysize = strlen(x->key);
901 if ((bsize + keysize + 1) > MAX_IPC_BUFFER_SIZE)
902 {
903 buf->xattr.flags_rc = ERANGE;
904 break;
905 }
906 strcpy(&buf->xattr.buf[bsize], x->key);
907 bsize += keysize + 1;
908 x = x->next;
909 }
910 buf->xattr.buffersize = bsize;
911 if(debug) {
912 fprintf(stderr,"FAKEROOT: (previously known): xattr=%s\n", buf->xattr.buf);
913 }
914 }
915 faked_send_fakem(buf);
916 #endif /* defined(HAVE_LISTXATTR) || defined(HAVE_LLISTXATTR) || defined(HAVE_FLISTXATTR) */
917 }
918
process_setxattr(struct fake_msg * buf)919 void process_setxattr(struct fake_msg *buf)
920 {
921 #if defined(HAVE_SETXATTR) || defined(HAVE_LSETXATTR) || defined(HAVE_FSETXATTR)
922 data_node_t *i;
923 xattr_node_t *x = NULL;
924 xattr_node_t **x_ref = NULL;
925 xattr_node_t *new_node = NULL;
926 struct fakestat st;
927 char *value = NULL;
928 int key_size, value_size;
929 int flags = buf->xattr.flags_rc;
930
931 buf->xattr.flags_rc = 0;
932 /* Need some more bounds checking */
933 key_size = strlen(buf->xattr.buf);
934 value = &buf->xattr.buf[key_size + 1];
935 value_size = buf->xattr.buffersize - key_size - 1;
936
937 i = data_find(&buf->st, buf->remote);
938 if(debug){
939 fprintf(stderr,"FAKEROOT: process setxattr key = %s\n", buf->xattr.buf);
940 }
941 if (i == data_end()) {
942 if (debug) {
943 fprintf(stderr,"FAKEROOT: (previously unknown)\n");
944 }
945 st=buf->st;
946 /* We pretend that unknown files are owned
947 by root.root, so we have to maintain that pretense when the
948 caller asks to leave an id unchanged. */
949 if ((uint32_t)st.uid == (uint32_t)-1)
950 st.uid = 0;
951 if ((uint32_t)st.gid == (uint32_t)-1)
952 st.gid = 0;
953 insert_or_overwrite(&st, buf->remote);
954 i = data_find(&buf->st, buf->remote);
955 }
956 x = xattr_find(i->xattr, buf->xattr.buf);
957 if (x) {
958 if (flags == XATTR_CREATE) {
959 buf->xattr.flags_rc = EEXIST;
960 if (debug) {
961 fprintf(stderr,"FAKEROOT: Already exists\n");
962 }
963 } else {
964 xattr_fill(x, buf->xattr.buf, value, value_size);
965 if (debug) {
966 fprintf(stderr,"FAKEROOT: Replaced\n");
967 }
968 }
969 } else {
970 if (flags == XATTR_REPLACE) {
971 buf->xattr.flags_rc = ENODATA;
972 if (debug) {
973 fprintf(stderr,"FAKEROOT: Replace requested but no previous entry found\n");
974 }
975 } else {
976 x = xattr_insert(&i->xattr);
977 xattr_fill(x, buf->xattr.buf, value, value_size);
978 if (debug) {
979 fprintf(stderr,"FAKEROOT: Inserted\n");
980 }
981 }
982 }
983 buf->xattr.buffersize = 0;
984 faked_send_fakem(buf);
985 #endif /* defined(HAVE_SETXATTR) || defined(HAVE_LSETXATTR) || defined(HAVE_FSETXATTR) */
986 }
987
process_getxattr(struct fake_msg * buf)988 void process_getxattr(struct fake_msg *buf)
989 {
990 #if defined(HAVE_GETXATTR) || defined(HAVE_LGETXATTR) || defined(HAVE_FGETXATTR)
991 data_node_t *i;
992 xattr_node_t *x = NULL;
993
994 buf->xattr.flags_rc = ENODATA;
995 i = data_find(&buf->st, buf->remote);
996 if(debug){
997 fprintf(stderr,"FAKEROOT: process getxattr key = %s\n", buf->xattr.buf);
998 }
999 if (i != data_end()) {
1000 x = xattr_find(i->xattr, buf->xattr.buf);
1001 }
1002 if (!x) {
1003 if (debug) {
1004 fprintf(stderr,"FAKEROOT: (previously unknown)\n");
1005 }
1006 buf->xattr.buffersize = 0;
1007 } else {
1008 if (debug) {
1009 fprintf(stderr,"FAKEROOT: (previously known): %s\n", x->value);
1010 }
1011 buf->xattr.buffersize = x->value_size;
1012 memcpy(buf->xattr.buf, x->value, x->value_size);
1013 buf->xattr.flags_rc = 0;
1014 }
1015 faked_send_fakem(buf);
1016 #endif /* defined(HAVE_GETXATTR) || defined(HAVE_LGETXATTR) || defined(HAVE_FGETXATTR) */
1017 }
1018
process_removexattr(struct fake_msg * buf)1019 void process_removexattr(struct fake_msg *buf)
1020 {
1021 #if defined(HAVE_REMOVEXATTR) || defined(HAVE_LREMOVEXATTR) || defined(HAVE_FREMOVEXATTR)
1022 data_node_t *i;
1023 xattr_node_t *x = NULL;
1024
1025 buf->xattr.flags_rc = ENODATA;
1026 i = data_find(&buf->st, buf->remote);
1027 if(debug){
1028 fprintf(stderr,"FAKEROOT: process removexattr key = %s\n", buf->xattr.buf);
1029 }
1030 if (i != data_end()) {
1031 x = xattr_find(i->xattr, buf->xattr.buf);
1032 }
1033 if (!x) {
1034 if (debug) {
1035 fprintf(stderr,"FAKEROOT: (previously unknown)\n");
1036 }
1037 } else {
1038 if (debug) {
1039 fprintf(stderr,"FAKEROOT: (previously known): %s\n", x->value);
1040 }
1041 xattr_erase(&i->xattr, buf->xattr.buf);
1042 buf->xattr.flags_rc = 0;
1043 }
1044 buf->xattr.buffersize = 0;
1045 faked_send_fakem(buf);
1046 #endif /* defined(HAVE_REMOVEXATTR) || defined(HAVE_LREMOVEXATTR) || defined(HAVE_FREMOVEXATTR) */
1047 }
1048
debugdata(int dummy UNUSED)1049 void debugdata(int dummy UNUSED){
1050 int stored_errno = errno;
1051 data_node_t *i;
1052
1053 fprintf(stderr," FAKED keeps data of %i inodes:\n", data_size());
1054 for (i = data_begin(); i != data_end(); i = data_node_next(i))
1055 debug_stat(data_node_get(i));
1056
1057 errno = stored_errno;
1058 }
1059
1060
process_msg(struct fake_msg * buf)1061 void process_msg(struct fake_msg *buf){
1062
1063 func_id_t f;
1064 f= buf->id;
1065 if (f <= highest_funcid)
1066 func_arr[f]((struct fake_msg*)buf);
1067 }
1068
1069 #ifndef FAKEROOT_FAKENET
1070
get_msg()1071 void get_msg()
1072 {
1073 struct fake_msg buf;
1074 int r = 0;
1075
1076 if(debug)
1077 fprintf(stderr,"FAKEROOT: msg=%i, key=%li\n",msg_get,(long)msg_key);
1078 do {
1079 r=msgrcv(msg_get,&buf,sizeof(struct fake_msg),0,0);
1080 if(debug)
1081 fprintf(stderr,"FAKEROOT: r=%i, received message type=%li, message=%i\n",r,buf.mtype,buf.id);
1082 if(r!=-1) {
1083 buf.remote = 0;
1084 process_msg(&buf);
1085 }
1086 }while ((r!=-1)||(errno==EINTR));
1087 if(debug){
1088 perror("FAKEROOT, get_msg");
1089 fprintf(stderr,"errno=%i, EINTR=%i\n",errno,EINTR);
1090 }
1091 }
1092
1093 #else /* FAKEROOT_FAKENET */
1094
get_msg(const int listen_sd)1095 void get_msg(const int listen_sd)
1096 {
1097 struct fake_msg buf;
1098 fd_set readfds;
1099
1100 while (1) {
1101 int count, maxfd;
1102 unsigned int i;
1103
1104 if (debug)
1105 fprintf(stderr, "fakeroot: detached=%i clients=%i\n", detached, sd_list_size());
1106
1107 if (detached && sd_list_size() == 0) {
1108 if (debug)
1109 fprintf(stderr, "fakeroot: exiting\n");
1110
1111 cleanup(0);
1112 }
1113
1114 FD_ZERO(&readfds);
1115
1116 FD_SET(listen_sd, &readfds);
1117 maxfd = listen_sd;
1118
1119 for (i = 0; i < sd_list_size(); i++) {
1120 const int sd = sd_list_index(i);
1121
1122 FD_SET(sd, &readfds);
1123 maxfd = MAX(sd, maxfd);
1124 }
1125
1126 count = select(maxfd + 1, &readfds, NULL, NULL, NULL);
1127 if (count < 0) {
1128 if (errno == EINTR)
1129 continue;
1130
1131 fail("select");
1132 }
1133
1134 for (i = 0; i < sd_list_size(); ) {
1135 const int sd = sd_list_index(i);
1136
1137 if (FD_ISSET(sd, &readfds)) {
1138 if (debug)
1139 fprintf(stderr, "fakeroot: message from fd=%d\n", sd);
1140
1141 comm_sd = sd;
1142
1143 if (get_fakem(&buf) < 0) {
1144 if (debug)
1145 fprintf(stderr, "fakeroot: closing fd=%d\n", sd);
1146
1147 close(sd);
1148
1149 sd_list_remove(i);
1150 continue;
1151 }
1152
1153 process_msg(&buf);
1154 }
1155
1156 i++;
1157 }
1158
1159 if (FD_ISSET(listen_sd, &readfds)) {
1160 struct sockaddr_in addr;
1161 socklen_t len = sizeof (addr);
1162 const int sd = accept(listen_sd, (struct sockaddr *) &addr, &len);
1163 if (sd < 0)
1164 fail("accept");
1165
1166 if (debug) {
1167 char host[256];
1168 if (getnameinfo((struct sockaddr *) &addr, len, host, sizeof (host),
1169 NULL, 0, 0) == 0)
1170 fprintf(stderr, "fakeroot: connection from %s, fd=%d\n", host, sd);
1171 }
1172
1173 comm_sd = sd;
1174
1175 if (get_fakem(&buf) < 0) {
1176 if (debug)
1177 fprintf(stderr, "fakeroot: closing fd=%d\n", sd);
1178
1179 close(sd);
1180 continue;
1181 }
1182
1183 process_msg(&buf);
1184 sd_list_add(sd);
1185 }
1186 }
1187 }
1188
1189 #endif /* FAKEROOT_FAKENET */
1190
1191 /***********/
1192 /* */
1193 /* misc */
1194 /* */
1195 /***********/
1196
save(int dummy)1197 void save(int dummy){
1198 int savedb_state;
1199 savedb_state = save_database(0);
1200 if(!savedb_state) {
1201 if(debug && save_file)
1202 fprintf(stderr, "fakeroot: saved database in %s\n", save_file);
1203 } else
1204 fprintf(stderr, "fakeroot: database save FAILED\n");
1205 }
1206
1207 #ifdef FAKEROOT_FAKENET
detach(int g)1208 static void detach(int g)
1209 {
1210 int saved_errno = errno;
1211
1212 if (debug)
1213 fprintf(stderr, "fakeroot: detaching, signal=%i\n", g);
1214
1215 detached = 1;
1216
1217 errno = saved_errno;
1218 }
1219 #endif /* FAKEROOT_FAKENET */
1220
1221 #ifndef FAKEROOT_FAKENET
1222 # define FAKEROOT_CLEANUPMSG "fakeroot: clearing up message queues and semaphores, signal=%i\n"
1223 #else /* FAKEROOT_FAKENET */
1224 # define FAKEROOT_CLEANUPMSG "fakeroot: signal=%i\n"
1225 #endif /* FAKEROOT_FAKENET */
1226
cleanup(int g)1227 void cleanup(int g)
1228 {
1229 #ifndef FAKEROOT_FAKENET
1230 union semun sem_union;
1231 #endif /* ! FAKEROOT_FAKENET */
1232
1233 if(debug)
1234 fprintf(stderr, FAKEROOT_CLEANUPMSG, g);
1235
1236 #ifndef FAKEROOT_FAKENET
1237 msgctl (msg_get, IPC_RMID,NULL);
1238 msgctl (msg_snd, IPC_RMID,NULL);
1239 semctl (sem_id,0,IPC_RMID,sem_union);
1240 #endif /* ! FAKEROOT_FAKENET */
1241
1242 save(0);
1243
1244 if(g!=-1)
1245 exit(0);
1246 }
1247
1248 /*************/
1249 /* */
1250 /* main */
1251 /* */
1252 /*************/
1253
read_intarg(char ** argv)1254 static long int read_intarg(char **argv)
1255 {
1256 if(!*argv){
1257 fprintf(stderr,"%s needs numeric argument\n",*(argv-1));
1258 exit(1);
1259 } else
1260 {
1261 return atoi(*argv);
1262 }
1263 }
1264
1265 #ifdef FAKEROOT_FAKENET
get_fakem(struct fake_msg * buf)1266 static int get_fakem(struct fake_msg *buf)
1267 {
1268 while (1) {
1269 ssize_t len;
1270
1271 len = read(comm_sd, buf, sizeof (struct fake_msg));
1272 if (len > 0)
1273 break;
1274
1275 if (len == 0)
1276 return -1;
1277
1278 if (errno == EINTR)
1279 continue;
1280
1281 fail("read");
1282 }
1283
1284 buf->id = ntohl(buf->id);
1285 buf->st.uid = ntohl(buf->st.uid);
1286 buf->st.gid = ntohl(buf->st.gid);
1287 buf->st.ino = ntohll(buf->st.ino);
1288 buf->st.dev = ntohll(buf->st.dev);
1289 buf->st.rdev = ntohll(buf->st.rdev);
1290 buf->st.mode = ntohl(buf->st.mode);
1291 buf->st.nlink = ntohl(buf->st.nlink);
1292 buf->remote = ntohl(buf->remote);
1293 buf->xattr.buffersize = ntohl(buf->xattr.buffersize);
1294 buf->xattr.flags_rc = ntohl(buf->xattr.flags_rc);
1295
1296 return 0;
1297 }
1298 #endif /* FAKEROOT_FAKENET */
1299
main(int argc,char ** argv)1300 int main(int argc, char **argv){
1301 struct sigaction sa,sa_debug,sa_save;
1302 int i;
1303 int foreground = 0;
1304 int load = 0;
1305 int pid;
1306 #ifndef FAKEROOT_FAKENET
1307 union semun sem_union;
1308 int justcleanup = 0;
1309 #else /* FAKEROOT_FAKENET */
1310 int sd, val;
1311 unsigned int port = 0;
1312 struct sockaddr_in addr;
1313 socklen_t addr_len;
1314 struct sigaction sa_detach;
1315 #endif /* FAKEROOT_FAKENET */
1316
1317 if(getenv(FAKEROOTKEY_ENV)) {
1318 /* I'm not sure -- maybe this can work?) */
1319 fprintf(stderr,"Please, don't run fakeroot from within fakeroot!\n");
1320 exit(1);
1321 }
1322
1323 while(*(++argv)){
1324 if(!strcmp(*argv,"--key"))
1325 #ifndef FAKEROOT_FAKENET
1326 msg_key=read_intarg(++argv);
1327 #else /* FAKEROOT_FAKENET */
1328 fprintf(stderr,"This fakeroot has been compiled for TCP and does not support --key\n");
1329 #endif /* FAKEROOT_FAKENET */
1330 else if(!strcmp(*argv,"--cleanup")) {
1331 #ifndef FAKEROOT_FAKENET
1332 msg_key=read_intarg(++argv);
1333 justcleanup= 1;
1334 #else /* FAKEROOT_FAKENET */
1335 fprintf(stderr,"This fakeroot has been compiled for TCP and does not support --cleanup\n");
1336 #endif /* FAKEROOT_FAKENET */
1337 }
1338 else if(!strcmp(*argv,"--port"))
1339 #ifndef FAKEROOT_FAKENET
1340 fprintf(stderr,"This fakeroot has been compiled for SYSV IPC and does not support --port\n");
1341 #else /* FAKEROOT_FAKENET */
1342 port=read_intarg(++argv);
1343 #endif /* FAKEROOT_FAKENET */
1344 else if(!strcmp(*argv,"--foreground"))
1345 foreground = 1;
1346 else if(!strcmp(*argv,"--debug"))
1347 debug=1;
1348 else if(!strcmp(*argv,"--save-file"))
1349 save_file=*(++argv);
1350 else if(!strcmp(*argv,"--load"))
1351 load=1;
1352 else if(!strcmp(*argv,"--unknown-is-real"))
1353 unknown_is_real = 1;
1354 else if(!strcmp(*argv,"--version")) {
1355 fprintf(stderr,"fakeroot version " VERSION "\n");
1356 exit(0);
1357 } else {
1358 fprintf(stderr,"faked, daemon for fake root environment\n");
1359 fprintf(stderr,"Best used from the shell script `fakeroot'\n");
1360 #ifndef FAKEROOT_FAKENET
1361 fprintf(stderr,"options for fakeroot: --key, --cleanup, --foreground, --debug, --save-file, --load, --unknown-is-real\n");
1362 #else /* FAKEROOT_FAKENET */
1363 fprintf(stderr,"options for fakeroot: --port, --foreground, --debug, --save-file, --load, --unknown-is-real\n");
1364 #endif /* FAKEROOT_FAKENET */
1365 exit(1);
1366 }
1367 }
1368
1369 init_hash_table();
1370
1371 if(load)
1372 if(!load_database(0)) {
1373 fprintf(stderr,"Database load failed\n");
1374 exit(1);
1375 }
1376
1377 #ifndef FAKEROOT_FAKENET
1378
1379 if(!msg_key) {
1380 srandom(time(NULL)+getpid()*33151);
1381 while(!msg_key && (msg_key!=-1)) /* values 0 and -1 are treated
1382 specially by libfake */
1383 msg_key=random();
1384 }
1385
1386 if(debug)
1387 fprintf(stderr,"using %li as msg key\n",(long)msg_key);
1388
1389 msg_get=msgget(msg_key,IPC_CREAT|0600);
1390 msg_snd=msgget(msg_key+1,IPC_CREAT|0600);
1391 sem_id=semget(msg_key+2,1,IPC_CREAT|0600);
1392 sem_union.val=1;
1393 semctl (sem_id,0,SETVAL,sem_union);
1394
1395 if((msg_get==-1)||(msg_snd==-1)||(sem_id==-1)){
1396 perror("fakeroot, while creating message channels");
1397 fprintf(stderr, "This may be due to a lack of SYSV IPC support.\n");
1398 cleanup(-1);
1399 exit(1);
1400 }
1401
1402 if(debug)
1403 fprintf(stderr,"msg_key=%li\n",(long)msg_key);
1404
1405 if(justcleanup)
1406 cleanup(0);
1407
1408 #else /* FAKEROOT_FAKENET */
1409
1410 sd = socket(PF_INET, SOCK_STREAM, 0);
1411 if (sd < 0)
1412 fail("socket");
1413
1414 val = 1;
1415 if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof (val)) < 0)
1416 fail("setsockopt(SO_REUSEADDR)");
1417
1418 val = 1;
1419 if (setsockopt(sd, SOL_TCP, TCP_NODELAY, &val, sizeof (val)) < 0)
1420 fail("setsockopt(TCP_NODELAY)");
1421
1422 if (port > 0) {
1423 memset((char *) &addr, 0, sizeof (addr));
1424 addr.sin_family = AF_INET;
1425 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1426 addr.sin_port = htons(port);
1427
1428 if (bind(sd, (struct sockaddr *) &addr, sizeof (addr)) < 0)
1429 fail("bind");
1430 }
1431
1432 if (listen(sd, SOMAXCONN) < 0)
1433 fail("listen");
1434
1435 addr_len = sizeof (addr);
1436 if (getsockname(sd, (struct sockaddr *) &addr, &addr_len) < 0)
1437 fail("getsockname");
1438
1439 port = ntohs(addr.sin_port);
1440
1441 sa_detach.sa_handler=detach;
1442 sigemptyset(&sa_detach.sa_mask);
1443 sa_detach.sa_flags=0;
1444
1445 #endif /* FAKEROOT_FAKENET */
1446
1447 sa.sa_handler=cleanup;
1448 sigemptyset(&sa.sa_mask);
1449 sa.sa_flags=0;
1450 // sa.sa_restorer=0;
1451
1452 sa_debug.sa_handler=debugdata;
1453 sigemptyset(&sa_debug.sa_mask);
1454 sa_debug.sa_flags=0;
1455 // sa_debug.sa_restorer=0;
1456
1457 sa_save.sa_handler=save;
1458 sigemptyset(&sa_save.sa_mask);
1459 sa_save.sa_flags=0;
1460
1461 for(i=1; i< NSIG; i++){
1462 switch (i){
1463 case SIGKILL:
1464 case SIGTSTP:
1465 case SIGCONT:
1466 break;
1467 case SIGUSR1:
1468 /* this is strictly a debugging feature, unless someone can confirm
1469 that save will always get a consistent database */
1470 sigaction(i,&sa_save,NULL);
1471 break;
1472 case SIGUSR2:
1473 sigaction(i,&sa_debug,NULL);
1474 break;
1475 #ifdef FAKEROOT_FAKENET
1476 case SIGHUP:
1477 sigaction(i,&sa_detach,NULL);
1478 break;
1479 #endif /* FAKEROOT_FAKENET */
1480 default:
1481 sigaction(i,&sa,NULL);
1482 break;
1483 }
1484 }
1485
1486 if(!foreground){
1487 /* literally copied from the linux klogd code, go to background */
1488 if ((pid=fork()) == 0){
1489 int fl;
1490 int num_fds = getdtablesize();
1491
1492 fflush(stdout);
1493
1494 /* This is the child closing its file descriptors. */
1495 for (fl= 0; fl <= num_fds; ++fl)
1496 #ifdef FAKEROOT_FAKENET
1497 if (fl != sd)
1498 #endif /* FAKEROOT_FAKENET */
1499 close(fl);
1500 setsid();
1501 } else {
1502 printf("%li:%i\n",(long)FAKE_KEY,pid);
1503
1504 exit(0);
1505 }
1506 } else {
1507 printf("%li:%i\n",(long)FAKE_KEY,getpid());
1508 fflush(stdout);
1509 }
1510
1511 #ifndef FAKEROOT_FAKENET
1512 get_msg(); /* we shouldn't return from this function */
1513 #else /* FAKEROOT_FAKENET */
1514 get_msg(sd); /* we shouldn't return from this function */
1515 #endif /* FAKEROOT_FAKENET */
1516
1517 cleanup(-1); /* if we do return, try to clean up and exit with a nonzero
1518 return status */
1519 return 1;
1520 }
1521