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  This file contains the code (wrapper functions) that gets linked with
16  the programes run from inside fakeroot. These programes then communicate
17  with the fakeroot daemon, that keeps information about the "fake"
18  ownerships etc. of the files etc.
19 
20  */
21 
22 #ifdef __APPLE__
23 /*
24    In this file, we want 'struct stat' to have a 32-bit 'ino_t'.
25    We use 'struct stat64' when we need a 64-bit 'ino_t'.
26 */
27 #define _DARWIN_NO_64_BIT_INODE
28 #endif
29 
30 #include "communicate.h"
31 #include <dlfcn.h>
32 #include <stdio.h>
33 #ifndef FAKEROOT_FAKENET
34 # include <sys/ipc.h>
35 # include <sys/msg.h>
36 # include <sys/sem.h>
37 #else /* FAKEROOT_FAKENET */
38 # include <netinet/in.h>
39 # include <netinet/tcp.h>
40 # include <netdb.h>
41 # include <pthread.h>
42 # ifdef HAVE_ENDIAN_H
43 #  include <endian.h>
44 # endif
45 #endif /* FAKEROOT_FAKENET */
46 #include <fcntl.h>
47 #include <unistd.h>
48 #include <errno.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <ctype.h>
52 #include <stdarg.h>
53 #ifdef HAVE_SYS_SOCKET_H
54 # include <sys/socket.h>
55 #endif
56 
57 #ifdef STUPID_ALPHA_HACK
58 #include "stats.h"
59 #endif
60 
61 #ifndef _UTSNAME_LENGTH
62 /* for LINUX libc5 */
63 #  define _UTSNAME_LENGTH _SYS_NMLN
64 #endif
65 
66 
67 #ifndef FAKEROOT_FAKENET
68 int msg_snd=-1;
69 int msg_get=-1;
70 int sem_id=-1;
71 #else /* FAKEROOT_FAKENET */
72 volatile int comm_sd = -1;
73 static pthread_mutex_t comm_sd_mutex = PTHREAD_MUTEX_INITIALIZER;
74 #endif /* FAKEROOT_FAKENET */
75 
76 
77 #ifdef FAKEROOT_FAKENET
fail(const char * msg)78 static void fail(const char *msg)
79 {
80   if (errno > 0)
81     fprintf(stderr, "libfakeroot: %s: %s\n", msg, strerror(errno));
82   else
83     fprintf(stderr, "libfakeroot: %s\n", msg);
84 
85   exit(1);
86 }
87 #endif /* FAKEROOT_FAKENET */
88 
env_var_set(const char * env)89 const char *env_var_set(const char *env){
90   const char *s;
91 
92   s=getenv(env);
93 
94   if(s && *s)
95     return s;
96   else
97     return NULL;
98 }
99 
cpyfakemstat(struct fake_msg * f,const struct stat * st,int ver)100 void cpyfakemstat(struct fake_msg *f, const struct stat *st
101 #ifdef STUPID_ALPHA_HACK
102 		, int ver
103 #endif
104 		){
105 
106 #ifndef STUPID_ALPHA_HACK
107   f->st.mode =st->st_mode;
108   f->st.ino  =st->st_ino ;
109   f->st.uid  =st->st_uid ;
110   f->st.gid  =st->st_gid ;
111   f->st.dev  =st->st_dev ;
112   f->st.rdev =st->st_rdev;
113 
114   /* DO copy the nlink count. Although the system knows this
115      one better, we need it for unlink().
116      This actually opens up a race condition, if another command
117      makes a hardlink on a file, while we try to unlink it. This
118      may cause the record to be deleted, while the link continues
119      to live on the disk. But the chance is small, and unlikely
120      to occur in practical fakeroot conditions. */
121 
122   f->st.nlink=st->st_nlink;
123 #else
124   switch(ver) {
125 	  case _STAT_VER_KERNEL:
126   f->st.mode  = ((struct fakeroot_kernel_stat *)st)->st_mode;
127   f->st.ino   = ((struct fakeroot_kernel_stat *)st)->st_ino;
128   f->st.uid   = ((struct fakeroot_kernel_stat *)st)->st_uid;
129   f->st.gid   = ((struct fakeroot_kernel_stat *)st)->st_gid;
130   f->st.dev   = ((struct fakeroot_kernel_stat *)st)->st_dev;
131   f->st.rdev  = ((struct fakeroot_kernel_stat *)st)->st_rdev;
132   f->st.nlink = ((struct fakeroot_kernel_stat *)st)->st_nlink;
133   break;
134 	  case _STAT_VER_GLIBC2:
135   f->st.mode  = ((struct fakeroot_glibc2_stat *)st)->st_mode;
136   f->st.ino   = ((struct fakeroot_glibc2_stat *)st)->st_ino;
137   f->st.uid   = ((struct fakeroot_glibc2_stat *)st)->st_uid;
138   f->st.gid   = ((struct fakeroot_glibc2_stat *)st)->st_gid;
139   f->st.dev   = ((struct fakeroot_glibc2_stat *)st)->st_dev;
140   f->st.rdev  = ((struct fakeroot_glibc2_stat *)st)->st_rdev;
141   f->st.nlink = ((struct fakeroot_glibc2_stat *)st)->st_nlink;
142   break;
143 		  case _STAT_VER_GLIBC2_1:
144   f->st.mode  = ((struct fakeroot_glibc21_stat *)st)->st_mode;
145   f->st.ino   = ((struct fakeroot_glibc21_stat *)st)->st_ino;
146   f->st.uid   = ((struct fakeroot_glibc21_stat *)st)->st_uid;
147   f->st.gid   = ((struct fakeroot_glibc21_stat *)st)->st_gid;
148   f->st.dev   = ((struct fakeroot_glibc21_stat *)st)->st_dev;
149   f->st.rdev  = ((struct fakeroot_glibc21_stat *)st)->st_rdev;
150   f->st.nlink = ((struct fakeroot_glibc21_stat *)st)->st_nlink;
151   break;
152 		  default:
153   f->st.mode  = st->st_mode;
154   f->st.ino   = st->st_ino;
155   f->st.uid   = st->st_uid;
156   f->st.gid   = st->st_gid;
157   f->st.dev   = st->st_dev;
158   f->st.rdev  = st->st_rdev;
159   f->st.nlink = st->st_nlink;
160   break;
161   }
162 #endif
163 }
164 
cpystatfakem(struct stat * st,const struct fake_msg * f,int ver)165 void cpystatfakem(struct stat *st, const struct fake_msg *f
166 #ifdef STUPID_ALPHA_HACK
167 		, int ver
168 #endif
169 		){
170 #ifndef STUPID_ALPHA_HACK
171   st->st_mode =f->st.mode;
172   st->st_ino  =f->st.ino ;
173   st->st_uid  =f->st.uid ;
174   st->st_gid  =f->st.gid ;
175   st->st_dev  =f->st.dev ;
176   st->st_rdev =f->st.rdev;
177   /* DON'T copy the nlink count! The system always knows
178      this one better! */
179   /*  st->st_nlink=f->st.nlink;*/
180 #else
181   switch(ver) {
182 	  case _STAT_VER_KERNEL:
183   ((struct fakeroot_kernel_stat *)st)->st_mode = f->st.mode;
184   ((struct fakeroot_kernel_stat *)st)->st_ino  = f->st.ino;
185   ((struct fakeroot_kernel_stat *)st)->st_uid  = f->st.uid;
186   ((struct fakeroot_kernel_stat *)st)->st_gid  = f->st.gid;
187   ((struct fakeroot_kernel_stat *)st)->st_dev  = f->st.dev;
188   ((struct fakeroot_kernel_stat *)st)->st_rdev = f->st.rdev;
189   break;
190 	  case _STAT_VER_GLIBC2:
191   ((struct fakeroot_glibc2_stat *)st)->st_mode = f->st.mode;
192   ((struct fakeroot_glibc2_stat *)st)->st_ino  = f->st.ino;
193   ((struct fakeroot_glibc2_stat *)st)->st_uid  = f->st.uid;
194   ((struct fakeroot_glibc2_stat *)st)->st_gid  = f->st.gid;
195   ((struct fakeroot_glibc2_stat *)st)->st_dev  = f->st.dev;
196   ((struct fakeroot_glibc2_stat *)st)->st_rdev = f->st.rdev;
197   break;
198 		  case _STAT_VER_GLIBC2_1:
199   ((struct fakeroot_glibc21_stat *)st)->st_mode = f->st.mode;
200   ((struct fakeroot_glibc21_stat *)st)->st_ino  = f->st.ino;
201   ((struct fakeroot_glibc21_stat *)st)->st_uid  = f->st.uid;
202   ((struct fakeroot_glibc21_stat *)st)->st_gid  = f->st.gid;
203   ((struct fakeroot_glibc21_stat *)st)->st_dev  = f->st.dev;
204   ((struct fakeroot_glibc21_stat *)st)->st_rdev = f->st.rdev;
205   break;
206 		  default:
207   st->st_mode =f->st.mode;
208   st->st_ino  =f->st.ino ;
209   st->st_uid  =f->st.uid ;
210   st->st_gid  =f->st.gid ;
211   st->st_dev  =f->st.dev ;
212   st->st_rdev =f->st.rdev;
213   break;
214   }
215 #endif
216 }
217 
218 #ifdef STAT64_SUPPORT
219 
cpyfakemstat64(struct fake_msg * f,const struct stat64 * st,int ver)220 void cpyfakemstat64(struct fake_msg *f,
221                  const struct stat64 *st
222 #ifdef STUPID_ALPHA_HACK
223                  , int ver
224 #endif
225                  ){
226 #ifndef STUPID_ALPHA_HACK
227   f->st.mode =st->st_mode;
228   f->st.ino  =st->st_ino ;
229   f->st.uid  =st->st_uid ;
230   f->st.gid  =st->st_gid ;
231   f->st.dev  =st->st_dev ;
232   f->st.rdev =st->st_rdev;
233 
234   /* DO copy the nlink count. Although the system knows this
235      one better, we need it for unlink().
236      This actually opens up a race condition, if another command
237      makes a hardlink on a file, while we try to unlink it. This
238      may cause the record to be deleted, while the link continues
239      to live on the disk. But the chance is small, and unlikely
240      to occur in practical fakeroot conditions. */
241 
242   f->st.nlink=st->st_nlink;
243 #else
244   switch(ver) {
245 	  case _STAT_VER_KERNEL:
246   f->st.mode  = ((struct fakeroot_kernel_stat *)st)->st_mode;
247   f->st.ino   = ((struct fakeroot_kernel_stat *)st)->st_ino;
248   f->st.uid   = ((struct fakeroot_kernel_stat *)st)->st_uid;
249   f->st.gid   = ((struct fakeroot_kernel_stat *)st)->st_gid;
250   f->st.dev   = ((struct fakeroot_kernel_stat *)st)->st_dev;
251   f->st.rdev  = ((struct fakeroot_kernel_stat *)st)->st_rdev;
252   f->st.nlink = ((struct fakeroot_kernel_stat *)st)->st_nlink;
253   break;
254 	  case _STAT_VER_GLIBC2:
255   f->st.mode  = ((struct fakeroot_glibc2_stat *)st)->st_mode;
256   f->st.ino   = ((struct fakeroot_glibc2_stat *)st)->st_ino;
257   f->st.uid   = ((struct fakeroot_glibc2_stat *)st)->st_uid;
258   f->st.gid   = ((struct fakeroot_glibc2_stat *)st)->st_gid;
259   f->st.dev   = ((struct fakeroot_glibc2_stat *)st)->st_dev;
260   f->st.rdev  = ((struct fakeroot_glibc2_stat *)st)->st_rdev;
261   f->st.nlink = ((struct fakeroot_glibc2_stat *)st)->st_nlink;
262   break;
263 	  case _STAT_VER_GLIBC2_1:
264   f->st.mode  = ((struct fakeroot_glibc21_stat *)st)->st_mode;
265   f->st.ino   = ((struct fakeroot_glibc21_stat *)st)->st_ino;
266   f->st.uid   = ((struct fakeroot_glibc21_stat *)st)->st_uid;
267   f->st.gid   = ((struct fakeroot_glibc21_stat *)st)->st_gid;
268   f->st.dev   = ((struct fakeroot_glibc21_stat *)st)->st_dev;
269   f->st.rdev  = ((struct fakeroot_glibc21_stat *)st)->st_rdev;
270   f->st.nlink = ((struct fakeroot_glibc21_stat *)st)->st_nlink;
271   break;
272 		  default:
273   f->st.mode  = st->st_mode;
274   f->st.ino   = st->st_ino;
275   f->st.uid   = st->st_uid;
276   f->st.gid   = st->st_gid;
277   f->st.dev   = st->st_dev;
278   f->st.rdev  = st->st_rdev;
279   f->st.nlink = st->st_nlink;
280   break;
281   }
282 #endif
283 }
cpystat64fakem(struct stat64 * st,const struct fake_msg * f,int ver)284 void cpystat64fakem(struct stat64 *st,
285                  const struct fake_msg *f
286 #ifdef STUPID_ALPHA_HACK
287                  , int ver
288 #endif
289                  ){
290 #ifndef STUPID_ALPHA_HACK
291   st->st_mode =f->st.mode;
292   st->st_ino  =f->st.ino ;
293   st->st_uid  =f->st.uid ;
294   st->st_gid  =f->st.gid ;
295   st->st_dev  =f->st.dev ;
296   st->st_rdev =f->st.rdev;
297   /* DON'T copy the nlink count! The system always knows
298      this one better! */
299   /*  st->st_nlink=f->st.nlink;*/
300 #else
301   switch(ver) {
302 	  case _STAT_VER_KERNEL:
303   ((struct fakeroot_kernel_stat *)st)->st_mode = f->st.mode;
304   ((struct fakeroot_kernel_stat *)st)->st_ino  = f->st.ino;
305   ((struct fakeroot_kernel_stat *)st)->st_uid  = f->st.uid;
306   ((struct fakeroot_kernel_stat *)st)->st_gid  = f->st.gid;
307   ((struct fakeroot_kernel_stat *)st)->st_dev  = f->st.dev;
308   ((struct fakeroot_kernel_stat *)st)->st_rdev = f->st.rdev;
309   break;
310 	  case _STAT_VER_GLIBC2:
311   ((struct fakeroot_glibc2_stat *)st)->st_mode = f->st.mode;
312   ((struct fakeroot_glibc2_stat *)st)->st_ino  = f->st.ino;
313   ((struct fakeroot_glibc2_stat *)st)->st_uid  = f->st.uid;
314   ((struct fakeroot_glibc2_stat *)st)->st_gid  = f->st.gid;
315   ((struct fakeroot_glibc2_stat *)st)->st_dev  = f->st.dev;
316   ((struct fakeroot_glibc2_stat *)st)->st_rdev = f->st.rdev;
317   break;
318 		  case _STAT_VER_GLIBC2_1:
319   ((struct fakeroot_glibc21_stat *)st)->st_mode = f->st.mode;
320   ((struct fakeroot_glibc21_stat *)st)->st_ino  = f->st.ino;
321   ((struct fakeroot_glibc21_stat *)st)->st_uid  = f->st.uid;
322   ((struct fakeroot_glibc21_stat *)st)->st_gid  = f->st.gid;
323   ((struct fakeroot_glibc21_stat *)st)->st_dev  = f->st.dev;
324   ((struct fakeroot_glibc21_stat *)st)->st_rdev = f->st.rdev;
325   break;
326 		  default:
327   st->st_mode =f->st.mode;
328   st->st_ino  =f->st.ino ;
329   st->st_uid  =f->st.uid ;
330   st->st_gid  =f->st.gid ;
331   st->st_dev  =f->st.dev ;
332   st->st_rdev =f->st.rdev;
333   break;
334   }
335 #endif
336 }
337 
338 #endif /* STAT64_SUPPORT */
339 
cpyfakefake(struct fakestat * dest,const struct fakestat * source)340 void cpyfakefake(struct fakestat *dest,
341                  const struct fakestat *source){
342   dest->mode =source->mode;
343   dest->ino  =source->ino ;
344   dest->uid  =source->uid ;
345   dest->gid  =source->gid ;
346   dest->dev  =source->dev ;
347   dest->rdev =source->rdev;
348   /* DON'T copy the nlink count! The system always knows
349      this one better! */
350   /*  dest->nlink=source->nlink;*/
351 }
352 
353 
354 #ifdef _LARGEFILE_SOURCE
355 
stat64from32(struct stat64 * s64,const struct stat * s32)356 void stat64from32(struct stat64 *s64, const struct stat *s32)
357 {
358   /* I've added st_size and st_blocks here.
359      Don't know why they were missing -- joost*/
360    s64->st_dev = s32->st_dev;
361    s64->st_ino = s32->st_ino;
362    s64->st_mode = s32->st_mode;
363    s64->st_nlink = s32->st_nlink;
364    s64->st_uid = s32->st_uid;
365    s64->st_gid = s32->st_gid;
366    s64->st_rdev = s32->st_rdev;
367    s64->st_size = s32->st_size;
368    s64->st_blksize = s32->st_blksize;
369    s64->st_blocks = s32->st_blocks;
370    s64->st_atime = s32->st_atime;
371    s64->st_mtime = s32->st_mtime;
372    s64->st_ctime = s32->st_ctime;
373 }
374 
375 /* This assumes that the 64 bit structure is actually filled in and does not
376    down case the sizes from the 32 bit one.. */
stat32from64(struct stat * s32,const struct stat64 * s64)377 void stat32from64(struct stat *s32, const struct stat64 *s64)
378 {
379    s32->st_dev = s64->st_dev;
380    s32->st_ino = s64->st_ino;
381    s32->st_mode = s64->st_mode;
382    s32->st_nlink = s64->st_nlink;
383    s32->st_uid = s64->st_uid;
384    s32->st_gid = s64->st_gid;
385    s32->st_rdev = s64->st_rdev;
386    s32->st_size = (long)s64->st_size;
387    s32->st_blksize = s64->st_blksize;
388    s32->st_blocks = (long)s64->st_blocks;
389    s32->st_atime = s64->st_atime;
390    s32->st_mtime = s64->st_mtime;
391    s32->st_ctime = s64->st_ctime;
392 }
393 
394 #endif
395 
396 #ifndef FAKEROOT_FAKENET
397 
semaphore_up()398 void semaphore_up(){
399   struct sembuf op;
400   if(sem_id==-1)
401     sem_id=semget(get_ipc_key(0)+2,1,IPC_CREAT|0600);
402   op.sem_num=0;
403   op.sem_op=-1;
404   op.sem_flg=SEM_UNDO;
405   init_get_msg();
406   while (1) {
407     if (semop(sem_id,&op,1)) {
408       if (errno != EINTR) {
409 	perror("semop(1): encountered an error");
410         exit(1);
411       }
412     } else {
413       break;
414     }
415   }
416 }
417 
semaphore_down()418 void semaphore_down(){
419   struct sembuf op;
420   if(sem_id==-1)
421     sem_id=semget(get_ipc_key(0)+2,1,IPC_CREAT|0600);
422   op.sem_num=0;
423   op.sem_op=1;
424   op.sem_flg=SEM_UNDO;
425   while (1) {
426     if (semop(sem_id,&op,1)) {
427       if (errno != EINTR) {
428         perror("semop(2): encountered an error");
429         exit(1);
430       }
431     } else {
432       break;
433     }
434   }
435 }
436 
437 #else /* FAKEROOT_FAKENET */
438 
get_addr(void)439 static struct sockaddr *get_addr(void)
440 {
441   static struct sockaddr_in addr = { 0, 0, { 0 } };
442 
443   if (!addr.sin_port) {
444     char *str;
445     int port;
446 
447     str = (char *) env_var_set(FAKEROOTKEY_ENV);
448     if (!str) {
449       errno = 0;
450       fail("FAKEROOTKEY not defined in environment");
451     }
452 
453     port = atoi(str);
454     if (port <= 0 || port >= 65536) {
455       errno = 0;
456       fail("invalid port number in FAKEROOTKEY");
457     }
458 
459     addr.sin_family = AF_INET;
460     addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
461     addr.sin_port = htons(port);
462   }
463 
464   return (struct sockaddr *) &addr;
465 }
466 
open_comm_sd(void)467 static void open_comm_sd(void)
468 {
469   if (comm_sd >= 0)
470     return;
471 
472   comm_sd = socket(PF_INET, SOCK_STREAM, 0);
473   if (comm_sd < 0)
474     fail("socket");
475 
476   if (fcntl(comm_sd, F_SETFD, FD_CLOEXEC) < 0)
477     fail("fcntl(F_SETFD, FD_CLOEXEC)");
478 
479   while (1) {
480     if (connect(comm_sd, get_addr(), sizeof (struct sockaddr_in)) < 0) {
481       if (errno != EINTR)
482         fail("connect");
483     } else
484       break;
485   }
486 }
487 
lock_comm_sd(void)488 void lock_comm_sd(void)
489 {
490   pthread_mutex_lock(&comm_sd_mutex);
491 }
492 
unlock_comm_sd(void)493 void unlock_comm_sd(void)
494 {
495   pthread_mutex_unlock(&comm_sd_mutex);
496 }
497 
498 #endif /* FAKEROOT_FAKENET */
499 
500 #ifndef FAKEROOT_FAKENET
501 
send_fakem(const struct fake_msg * buf)502 void send_fakem(const struct fake_msg *buf)
503 {
504   int r;
505 
506   if(init_get_msg()!=-1){
507     ((struct fake_msg *)buf)->mtype=1;
508     r=msgsnd(msg_snd, (struct fake_msg *)buf,
509 	     sizeof(*buf)-sizeof(buf->mtype), 0);
510     if(r==-1)
511       perror("libfakeroot, when sending message");
512   }
513 }
514 
send_get_fakem(struct fake_msg * buf)515 void send_get_fakem(struct fake_msg *buf)
516 {
517   /*
518   send and get a struct fakestat from the daemon.
519   We have to use serial/pid numbers in addidtion to
520      the semaphore locking, to prevent the following:
521 
522   Client 1 locks and sends a stat() request to deamon.
523   meantime, client 2 tries to up the semaphore too, but blocks.
524   While client 1 is waiting, it recieves a KILL signal, and dies.
525   SysV semaphores can eighter be automatically cleaned up when
526   a client dies, or they can stay in place. We have to use the
527   cleanup version, as otherwise client 2 will block forever.
528   So, the semaphore is cleaned up when client 1 recieves the KILL signal.
529   Now, client 1 falls through the semaphore_up, and
530   sends a stat() request to the daemon --  it will now recieve
531   the answer intended for client 1, and hell breaks lose (yes,
532   this has actually happened, and yes, it was hell (to debug)).
533 
534   I realise that I may well do away with the semaphore stuff,
535   if I put the serial/pid numbers in the mtype field. But I cannot
536   store both PID and serial in mtype (just 32 bits on Linux). So
537   there will always be some (small) chance it will go wrong.
538   */
539 
540   int l;
541   pid_t pid;
542   static int serial=0;
543 
544   if(init_get_msg()!=-1){
545     pid=getpid();
546     semaphore_up();
547     serial++;
548     buf->serial=serial;
549     buf->pid=pid;
550     send_fakem(buf);
551 
552     do
553       l=msgrcv(msg_get,
554                (struct my_msgbuf*)buf,
555                sizeof(*buf)-sizeof(buf->mtype),0,0);
556     while(((l==-1)&&(errno==EINTR))||(buf->serial!=serial)||buf->pid!=pid);
557 
558     if(l==-1){
559       buf->xattr.flags_rc=errno;
560       fprintf(stderr,"fakeroot internal error #%d: %s\n",
561               errno, strerror(errno));
562     }
563 
564     semaphore_down();
565 
566     /*
567     (nah, may be wrong, due to allignment)
568 
569     if(l!=sizeof(*buf)-sizeof(buf->mtype))
570     printf("libfakeroot/fakeroot, internal bug!! get_fake: length=%i != l=%i",
571     sizeof(*buf)-sizeof(buf->mtype),l);
572     */
573 
574   }
575 }
576 
577 #else /* FAKEROOT_FAKENET */
578 
579 
write_all(int fd,const void * buf,size_t count)580 static size_t write_all(int fd,const void*buf,size_t count) {
581   ssize_t rc,remaining=count;
582   while(remaining>0) {
583 	  rc= write(fd, buf+(count-remaining), remaining);
584 	  if(rc<=0) {
585 		  if(remaining==count) return rc;
586 		  else fail("partial write");
587 	  } else {
588 		  remaining-=rc;
589 	  }
590   }
591   return count-remaining;
592 }
593 
read_all(int fd,void * buf,size_t count)594 static size_t read_all(int fd,void *buf,size_t count) {
595   ssize_t rc,remaining=count;
596   while(remaining>0) {
597 	  rc = read(fd,buf+(count-remaining),remaining);
598 	  if(rc<=0) {
599 		  if(remaining==count) return rc;
600 		  else fail("partial read");
601 	  } else {
602 		  remaining-=rc;
603 	  }
604   }
605   return count-remaining;
606 }
607 
send_fakem_nr(const struct fake_msg * buf)608 static void send_fakem_nr(const struct fake_msg *buf)
609 {
610   struct fake_msg fm;
611 
612   fm.id = htonl(buf->id);
613   fm.st.uid = htonl(buf->st.uid);
614   fm.st.gid = htonl(buf->st.gid);
615   fm.st.ino = htonll(buf->st.ino);
616   fm.st.dev = htonll(buf->st.dev);
617   fm.st.rdev = htonll(buf->st.rdev);
618   fm.st.mode = htonl(buf->st.mode);
619   fm.st.nlink = htonl(buf->st.nlink);
620   fm.remote = htonl(0);
621   fm.xattr.buffersize = htonl(buf->xattr.buffersize);
622   fm.xattr.flags_rc = htonl(buf->xattr.flags_rc);
623   memcpy(fm.xattr.buf, buf->xattr.buf, MAX_IPC_BUFFER_SIZE);
624 
625   while (1) {
626     ssize_t len;
627 
628     len = write_all(comm_sd, &fm, sizeof (fm));
629     if (len > 0)
630       break;
631 
632     if (len == 0) {
633       errno = 0;
634       fail("write: socket is closed");
635     }
636 
637     if (errno == EINTR)
638       continue;
639 
640     fail("write");
641   }
642 }
643 
send_fakem(const struct fake_msg * buf)644 void send_fakem(const struct fake_msg *buf)
645 {
646   lock_comm_sd();
647 
648   open_comm_sd();
649   send_fakem_nr(buf);
650 
651   unlock_comm_sd();
652 }
653 
get_fakem_nr(struct fake_msg * buf)654 static void get_fakem_nr(struct fake_msg *buf)
655 {
656   while (1) {
657     ssize_t len;
658 
659     len = read_all(comm_sd, buf, sizeof (struct fake_msg));
660     if (len > 0)
661       break;
662     if (len == 0) {
663       errno = 0;
664       fail("read: socket is closed");
665     }
666     if (errno == EINTR)
667       continue;
668    fail("read");
669   }
670 
671   buf->id = ntohl(buf->id);
672   buf->st.uid = ntohl(buf->st.uid);
673   buf->st.gid = ntohl(buf->st.gid);
674   buf->st.ino = ntohll(buf->st.ino);
675   buf->st.dev = ntohll(buf->st.dev);
676   buf->st.rdev = ntohll(buf->st.rdev);
677   buf->st.mode = ntohl(buf->st.mode);
678   buf->st.nlink = ntohl(buf->st.nlink);
679   buf->remote = ntohl(buf->remote);
680   buf->xattr.buffersize = ntohl(buf->xattr.buffersize);
681   buf->xattr.flags_rc = ntohl(buf->xattr.flags_rc);
682 }
683 
send_get_fakem(struct fake_msg * buf)684 void send_get_fakem(struct fake_msg *buf)
685 {
686   lock_comm_sd();
687 
688   open_comm_sd();
689   send_fakem_nr(buf);
690   get_fakem_nr(buf);
691 
692   unlock_comm_sd();
693 }
694 
695 #endif /* FAKEROOT_FAKENET */
696 
send_stat(const struct stat * st,func_id_t f,int ver)697 void send_stat(const struct stat *st,
698 	       func_id_t f
699 #ifdef STUPID_ALPHA_HACK
700 	       , int ver
701 #endif
702 	       ){
703   struct fake_msg buf;
704 
705 #ifndef FAKEROOT_FAKENET
706   if(init_get_msg()!=-1)
707 #endif /* ! FAKEROOT_FAKENET */
708   {
709 #ifndef STUPID_ALPHA_HACK
710     cpyfakemstat(&buf,st);
711 #else
712     cpyfakemstat(&buf,st,ver);
713 #endif
714     buf.id=f;
715     send_fakem(&buf);
716   }
717 }
718 
719 #ifdef STAT64_SUPPORT
send_stat64(const struct stat64 * st,func_id_t f,int ver)720 void send_stat64(const struct stat64 *st,
721                  func_id_t f
722 #ifdef STUPID_ALPHA_HACK
723                  , int ver
724 #endif
725                  ){
726   struct fake_msg buf;
727 
728 #ifndef FAKEROOT_FAKENET
729   if(init_get_msg()!=-1)
730 #endif /* ! FAKEROOT_FAKENET */
731   {
732 #ifndef STUPID_ALPHA_HACK
733     cpyfakemstat64(&buf,st);
734 #else
735     cpyfakemstat64(&buf,st,ver);
736 #endif
737     buf.id=f;
738     send_fakem(&buf);
739   }
740 }
741 #endif /* STAT64_SUPPORT */
742 
send_get_stat(struct stat * st,int ver)743 void send_get_stat(struct stat *st
744 #ifdef STUPID_ALPHA_HACK
745 		, int ver
746 #endif
747 		){
748   struct fake_msg buf;
749 
750 #ifndef FAKEROOT_FAKENET
751   if(init_get_msg()!=-1)
752 #endif /* ! FAKEROOT_FAKENET */
753   {
754 #ifndef STUPID_ALPHA_HACK
755     cpyfakemstat(&buf,st);
756 #else
757     cpyfakemstat(&buf,st,ver);
758 #endif
759 
760     buf.id=stat_func;
761     send_get_fakem(&buf);
762 #ifndef STUPID_ALPHA_HACK
763     cpystatfakem(st,&buf);
764 #else
765     cpystatfakem(st,&buf,ver);
766 #endif
767   }
768 }
769 
send_get_xattr(struct stat * st,xattr_args * xattr,int ver)770 void send_get_xattr(struct stat *st
771 		, xattr_args *xattr
772 #ifdef STUPID_ALPHA_HACK
773 		, int ver
774 #endif
775 		){
776   struct fake_msg buf;
777   size_t in_size;
778   size_t name_size;
779   size_t total_size;
780 
781 #ifndef FAKEROOT_FAKENET
782   if(init_get_msg()!=-1)
783 #endif /* ! FAKEROOT_FAKENET */
784   {
785 #ifndef STUPID_ALPHA_HACK
786     cpyfakemstat(&buf,st);
787 #else
788     cpyfakemstat(&buf,st,ver);
789 #endif
790     in_size = xattr->size;
791     total_size = (xattr->func == setxattr_func) ? (in_size) : 0;
792     if (xattr->name)
793     {
794       name_size = strlen(xattr->name);
795       total_size += name_size + 1;
796     }
797     if (total_size > MAX_IPC_BUFFER_SIZE)
798     {
799       xattr->rc = ERANGE;
800       return;
801     }
802     if (xattr->name) {
803       strcpy(buf.xattr.buf, xattr->name);
804       if (xattr->func == setxattr_func)
805         memcpy(&buf.xattr.buf[name_size + 1], xattr->value, in_size);
806     }
807     buf.xattr.buffersize = total_size;
808     buf.xattr.flags_rc = xattr->flags;
809     buf.id=xattr->func;
810     send_get_fakem(&buf);
811     xattr->rc = buf.xattr.flags_rc;
812     xattr->size = buf.xattr.buffersize;
813     if (buf.xattr.buffersize) {
814       if (!in_size) {
815         /* Special case. Return size of required buffer */
816         return;
817       }
818       if (xattr->size > in_size) {
819         xattr->rc = ERANGE;
820         return;
821       }
822       memcpy(xattr->value, buf.xattr.buf, xattr->size);
823     }
824   }
825 }
826 
827 #ifdef STAT64_SUPPORT
send_get_stat64(struct stat64 * st,int ver)828 void send_get_stat64(struct stat64 *st
829 #ifdef STUPID_ALPHA_HACK
830                      , int ver
831 #endif
832                     )
833 {
834   struct fake_msg buf;
835 
836 #ifndef FAKEROOT_FAKENET
837   if(init_get_msg()!=-1)
838 #endif /* ! FAKEROOT_FAKENET */
839   {
840 #ifndef STUPID_ALPHA_HACK
841     cpyfakemstat64(&buf,st);
842 #else
843     cpyfakemstat64(&buf,st,ver);
844 #endif
845 
846     buf.id=stat_func;
847     send_get_fakem(&buf);
848 #ifndef STUPID_ALPHA_HACK
849     cpystat64fakem(st,&buf);
850 #else
851     cpystat64fakem(st,&buf,ver);
852 #endif
853   }
854 }
855 
send_get_xattr64(struct stat64 * st,xattr_args * xattr,int ver)856 void send_get_xattr64(struct stat64 *st
857 		, xattr_args *xattr
858 #ifdef STUPID_ALPHA_HACK
859 		, int ver
860 #endif
861 		){
862   struct fake_msg buf;
863   size_t in_size;
864   size_t name_size;
865   size_t total_size;
866 
867 #ifndef FAKEROOT_FAKENET
868   if(init_get_msg()!=-1)
869 #endif /* ! FAKEROOT_FAKENET */
870   {
871 #ifndef STUPID_ALPHA_HACK
872     cpyfakemstat64(&buf,st);
873 #else
874     cpyfakemstat64(&buf,st,ver);
875 #endif
876     in_size = xattr->size;
877     total_size = (xattr->func == setxattr_func) ? (in_size) : 0;
878     if (xattr->name)
879     {
880       name_size = strlen(xattr->name);
881       total_size += name_size + 1;
882     }
883     if (total_size > MAX_IPC_BUFFER_SIZE)
884     {
885       xattr->rc = ERANGE;
886       return;
887     }
888     if (xattr->name) {
889       strcpy(buf.xattr.buf, xattr->name);
890       if (xattr->func == setxattr_func)
891         memcpy(&buf.xattr.buf[name_size + 1], xattr->value, in_size);
892     }
893     buf.xattr.buffersize = total_size;
894     buf.xattr.flags_rc = xattr->flags;
895     buf.id=xattr->func;
896     send_get_fakem(&buf);
897     xattr->rc = buf.xattr.flags_rc;
898     xattr->size = buf.xattr.buffersize;
899     if (buf.xattr.buffersize) {
900       if (!in_size) {
901         /* Special case. Return size of required buffer */
902         return;
903       }
904       if (xattr->size > in_size) {
905         xattr->rc = ERANGE;
906         return;
907       }
908       memcpy(xattr->value, buf.xattr.buf, xattr->size);
909     }
910   }
911 }
912 #endif /* STAT64_SUPPORT */
913 
914 #ifndef FAKEROOT_FAKENET
915 
get_ipc_key(key_t new_key)916 key_t get_ipc_key(key_t new_key)
917 {
918   const char *s;
919   static key_t key=-1;
920 
921   if(key==-1){
922     if(new_key!=0)
923       key=new_key;
924     else if((s=env_var_set(FAKEROOTKEY_ENV)))
925       key=atoi(s);
926     else
927       key=0;
928   };
929   return key;
930 }
931 
932 
init_get_msg()933 int init_get_msg(){
934   /* a msgget call generates a fstat() call. As fstat() is wrapped,
935      that call will in turn call semaphore_up(). So, before
936      the semaphores are setup, we should make sure we already have
937      the msg_get and msg_set id.
938      This is why semaphore_up() calls this function.*/
939   static int done=0;
940   key_t key;
941 
942   if((!done)&&(msg_get==-1)){
943     key=get_ipc_key(0);
944     if(key){
945       msg_snd=msgget(get_ipc_key(0),IPC_CREAT|00600);
946       msg_get=msgget(get_ipc_key(0)+1,IPC_CREAT|00600);
947     }
948     else{
949       msg_get=-1;
950       msg_snd=-1;
951     }
952     done=1;
953   }
954   return msg_snd;
955 }
956 
957 /* fake_get_owner() allows a process which has not set LD_PRELOAD to query
958    the fake ownership etc. of files.  That process needs to know the key
959    in use by faked - faked prints this at startup. */
fake_get_owner(int is_lstat,const char * key,const char * path,uid_t * uid,gid_t * gid,mode_t * mode)960 int fake_get_owner(int is_lstat, const char *key, const char *path,
961                   uid_t *uid, gid_t *gid, mode_t *mode){
962   struct stat st;
963   int i;
964 
965   if (!key || !strlen(key))
966     return 0;
967 
968   /* Do the stat or lstat */
969   i = (is_lstat ? lstat(path, &st) : stat(path, &st));
970   if (i < 0)
971     return i;
972 
973   /* Now pass it to faked */
974   get_ipc_key(atoi(key));
975 #ifndef STUPID_ALPHA_HACK
976   send_get_stat(&st);
977 #else
978   send_get_stat(&st, _STAT_VER);
979 #endif
980 
981   /* Return the values inside the pointers */
982   if (uid)
983     *uid = st.st_uid;
984   if (gid)
985     *gid = st.st_gid;
986   if (mode)
987     *mode = st.st_mode;
988 
989   return 0;
990 }
991 
992 #endif /* ! FAKEROOT_FAKENET */
993