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