[GH-ISSUE #188] Attempts to access non-existent files may result in bogus EPERM instead of ENOENT #104

Closed
opened 2026-03-04 01:42:09 +03:00 by kerem · 4 comments
Owner

Originally created by @UnitedMarsupials-zz on GitHub (May 12, 2015).
Original GitHub issue: https://github.com/s3fs-fuse/s3fs-fuse/issues/188

If the attempted name contains asterisk, the error-code will be EPERM, which is incorrect. Otherwise, the failure is ENOENT. Here, for example, we have an S3-bucket mounted under /data/ftp. Trying to list three non-existent names, one gets different results:

% ls -l '/data/ftp/*ogus' '/data/ftp/?ogus' '/data/ftp/bogus'
ls: cannot access /data/ftp/*ogus: Operation not permitted
ls: cannot access /data/ftp/?ogus: No such file or directory
ls: cannot access /data/ftp/bogus: No such file or directory

Note, how using ?-template still works properly, but asterisk must have some special meaning, which causes erroneous behavior.

Originally created by @UnitedMarsupials-zz on GitHub (May 12, 2015). Original GitHub issue: https://github.com/s3fs-fuse/s3fs-fuse/issues/188 If the attempted name contains asterisk, the error-code will be `EPERM`, which is incorrect. Otherwise, the failure is `ENOENT`. Here, for example, we have an S3-bucket mounted under `/data/ftp`. Trying to list three non-existent names, one gets different results: ``` % ls -l '/data/ftp/*ogus' '/data/ftp/?ogus' '/data/ftp/bogus' ls: cannot access /data/ftp/*ogus: Operation not permitted ls: cannot access /data/ftp/?ogus: No such file or directory ls: cannot access /data/ftp/bogus: No such file or directory ``` Note, how using ?-template still works properly, but asterisk must have some special meaning, which causes erroneous behavior.
kerem closed this issue 2026-03-04 01:42:10 +03:00
Author
Owner

@UnitedMarsupials-zz commented on GitHub (May 12, 2015):

This is, probably, due to the fact, that * is copied verbatim instead of being escaped in urlEncode().

BTW, this function seems to have another problem -- it relies on isalnum(), which can have a different result depending on locale. It should instead check for the characters being one of the three ranges instead: 'a'-'z', 'A'-'Z', '0'-'9'.

Oh, and the special case for space is gratuitous for it is indistinguishable for the general case implemented after it.

<!-- gh-comment-id:101443715 --> @UnitedMarsupials-zz commented on GitHub (May 12, 2015): This is, probably, due to the fact, that `*` is copied verbatim instead of being escaped in `urlEncode()`. BTW, this function seems to have another problem -- it relies on `isalnum()`, which can have a different result depending on locale. It should instead check for the characters being one of the three ranges instead: `'a'`-`'z'`, `'A'`-`'Z'`, `'0'`-`'9'`. Oh, and the special case for space is gratuitous for it is indistinguishable for the general case implemented after it.
Author
Owner

@UnitedMarsupials-zz commented on GitHub (May 12, 2015):

This fixes the problem for me -- and picks the above-mentioned nits from urlEncode():

--- src/string_util.cpp 2015-03-25 14:00:46 -0400
+++ src/string_util.cpp 2015-05-12 18:39:19 -0400
@@ -124,14 +124,12 @@
   string result;
   for (unsigned i = 0; i < s.length(); ++i) {
-    if (s[i] == '/') { // Note- special case for fuse paths...
+    if (s[i] == '/' // Note- special case for fuse paths...
+      || (s[i] <= 'z' && s[i] >= 'a')
+      || (s[i] <= 'Z' && s[i] >= 'A')
+      || (s[i] <= '9' && s[i] >= '0')
+      || s[i] == '.'
+      || s[i] == '-'
+      || s[i] == '_') { // Should more characters -- like ^ -- be added here?
       result += s[i];
-    } else if (isalnum(s[i])) {
-      result += s[i];
-    } else if (s[i] == '.' || s[i] == '-' || s[i] == '*' || s[i] == '_') {
-      result += s[i];
-    } else if (s[i] == ' ') {
-      result += '%';
-      result += '2';
-      result += '0';
     } else {
       result += "%";

Actually, the last line in the above code should use single quotes to append a character '%' instead of a one-character string "%". Works either way, just less work for the string-class to do.

<!-- gh-comment-id:101449676 --> @UnitedMarsupials-zz commented on GitHub (May 12, 2015): This fixes the problem for me -- and picks the above-mentioned nits from `urlEncode()`: ``` diff --- src/string_util.cpp 2015-03-25 14:00:46 -0400 +++ src/string_util.cpp 2015-05-12 18:39:19 -0400 @@ -124,14 +124,12 @@ string result; for (unsigned i = 0; i < s.length(); ++i) { - if (s[i] == '/') { // Note- special case for fuse paths... + if (s[i] == '/' // Note- special case for fuse paths... + || (s[i] <= 'z' && s[i] >= 'a') + || (s[i] <= 'Z' && s[i] >= 'A') + || (s[i] <= '9' && s[i] >= '0') + || s[i] == '.' + || s[i] == '-' + || s[i] == '_') { // Should more characters -- like ^ -- be added here? result += s[i]; - } else if (isalnum(s[i])) { - result += s[i]; - } else if (s[i] == '.' || s[i] == '-' || s[i] == '*' || s[i] == '_') { - result += s[i]; - } else if (s[i] == ' ') { - result += '%'; - result += '2'; - result += '0'; } else { result += "%"; ``` Actually, the last line in the above code should use single quotes to append a character `'%'` instead of a one-character string `"%"`. Works either way, just less work for the string-class to do.
Author
Owner

@gaul commented on GitHub (May 12, 2015):

I have not looked into this yet, but we should add tests for special characters to integration-test-main.sh.

<!-- gh-comment-id:101450651 --> @gaul commented on GitHub (May 12, 2015): I have not looked into this yet, but we should add tests for special characters to `integration-test-main.sh`.
Author
Owner

@gaul commented on GitHub (May 26, 2015):

Some percent-encoding references:

http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html
http://en.wikipedia.org/wiki/Percent-encoding

<!-- gh-comment-id:105615706 --> @gaul commented on GitHub (May 26, 2015): Some percent-encoding references: http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html http://en.wikipedia.org/wiki/Percent-encoding
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/s3fs-fuse#104
No description provided.