Problem/Motivation

When attempting to create a private file folder, I put in an invalid path and get one of two errors:

When making a directory that cannot be created by the webuser on OSX in the root dir
IE "/home/a/dev/files-private" (OSX has a home directory not writeable by webuser)
"Operation not supported in _drupal_mkdir_call()"

When making a directory that cannot be created due to permissions (OSX, Linux, Windows)
"Permission Denied in _drupal_mkdir_call()"

Followed by the correct error:
"The directory /home/i/dev/files-private does not exist and could not be created."

Screenshot_10_6_13_12_01_PM.png

Proposed resolution

To use @mkdir() instead of mkdir().

Remaining tasks

Beta phase evaluation

Reference: https://www.drupal.org/core/beta-changes
Issue category Bug
Unfrozen changes Unfrozen because it only changes what error messages are revealed to the end user
Prioritized changes The main goal of this issue is usability

Comments

fenstrat’s picture

Status: Active » Needs review
StatusFileSize
new576 bytes

This patch gets rid of the icky error, but keeps the friendly "The directory %directory does not exist and could not be created." error.

Sitting here at the table with @chx at PNWDS who okayed this approach. He also waxed quite lyrically about how PHP's handling of errors like this is ... far from ideal.

fenstrat’s picture

The fact that this passes suggests we need a test for this.

Also related #1068266: drupal_mkdir does not set permissions to directories it created recursively .

jhedstrom’s picture

Issue summary: View changes
Status: Needs review » Needs work
Issue tags: +Needs tests

Needs tests as per #2. Patch still applies, and the approach makes sense to me as well.

fenstrat’s picture

@jhedstrom Any pointers on how'd you go about writing a test for this? Happy to give it a shot, but not sure of the best approach.

jhedstrom’s picture

@fenstrat, take a look at \Drupal\system\Tests\File\DirectoryTest -- that is testing drupal_mkdir(). I'd guess you could create a directory, remove access to that directory, then call drupal_mkdir() and ensure the icky errors don't appear?

areke’s picture

Issue summary: View changes
fenstrat’s picture

Status: Needs work » Needs review
StatusFileSize
new1.67 KB
new1.11 KB

Thanks @jhedstrom, here's a shot at that. The test-only patch should fail, but with an exception as mkdir() isn't silenced with @mkdir.

As DirectoryTest is a unit test (it extends from DrupalUnitTestBase (soon to be KernelTestBase I believe) and not WebTestBase) I'm not quite sure how to test the output of php warnings. So while the test will cause an exception if mkdir isn't silenced I'm not sure how to actually test there is no icky PHP warning?

fenstrat’s picture

Hmm, hidden files aren't tested?

fenstrat’s picture

StatusFileSize
new1.11 KB

Trying again.

Status: Needs review » Needs work

The last submitted patch, 10: 2105949-7-silence_mkdir_errors-test-only.patch, failed testing.

jhedstrom’s picture

Issue summary: View changes
Status: Needs work » Reviewed & tested by the community

I think failure by exception is a fine way to test. #7 is RTBC I think (#11 is just the test, which is expected to fail without the fix).

I've added the beta phase evaluation to the summary.

fenstrat’s picture

Issue tags: -Needs tests

Great, thanks @jhedstrom.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

I think we should be adding the @ to the call to drupal_mkdir() in system_check_directory()

We rely on the errors in LocalStream::mkdir() - which is obviously missing test coverage.

    if ($options & STREAM_REPORT_ERRORS) {
      return drupal_mkdir($localpath, $mode, $recursive);
    }
    else {
      return @drupal_mkdir($localpath, $mode, $recursive);
    }

With this change this logic is broken.

And we do this elsewhere.

  if (@drupal_mkdir($file, $mod)) {
    return TRUE;
  }
  else {
    return FALSE;
  }

From drupal_install_mkdir()

    // Let mkdir() recursively create directories and use the default directory
    // permissions.
    if ($options & FILE_CREATE_DIRECTORY) {
      return @drupal_mkdir($directory, NULL, TRUE);
    }

From file_prepare_directory().

fenstrat’s picture

Status: Needs work » Needs review
StatusFileSize
new1.94 KB

@alexpott in #14 is correct, the errors are relied upon in other locations. I've moved the @ into system_check_directory().

I've kept the test, and silence the call there, i.e. @drupal_mkdir().

Also, while #2050759: Move drupal_chmod and other code in file.inc to a Drupal\Core\File\FileSystem class deprecated drupal_mkdir() there are still calls all over core to it.

mile23’s picture

Patch in #15 still applies.

DirectoryTest passes locally.

Retesting, and also here's a review:

+++ b/core/modules/system/src/Tests/File/DirectoryTest.php
@@ -51,6 +51,13 @@ function testFileCheckLocalDirectoryHandling() {
+    @drupal_chmod($parent_path, 0444);

...

+    $this->assertFalse(@drupal_mkdir($second_child_path, 0775, TRUE), t('Creating child directory under a non writable parent fails.'), 'File');


+++ b/core/modules/system/system.module
@@ -801,7 +801,7 @@ function system_check_directory($form_element, FormStateInterface $form_state) {
+  if (!is_dir($directory) && !@drupal_mkdir($directory, NULL, TRUE)) {

Should use the file_system service.

fenstrat’s picture

StatusFileSize
new2.02 KB

Here's the changes as requested by @Mile23 in #16.

dawehner’s picture

I would be nice to be able to pass a silent as parameter to the method ... Is there a way to check beforehand whether a mkdir would fail?

fenstrat’s picture

@dawehner It doesn't look like there is a way to check before hand if php's mkdir() will fail. As @alexpott noted in #14 LocalStream::mkdir() does call drupal_mkdir() if STREAM_REPORT_ERRORS is set (and calls @drupal_mkdir() if it is not). However I think properly implementing a silent param in FileSystem::mkdir() would be best as a follow up.

#18 fixes this bug and adds a test to prove it.

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

joelpittet’s picture

Status: Needs review » Needs work

Shouldn't the patch be doing the silencing inside the service on the actual PHP call to mkdir?

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

quietone’s picture

Version: 8.9.x-dev » 7.x-dev
Issue tags: +Bug Smash Initiative

This is not reproducible in Drupal 8 because The private files directory is no longer configurable in the UI or available in config. However, it is reproducible in Drupal 7, so changing version.

Status: Needs work » Closed (outdated)

Automatically closed because Drupal 7 security and bugfix support has ended as of 5 January 2025. If the issue verifiably applies to later versions, please reopen with details and update the version.