ZF-3565: Zend_Cache_Backend_File fails to set directory permissions when hashed_directory_level > 1

Description

Environment:

OS: Fedora Core release 6 (Zod) PHP: 5.1.6

Initial cache params:

$backendOptions parameter hashed_directory_level is set to be grater than 1 and hashed_directory_umask is set to 0777 (so that every user can read/write to the cache structure)

Problem:

Because hash directory is created by giving mkdir and chmod the full path:

            mkdir($this->_path($id), $this->_options['hashed_directory_umask'], true);
            chmod($this->_path($id), $this->_options['hashed_directory_umask']); // see #ZF-320 (this line is required in some configurations)      

sometimes only the last directory within the path has the permission set correctly - all directories "in between" may have incorrect permissions set.

Example:

    $frontendOptions = array(
       'lifetime' => 3600,
       'automatic_serialization' => true,
       'automatic_cleaning_factor' => 0
    );

    $backendOptions = array(
        'cache_dir' => '/tmp/leksyka_cache/',
        'read_control' => false,
        'read_control_type' => 'adler32',
        'hashed_directory_level' => 2,
        'cache_file_umask' => 0666,
        'hashed_directory_umask' => 0777,
        'file_name_prefix' => 'leksyka',
        'file_locking' => true
    );

    // getting a Zend_Cache_Core object
    $this->_cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions);

    $this->_cache->save($data, $id, array() , 1000);

this creates a file:

/tmp/leksyka_cache/leksyka--f/leksyka--fa/leksyka---3f60fa1d8efca5d578a309a20999f1b6

with /tmp/leksyka_cache/leksyka--f permissions set to (0775/drwxrwxr-x)

Comments

Here is proposal for the patch:

    if ($this->_options['hashed_directory_level'] > 0) {
        if (!is_writable($path)) {
            // maybe, we just have to build the directory structure

            // commented out: $res = @mkdir($path, $this->_options['hashed_directory_umask'], true);
            // commented out: @chmod($path, $this->_options['hashed_directory_umask']); // see #ZF-320 (this line is required in some configurations)      

            //we crawl up the directory tree and check for missing directory nodes
            $pathCrawl = ($path[0]==DIRECTORY_SEPARATOR) ? DIRECTORY_SEPARATOR : ".";
            $pathParts = explode(DIRECTORY_SEPARATOR,trim($path,DIRECTORY_SEPARATOR));
            foreach($pathParts as &$part)
            {
                $pathCrawl .= ( $pathCrawl !=DIRECTORY_SEPARATOR ? DIRECTORY_SEPARATOR : "" ) . $part;
                if (!is_dir($pathCrawl))
                {
                    $res = @mkdir($pathCrawl, $this->_options['hashed_directory_umask'], true);
                    if ($res) @chmod($pathCrawl, $this->_options['hashed_directory_umask']);
                };
            };
        }
        if (!is_writable($path)) {
            return false;    
        }
    }  

you are right

I just commited into SVN trunk a fix for this (in a different way), it seems to be ok for me

please reopen this issue if there is still a problem

thanks for the good report

Updating for the 1.6.0 release.