c0f3987438dacbb21cab3d5c3ec8509b759d1450
8 typedef struct Rfile Rfile
;
9 typedef struct Rpath Rpath
;
32 static Rpath
*rpathtab
[64];
33 static QLock rpathtablk
;
40 prp
= &rpathtab
[hashpath(path
) % nelem(rpathtab
)];
42 if(strcmp(path
, (*prp
)->str
) == 0)
44 prp
= &((*prp
)->hash
);
52 if(strncmp(name
, ".udir.L.", 8) == 0)
58 udirpath(char *base
, char *name
, char type
)
62 strcpy(buf
, ".udir.T.");
64 return allocpath(base
, buf
, name
);
68 udirget(char *base
, char *name
, char type
, char **val
)
75 f
= udirpath(base
, name
, type
);
76 if((fd
= open(shortpath(current
->kcwd
, f
), OREAD
)) < 0)
82 if((s
= seek(fd
, 0, 2)) < 0)
88 if((n
= read(fd
, b
, s
)) < 0){
104 resolvepath1(char *path
, int link
)
106 char *r
, *b
, *p
, *o
, *e
;
120 a
= krealloc(a
, sizeof(a
[0]) * (n
+16));
126 for(i
=n
-1; i
>=0; i
--){
137 if(!udirget(b
, f
, 'L', &t
)){
144 t
= udirpath(b
, e
, 'L');
150 r
= fullpath(t
, &o
[1]);
166 resolvepath(char *path
, int link
)
172 path
= kstrdup(path
);
173 while(t
= resolvepath1(path
, link
)){
179 free(path
); path
= t
;
185 ropen(char *path
, int mode
, int perm
, Ufile
**pf
)
196 trace("ropen(%s, %#o, %#o, ...)", path
, mode
, perm
);
201 perm9
= (perm
& ~current
->umask
) & 0777;
203 s
= shortpath(current
->kcwd
, path
);
209 if((base
= basepath(path
, &name
)) == nil
)
212 /* resolve base directory */
213 if((d
= dirstat(shortpath(current
->kcwd
, base
))) == nil
){
215 if(t
= resolvepath1(base
, 0)){
216 free(base
); base
= t
;
217 t
= allocpath(t
, nil
, name
);
218 err
= fsopen(t
, mode
, perm
, pf
);
224 if((d
->mode
& DMDIR
) == 0){
230 /* check if here is a symlink in the way */
231 t
= udirpath(base
, name
, 'L');
232 if((fd
= open(shortpath(current
->kcwd
, t
), OREAD
)) >= 0){
241 if((t
= resolvepath1(path
, 0)) == nil
)
243 err
= fsopen(t
, mode
, perm
, pf
);
249 if(mode
& (O_EXCL
| O_TRUNC
)){
252 fd
= create(s
, mode9
, perm9
);
254 /* try open first to avoid truncating existing the file */
255 if((fd
= open(s
, mode9
)) < 0)
256 fd
= create(s
, mode9
, perm9
);
263 if(((mode
& 3) == O_RDWR
) || ((mode
& 3) == O_WRONLY
))
267 if((fd
= open(s
, mode9
)) < 0){
269 if(t
= resolvepath1(path
, 0)){
270 err
= fsopen(t
, mode
, perm
, pf
);
278 prp
= rpathent(path
);
284 rp
= kmalloc(sizeof(*rp
) + strlen(path
) + 1);
288 strcpy(rp
->str
, path
);
291 qunlock(&rpathtablk
);
293 f
= kmallocz(sizeof(Rfile
), 1);
295 f
->path
= kstrdup(path
);
315 Rfile
*file
= (Rfile
*)f
;
316 static char path
[1024]; /* protected by rpathtablk */
319 prp
= rpathent(file
->path
);
324 if(fd2path(file
->fd
, path
, sizeof(path
)) == 0)
325 remove(shortpath(current
->kcwd
, path
));
329 qunlock(&rpathtablk
);
336 rread(Ufile
*f
, void *buf
, int len
, vlong off
)
338 Rfile
*file
= (Rfile
*)f
;
344 while((n
< len
) && ((ret
= pread(file
->fd
, (uchar
*)buf
+ n
, len
- n
, off
+ n
)) > 0))
353 rwrite(Ufile
*f
, void *buf
, int len
, vlong off
)
355 Rfile
*file
= (Rfile
*)f
;
360 ret
= pwrite(file
->fd
, buf
, len
, off
);
370 Rfile
*file
= (Rfile
*)f
;
372 return seek(file
->fd
, 0, 2);
376 raccess(char *path
, int mode
)
378 static char omode
[] = {
398 s
= shortpath(current
->kcwd
, path
);
399 if((d
= dirstat(s
)) == nil
){
401 if(path
= resolvepath1(path
, 0)){
402 err
= fsaccess(path
, mode
);
408 /* ignore the exec bit... firefox gets confused */
410 if((mode
== 0) || (d
->mode
& DMDIR
)){
414 if((mode
& 01) && ((d
->mode
& 0111) == 0))
416 if((mode
& 02) && ((d
->mode
& 0222) == 0))
418 if((mode
& 04) && ((d
->mode
& 0444) == 0))
420 if((fd
= open(s
, omode
[mode
])) >= 0){
435 mode
= d
->mode
& 0777;
438 else if(strcmp(d
->name
, "cons") == 0)
440 else if(strncmp(d
->name
, "PTS.", 4) == 0)
442 else if(strcmp(d
->name
, "zero") == 0)
443 mode
|= S_IFCHR
| 0222;
444 else if(strcmp(d
->name
, "null") == 0)
445 mode
|= S_IFCHR
| 0222;
446 else if(strncmp(d
->name
, ".udir.", 6) == 0){
464 } else if(d
->type
== '|')
466 else if(d
->type
== 'H')
475 dir2ustat(Dir
*d
, Ustat
*s
)
477 s
->mode
= dir2statmode(d
);
478 s
->uid
= current
->uid
;
479 s
->gid
= current
->gid
;
484 s
->ino
= 0; // use d->qid?
490 rstat(char *path
, int link
, Ustat
*s
)
496 if((d
= dirstat(shortpath(current
->kcwd
, path
))) == nil
){
500 if(base
= basepath(path
, &name
)){
501 t
= udirpath(base
, name
, 'L');
504 d
= dirstat(shortpath(current
->kcwd
, t
));
512 if(t
= resolvepath1(path
, 0)){
513 err
= fsstat(t
, link
, s
);
520 s
->ino
= hashpath(path
);
527 rfstat(Ufile
*f
, Ustat
*s
)
531 if((d
= dirfstat(f
->fd
)) == nil
)
535 s
->ino
= hashpath(f
->path
);
546 if(strncmp(name
, ".udir.", 6) == 0){
547 if(name
[6] && name
[7]=='.')
554 rreaddir(Ufile
*f
, Udirent
**pd
)
560 n
= dirreadall(f
->fd
, &d
);
564 if((*pd
= newdirent(f
->path
, fixname(d
[i
].name
), dir2statmode(&d
[i
]))) == nil
)
573 rreadlink(char *path
, char *buf
, int len
)
582 trace("rreadlink(%s)", path
);
584 if((base
= basepath(path
, &name
)) == nil
)
587 /* resolve base path */
588 if((fd
= open(shortpath(current
->kcwd
, base
), OREAD
)) < 0){
590 if(t
= resolvepath1(base
, 0)){
591 free(base
); base
= t
;
592 t
= allocpath(base
, nil
, name
);
593 err
= fsreadlink(t
, buf
, len
);
600 /* check if path is regular file */
601 if((fd
= open(shortpath(current
->kcwd
, path
), OREAD
)) >= 0){
607 t
= udirpath(base
, name
, 'L');
608 if((fd
= open(shortpath(current
->kcwd
, t
), OREAD
)) < 0){
614 if((err
= read(fd
, buf
, len
)) < 0)
628 copyfile(char *from
, char *to
)
630 int err
, fromfd
, tofd
;
641 trace("copyfile(%s, %s)", from
, to
);
643 if((fromfd
= open(shortpath(current
->kcwd
, from
), OREAD
)) < 0){
647 if((dir
= dirfstat(fromfd
)) == nil
){
651 s
= shortpath(current
->kcwd
, to
);
652 if((err
= open(s
, OREAD
)) >= 0){
657 if(dir
->mode
& DMDIR
){
659 if((tofd
= create(s
, OREAD
, dir
->mode
)) < 0){
665 while((n
= dirread(fromfd
, &ent
)) > 0){
669 char *froment
, *toent
;
671 froment
= allocpath(from
, nil
, ent
[i
].name
);
672 toent
= allocpath(to
, nil
, ent
[i
].name
);
673 err
= copyfile(froment
, toent
);
680 free(ent
); ent
= nil
;
683 if((tofd
= create(s
, OWRITE
, dir
->mode
)) < 0){
687 buf
= kmalloc(COPYSIZE
);
689 err
= read(fromfd
, buf
, COPYSIZE
);
696 if(write(tofd
, buf
, err
) != err
){
714 removefile(char *path
)
722 trace("removefile(%s)", path
);
724 s
= shortpath(current
->kcwd
, path
);
726 if((d
= dirstat(s
)) == nil
)
732 if((d
->mode
& DMDIR
) == 0){
737 if((fd
= open(s
, OREAD
)) < 0)
741 while((n
= dirread(fd
, &d
)) > 0){
746 t
= allocpath(path
, nil
, d
[i
].name
);
769 resolvefromtopath(char **from
, char **to
)
773 trace("resolvefromtopath(%s, %s)", *from
, *to
);
775 if((*from
= resolvepath(*from
, 1)) == nil
){
779 if((*to
= resolvepath(*to
, 1)) == nil
){
784 if(strstr(*from
, ".udir.L")){
793 if(strncmp(x
+1, ".udir.", 6)){
795 t
= udirpath(*to
, x
+1, 'L');
804 rrename(char *from
, char *to
)
809 trace("rrename(%s, %s)", from
, to
);
811 if((err
= resolvefromtopath(&from
, &to
)) < 0)
813 if(strcmp(from
, to
) == 0)
816 for(t
=from
; *t
; t
++){
830 if(strcmp(from
, to
) == 0)
841 if(dirwstat(shortpath(current
->kcwd
, from
), &d
) < 0)
846 t
= ksmprint("%s%d%d.tmp", to
, current
->pid
, current
->tid
);
847 if((err
= copyfile(from
, t
)) == 0){
853 remove(shortpath(current
->kcwd
, to
));
854 if(dirwstat(shortpath(current
->kcwd
, t
), &d
) < 0) {
871 rmkdir(char *path
, int mode
)
882 trace("rmkdir(%s, %#o)", path
, mode
);
884 if((base
= basepath(path
, &name
)) == nil
)
887 if((d
= dirstat(shortpath(current
->kcwd
, base
))) == nil
){
889 if(t
= resolvepath1(base
, 0)){
890 free(base
); base
= t
;
891 t
= allocpath(base
, nil
, name
);
892 err
= fsmkdir(t
, mode
);
898 if((d
->mode
& DMDIR
) == 0){
905 t
= udirpath(base
, name
, 'L');
906 if(d
= dirstat(shortpath(current
->kcwd
, t
))){
913 mode9
= DMDIR
| ((mode
& ~current
->umask
) & 0777);
914 if((fd
= create(shortpath(current
->kcwd
, path
), OREAD
|OEXCL
, mode9
)) < 0){
928 combinedir(Dir
*ndir
, Dir
*odir
)
931 ndir
->mode
= (odir
->mode
& ~0777) | (ndir
->mode
& 0777);
935 uwstat(char *path
, Dir
*ndir
, int link
)
941 trace("uwstat(%s, ..., %d)", path
, link
);
943 s
= shortpath(current
->kcwd
, path
);
944 if((dir
= dirstat(s
)) == nil
){
950 if(base
= basepath(path
, &name
)){
953 t
= udirpath(base
, name
, 'L');
957 err
= uwstat(t
, ndir
, 0);
963 combinedir(ndir
, dir
);
965 if(dirwstat(s
, ndir
) < 0)
972 uwfstat(Ufile
*f
, Dir
*ndir
)
977 if((dir
= dirfstat(f
->fd
)) == nil
){
981 combinedir(ndir
, dir
);
983 if(dirfwstat(f
->fd
, ndir
) < 0)
991 rutime(char *path
, long atime
, long mtime
)
996 trace("rutime(%s, %ld, %ld)", path
, atime
, mtime
);
1002 if((err
= uwstat(path
, &ndir
, 1)) < 0){
1005 if(t
= resolvepath1(path
, 0)){
1006 err
= fsutime(t
, atime
, mtime
);
1014 rchmod(char *path
, int mode
)
1019 trace("rchmod(%s, %#o)", path
, mode
);
1024 if((err
= uwstat(path
, &ndir
, 1)) < 0){
1027 if(t
= resolvepath1(path
, 0)){
1028 err
= fschmod(t
, mode
);
1036 rchown(char *path
, int uid
, int gid
, int link
)
1043 /* FIXME, just return the right errorcode for now */
1044 return fsstat(path
, link
, &s
);
1048 rtruncate(char *path
, vlong size
)
1053 trace("rtruncate(%s, %lld)", path
, size
);
1058 if((err
= uwstat(path
, &ndir
, 0)) < 0){
1061 if(t
= resolvepath1(path
, 0)){
1062 err
= fstruncate(t
, size
);
1070 rfchmod(Ufile
*f
, int mode
)
1076 return uwfstat(f
, &ndir
);
1080 rfchown(Ufile
*f
, int uid
, int gid
)
1090 rftruncate(Ufile
*f
, vlong size
)
1096 return uwfstat(f
, &ndir
);
1100 runlink(char *path
, int rmdir
)
1110 trace("runlink(%s, %d)", path
, rmdir
);
1115 if((base
= basepath(path
, &name
)) == nil
)
1117 if(dir
= dirstat(shortpath(current
->kcwd
, path
))){
1118 rpath
= kstrdup(path
);
1120 rpath
= udirpath(base
, name
, 'L');
1121 dir
= dirstat(shortpath(current
->kcwd
, rpath
));
1125 if(t
= resolvepath1(path
, 0)){
1126 err
= fsunlink(t
, rmdir
);
1132 if((dir
->mode
& DMDIR
) == 0){
1137 if(dir
->mode
& DMDIR
){
1143 s
= shortpath(current
->kcwd
, rpath
);
1146 prp
= rpathent(path
);
1150 t
= ksmprint(".%s.%d.deleted", name
, current
->kpid
);
1153 trace("runlink: file %s still in use renaming to -> %s", path
, t
);
1154 if(dirwstat(s
, &ndir
) < 0){
1155 qunlock(&rpathtablk
);
1161 (*prp
)->deleted
= 1;
1162 qunlock(&rpathtablk
);
1166 qunlock(&rpathtablk
);
1169 while(remove(s
) < 0){
1172 /* old debian bug clashes with mntgen */
1173 if(strcmp(base
, "/")==0 && strstr(path
, ".dpkg-"))
1190 rlink(char *old
, char *new, int sym
)
1198 trace("rlink(%s, %s, %d)", old
, new, sym
);
1200 if((base
= basepath(new, &name
)) == nil
)
1203 /* resolve base directory */
1204 if((fd
= open(shortpath(current
->kcwd
, base
), OREAD
)) < 0){
1206 if(t
= resolvepath1(base
, 0)){
1207 free(base
); base
= t
;
1208 t
= allocpath(base
, nil
, name
);
1209 err
= fslink(old
, t
, sym
);
1217 if((err
= resolvefromtopath(&old
, &new)) == 0)
1218 err
= copyfile(old
, new);
1224 /* check if regular file is in the way */
1226 if((fd
= open(shortpath(current
->kcwd
, new), OREAD
)) >= 0){
1231 /* try to create the link, will fail if alreadt exists */
1232 t
= udirpath(base
, name
, 'L');
1233 if((fd
= create(shortpath(current
->kcwd
, t
), OWRITE
|OEXCL
, 0777)) < 0){
1240 if(write(fd
, old
, strlen(old
)) < 0){
1253 static Udev rootdev
=
1265 .truncate
= rtruncate
,
1273 .readdir
= rreaddir
,
1274 .readlink
= rreadlink
,
1278 .ftruncate
= rftruncate
,
1281 void rootdevinit(void)
1283 devtab
[ROOTDEV
] = &rootdev
;
1285 fsmount(&rootdev
, "");