diff options
Diffstat (limited to 'uisimulator')
-rw-r--r-- | uisimulator/common/io.c | 72 |
1 files changed, 59 insertions, 13 deletions
diff --git a/uisimulator/common/io.c b/uisimulator/common/io.c index 9401f7d54a..179a919013 100644 --- a/uisimulator/common/io.c +++ b/uisimulator/common/io.c | |||
@@ -27,7 +27,9 @@ | |||
27 | #include <time.h> | 27 | #include <time.h> |
28 | #include <errno.h> | 28 | #include <errno.h> |
29 | #include "config.h" | 29 | #include "config.h" |
30 | #include "system.h" | ||
30 | #include "ata_idle_notify.h" | 31 | #include "ata_idle_notify.h" |
32 | #include "mv.h" | ||
31 | 33 | ||
32 | #define HAVE_STATVFS (!defined(WIN32)) | 34 | #define HAVE_STATVFS (!defined(WIN32)) |
33 | #define HAVE_LSTAT (!defined(WIN32)) | 35 | #define HAVE_LSTAT (!defined(WIN32)) |
@@ -124,7 +126,8 @@ extern int _wrmdir(const wchar_t*); | |||
124 | #define CLOSE(a) (close)(a) | 126 | #define CLOSE(a) (close)(a) |
125 | #define REMOVE(a) (_wremove)(UTF8_TO_OS(a)) | 127 | #define REMOVE(a) (_wremove)(UTF8_TO_OS(a)) |
126 | #define RENAME(a,b) (_wrename)(UTF8_TO_OS(a),utf8_to_ucs2(b,convbuf2)) | 128 | #define RENAME(a,b) (_wrename)(UTF8_TO_OS(a),utf8_to_ucs2(b,convbuf2)) |
127 | 129 | /* readlink isn't used in the sim yet (FIXME) */ | |
130 | #define READLINK(a,b,c) ({ fprintf(stderr, "no readlink on windows yet"); abort(); }) | ||
128 | #else /* !__MINGW32__ */ | 131 | #else /* !__MINGW32__ */ |
129 | 132 | ||
130 | #define UTF8_TO_OS(a) (a) | 133 | #define UTF8_TO_OS(a) (a) |
@@ -144,6 +147,7 @@ extern int _wrmdir(const wchar_t*); | |||
144 | #define CLOSE(x) (close)(x) | 147 | #define CLOSE(x) (close)(x) |
145 | #define REMOVE(a) (remove)(a) | 148 | #define REMOVE(a) (remove)(a) |
146 | #define RENAME(a,b) (rename)(a,b) | 149 | #define RENAME(a,b) (rename)(a,b) |
150 | #define READLINK(a,b,c) (readlink)(a,b,c) | ||
147 | 151 | ||
148 | #endif /* !__MINGW32__ */ | 152 | #endif /* !__MINGW32__ */ |
149 | 153 | ||
@@ -183,6 +187,7 @@ struct dirstruct { | |||
183 | 187 | ||
184 | struct mydir { | 188 | struct mydir { |
185 | DIR_T *dir; | 189 | DIR_T *dir; |
190 | IF_MV(int volumes_returned); | ||
186 | char *name; | 191 | char *name; |
187 | }; | 192 | }; |
188 | 193 | ||
@@ -323,6 +328,30 @@ ssize_t sim_write(int fd, const void *buf, size_t count) | |||
323 | } | 328 | } |
324 | 329 | ||
325 | #if !defined(APPLICATION) | 330 | #if !defined(APPLICATION) |
331 | |||
332 | static const char *handle_special_links(const char* link) | ||
333 | { | ||
334 | static char buffer[MAX_PATH]; /* sufficiently big */ | ||
335 | char vol_string[VOL_ENUM_POS + 8]; | ||
336 | int len = sprintf(vol_string, VOL_NAMES, 1); | ||
337 | |||
338 | /* link might be passed with or without HOME_DIR expanded. To handle | ||
339 | * both perform substring matching (VOL_NAMES is unique enough) */ | ||
340 | const char *begin = strstr(link, vol_string); | ||
341 | if (begin) | ||
342 | { | ||
343 | /* begin now points to the start of vol_string within link, | ||
344 | * we want to copy the remainder of the paths, prefixed by | ||
345 | * the actual mount point (the remainder might be "") */ | ||
346 | snprintf(buffer, sizeof(buffer), "%s/../simext/%s", | ||
347 | sim_root_dir ?: SIMULATOR_DEFAULT_ROOT, begin + len); | ||
348 | return buffer; | ||
349 | } | ||
350 | else | ||
351 | return link; | ||
352 | } | ||
353 | |||
354 | |||
326 | static const char *get_sim_pathname(const char *name) | 355 | static const char *get_sim_pathname(const char *name) |
327 | { | 356 | { |
328 | static char buffer[MAX_PATH]; /* sufficiently big */ | 357 | static char buffer[MAX_PATH]; /* sufficiently big */ |
@@ -330,13 +359,14 @@ static const char *get_sim_pathname(const char *name) | |||
330 | if(name[0] == '/') | 359 | if(name[0] == '/') |
331 | { | 360 | { |
332 | snprintf(buffer, sizeof(buffer), "%s%s", | 361 | snprintf(buffer, sizeof(buffer), "%s%s", |
333 | sim_root_dir != NULL ? sim_root_dir : SIMULATOR_DEFAULT_ROOT, name); | 362 | sim_root_dir ?: SIMULATOR_DEFAULT_ROOT, name); |
334 | return buffer; | 363 | return handle_special_links(buffer); |
335 | } | 364 | } |
336 | fprintf(stderr, "WARNING, bad file name lacks slash: %s\n", name); | 365 | fprintf(stderr, "WARNING, bad file name lacks slash: %s\n", name); |
337 | return name; | 366 | return name; |
338 | } | 367 | } |
339 | 368 | ||
369 | |||
340 | MYDIR *sim_opendir(const char *name) | 370 | MYDIR *sim_opendir(const char *name) |
341 | { | 371 | { |
342 | DIR_T *dir; | 372 | DIR_T *dir; |
@@ -348,6 +378,7 @@ MYDIR *sim_opendir(const char *name) | |||
348 | my->dir = dir; | 378 | my->dir = dir; |
349 | my->name = (char *)malloc(strlen(name)+1); | 379 | my->name = (char *)malloc(strlen(name)+1); |
350 | strcpy(my->name, name); | 380 | strcpy(my->name, name); |
381 | IF_MV(my->volumes_returned = 0); | ||
351 | 382 | ||
352 | return my; | 383 | return my; |
353 | } | 384 | } |
@@ -374,16 +405,34 @@ struct sim_dirent *sim_readdir(MYDIR *dir) | |||
374 | #ifdef EOVERFLOW | 405 | #ifdef EOVERFLOW |
375 | read_next: | 406 | read_next: |
376 | #endif | 407 | #endif |
377 | x11 = READDIR(dir->dir); | ||
378 | 408 | ||
379 | if(!x11) | 409 | #define ATTR_LINK 0x80 /* see dir.h */ |
380 | return (struct sim_dirent *)0; | 410 | |
411 | secret.info.attribute = 0; | ||
412 | #ifdef HAVE_MULTIVOLUME | ||
413 | if (dir->name[0] == '/' && dir->name[1] == '\0' | ||
414 | && dir->volumes_returned++ < (NUM_VOLUMES-1) | ||
415 | && volume_present(dir->volumes_returned)) | ||
416 | { | ||
417 | sprintf((char *)secret.d_name, VOL_NAMES, dir->volumes_returned); | ||
418 | secret.info.attribute = ATTR_LINK; | ||
419 | /* build file name for stat() which is the actual mount point */ | ||
420 | snprintf(buffer, sizeof(buffer), "%s/../simext", | ||
421 | sim_root_dir ?: SIMULATOR_DEFAULT_ROOT); | ||
422 | } | ||
423 | else | ||
424 | #endif | ||
425 | { | ||
426 | x11 = READDIR(dir->dir); | ||
381 | 427 | ||
382 | strcpy((char *)secret.d_name, OS_TO_UTF8(x11->d_name)); | 428 | if(!x11) |
429 | return (struct sim_dirent *)0; | ||
383 | 430 | ||
384 | /* build file name */ | 431 | strcpy((char *)secret.d_name, OS_TO_UTF8(x11->d_name)); |
385 | snprintf(buffer, sizeof(buffer), "%s/%s", | 432 | /* build file name for stat() */ |
386 | get_sim_pathname(dir->name), secret.d_name); | 433 | snprintf(buffer, sizeof(buffer), "%s/%s", |
434 | get_sim_pathname(dir->name), secret.d_name); | ||
435 | } | ||
387 | 436 | ||
388 | if (STAT(buffer, &s)) /* get info */ | 437 | if (STAT(buffer, &s)) /* get info */ |
389 | { | 438 | { |
@@ -401,8 +450,6 @@ read_next: | |||
401 | 450 | ||
402 | #define ATTR_DIRECTORY 0x10 | 451 | #define ATTR_DIRECTORY 0x10 |
403 | 452 | ||
404 | secret.info.attribute = 0; | ||
405 | |||
406 | if (S_ISDIR(s.st_mode)) | 453 | if (S_ISDIR(s.st_mode)) |
407 | secret.info.attribute = ATTR_DIRECTORY; | 454 | secret.info.attribute = ATTR_DIRECTORY; |
408 | 455 | ||
@@ -418,7 +465,6 @@ read_next: | |||
418 | (tm.tm_sec >> 1); | 465 | (tm.tm_sec >> 1); |
419 | 466 | ||
420 | #if HAVE_LSTAT | 467 | #if HAVE_LSTAT |
421 | #define ATTR_LINK 0x80 | ||
422 | if (!lstat(buffer, &s) && S_ISLNK(s.st_mode)) | 468 | if (!lstat(buffer, &s) && S_ISLNK(s.st_mode)) |
423 | { | 469 | { |
424 | secret.info.attribute |= ATTR_LINK; | 470 | secret.info.attribute |= ATTR_LINK; |