@@ -26,6 +26,18 @@ function closeFd(propagatedErr, fd, callback) {
26
26
}
27
27
}
28
28
29
+ function isValidUnixId ( id ) {
30
+ if ( typeof id !== 'number' ) {
31
+ return false ;
32
+ }
33
+
34
+ if ( id < 0 ) {
35
+ return false ;
36
+ }
37
+
38
+ return true ;
39
+ }
40
+
29
41
function getModeDiff ( fsMode , vinylMode ) {
30
42
var modeDiff = 0 ;
31
43
@@ -66,6 +78,40 @@ function getTimesDiff(fsStat, vinylStat) {
66
78
return timesDiff ;
67
79
}
68
80
81
+ function getOwnerDiff ( fsStat , vinylStat ) {
82
+ if ( ! isValidUnixId ( vinylStat . uid ) &&
83
+ ! isValidUnixId ( vinylStat . gid ) ) {
84
+ return ;
85
+ }
86
+
87
+ if ( ( ! isValidUnixId ( fsStat . uid ) && ! isValidUnixId ( vinylStat . uid ) ) ||
88
+ ( ! isValidUnixId ( fsStat . gid ) && ! isValidUnixId ( vinylStat . gid ) ) ) {
89
+ return ;
90
+ }
91
+
92
+ var uid = fsStat . uid ; // Default to current uid.
93
+ if ( isValidUnixId ( vinylStat . uid ) ) {
94
+ uid = vinylStat . uid ;
95
+ }
96
+
97
+ var gid = fsStat . gid ; // Default to current gid.
98
+ if ( isValidUnixId ( vinylStat . gid ) ) {
99
+ gid = vinylStat . gid ;
100
+ }
101
+
102
+ if ( isEqual ( uid , fsStat . uid ) &&
103
+ isEqual ( gid , fsStat . gid ) ) {
104
+ return ;
105
+ }
106
+
107
+ var ownerDiff = {
108
+ uid : uid ,
109
+ gid : gid ,
110
+ } ;
111
+
112
+ return ownerDiff ;
113
+ }
114
+
69
115
function isOwner ( fsStat ) {
70
116
var hasGetuid = ( typeof process . getuid === 'function' ) ;
71
117
var hasGeteuid = ( typeof process . geteuid === 'function' ) ;
@@ -106,11 +152,14 @@ function updateMetadata(fd, file, callback) {
106
152
// Check if atime/mtime need to be updated
107
153
var timesDiff = getTimesDiff ( stat , file . stat ) ;
108
154
155
+ // Check if uid/gid need to be updated
156
+ var ownerDiff = getOwnerDiff ( stat , file . stat ) ;
157
+
109
158
// Set file.stat to the reflect current state on disk
110
159
assign ( file . stat , stat ) ;
111
160
112
161
// Nothing to do
113
- if ( ! modeDiff && ! timesDiff ) {
162
+ if ( ! modeDiff && ! timesDiff && ! ownerDiff ) {
114
163
return callback ( null ) ;
115
164
}
116
165
@@ -123,7 +172,10 @@ function updateMetadata(fd, file, callback) {
123
172
if ( modeDiff ) {
124
173
return mode ( ) ;
125
174
}
126
- times ( ) ;
175
+ if ( timesDiff ) {
176
+ return times ( ) ;
177
+ }
178
+ owner ( ) ;
127
179
128
180
function mode ( ) {
129
181
var mode = stat . mode ^ modeDiff ;
@@ -137,6 +189,9 @@ function updateMetadata(fd, file, callback) {
137
189
if ( timesDiff ) {
138
190
return times ( fchmodErr ) ;
139
191
}
192
+ if ( ownerDiff ) {
193
+ return owner ( fchmodErr ) ;
194
+ }
140
195
callback ( fchmodErr ) ;
141
196
}
142
197
}
@@ -149,9 +204,24 @@ function updateMetadata(fd, file, callback) {
149
204
file . stat . atime = timesDiff . atime ;
150
205
file . stat . mtime = timesDiff . mtime ;
151
206
}
207
+ if ( ownerDiff ) {
208
+ return owner ( fchmodErr || futimesErr ) ;
209
+ }
152
210
callback ( fchmodErr || futimesErr ) ;
153
211
}
154
212
}
213
+
214
+ function owner ( earlierErr ) {
215
+ fs . fchown ( fd , ownerDiff . uid , ownerDiff . gid , onFchown ) ;
216
+
217
+ function onFchown ( fchownErr ) {
218
+ if ( ! fchownErr ) {
219
+ file . stat . uid = ownerDiff . uid ;
220
+ file . stat . gid = ownerDiff . gid ;
221
+ }
222
+ callback ( earlierErr || fchownErr ) ;
223
+ }
224
+ }
155
225
}
156
226
}
157
227
@@ -257,8 +327,10 @@ function mkdirp(dirpath, customMode, callback) {
257
327
258
328
module . exports = {
259
329
closeFd : closeFd ,
330
+ isValidUnixId : isValidUnixId ,
260
331
getModeDiff : getModeDiff ,
261
332
getTimesDiff : getTimesDiff ,
333
+ getOwnerDiff : getOwnerDiff ,
262
334
isOwner : isOwner ,
263
335
updateMetadata : updateMetadata ,
264
336
writeFile : writeFile ,
0 commit comments