1 #include "lib.h" 2 #include <stddef.h> 3 #include <unistd.h> 4 #include <errno.h> 5 #include <string.h> 6 #include <stdio.h> 7 #include "sys9.h" 8 #include "dir.h" 9 10 #define DBG(s) 11 #define MAXDEPTH 100 12 13 static void namedev(Dir *); 14 static int samefile(Dir *, Dir *); 15 16 char * 17 getcwd(char *s , size_t size) 18 { 19 Dir *p, db[MAXDEPTH], root; 20 int depth, l; 21 char *x, *v; 22 char cd[DIRLEN]; 23 24 if(size == 0) { 25 errno = EINVAL; 26 return 0; 27 } 28 x = s; 29 if(_STAT("/", cd) < 0) { 30 errno = EACCES; 31 return 0; 32 } 33 convM2D(cd, &root); 34 35 for(depth = 0; depth < MAXDEPTH; depth++) { 36 p = &db[depth]; 37 if(_STAT(".", cd) < 0) { 38 errno = EACCES; 39 return 0; 40 } 41 convM2D(cd, p); 42 43 DBG(print("stat: %s %lux\n", p->name, p->qid);) 44 45 if(samefile(p, &root)) { 46 depth--; 47 break; 48 } 49 50 if(depth > 1 && samefile(p, &db[depth-1])) { 51 p->name[0] = '#'; 52 p->name[1] = p->type; 53 p->name[2] = '\0'; 54 break; 55 } 56 57 if((p->name[0] == '.' || p->name[0] == '/') && 58 p->name[1] == '\0') 59 namedev(p); 60 61 if(chdir("..") < 0) { 62 errno = EACCES; 63 return 0; 64 } 65 } 66 67 while(depth >= 0) { 68 v = db[depth--].name; 69 if(v[0] == '.' && v[1] == '\0') 70 continue; 71 if(v[0] != '#') 72 *x++ = '/'; 73 l = strlen(v); 74 size -= l+1; 75 if(size <= 0) { 76 errno = ERANGE; 77 return 0; 78 } 79 strcpy(x, v); 80 x += l; 81 } 82 DBG(print("chdir %s\n", s);) 83 if(chdir(s) < 0) { 84 errno = EACCES; 85 return 0; 86 } 87 return s; 88 } 89 90 static void 91 namedev(Dir *p) 92 { 93 Dir dirb, tdirb; 94 char buf[DIRLEN*50], sd[NAMELEN*2]; 95 char cd[DIRLEN]; 96 int fd, n; 97 char *t, *e; 98 99 fd = _OPEN("..", OREAD); 100 if(fd < 0) 101 return; 102 103 for(;;) { 104 n = _READ(fd, buf, sizeof(buf)); 105 if(n <= 0) { 106 _CLOSE(fd); 107 return; 108 } 109 e = &buf[n]; 110 111 for(t = buf; t < e; t += DIRLEN) { 112 convM2D(t, &dirb); 113 if((dirb.qid.path&CHDIR) == 0) 114 continue; 115 sprintf(sd, "../%s/.", dirb.name); 116 if(_STAT(sd, cd) < 0) 117 continue; 118 convM2D(cd, &tdirb); 119 120 if(samefile(&tdirb, p) == 0) 121 continue; 122 _CLOSE(fd); 123 DBG(print("%s->%s\n", p->name, dirb.name);) 124 strcpy(p->name, dirb.name); 125 return; 126 } 127 } 128 _CLOSE(fd); 129 } 130 131 static int 132 samefile(Dir *a, Dir *b) 133 { 134 if(a->type != b->type) 135 return 0; 136 if(a->dev != b->dev) 137 return 0; 138 if(a->qid.path != b->qid.path) 139 return 0; 140 return 1; 141 } 142