Unified · Split
| @@ -1,16 +1,8 @@ | |||
| 1 | /* | ||
| 2 | * Disable Unicode until the calls to FindFirstFile etc | ||
| 3 | * are changed to use wide character strings. | ||
| 4 | */ | ||
| 5 | #undef UNICODE | ||
| 6 | #include <windows.h> | 1 | #include <windows.h> |
| 7 | #include <sys/types.h> | 2 | #include <sys/types.h> |
| 8 | #include <sys/stat.h> | 3 | #include <sys/stat.h> |
| 9 | #include <fcntl.h> | 4 | #include <fcntl.h> |
| 10 | 5 | ||
| 11 | #ifndef NAME_MAX | ||
| 12 | # define NAME_MAX 256 | ||
| 13 | #endif | ||
| 14 | #include "u.h" | 6 | #include "u.h" |
| 15 | #include "lib.h" | 7 | #include "lib.h" |
| 16 | #include "dat.h" | 8 | #include "dat.h" |
| @@ -20,47 +12,148 @@ · 3 unmodified lines | |||
| 20 | typedef struct DIR DIR; | 12 | typedef struct DIR DIR; |
| 21 | typedef struct Ufsinfo Ufsinfo; | 13 | typedef struct Ufsinfo Ufsinfo; |
| 22 | 14 | ||
| 15 | |||
| 23 | enum | 16 | enum |
| 24 | { | 17 | { |
| 25 | NUID = 256, | ||
| 26 | NGID = 256, | ||
| 27 | MAXPATH = 1024, | 18 | MAXPATH = 1024, |
| 28 | MAXCOMP = 128 | 19 | TPATH_ROOT = 0, // "" |
| 20 | TPATH_VOLUME = 1, // "C:" | ||
| 21 | TPATH_FILE = 2, // "C:\bla" | ||
| 29 | }; | 22 | }; |
| 30 | 23 | ||
| 31 | struct DIR | 24 | struct DIR |
| 32 | { | 25 | { |
| 33 | HANDLE handle; | 26 | // for FindFileFirst() |
| 34 | char* path; | 27 | HANDLE handle; |
| 35 | int index; | ||
| 36 | WIN32_FIND_DATA wfd; | 28 | WIN32_FIND_DATA wfd; |
| 29 | |||
| 30 | // for GetLogicalDriveStrings() | ||
| 31 | TCHAR *drivebuf; | ||
| 32 | TCHAR *drivep; | ||
| 33 | |||
| 34 | // dont move to the next item | ||
| 35 | int keep; | ||
| 37 | }; | 36 | }; |
| 38 | 37 | ||
| 39 | struct Ufsinfo | 38 | struct Ufsinfo |
| 40 | { | 39 | { |
| 41 | int mode; | 40 | int mode; |
| 42 | int fd; | 41 | HANDLE fh; |
| 43 | int uid; | ||
| 44 | int gid; | ||
| 45 | DIR* dir; | 42 | DIR* dir; |
| 46 | ulong offset; | 43 | vlong offset; |
| 47 | QLock oq; | 44 | QLock oq; |
| 48 | char nextname[NAME_MAX]; | ||
| 49 | }; | 45 | }; |
| 50 | 46 | ||
| 51 | DIR* opendir(char*); | 47 | static void fspath(Chan *, char *, TCHAR *, int); |
| 52 | int readdir(char*, DIR*); | 48 | static ulong fsdirread(Chan*, uchar*, int, vlong); |
| 53 | void closedir(DIR*); | 49 | static int fsomode(int); |
| 54 | void rewinddir(DIR*); | 50 | static ulong fsaccess(int); |
| 51 | static ulong pathtype(TCHAR *); | ||
| 52 | static int checkvolume(TCHAR *); | ||
| 55 | 53 | ||
| 56 | char *base = "c:/."; | 54 | char *base = ""; |
| 57 | 55 | ||
| 58 | static Qid fsqid(char*, struct stat *); | 56 | static ulong |
| 59 | static void fspath(Chan*, char*, char*); | 57 | unixtime(FILETIME *ft) |
| 60 | // static void fsperm(Chan*, int); | 58 | { |
| 61 | static ulong fsdirread(Chan*, uchar*, int, ulong); | 59 | vlong t; |
| 62 | static int fsomode(int); | 60 | t = ((vlong)ft->dwHighDateTime << 32)|((vlong)ft->dwLowDateTime); |
| 63 | static int chown(char *path, int uid, int); | 61 | t -= 116444736000000000LL; |
| 62 | return ((t<0)?(-1 - (-t - 1)) : t)/10000000; | ||
| 63 | } | ||
| 64 | |||
| 65 | static uvlong | ||
| 66 | pathhash(TCHAR *p) | ||
| 67 | { | ||
| 68 | uvlong h; | ||
| 69 | h = 0LL; | ||
| 70 | for(; *p; p++) | ||
| 71 | h += *p * 13; | ||
| 72 | return h; | ||
| 73 | } | ||
| 74 | |||
| 75 | static ulong | ||
| 76 | wfdtodmode(WIN32_FIND_DATA *wfd) | ||
| 77 | { | ||
| 78 | int m; | ||
| 79 | m = DMREAD|DMWRITE|DMEXEC; | ||
| 80 | if(wfd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) | ||
| 81 | m |= DMDIR; | ||
| 82 | if(wfd->dwFileAttributes & FILE_ATTRIBUTE_READONLY) | ||
| 83 | m &= ~DMWRITE; | ||
| 84 | m |= (m & 07)<<3; | ||
| 85 | m |= (m & 07)<<6; | ||
| 86 | return m; | ||
| 87 | } | ||
| 88 | |||
| 89 | static Qid | ||
| 90 | wfdtoqid(TCHAR *path, WIN32_FIND_DATA *wfd) | ||
| 91 | { | ||
| 92 | ulong t; | ||
| 93 | WIN32_FIND_DATA f; | ||
| 94 | Qid q; | ||
| 95 | |||
| 96 | t = pathtype(path); | ||
| 97 | |||
| 98 | switch(t){ | ||
| 99 | case TPATH_VOLUME: | ||
| 100 | case TPATH_ROOT: | ||
| 101 | q.type = QTDIR; | ||
| 102 | q.path = pathhash(path); | ||
| 103 | q.vers = 0; | ||
| 104 | break; | ||
| 105 | |||
| 106 | case TPATH_FILE: | ||
| 107 | if(!wfd){ | ||
| 108 | HANDLE h; | ||
| 109 | if((h = FindFirstFile(path, &f))==INVALID_HANDLE_VALUE) | ||
| 110 | oserror(); | ||
| 111 | FindClose(h); | ||
| 112 | wfd = &f; | ||
| 113 | } | ||
| 114 | q.type = (wfd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? QTDIR : QTFILE; | ||
| 115 | q.path = pathhash(path); | ||
| 116 | q.vers = unixtime(&wfd->ftLastWriteTime); | ||
| 117 | break; | ||
| 118 | } | ||
| 119 | return q; | ||
| 120 | } | ||
| 121 | |||
| 122 | static void | ||
| 123 | wfdtodir(TCHAR *path, Dir *d, WIN32_FIND_DATA *wfd) | ||
| 124 | { | ||
| 125 | WIN32_FIND_DATA f; | ||
| 126 | |||
| 127 | d->uid = "nul"; | ||
| 128 | d->gid = "nul"; | ||
| 129 | d->muid = "nul"; | ||
| 130 | |||
| 131 | switch(pathtype(path)){ | ||
| 132 | case TPATH_VOLUME: | ||
| 133 | case TPATH_ROOT: | ||
| 134 | wfd = nil; | ||
| 135 | d->mode = 0777 | DMDIR; | ||
| 136 | d->atime = 0; | ||
| 137 | d->mtime = 0; | ||
| 138 | d->length = 0; | ||
| 139 | break; | ||
| 140 | |||
| 141 | case TPATH_FILE: | ||
| 142 | if(!wfd){ | ||
| 143 | HANDLE h; | ||
| 144 | if((h = FindFirstFile(path, &f))==INVALID_HANDLE_VALUE) | ||
| 145 | oserror(); | ||
| 146 | FindClose(h); | ||
| 147 | wfd = &f; | ||
| 148 | } | ||
| 149 | d->mode = wfdtodmode(wfd); | ||
| 150 | d->atime = unixtime(&wfd->ftLastAccessTime); | ||
| 151 | d->mtime = unixtime(&wfd->ftLastWriteTime); | ||
| 152 | d->length = ((uvlong)wfd->nFileSizeHigh << 32)|((uvlong)wfd->nFileSizeLow); | ||
| 153 | break; | ||
| 154 | } | ||
| 155 | d->qid = wfdtoqid(path, wfd); | ||
| 156 | } | ||
| 64 | 157 | ||
| 65 | /* clumsy hack, but not worse than the Path stuff in the last one */ | 158 | /* clumsy hack, but not worse than the Path stuff in the last one */ |
| 66 | static char* | 159 | static char* |
| @@ -69,10 +162,12 @@ uc2name(Chan *c) · 2 unmodified lines | |||
| 69 | char *s; | 162 | char *s; |
| 70 | 163 | ||
| 71 | if(c->name == nil) | 164 | if(c->name == nil) |
| 72 | return "/"; | 165 | return ""; |
| 73 | s = c2name(c); | 166 | s = c2name(c); |
| 74 | if(s[0]=='#' && s[1]=='U') | 167 | if(s[0]=='#' && s[1]=='U') |
| 75 | return s+2; | 168 | s += 2; |
| 169 | if(*s=='/') | ||
| 170 | s++; | ||
| 76 | return s; | 171 | return s; |
| 77 | } | 172 | } |
| 78 | 173 | ||
| @@ -88,29 +183,69 @@ lastelem(Chan *c) · 9 unmodified lines | |||
| 88 | return t; | 183 | return t; |
| 89 | return t+1; | 184 | return t+1; |
| 90 | } | 185 | } |
| 186 | |||
| 187 | static ulong | ||
| 188 | pathtype(TCHAR *path) | ||
| 189 | { | ||
| 190 | int n; | ||
| 191 | n = wcslen(path); | ||
| 192 | if(n < 2){ | ||
| 193 | return TPATH_ROOT; | ||
| 194 | } | ||
| 195 | if(n==2){ | ||
| 196 | return TPATH_VOLUME; | ||
| 197 | } | ||
| 198 | return TPATH_FILE; | ||
| 199 | } | ||
| 200 | |||
| 201 | static int | ||
| 202 | checkvolume(TCHAR *path) | ||
| 203 | { | ||
| 204 | TCHAR vol[MAX_PATH]; | ||
| 205 | TCHAR volname[MAX_PATH]; | ||
| 206 | TCHAR fsysname[MAX_PATH]; | ||
| 207 | DWORD complen; | ||
| 208 | DWORD flags; | ||
| 209 | |||
| 210 | wcsncpy(vol, path, MAX_PATH); | ||
| 211 | #ifdef UNICODE | ||
| 212 | wcsncat(vol, L"\\", MAXPATH); | ||
| 213 | #else | ||
| 214 | wcsncat(vol, "\\", MAXPATH); | ||
| 215 | #endif | ||
| 216 | |||
| 217 | if(!GetVolumeInformation( | ||
| 218 | vol, | ||
| 219 | volname, | ||
| 220 | MAX_PATH, | ||
| 221 | NULL, | ||
| 222 | &complen, | ||
| 223 | &flags, | ||
| 224 | fsysname, | ||
| 225 | MAX_PATH)){ | ||
| 226 | return 0; | ||
| 227 | } | ||
| 228 | return 1; | ||
| 229 | } | ||
| 230 | |||
| 231 | static int | ||
| 232 | getfileowner(TCHAR *path, char *owner, int nowner) | ||
| 233 | { | ||
| 234 | strncpy(owner, "Bill", nowner); | ||
| 235 | return 1; | ||
| 236 | } | ||
| 91 | 237 | ||
| 92 | static Chan* | 238 | static Chan* |
| 93 | fsattach(char *spec) | 239 | fsattach(char *spec) |
| 94 | { | 240 | { |
| 95 | Chan *c; | 241 | Chan *c; |
| 96 | struct stat stbuf; | ||
| 97 | static int devno; | 242 | static int devno; |
| 98 | Ufsinfo *uif; | 243 | Ufsinfo *uif; |
| 99 | |||
| 100 | if(stat(base, &stbuf) < 0) | ||
| 101 | error(strerror(errno)); | ||
| 102 | |||
| 103 | c = devattach('U', spec); | 244 | c = devattach('U', spec); |
| 104 | |||
| 105 | uif = mallocz(sizeof(Ufsinfo), 1); | 245 | uif = mallocz(sizeof(Ufsinfo), 1); |
| 106 | uif->gid = stbuf.st_gid; | ||
| 107 | uif->uid = stbuf.st_uid; | ||
| 108 | uif->mode = stbuf.st_mode; | ||
| 109 | |||
| 110 | c->aux = uif; | 246 | c->aux = uif; |
| 111 | c->dev = devno++; | 247 | c->dev = devno++; |
| 112 | c->qid.type = QTDIR; | 248 | c->qid.type = QTDIR; |
| 113 | /*print("fsattach %s\n", c2name(c));*/ | ||
| 114 | 249 | ||
| 115 | return c; | 250 | return c; |
| 116 | } | 251 | } |
| @@ -130,25 +265,27 @@ fsclone(Chan *c, Chan *nc) · 13 unmodified lines | |||
| 130 | static int | 265 | static int |
| 131 | fswalk1(Chan *c, char *name) | 266 | fswalk1(Chan *c, char *name) |
| 132 | { | 267 | { |
| 133 | struct stat stbuf; | 268 | HANDLE h; |
| 134 | char path[MAXPATH]; | 269 | WIN32_FIND_DATA wfd; |
| 135 | Ufsinfo *uif; | 270 | TCHAR path[MAXPATH]; |
| 136 | 271 | ||
| 137 | fspath(c, name, path); | 272 | fspath(c, name, path, MAXPATH); |
| 138 | |||
| 139 | /* print("** fs walk '%s' -> %s\n", path, name); */ | ||
| 140 | |||
| 141 | if(stat(path, &stbuf) < 0) | ||
| 142 | return 0; | ||
| 143 | 273 | ||
| 144 | uif = c->aux; | 274 | switch(pathtype(path)){ |
| 145 | 275 | case TPATH_VOLUME: | |
| 146 | uif->gid = stbuf.st_gid; | 276 | if(!checkvolume(path)) |
| 147 | uif->uid = stbuf.st_uid; | 277 | return 0; |
| 148 | uif->mode = stbuf.st_mode; | 278 | case TPATH_ROOT: |
| 149 | 279 | c->qid = wfdtoqid(path, nil); | |
| 150 | c->qid = fsqid(path, &stbuf); | 280 | break; |
| 151 | 281 | ||
| 282 | case TPATH_FILE: | ||
| 283 | if((h = FindFirstFile(path, &wfd)) == INVALID_HANDLE_VALUE) | ||
| 284 | return 0; | ||
| 285 | FindClose(h); | ||
| 286 | c->qid = wfdtoqid(path, &wfd); | ||
| 287 | break; | ||
| 288 | } | ||
| 152 | return 1; | 289 | return 1; |
| 153 | } | 290 | } |
| 154 | 291 | ||
| @@ -190,25 +327,21 @@ static int · 35 unmodified lines | |||
| 190 | fsstat(Chan *c, uchar *buf, int n) | 327 | fsstat(Chan *c, uchar *buf, int n) |
| 191 | { | 328 | { |
| 192 | Dir d; | 329 | Dir d; |
| 193 | struct stat stbuf; | 330 | TCHAR path[MAXPATH]; |
| 194 | char path[MAXPATH]; | 331 | char owner[MAXPATH]; |
| 195 | 332 | ||
| 196 | if(n < BIT16SZ) | 333 | if(n < BIT16SZ) |
| 197 | error(Eshortstat); | 334 | error(Eshortstat); |
| 335 | fspath(c, 0, path, MAXPATH); | ||
| 336 | d.name = lastelem(c); | ||
| 337 | wfdtodir(path, &d, nil); | ||
| 198 | 338 | ||
| 199 | fspath(c, 0, path); | 339 | if(getfileowner(path, owner, MAXPATH)){ |
| 200 | if(stat(path, &stbuf) < 0) | 340 | d.uid = owner; |
| 201 | error(strerror(errno)); | 341 | d.gid = owner; |
| 342 | d.muid = owner; | ||
| 343 | } | ||
| 202 | 344 | ||
| 203 | d.name = lastelem(c); | ||
| 204 | d.uid = "unknown"; | ||
| 205 | d.gid = "unknown"; | ||
| 206 | d.muid = "unknown"; | ||
| 207 | d.qid = c->qid; | ||
| 208 | d.mode = (c->qid.type<<24)|(stbuf.st_mode&0777); | ||
| 209 | d.atime = stbuf.st_atime; | ||
| 210 | d.mtime = stbuf.st_mtime; | ||
| 211 | d.length = stbuf.st_size; | ||
| 212 | d.type = 'U'; | 345 | d.type = 'U'; |
| 213 | d.dev = c->dev; | 346 | d.dev = c->dev; |
| 214 | return convD2M(&d, buf, n); | 347 | return convD2M(&d, buf, n); |
| @@ -217,11 +350,11 @@ fsstat(Chan *c, uchar *buf, int n) · 2 unmodified lines | |||
| 217 | static Chan* | 350 | static Chan* |
| 218 | fsopen(Chan *c, int mode) | 351 | fsopen(Chan *c, int mode) |
| 219 | { | 352 | { |
| 220 | char path[MAXPATH]; | 353 | TCHAR path[MAXPATH]; |
| 354 | ulong t; | ||
| 221 | int m, isdir; | 355 | int m, isdir; |
| 222 | Ufsinfo *uif; | 356 | Ufsinfo *uif; |
| 223 | 357 | ||
| 224 | /*print("fsopen %s\n", c2name(c));*/ | ||
| 225 | m = mode & (OTRUNC|3); | 358 | m = mode & (OTRUNC|3); |
| 226 | switch(m) { | 359 | switch(m) { |
| 227 | case 0: | 360 | case 0: |
| @@ -240,31 +373,55 @@ fsopen(Chan *c, int mode) · 12 unmodified lines | |||
| 240 | } | 373 | } |
| 241 | 374 | ||
| 242 | isdir = c->qid.type & QTDIR; | 375 | isdir = c->qid.type & QTDIR; |
| 243 | |||
| 244 | if(isdir && mode != OREAD) | 376 | if(isdir && mode != OREAD) |
| 245 | error(Eperm); | 377 | error(Eperm); |
| 246 | |||
| 247 | m = fsomode(m & 3); | 378 | m = fsomode(m & 3); |
| 248 | c->mode = openmode(mode); | 379 | c->mode = openmode(mode); |
| 249 | |||
| 250 | uif = c->aux; | 380 | uif = c->aux; |
| 251 | |||
| 252 | fspath(c, 0, path); | ||
| 253 | if(isdir) { | ||
| 254 | uif->dir = opendir(path); | ||
| 255 | if(uif->dir == 0) | ||
| 256 | error(strerror(errno)); | ||
| 257 | } | ||
| 258 | else { | ||
| 259 | if(mode & OTRUNC) | ||
| 260 | m |= O_TRUNC; | ||
| 261 | uif->fd = open(path, m|_O_BINARY, 0666); | ||
| 262 | |||
| 263 | if(uif->fd < 0) | ||
| 264 | error(strerror(errno)); | ||
| 265 | } | ||
| 266 | uif->offset = 0; | 381 | uif->offset = 0; |
| 267 | 382 | fspath(c, 0, path, MAXPATH); | |
| 383 | t = pathtype(path); | ||
| 384 | if(isdir){ | ||
| 385 | DIR *d; | ||
| 386 | d = malloc(sizeof(*d)); | ||
| 387 | switch(t){ | ||
| 388 | case TPATH_ROOT: | ||
| 389 | d->drivebuf = malloc(sizeof(TCHAR)*MAX_PATH); | ||
| 390 | if(GetLogicalDriveStrings(MAX_PATH-1, d->drivebuf) == 0){ | ||
| 391 | free(d->drivebuf); | ||
| 392 | d->drivebuf = nil; | ||
| 393 | oserror(); | ||
| 394 | } | ||
| 395 | d->drivep = d->drivebuf; | ||
| 396 | break; | ||
| 397 | case TPATH_VOLUME: | ||
| 398 | case TPATH_FILE: | ||
| 399 | #ifdef UNICODE | ||
| 400 | wcsncat(path, L"\\*.*", MAXPATH); | ||
| 401 | #else | ||
| 402 | wcsncat(path, "\\*.*", MAXPATH); | ||
| 403 | #endif | ||
| 404 | if((d->handle = FindFirstFile(path, &d->wfd)) == INVALID_HANDLE_VALUE){ | ||
| 405 | free(d); | ||
| 406 | oserror(); | ||
| 407 | } | ||
| 408 | break; | ||
| 409 | } | ||
| 410 | d->keep = 1; | ||
| 411 | uif->dir = d; | ||
| 412 | } else { | ||
| 413 | uif->dir = nil; | ||
| 414 | if((uif->fh = CreateFile( | ||
| 415 | path, | ||
| 416 | fsaccess(mode), | ||
| 417 | FILE_SHARE_READ | FILE_SHARE_WRITE, | ||
| 418 | NULL, | ||
| 419 | (mode & OTRUNC) ? TRUNCATE_EXISTING : OPEN_EXISTING, | ||
| 420 | FILE_ATTRIBUTE_NORMAL, | ||
| 421 | 0)) == INVALID_HANDLE_VALUE){ | ||
| 422 | oserror(); | ||
| 423 | } | ||
| 424 | } | ||
| 268 | c->offset = 0; | 425 | c->offset = 0; |
| 269 | c->flag |= COPEN; | 426 | c->flag |= COPEN; |
| 270 | return c; | 427 | return c; |
| @@ -273,82 +430,88 @@ fsopen(Chan *c, int mode) · 2 unmodified lines | |||
| 273 | static void | 430 | static void |
| 274 | fscreate(Chan *c, char *name, int mode, ulong perm) | 431 | fscreate(Chan *c, char *name, int mode, ulong perm) |
| 275 | { | 432 | { |
| 276 | int fd, m; | 433 | int m; |
| 277 | char path[MAXPATH]; | 434 | TCHAR path[MAXPATH]; |
| 278 | struct stat stbuf; | ||
| 279 | Ufsinfo *uif; | 435 | Ufsinfo *uif; |
| 436 | ulong t; | ||
| 280 | 437 | ||
| 281 | m = fsomode(mode&3); | 438 | m = fsomode(mode&3); |
| 282 | 439 | ||
| 283 | fspath(c, name, path); | 440 | fspath(c, name, path, MAXPATH); |
| 441 | t = pathtype(path); | ||
| 284 | 442 | ||
| 285 | uif = c->aux; | 443 | uif = c->aux; |
| 286 | 444 | ||
| 287 | if(perm & DMDIR) { | 445 | if(perm & DMDIR) { |
| 288 | if(m) | 446 | TCHAR *p; |
| 447 | DIR *d; | ||
| 448 | if(m || t!=TPATH_FILE) | ||
| 289 | error(Eperm); | 449 | error(Eperm); |
| 290 | 450 | if(!CreateDirectory(path, NULL)) | |
| 291 | if(mkdir(path) < 0) | 451 | oserror(); |
| 292 | error(strerror(errno)); | 452 | d = malloc(sizeof(*d)); |
| 293 | 453 | p = &path[wcslen(path)]; | |
| 294 | fd = open(path, 0); | 454 | #ifdef UNICODE |
| 295 | if(fd >= 0) { | 455 | wcsncat(path, L"\\*.*", MAXPATH); |
| 296 | chmod(path, perm & 0777); | 456 | #else |
| 297 | chown(path, uif->uid, uif->uid); | 457 | wcsncat(path, "\\*.*", MAXPATH); |
| 298 | } | 458 | #endif |
| 299 | close(fd); | 459 | if((d->handle = FindFirstFile(path, &d->wfd)) == INVALID_HANDLE_VALUE){ |
| 300 | 460 | free(d); | |
| 301 | uif->dir = opendir(path); | 461 | oserror(); |
| 302 | if(uif->dir == 0) | ||
| 303 | error(strerror(errno)); | ||
| 304 | } | ||
| 305 | else { | ||
| 306 | fd = open(path, _O_WRONLY|_O_BINARY|_O_CREAT|_O_TRUNC, 0666); | ||
| 307 | if(fd >= 0) { | ||
| 308 | if(m != 1) { | ||
| 309 | close(fd); | ||
| 310 | fd = open(path, m|_O_BINARY); | ||
| 311 | } | ||
| 312 | chmod(path, perm & 0777); | ||
| 313 | chown(path, uif->uid, uif->gid); | ||
| 314 | } | 462 | } |
| 315 | if(fd < 0) | 463 | *p = 0; |
| 316 | error(strerror(errno)); | 464 | d->keep = 1; |
| 317 | uif->fd = fd; | 465 | uif->dir = d; |
| 466 | } else { | ||
| 467 | uif->dir = nil; | ||
| 468 | if((uif->fh = CreateFile( | ||
| 469 | path, | ||
| 470 | fsaccess(mode), | ||
| 471 | FILE_SHARE_READ | FILE_SHARE_WRITE, | ||
| 472 | NULL, | ||
| 473 | CREATE_NEW, | ||
| 474 | FILE_ATTRIBUTE_NORMAL, | ||
| 475 | 0)) == INVALID_HANDLE_VALUE){ | ||
| 476 | oserror(); | ||
| 477 | } | ||
| 318 | } | 478 | } |
| 319 | 479 | c->qid = wfdtoqid(path, nil); | |
| 320 | if(stat(path, &stbuf) < 0) | ||
| 321 | error(strerror(errno)); | ||
| 322 | c->qid = fsqid(path, &stbuf); | ||
| 323 | c->offset = 0; | 480 | c->offset = 0; |
| 324 | c->flag |= COPEN; | 481 | c->flag |= COPEN; |
| 325 | c->mode = openmode(mode); | 482 | c->mode = openmode(mode); |
| 326 | } | 483 | } |
| 327 | 484 | ||
| 485 | |||
| 328 | static void | 486 | static void |
| 329 | fsclose(Chan *c) | 487 | fsclose(Chan *c) |
| 330 | { | 488 | { |
| 331 | Ufsinfo *uif; | 489 | Ufsinfo *uif; |
| 332 | 490 | ||
| 333 | uif = c->aux; | 491 | uif = c->aux; |
| 334 | |||
| 335 | if(c->flag & COPEN) { | 492 | if(c->flag & COPEN) { |
| 336 | if(c->qid.type & QTDIR) | 493 | if(uif->dir){ |
| 337 | closedir(uif->dir); | 494 | if(uif->dir->drivebuf){ |
| 338 | else | 495 | free(uif->dir->drivebuf); |
| 339 | close(uif->fd); | 496 | uif->dir->drivebuf = nil; |
| 497 | } else { | ||
| 498 | FindClose(uif->dir->handle); | ||
| 499 | free(uif->dir); | ||
| 500 | } | ||
| 501 | } else { | ||
| 502 | CloseHandle(uif->fh); | ||
| 503 | } | ||
| 340 | } | 504 | } |
| 341 | |||
| 342 | free(uif); | 505 | free(uif); |
| 343 | } | 506 | } |
| 344 | 507 | ||
| 345 | static long | 508 | static long |
| 346 | fsread(Chan *c, void *va, long n, vlong offset) | 509 | fsread(Chan *c, void *va, long n, vlong offset) |
| 347 | { | 510 | { |
| 348 | int fd, r; | 511 | HANDLE fh; |
| 512 | DWORD r; | ||
| 349 | Ufsinfo *uif; | 513 | Ufsinfo *uif; |
| 350 | 514 | ||
| 351 | /*print("fsread %s\n", c2name(c));*/ | ||
| 352 | if(c->qid.type & QTDIR) | 515 | if(c->qid.type & QTDIR) |
| 353 | return fsdirread(c, va, n, offset); | 516 | return fsdirread(c, va, n, offset); |
| 354 | 517 | ||
| @@ -358,166 +521,158 @@ fsread(Chan *c, void *va, long n, vlong offset) · 3 unmodified lines | |||
| 358 | qunlock(&uif->oq); | 521 | qunlock(&uif->oq); |
| 359 | nexterror(); | 522 | nexterror(); |
| 360 | } | 523 | } |
| 361 | fd = uif->fd; | 524 | fh = uif->fh; |
| 362 | if(uif->offset != offset) { | 525 | if(uif->offset != offset) { |
| 363 | r = lseek(fd, offset, 0); | 526 | LONG high; |
| 364 | if(r < 0) | 527 | high = offset>>32; |
| 365 | error(strerror(errno)); | 528 | offset = SetFilePointer(fh, (LONG)(offset & 0xFFFFFFFF), &high, FILE_BEGIN); |
| 529 | offset |= (vlong)high<<32; | ||
| 366 | uif->offset = offset; | 530 | uif->offset = offset; |
| 367 | } | 531 | } |
| 368 | 532 | r = 0; | |
| 369 | n = read(fd, va, n); | 533 | if(!ReadFile(fh, va, (DWORD)n, &r, NULL)){ |
| 370 | if(n < 0) | 534 | oserror(); |
| 371 | error(strerror(errno)); | 535 | } |
| 372 | 536 | n = r; | |
| 373 | uif->offset += n; | 537 | uif->offset += n; |
| 374 | qunlock(&uif->oq); | 538 | qunlock(&uif->oq); |
| 375 | poperror(); | 539 | poperror(); |
| 376 | |||
| 377 | return n; | 540 | return n; |
| 378 | } | 541 | } |
| 379 | 542 | ||
| 380 | static long | 543 | static long |
| 381 | fswrite(Chan *c, void *va, long n, vlong offset) | 544 | fswrite(Chan *c, void *va, long n, vlong offset) |
| 382 | { | 545 | { |
| 383 | int fd, r; | 546 | HANDLE fh; |
| 547 | DWORD w; | ||
| 384 | Ufsinfo *uif; | 548 | Ufsinfo *uif; |
| 385 | 549 | ||
| 386 | uif = c->aux; | 550 | if(c->qid.type & QTDIR) |
| 551 | return fsdirread(c, va, n, offset); | ||
| 387 | 552 | ||
| 553 | uif = c->aux; | ||
| 388 | qlock(&uif->oq); | 554 | qlock(&uif->oq); |
| 389 | if(waserror()) { | 555 | if(waserror()) { |
| 390 | qunlock(&uif->oq); | 556 | qunlock(&uif->oq); |
| 391 | nexterror(); | 557 | nexterror(); |
| 392 | } | 558 | } |
| 393 | fd = uif->fd; | 559 | fh = uif->fh; |
| 394 | if(uif->offset != offset) { | 560 | if(uif->offset != offset) { |
| 395 | r = lseek(fd, offset, 0); | 561 | LONG high; |
| 396 | if(r < 0) | 562 | high = offset>>32; |
| 397 | error(strerror(errno)); | 563 | offset = SetFilePointer(fh, (LONG)(offset & 0xFFFFFFFF), &high, FILE_BEGIN); |
| 564 | offset |= (vlong)high<<32; | ||
| 398 | uif->offset = offset; | 565 | uif->offset = offset; |
| 399 | } | 566 | } |
| 400 | 567 | w = 0; | |
| 401 | n = write(fd, va, n); | 568 | if(!WriteFile(fh, va, (DWORD)n, &w, NULL)){ |
| 402 | if(n < 0) | 569 | oserror(); |
| 403 | error(strerror(errno)); | 570 | } |
| 404 | 571 | n = w; | |
| 405 | uif->offset += n; | 572 | uif->offset += n; |
| 406 | qunlock(&uif->oq); | 573 | qunlock(&uif->oq); |
| 407 | poperror(); | 574 | poperror(); |
| 408 | |||
| 409 | return n; | 575 | return n; |
| 410 | } | 576 | } |
| 411 | 577 | ||
| 412 | static void | 578 | static void |
| 413 | fsremove(Chan *c) | 579 | fsremove(Chan *c) |
| 414 | { | 580 | { |
| 415 | int n; | 581 | TCHAR path[MAXPATH]; |
| 416 | char path[MAXPATH]; | 582 | |
| 417 | 583 | fspath(c, 0, path, MAXPATH); | |
| 418 | fspath(c, 0, path); | 584 | if(c->qid.type & QTDIR){ |
| 419 | if(c->qid.type & QTDIR) | 585 | if(!RemoveDirectory(path)) |
| 420 | n = rmdir(path); | 586 | error("RemoveDirectory..."); |
| 421 | else | 587 | } else { |
| 422 | n = remove(path); | 588 | if(!DeleteFile(path)) |
| 423 | if(n < 0) | 589 | error("DeleteFile..."); |
| 424 | error(strerror(errno)); | 590 | } |
| 425 | } | 591 | } |
| 426 | 592 | ||
| 427 | static int | 593 | static int |
| 428 | fswstat(Chan *c, uchar *buf, int n) | 594 | fswstat(Chan *c, uchar *buf, int n) |
| 429 | { | 595 | { |
| 596 | TCHAR path[MAXPATH]; | ||
| 597 | char strs[MAXPATH*3]; | ||
| 430 | Dir d; | 598 | Dir d; |
| 431 | struct stat stbuf; | 599 | ulong t; |
| 432 | char old[MAXPATH], new[MAXPATH]; | ||
| 433 | char strs[MAXPATH*3], *p; | ||
| 434 | Ufsinfo *uif; | ||
| 435 | 600 | ||
| 436 | if (convM2D(buf, n, &d, strs) != n) | 601 | if (convM2D(buf, n, &d, strs) != n) |
| 437 | error(Ebadstat); | 602 | error(Ebadstat); |
| 438 | 603 | fspath(c, 0, path, MAXPATH); | |
| 439 | fspath(c, 0, old); | 604 | t = pathtype(path); |
| 440 | if(stat(old, &stbuf) < 0) | 605 | if(t != TPATH_FILE) |
| 441 | error(strerror(errno)); | 606 | error(Ebadstat); |
| 442 | 607 | /* change name */ | |
| 443 | uif = c->aux; | 608 | if(d.name[0]){ |
| 444 | 609 | int l; | |
| 445 | // if(uif->uid != stbuf.st_uid) | 610 | TCHAR newpath[MAXPATH]; |
| 446 | // error(Eowner); | 611 | wcsncpy(newpath, path, MAXPATH); |
| 447 | 612 | ||
| 448 | if(d.name[0] && strcmp(d.name, lastelem(c)) != 0) { | 613 | /* replace last path-element with d.name */ |
| 449 | fspath(c, 0, old); | 614 | l = wcslen(newpath)-1; |
| 450 | strcpy(new, old); | 615 | if(l <= 0) |
| 451 | p = strrchr(new, '/'); | 616 | error(Ebadstat); |
| 452 | strcpy(p+1, d.name); | 617 | for(;l>0; l--){ |
| 453 | if(rename(old, new) < 0) | 618 | if(newpath[l-1]=='\\') |
| 454 | error(strerror(errno)); | 619 | break; |
| 455 | } | 620 | } |
| 456 | 621 | if(l <= 0) | |
| 457 | fspath(c, 0, old); | 622 | error(Ebadstat); |
| 458 | if(~d.mode != 0 && (int)(d.mode&0777) != (int)(stbuf.st_mode&0777)) { | 623 | newpath[l] = 0; |
| 459 | if(chmod(old, d.mode&0777) < 0) | 624 | #ifdef UNICODE |
| 460 | error(strerror(errno)); | 625 | if(!MultiByteToWideChar(CP_UTF8,0,d.name,-1,&newpath[l],MAXPATH-l-1)) |
| 461 | uif->mode &= ~0777; | 626 | oserror(); |
| 462 | uif->mode |= d.mode&0777; | 627 | #else |
| 628 | wcsncpy(&newpath[l], d.name, MAXPATH-l-1); | ||
| 629 | #endif | ||
| 630 | if(wcscmp(path, newpath)!=0){ | ||
| 631 | if(!MoveFile(path, newpath)) | ||
| 632 | oserror(); | ||
| 633 | wcsncpy(path, newpath, MAXPATH); | ||
| 634 | } | ||
| 463 | } | 635 | } |
| 464 | /* | ||
| 465 | p = name2pass(gid, d.gid); | ||
| 466 | if(p == 0) | ||
| 467 | error(Eunknown); | ||
| 468 | |||
| 469 | if(p->id != stbuf.st_gid) { | ||
| 470 | if(chown(old, stbuf.st_uid, p->id) < 0) | ||
| 471 | error(sys_errlist[errno]); | ||
| 472 | 636 | ||
| 473 | uif->gid = p->id; | 637 | /* fixme: change attributes */ |
| 474 | } | 638 | c->qid = wfdtoqid(path, nil); |
| 475 | */ | 639 | return n; |
| 476 | return n; | ||
| 477 | } | 640 | } |
| 478 | 641 | ||
| 479 | static Qid | ||
| 480 | fsqid(char *p, struct stat *st) | ||
| 481 | { | ||
| 482 | Qid q; | ||
| 483 | int dev; | ||
| 484 | ulong h; | ||
| 485 | static int nqdev; | ||
| 486 | static uchar *qdev; | ||
| 487 | |||
| 488 | if(qdev == 0) | ||
| 489 | qdev = mallocz(65536U, 1); | ||
| 490 | |||
| 491 | q.type = 0; | ||
| 492 | if((st->st_mode&S_IFMT) == S_IFDIR) | ||
| 493 | q.type = QTDIR; | ||
| 494 | |||
| 495 | dev = st->st_dev & 0xFFFFUL; | ||
| 496 | if(qdev[dev] == 0) | ||
| 497 | qdev[dev] = ++nqdev; | ||
| 498 | |||
| 499 | h = 0; | ||
| 500 | while(*p != '\0') | ||
| 501 | h += *p++ * 13; | ||
| 502 | |||
| 503 | q.path = (vlong)qdev[dev]<<32; | ||
| 504 | q.path |= h; | ||
| 505 | q.vers = st->st_mtime; | ||
| 506 | |||
| 507 | return q; | ||
| 508 | } | ||
| 509 | 642 | ||
| 510 | static void | 643 | static void |
| 511 | fspath(Chan *c, char *ext, char *path) | 644 | _fspath(Chan *c, char *ext, char *path, int npath) |
| 512 | { | 645 | { |
| 513 | strcpy(path, base); | 646 | *path = 0; |
| 514 | strcat(path, "/"); | 647 | strncat(path, uc2name(c), npath); |
| 515 | strcat(path, uc2name(c)); | ||
| 516 | if(ext) { | 648 | if(ext) { |
| 517 | strcat(path, "/"); | 649 | if(*path) |
| 518 | strcat(path, ext); | 650 | strncat(path, "/", npath); |
| 651 | strncat(path, ext, npath); | ||
| 519 | } | 652 | } |
| 520 | cleanname(path); | 653 | cleanname(path); |
| 654 | if(*path == '.') | ||
| 655 | *path = 0; | ||
| 656 | } | ||
| 657 | |||
| 658 | static void | ||
| 659 | fspath(Chan *c, char *ext, TCHAR *path, int npath) | ||
| 660 | { | ||
| 661 | TCHAR *p; | ||
| 662 | #ifdef UNICODE | ||
| 663 | char buf[MAXPATH]; | ||
| 664 | _fspath(c, ext, buf, sizeof(buf)); | ||
| 665 | if(!MultiByteToWideChar(CP_UTF8,0,buf,-1,path,npath)){ | ||
| 666 | oserror(); | ||
| 667 | } | ||
| 668 | #else | ||
| 669 | _fspath(c, ext, path, npath); | ||
| 670 | #endif | ||
| 671 | /* make a DOS path */ | ||
| 672 | for(p=path; *p; p++){ | ||
| 673 | if(*p == '/') | ||
| 674 | *p = '\\'; | ||
| 675 | } | ||
| 521 | } | 676 | } |
| 522 | 677 | ||
| 523 | static int | 678 | static int |
| @@ -534,78 +689,116 @@ isdots(char *name) · 10 unmodified lines | |||
| 534 | return 0; | 689 | return 0; |
| 535 | } | 690 | } |
| 536 | 691 | ||
| 537 | static int | ||
| 538 | p9readdir(char *name, Ufsinfo *uif) | ||
| 539 | { | ||
| 540 | if(uif->nextname[0]){ | ||
| 541 | strcpy(name, uif->nextname); | ||
| 542 | uif->nextname[0] = 0; | ||
| 543 | return 1; | ||
| 544 | } | ||
| 545 | |||
| 546 | return readdir(name, uif->dir); | ||
| 547 | } | ||
| 548 | |||
| 549 | static ulong | 692 | static ulong |
| 550 | fsdirread(Chan *c, uchar *va, int count, ulong offset) | 693 | fsdirread(Chan *c, uchar *va, int count, vlong offset) |
| 551 | { | 694 | { |
| 552 | int i; | 695 | int i; |
| 696 | ulong t; | ||
| 553 | Dir d; | 697 | Dir d; |
| 554 | long n; | 698 | long n; |
| 555 | char de[NAME_MAX]; | ||
| 556 | struct stat stbuf; | ||
| 557 | char path[MAXPATH], dirpath[MAXPATH]; | ||
| 558 | Ufsinfo *uif; | 699 | Ufsinfo *uif; |
| 700 | char de[MAX_PATH*3]; | ||
| 701 | int ndirpath; | ||
| 702 | TCHAR dirpath[MAXPATH]; | ||
| 559 | 703 | ||
| 560 | /*print("fsdirread %s\n", c2name(c));*/ | ||
| 561 | i = 0; | 704 | i = 0; |
| 562 | uif = c->aux; | 705 | uif = c->aux; |
| 563 | |||
| 564 | errno = 0; | 706 | errno = 0; |
| 707 | |||
| 708 | fspath(c, 0, dirpath, MAXPATH); | ||
| 709 | ndirpath = wcslen(dirpath); | ||
| 710 | t = pathtype(dirpath); | ||
| 711 | |||
| 565 | if(uif->offset != offset) { | 712 | if(uif->offset != offset) { |
| 566 | if(offset != 0) | 713 | if(offset != 0) |
| 567 | error("bad offset in fsdirread"); | 714 | error("bad offset in fsdirread"); |
| 568 | uif->offset = offset; /* sync offset */ | 715 | uif->offset = offset; /* sync offset */ |
| 569 | uif->nextname[0] = 0; | 716 | switch(t){ |
| 570 | rewinddir(uif->dir); | 717 | case TPATH_ROOT: |
| 718 | uif->dir->drivep = uif->dir->drivebuf; | ||
| 719 | break; | ||
| 720 | case TPATH_VOLUME: | ||
| 721 | case TPATH_FILE: | ||
| 722 | FindClose(uif->dir->handle); | ||
| 723 | #ifdef UNICODE | ||
| 724 | wcsncat(dirpath, L"\\*.*", MAXPATH); | ||
| 725 | #else | ||
| 726 | wcsncat(dirpath, "\\*.*", MAXPATH); | ||
| 727 | #endif | ||
| 728 | if((uif->dir->handle = FindFirstFile(dirpath, &uif->dir->wfd))==INVALID_HANDLE_VALUE){ | ||
| 729 | oserror(); | ||
| 730 | } | ||
| 731 | break; | ||
| 732 | } | ||
| 733 | uif->dir->keep = 1; | ||
| 571 | } | 734 | } |
| 572 | 735 | ||
| 573 | fspath(c, 0, dirpath); | ||
| 574 | |||
| 575 | while(i+BIT16SZ < count) { | 736 | while(i+BIT16SZ < count) { |
| 576 | if(!p9readdir(de, uif)) | 737 | char owner[MAXPATH]; |
| 577 | break; | 738 | |
| 578 | 739 | if(!uif->dir->keep) { | |
| 740 | switch(t){ | ||
| 741 | case TPATH_ROOT: | ||
| 742 | uif->dir->drivep += 4; | ||
| 743 | if(*uif->dir->drivep == 0) | ||
| 744 | goto out; | ||
| 745 | break; | ||
| 746 | case TPATH_VOLUME: | ||
| 747 | case TPATH_FILE: | ||
| 748 | if(!FindNextFile(uif->dir->handle, &uif->dir->wfd)) | ||
| 749 | goto out; | ||
| 750 | break; | ||
| 751 | } | ||
| 752 | } else { | ||
| 753 | uif->dir->keep = 0; | ||
| 754 | } | ||
| 755 | if(t == TPATH_ROOT){ | ||
| 756 | uif->dir->drivep[2] = 0; | ||
| 757 | #ifdef UNICODE | ||
| 758 | WideCharToMultiByte(CP_UTF8,0,uif->dir->drivep,-1,de,sizeof(de),0,0); | ||
| 759 | #else | ||
| 760 | strncpy(de, uif->dir->drivep, sizeof(de)); | ||
| 761 | #endif | ||
| 762 | } else { | ||
| 763 | #ifdef UNICODE | ||
| 764 | WideCharToMultiByte(CP_UTF8,0,uif->dir->wfd.cFileName,-1,de,sizeof(de),0,0); | ||
| 765 | #else | ||
| 766 | strncpy(de, uif->dir->wfd.cFileName, sizeof(de)); | ||
| 767 | #endif | ||
| 768 | } | ||
| 579 | if(de[0]==0 || isdots(de)) | 769 | if(de[0]==0 || isdots(de)) |
| 580 | continue; | 770 | continue; |
| 581 | |||
| 582 | d.name = de; | 771 | d.name = de; |
| 583 | sprint(path, "%s/%s", dirpath, de); | 772 | dirpath[ndirpath] = 0; |
| 584 | memset(&stbuf, 0, sizeof stbuf); | 773 | if(t == TPATH_ROOT){ |
| 774 | wcsncat(dirpath, uif->dir->drivep, MAXPATH); | ||
| 775 | wfdtodir(dirpath, &d, nil); | ||
| 776 | } else { | ||
| 777 | #ifdef UNICODE | ||
| 778 | wcsncat(dirpath, L"\\", MAXPATH); | ||
| 779 | #else | ||
| 780 | wcsncat(dirpath, "\\", MAXPATH); | ||
| 781 | #endif | ||
| 782 | wcsncat(dirpath, uif->dir->wfd.cFileName, MAXPATH); | ||
| 783 | wfdtodir(dirpath, &d, &uif->dir->wfd); | ||
| 784 | } | ||
| 585 | 785 | ||
| 586 | if(stat(path, &stbuf) < 0) { | 786 | if(getfileowner(dirpath, owner, MAXPATH)){ |
| 587 | print("dir: bad path %s\n", path); | 787 | d.uid = owner; |
| 588 | /* but continue... probably a bad symlink */ | 788 | d.gid = owner; |
| 789 | d.muid = owner; | ||
| 589 | } | 790 | } |
| 590 | 791 | ||
| 591 | d.uid = "unknown"; | ||
| 592 | d.gid = "unknown"; | ||
| 593 | d.muid = "unknown"; | ||
| 594 | d.qid = fsqid(path, &stbuf); | ||
| 595 | d.mode = (d.qid.type<<24)|(stbuf.st_mode&0777); | ||
| 596 | d.atime = stbuf.st_atime; | ||
| 597 | d.mtime = stbuf.st_mtime; | ||
| 598 | d.length = stbuf.st_size; | ||
| 599 | d.type = 'U'; | 792 | d.type = 'U'; |
| 600 | d.dev = c->dev; | 793 | d.dev = c->dev; |
| 601 | n = convD2M(&d, (uchar*)va+i, count-i); | 794 | n = convD2M(&d, (uchar*)va+i, count-i); |
| 602 | if(n == BIT16SZ){ | 795 | if(n == BIT16SZ){ |
| 603 | strcpy(uif->nextname, de); | 796 | uif->dir->keep = 1; |
| 604 | break; | 797 | break; |
| 605 | } | 798 | } |
| 606 | i += n; | 799 | i += n; |
| 607 | } | 800 | } |
| 608 | /*print("got %d\n", i);*/ | 801 | out: |
| 609 | uif->offset += i; | 802 | uif->offset += i; |
| 610 | return i; | 803 | return i; |
| 611 | } | 804 | } |
| @@ -625,65 +818,29 @@ fsomode(int m) · 13 unmodified lines | |||
| 625 | error(Ebadarg); | 818 | error(Ebadarg); |
| 626 | return 0; | 819 | return 0; |
| 627 | } | 820 | } |
| 628 | void | ||
| 629 | closedir(DIR *d) | ||
| 630 | { | ||
| 631 | FindClose(d->handle); | ||
| 632 | free(d->path); | ||
| 633 | } | ||
| 634 | 821 | ||
| 635 | int | 822 | static ulong |
| 636 | readdir(char *name, DIR *d) | 823 | fsaccess(int m) |
| 637 | { | 824 | { |
| 638 | if(d->index != 0) { | 825 | ulong a; |
| 639 | if(FindNextFile(d->handle, &d->wfd) == FALSE) | 826 | a = 0; |
| 640 | return 0; | 827 | switch(m & 3){ |
| 828 | default: | ||
| 829 | error(Eperm); | ||
| 830 | break; | ||
| 831 | case OREAD: | ||
| 832 | a = GENERIC_READ; | ||
| 833 | break; | ||
| 834 | case OWRITE: | ||
| 835 | a = GENERIC_WRITE; | ||
| 836 | break; | ||
| 837 | case ORDWR: | ||
| 838 | a = GENERIC_READ | GENERIC_WRITE; | ||
| 839 | break; | ||
| 641 | } | 840 | } |
| 642 | strcpy(name, (char*)d->wfd.cFileName); | 841 | return a; |
| 643 | d->index++; | ||
| 644 | |||
| 645 | return 1; | ||
| 646 | } | ||
| 647 | |||
| 648 | void | ||
| 649 | rewinddir(DIR *d) | ||
| 650 | { | ||
| 651 | FindClose(d->handle); | ||
| 652 | d->handle = FindFirstFile(d->path, &d->wfd); | ||
| 653 | d->index = 0; | ||
| 654 | } | ||
| 655 | |||
| 656 | static int | ||
| 657 | chown(char *path, int uid, int perm) | ||
| 658 | { | ||
| 659 | /* panic("chown"); */ | ||
| 660 | return 0; | ||
| 661 | } | 842 | } |
| 662 | 843 | ||
| 663 | DIR* | ||
| 664 | opendir(char *p) | ||
| 665 | { | ||
| 666 | DIR *d; | ||
| 667 | char path[MAX_PATH]; | ||
| 668 | |||
| 669 | |||
| 670 | snprint(path, sizeof(path), "%s/*.*", p); | ||
| 671 | |||
| 672 | d = mallocz(sizeof(DIR), 1); | ||
| 673 | if(d == 0) | ||
| 674 | return 0; | ||
| 675 | |||
| 676 | d->index = 0; | ||
| 677 | |||
| 678 | d->handle = FindFirstFile(path, &d->wfd); | ||
| 679 | if(d->handle == INVALID_HANDLE_VALUE) { | ||
| 680 | free(d); | ||
| 681 | return 0; | ||
| 682 | } | ||
| 683 | |||
| 684 | d->path = strdup(path); | ||
| 685 | return d; | ||
| 686 | } | ||
| 687 | 844 | ||
| 688 | Dev fsdevtab = { | 845 | Dev fsdevtab = { |
| 689 | 'U', | 846 | 'U', |