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