blob: e70031b0a58ab2fc9df96b69f6c82130ad73d29f [file] [log] [blame]
Leo Repp58b9f112021-11-22 11:57:47 +01001'use strict';
2
3var path = require('path');
4
5var fs = require('graceful-fs');
6
7var MASK_MODE = parseInt('7777', 8);
8var DEFAULT_DIR_MODE = parseInt('0777', 8);
9
10function mkdirp(dirpath, customMode, callback) {
11 if (typeof customMode === 'function') {
12 callback = customMode;
13 customMode = undefined;
14 }
15
16 var mode = customMode || (DEFAULT_DIR_MODE & ~process.umask());
17 dirpath = path.resolve(dirpath);
18
19 fs.mkdir(dirpath, mode, onMkdir);
20
21 function onMkdir(mkdirErr) {
22 if (!mkdirErr) {
23 return fs.stat(dirpath, onStat);
24 }
25
26 switch (mkdirErr.code) {
27 case 'ENOENT': {
28 return mkdirp(path.dirname(dirpath), onRecurse);
29 }
30
31 case 'EEXIST': {
32 return fs.stat(dirpath, onStat);
33 }
34
35 default: {
36 return callback(mkdirErr);
37 }
38 }
39
40 function onStat(statErr, stats) {
41 if (statErr) {
42 return callback(statErr);
43 }
44
45 if (!stats.isDirectory()) {
46 return callback(mkdirErr);
47 }
48
49 // TODO: Is it proper to mask like this?
50 if ((stats.mode & MASK_MODE) === mode) {
51 return callback();
52 }
53
54 if (!customMode) {
55 return callback();
56 }
57
58 fs.chmod(dirpath, mode, callback);
59 }
60 }
61
62 function onRecurse(recurseErr) {
63 if (recurseErr) {
64 return callback(recurseErr);
65 }
66
67 mkdirp(dirpath, mode, callback);
68 }
69}
70
71module.exports = mkdirp;