diff options
Diffstat (limited to 'firmware/common/file_internal.c')
-rw-r--r-- | firmware/common/file_internal.c | 48 |
1 files changed, 34 insertions, 14 deletions
diff --git a/firmware/common/file_internal.c b/firmware/common/file_internal.c index f9c6bfb570..aa0edb7ebb 100644 --- a/firmware/common/file_internal.c +++ b/firmware/common/file_internal.c | |||
@@ -292,7 +292,7 @@ struct pathwalk_component | |||
292 | struct pathwalk_component *nextp; /* parent if in use else next free */ | 292 | struct pathwalk_component *nextp; /* parent if in use else next free */ |
293 | }; | 293 | }; |
294 | 294 | ||
295 | #define WALK_RC_NOT_FOUND 0 /* successfully not found */ | 295 | #define WALK_RC_NOT_FOUND 0 /* successfully not found (aid for file creation) */ |
296 | #define WALK_RC_FOUND 1 /* found and opened */ | 296 | #define WALK_RC_FOUND 1 /* found and opened */ |
297 | #define WALK_RC_FOUND_ROOT 2 /* found and opened sys/volume root */ | 297 | #define WALK_RC_FOUND_ROOT 2 /* found and opened sys/volume root */ |
298 | #define WALK_RC_CONT_AT_ROOT 3 /* continue at root level */ | 298 | #define WALK_RC_CONT_AT_ROOT 3 /* continue at root level */ |
@@ -351,7 +351,10 @@ static int fill_path_compinfo(struct pathwalk *walkp, | |||
351 | compinfo->length = compp->length; | 351 | compinfo->length = compp->length; |
352 | compinfo->attr = compp->attr; | 352 | compinfo->attr = compp->attr; |
353 | compinfo->filesize = walkp->filesize; | 353 | compinfo->filesize = walkp->filesize; |
354 | compinfo->parentinfo = (compp->nextp ?: compp)->info; | 354 | if (!(walkp->callflags & FF_SELFINFO)) |
355 | compinfo->parentinfo = (compp->nextp ?: compp)->info; | ||
356 | else | ||
357 | compinfo->info = compp->info; | ||
355 | } | 358 | } |
356 | 359 | ||
357 | return rc; | 360 | return rc; |
@@ -393,7 +396,10 @@ static int walk_open_info(struct pathwalk *walkp, | |||
393 | else | 396 | else |
394 | callflags &= ~FO_DIRECTORY; | 397 | callflags &= ~FO_DIRECTORY; |
395 | 398 | ||
396 | fileop_onopen_internal(stream, &compp->info, callflags); | 399 | /* make open official if not simply probing for presence */ |
400 | if (!(callflags & FF_PROBE)) | ||
401 | fileop_onopen_internal(stream, &compp->info, callflags); | ||
402 | |||
397 | return compp->nextp ? WALK_RC_FOUND : WALK_RC_FOUND_ROOT; | 403 | return compp->nextp ? WALK_RC_FOUND : WALK_RC_FOUND_ROOT; |
398 | } | 404 | } |
399 | 405 | ||
@@ -511,7 +517,8 @@ walk_path(struct pathwalk *walkp, struct pathwalk_component *compp, | |||
511 | { | 517 | { |
512 | /* is ".." */ | 518 | /* is ".." */ |
513 | struct pathwalk_component *parentp = compp->nextp; | 519 | struct pathwalk_component *parentp = compp->nextp; |
514 | if (!parentp) | 520 | |
521 | if (!parentp IF_MV( || parentp->attr == ATTR_SYSTEM_ROOT )) | ||
515 | return WALK_RC_CONT_AT_ROOT; | 522 | return WALK_RC_CONT_AT_ROOT; |
516 | 523 | ||
517 | compp->nextp = freep; | 524 | compp->nextp = freep; |
@@ -567,6 +574,9 @@ int open_stream_internal(const char *path, unsigned int callflags, | |||
567 | if (!compinfo) | 574 | if (!compinfo) |
568 | callflags &= ~FF_CHECKPREFIX; | 575 | callflags &= ~FF_CHECKPREFIX; |
569 | 576 | ||
577 | /* This lets it be passed quietly to directory scanning */ | ||
578 | stream->flags = callflags & FF_MASK; | ||
579 | |||
570 | struct pathwalk walk; | 580 | struct pathwalk walk; |
571 | walk.path = path; | 581 | walk.path = path; |
572 | walk.callflags = callflags; | 582 | walk.callflags = callflags; |
@@ -575,7 +585,7 @@ int open_stream_internal(const char *path, unsigned int callflags, | |||
575 | 585 | ||
576 | struct pathwalk_component *rootp = pathwalk_comp_alloc(NULL); | 586 | struct pathwalk_component *rootp = pathwalk_comp_alloc(NULL); |
577 | rootp->nextp = NULL; | 587 | rootp->nextp = NULL; |
578 | rootp->attr = ATTR_DIRECTORY; | 588 | rootp->attr = ATTR_SYSTEM_ROOT; |
579 | 589 | ||
580 | #ifdef HAVE_MULTIVOLUME | 590 | #ifdef HAVE_MULTIVOLUME |
581 | int volume = 0, rootrc = WALK_RC_FOUND; | 591 | int volume = 0, rootrc = WALK_RC_FOUND; |
@@ -584,7 +594,7 @@ int open_stream_internal(const char *path, unsigned int callflags, | |||
584 | while (1) | 594 | while (1) |
585 | { | 595 | { |
586 | const char *pathptr = walk.path; | 596 | const char *pathptr = walk.path; |
587 | 597 | ||
588 | #ifdef HAVE_MULTIVOLUME | 598 | #ifdef HAVE_MULTIVOLUME |
589 | /* this seamlessly integrates secondary filesystems into the | 599 | /* this seamlessly integrates secondary filesystems into the |
590 | root namespace (e.g. "/<0>/../../<1>/../foo/." :<=> "/foo") */ | 600 | root namespace (e.g. "/<0>/../../<1>/../foo/." :<=> "/foo") */ |
@@ -596,8 +606,19 @@ int open_stream_internal(const char *path, unsigned int callflags, | |||
596 | FILE_ERROR(ENXIO, -2); | 606 | FILE_ERROR(ENXIO, -2); |
597 | } | 607 | } |
598 | 608 | ||
599 | /* the root of this subpath is the system root? */ | 609 | if (p == pathptr) |
600 | rootrc = p == pathptr ? WALK_RC_FOUND_ROOT : WALK_RC_FOUND; | 610 | { |
611 | /* the root of this subpath is the system root */ | ||
612 | rootp->attr = ATTR_SYSTEM_ROOT; | ||
613 | rootrc = WALK_RC_FOUND_ROOT; | ||
614 | } | ||
615 | else | ||
616 | { | ||
617 | /* this subpath specifies a mount point */ | ||
618 | rootp->attr = ATTR_MOUNT_POINT; | ||
619 | rootrc = WALK_RC_FOUND; | ||
620 | } | ||
621 | |||
601 | walk.path = p; | 622 | walk.path = p; |
602 | #endif /* HAVE_MULTIVOLUME */ | 623 | #endif /* HAVE_MULTIVOLUME */ |
603 | 624 | ||
@@ -633,11 +654,9 @@ int open_stream_internal(const char *path, unsigned int callflags, | |||
633 | default: /* utter, abject failure :`( */ | 654 | default: /* utter, abject failure :`( */ |
634 | DEBUGF("Open failed: rc=%d, errno=%d\n", rc, errno); | 655 | DEBUGF("Open failed: rc=%d, errno=%d\n", rc, errno); |
635 | filestr_base_destroy(stream); | 656 | filestr_base_destroy(stream); |
636 | FILE_ERROR(-rc, -2); | 657 | FILE_ERROR(-rc, -3); |
637 | } | 658 | } |
638 | 659 | ||
639 | file_cache_reset(stream->cachep); | ||
640 | |||
641 | file_error: | 660 | file_error: |
642 | return rc; | 661 | return rc; |
643 | } | 662 | } |
@@ -757,9 +776,10 @@ int test_stream_exists_internal(const char *path, unsigned int callflags) | |||
757 | { | 776 | { |
758 | /* only FF_* flags should be in callflags */ | 777 | /* only FF_* flags should be in callflags */ |
759 | struct filestr_base stream; | 778 | struct filestr_base stream; |
760 | int rc = open_stream_internal(path, callflags, &stream, NULL); | 779 | int rc = open_stream_internal(path, callflags | FF_PROBE, &stream, NULL); |
761 | if (rc > 0) | 780 | |
762 | close_stream_internal(&stream); | 781 | if (rc >= 0) |
782 | filestr_base_destroy(&stream); | ||
763 | 783 | ||
764 | return rc; | 784 | return rc; |
765 | } | 785 | } |