Skip to content

Commit c57c187

Browse files
committed
Merge branch 'honour-umask'
2 parents 107e001 + 04b0796 commit c57c187

File tree

2 files changed

+57
-36
lines changed

2 files changed

+57
-36
lines changed

src/Toolkit/Utility/File.php

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -153,18 +153,23 @@ public static function getClosestPath(string $path): ?string
153153
*
154154
* @param int $permissions Applied if `$filename` is created.
155155
* @param int $dirPermissions Applied if `$filename`'s directory is created.
156-
* Parent directories, if any, are created with file mode `0755`.
156+
* Parent directories, if any, are created with file mode `0755`, or `0777 &
157+
* ~umask()` if `$applyUmask` is `true`.
157158
*/
158159
public static function create(
159160
string $filename,
160161
int $permissions = 0755,
161-
int $dirPermissions = 0755
162+
int $dirPermissions = 0755,
163+
bool $applyUmask = false
162164
): void {
163165
if (is_file($filename)) {
164166
return;
165167
}
166-
self::createDir(dirname($filename), $dirPermissions);
168+
self::createDir(dirname($filename), $dirPermissions, $applyUmask);
167169
$umask = umask();
170+
if ($applyUmask) {
171+
$permissions &= ~$umask;
172+
}
168173
try {
169174
umask(077);
170175
$handle = self::open($filename, 'x');
@@ -184,21 +189,26 @@ public static function create(
184189
* File mode defaults and behaviour are similar to `install` on *nix.
185190
*
186191
* @param int $permissions Applied if `$directory` is created. Parent
187-
* directories, if any, are created with file mode `0755`.
192+
* directories, if any, are created with file mode `0755`, or `0777 &
193+
* ~umask()` if `$applyUmask` is `true`.
188194
*/
189195
public static function createDir(
190196
string $directory,
191-
int $permissions = 0755
197+
int $permissions = 0755,
198+
bool $applyUmask = false
192199
): void {
193200
if (is_dir($directory)) {
194201
return;
195202
}
196203
$parent = dirname($directory);
197204
$umask = umask();
205+
if ($applyUmask) {
206+
$permissions &= ~$umask;
207+
}
198208
try {
199209
if (!is_dir($parent)) {
200-
umask(022);
201-
self::mkdir($parent, 0755, true);
210+
umask(0);
211+
self::mkdir($parent, $applyUmask ? 0777 & ~$umask : 0755, true);
202212
}
203213
umask(077);
204214
self::mkdir($directory);

tests/unit/Toolkit/Utility/FileTest.php

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -168,47 +168,58 @@ public function testGetClosestPath(): void
168168

169169
public function testCreateAndCreateDir(): void
170170
{
171-
$this->doTestCreateAndCreateDir(self::getRoot()->url(), false);
171+
$this->doTestCreateAndCreateDir(self::getRoot()->url());
172172

173-
// Repeat the test against a real filesystem and its umask behaviour
174-
$dir = File::createTempDir();
173+
// Repeat the test against a real filesystem using various umasks
174+
$umask = umask();
175175
try {
176-
$this->doTestCreateAndCreateDir($dir, Sys::isWindows());
176+
foreach ([null, 022, 02] as $u) {
177+
if ($u !== null) {
178+
umask($u);
179+
}
180+
$dir = File::createTempDir();
181+
try {
182+
$this->doTestCreateAndCreateDir($dir, $w ??= Sys::isWindows(), $u);
183+
} finally {
184+
File::pruneDir($dir, true, true);
185+
}
186+
}
177187
} finally {
178-
File::pruneDir($dir, true, true);
188+
umask($umask);
179189
}
180190
}
181191

182-
private function doTestCreateAndCreateDir(string $dir, bool $windows): void
192+
private function doTestCreateAndCreateDir(string $dir, bool $w = false, ?int $u = null): void
183193
{
184-
File::create("$dir/file1", 0777);
185-
File::create("$dir/dir1/dir4/file2");
186-
File::create("$dir/dir2/dir5/dir6/file3", 0600, 0700);
187-
File::create("$dir/dir3/file4", 0640, 0750);
188-
$this->assertFileExists("$dir/file1");
189-
$this->assertFileExists("$dir/dir1/dir4/file2");
190-
$this->assertFileExists("$dir/dir2/dir5/dir6/file3");
191-
$this->assertFileExists("$dir/dir3/file4");
192-
$this->assertSame(0, filesize("$dir/file1"));
193-
$this->assertSame(0, filesize("$dir/dir1/dir4/file2"));
194-
$this->assertSame(0, filesize("$dir/dir2/dir5/dir6/file3"));
195-
$this->assertSame(0, filesize("$dir/dir3/file4"));
194+
File::create("$dir/file1", 0777, 0755, $u !== null);
195+
File::create("$dir/dir1/dir4/file2", 0755, 0755, $u !== null);
196+
File::create("$dir/dir2/dir5/dir6/file3", 0600, 0700, $u !== null);
197+
File::create("$dir/dir3/file4", 0640, 0750, $u !== null);
198+
$message = sprintf('$w = %d, $u = 0%o', (int) $w, $u ?? 0);
199+
$this->assertFileExists("$dir/file1", $message);
200+
$this->assertFileExists("$dir/dir1/dir4/file2", $message);
201+
$this->assertFileExists("$dir/dir2/dir5/dir6/file3", $message);
202+
$this->assertFileExists("$dir/dir3/file4", $message);
203+
$this->assertSame(0, filesize("$dir/file1"), $message);
204+
$this->assertSame(0, filesize("$dir/dir1/dir4/file2"), $message);
205+
$this->assertSame(0, filesize("$dir/dir2/dir5/dir6/file3"), $message);
206+
$this->assertSame(0, filesize("$dir/dir3/file4"), $message);
196207
foreach ([
197-
[$windows ? 0666 : 0777, "$dir/file1"],
198-
[$windows ? 0666 : 0755, "$dir/dir1/dir4/file2"],
199-
[$windows ? 0777 : 0755, "$dir/dir1/dir4"],
200-
[$windows ? 0777 : 0755, "$dir/dir1"],
201-
[$windows ? 0666 : 0600, "$dir/dir2/dir5/dir6/file3"],
202-
[$windows ? 0777 : 0700, "$dir/dir2/dir5/dir6"],
203-
[$windows ? 0777 : 0755, "$dir/dir2/dir5"],
204-
[$windows ? 0777 : 0755, "$dir/dir2"],
205-
[$windows ? 0666 : 0640, "$dir/dir3/file4"],
206-
[$windows ? 0777 : 0750, "$dir/dir3"],
208+
[$w ? 0666 : ($u === null ? 0777 : ($u === 022 ? 0755 : 0775)), "$dir/file1"],
209+
[$w ? 0666 : ($u === null ? 0755 : ($u === 022 ? 0755 : 0755)), "$dir/dir1/dir4/file2"],
210+
[$w ? 0777 : ($u === null ? 0755 : ($u === 022 ? 0755 : 0755)), "$dir/dir1/dir4"],
211+
[$w ? 0777 : ($u === null ? 0755 : ($u === 022 ? 0755 : 0775)), "$dir/dir1"],
212+
[$w ? 0666 : ($u === null ? 0600 : ($u === 022 ? 0600 : 0600)), "$dir/dir2/dir5/dir6/file3"],
213+
[$w ? 0777 : ($u === null ? 0700 : ($u === 022 ? 0700 : 0700)), "$dir/dir2/dir5/dir6"],
214+
[$w ? 0777 : ($u === null ? 0755 : ($u === 022 ? 0755 : 0775)), "$dir/dir2/dir5"],
215+
[$w ? 0777 : ($u === null ? 0755 : ($u === 022 ? 0755 : 0775)), "$dir/dir2"],
216+
[$w ? 0666 : ($u === null ? 0640 : ($u === 022 ? 0640 : 0640)), "$dir/dir3/file4"],
217+
[$w ? 0777 : ($u === null ? 0750 : ($u === 022 ? 0750 : 0750)), "$dir/dir3"],
207218
] as [$perms, $file]) {
208219
$expected[] = [$perms, $file];
209220
$actual[] = [fileperms($file) & 0777, $file];
210221
}
211-
$this->assertSame($expected, $actual);
222+
$this->assertSame($expected, $actual, $message);
212223
}
213224

214225
public function testCreateTemp(): void

0 commit comments

Comments
 (0)