13

A friend asked me this question and I gave de-facto two options.

First way, testing the file permissions:

//adapted from https://stackoverflow.com/questions/11775884/nodejs-file-permissions#answer-11781404
var fs = require('fs')

function canWrite(directory) {
 var stat = fs.statSync(directory)

 // 2 is the octal value for chmod -w-
 return !!( 2 & (stat.mode & parseInt('777', 8)).toString(8)[0] ) //first char is the owner
}

What if the user (process.uid) was not the file system owner (stat.uid) neither in it's group (process.gid vs stat.gid)? It will still get the 644 permissions and writing will not be possible.

How may we actually know (with nodejs) that the current user belongs to the file system group (stat.gid)? Easy in bash but to be portable it'd be a mess with nodejs.

Second way, lazy:

var fs = require('fs')
var canWrite = true

try {
  fs.writeFileSync('./test')
  fs.unlinkSync('./test')
} catch(e) {
  canWrite = false
}

if(canWrite) {
 //go for it
}

Lazy solution of couse, but it should do the job. This could also block the kernel buffer. On the other side, fs.Stat is usually cached by operating systems.

Neither of these solution is perfect.

How would you do? Is there something I'm missing?

Community
  • 1
  • 1
soyuka
  • 8,839
  • 3
  • 39
  • 54

1 Answers1

24

What about:

var fs = require('fs');

fs.access(__dirname, fs.constants.W_OK, function(err) {
  if(err){
    console.error("can't write");
    process.exit(1);
  }

  console.log("can write");
  process.exit(0);
});

Docs here

fs.constants.W_OK : File can be written by the calling process.

If you run the above with sudo you may get different outputs depending on user permissions.

ohsully
  • 372
  • 3
  • 10
Maroshii
  • 3,937
  • 4
  • 23
  • 29
  • Interesting thanks, here's the [commit](https://github.com/joyent/node/commit/29449349da5ef7e23689396c21bae003d81e0081). `sudo` is not a portable thing. – soyuka May 08 '15 at 00:12
  • Yeah, I just meant that it yields different results based on current permissions – Maroshii May 08 '15 at 08:21
  • 6
    Heads up that `fs` has been refactored -- `W_OK` now lives at `fs.constants.W_OK`. – ohsully Apr 12 '18 at 23:59