help icon indicating copy to clipboard operation
help copied to clipboard

I want to know best practices for checking directory permissions

Open KazukiSugiyama107 opened this issue 3 years ago • 10 comments

Details

Before creating a directory under a specific directory like mkdir, I would like to check the permissions and see if the directory can be created. I think the method of receiving an error in the mkdir callback is correct originally, but that method cannot be used because mkdir is executed in the processing of the external library. After reviewing the documentation, I think the correct way is to use "opendir" to receive the callback. Is that the right way?

Also, if you use the fs module "opendir", "access" for a directory that you do not have write permission for, the result will be different. I'd like to know why the results are different, do you understand?

  • access (params : fs.constants.W_OK)
    • No error returned
  • opendir
    • Error callback is returned

OS: Windows 10 Directory: Program Files

Node.js version

14.15.3

Example code

No response

Operating system

Windows 10

Scope

other

Module and version

Not applicable.

KazukiSugiyama107 avatar May 25 '22 20:05 KazukiSugiyama107

This is formally answered in the documentation: https://nodejs.org/dist/latest-v18.x/docs/api/fs.html#fsaccesspath-mode-callback

Notice there is a subsection titled write (NOT RECOMMENDED) that makes use of the access method and a following subsection titled write (RECOMMENDED) that makes use of the open method. These code examples demonstrate how to proceed. The reason for this is stated immediately prior to the code examples:

Do not use fs.access() to check for the accessibility of a file before calling fs.open(), fs.readFile(), or fs.writeFile(). Doing so introduces a race condition, since other processes may change the file's state between the two calls. Instead, user code should open/read/write the file directly and handle the error raised if the file is not accessible.

prettydiff avatar May 27 '22 20:05 prettydiff

Confirmation was delayed. thank you for answering.

The process I want to implement is to check if the directory has read / execute permissions before using rmdir to delete the directory, and if so, display a dialog without running the delete process. I want to do it. Since the deletion process itself depends on the external library, the result of the rmdir callback cannot be received as it is. In that case, even if you perform synchronization processing with statSync or accesSync and call the processing with rmdir of the external library, the race condition does not occur. Is this idea correct?

Also, if you call statSync or accesSync synchronously for open and writeFile other than rmdir, wait for the result, and execute it, I think that no conflict will occur. Is that correct?

KazukiSugiyama107 avatar Jun 03 '22 09:06 KazukiSugiyama107

@KazukiSugiyama107 Thanks for creating this issue. I would suggest using fs.access/fs.accessSync/fsPromises.access to check if you have write permission in your scenario. fs.opendir is not necessary because you don't need to open the dir to check if you have the write permission, fs.opendir will also not readable when its motivation is just checking permission.

I'd like to know why the results are different, do you understand?

access (params : fs.constants.W_OK)
    No error returned
opendir
    Error callback is returned

I made an example code to test fs.access and fs.accessSync, it shows when we access a directory which has no write permission, an error will throw. If I understand your question correctly, then access method will have no problem checking the permission. is anything I missed?

$ cat test.mjs
import { accessSync, access, constants } from 'node:fs';

const dir = '/etc';

access(dir, constants.W_OK, (err) => {
  console.log(`check ${dir} permission before rm it via fs.access, result ${err ? 'is not writeable' : 'is writeable'}`);
});


try {
  accessSync(dir, constants.W_OK);
  console.log(`check ${dir} permission before rm it via fs.accessSync, result is writeable`);
} catch (err) {
  console.log(`check ${dir} permission before rm it via fs.accessSync, result is not writeable`);
}
$ node test.mjs  
check /etc permission before rm it via fs.accessSync, result is not writeable
check /etc permission before rm it via fs.access, result is not writeable

F3n67u avatar Jun 12 '22 04:06 F3n67u

@F3n67u thank you! What you answered was what I was looking for.

However, one question found that the results were different when using fs.accessSync on WinodwsOS and when using it on MacOS. I think this is a file system difference, but have you ever seen such a case?

The confirmation was carried out by changing the authority for the directory. The results on Mac OS seem correct, but the results on Windows OS do not seem to be correct.

Mac OS

Parameter Permission result
constants.R_OK Readable Success
constants.R_OK Writable Failure
constants.R_OK Executable Failure
constants.W_OK Readable Failure
constants.W_OK Writable Success
constants.W_OK Executable Failure
constants.X_OK Readable Failure
constants.X_OK Writable Failure
constants.X_OK Executable Success

Windows OS

Parameter Permission result
constants.R_OK Read Success
constants.R_OK Write Success
constants.R_OK List folder contens Success
constants.W_OK Read Success
constants.W_OK Write Success
constants.W_OK List folder contens Success
constants.X_OK Read Success
constants.X_OK Write Success
constants.X_OK List folder contens Success

KazukiSugiyama107 avatar Jun 12 '22 14:06 KazukiSugiyama107

On Windows, access-control policies (ACLs) on a directory may limit access to a file or directory. The fs.access() function, however, does not check the ACL and therefore may report that a path is accessible even if the ACL restricts the user from reading or writing to it.

I don't test it in Windows. Seems related to this problem in Windows.https://nodejs.org/dist/latest-v18.x/docs/api/fs.html#fsaccesspath-mode-callback

F3n67u avatar Jun 12 '22 14:06 F3n67u

I understand. As explained below, I have confirmed that it works fine on Windows using fs.openSync.

Using fs.exists() to check for the existence of a file before calling fs.open(), fs.readFile(), or fs.writeFile() is not recommended. Doing so introduces a race condition, since other processes may change the file's state between the two calls. Instead, user code should open/read/write the file directly and handle the error raised if the file does not exist.

I'm a little skeptical, but is it correct to run fs.openSync in a directory? The results I can get are correct, but I'm wondering if there are other ways.

KazukiSugiyama107 avatar Jun 13 '22 13:06 KazukiSugiyama107

I don't have an answer for you. I don't know the Windows-specific side of the fs module.

@nodejs/fs Could you folks help with this question?

F3n67u avatar Jun 13 '22 14:06 F3n67u

Can someone please answer how to use fs.openSync?

https://github.com/nodejs/help/issues/3871#issuecomment-1153947155

KazukiSugiyama107 avatar Jul 11 '22 14:07 KazukiSugiyama107

I would like to know if anyone has any knowledge of the following comments.

https://github.com/nodejs/help/issues/3871#issuecomment-1153947155

KazukiSugiyama107 avatar Oct 02 '22 04:10 KazukiSugiyama107

There has been no activity on this issue for 11 months. The help repository works best when sustained engagement moves conversation forward. The issue will be closed in 1 month. If you are still experiencing this issue on the latest supported versions of Node.js, please leave a comment.

github-actions[bot] avatar Mar 06 '24 01:03 github-actions[bot]

Closing after no activity on this issue for 12 months.

github-actions[bot] avatar Apr 05 '24 01:04 github-actions[bot]