dshoreman / servidor

A modern web application for managing servers

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`file_exists()` returns `false` for symlinks with missing targets

dshoreman opened this issue · comments

Background

If a symlink is passed and its target does not exist, PHP's file_exists function will return false regardless of whether the symlink itself exists at the given path or not.

The Issue

Currently we short-circuit when PHP claims the "file" doesn't exist:

public function delete(string $path): array
{
$remove = is_dir($path) ? 'rmdir' : 'unlink';
$error = ['code' => 500, 'msg' => 'Failed removing' . $path];
if (!file_exists($path)) {
return ['error' => null];
}
if (!is_writable($path)) {
return ['error' => ['code' => 403, 'msg' => 'No permission to write path']];
}
return ['error' => $remove($path) ? null : $error];
}

...meaning if we attempt to delete a symlink and its target has already been removed, it's not possible to remove the symlink without first pointing it to a file that exists (or creating the file it references).


We'll need another test (see below), but it may be necessary to check is_link() first so that special treatment can be given.

Theoretical Test

/** @test */
public function can_delete_symlink_when_target_is_missing(): void
{
    $link = 'test-skel/some-symlink';
    $target = 'test-skel/non-existent-path';

    createSymlink($link, $target);
    deleteWithFileManager($link);
    assertDoesNotExist($link);
}