public function checkPaths()
    {
        if ($this->path_checked)
            return true;

        foreach (array('root', 'webroot') as $type)
        {
            $path = $this->$type;
            if (!file_exists($path) || !is_dir($path))
                throw new IOException("Path '$type' does not exist: " . $path);

            if (!is_readable($path))
                throw new PermissionError($path, "Path '$type' cannot be read");
        }

        if (!is_dir($this->config) || is_readable($this->config))
            $this->config = null;

        foreach (array('var', 'cache', 'log', 'uploads') as $write_dir)
        {
            $path = $this->$write_dir;
            if (!is_dir($path))
            {
                $dn = dirname($path);
                if (!file_exists($path) && $dn === $this->var)
                {
                    // The parent directory is var/ and must be writeable as
                    // this was checked earlier in this loop.
                    Path::mkdir($path);
                }
                else
                {
                    if (file_exists($path))
                        throw new IOException("Path '$write_dir' exists but is not a directory: " . $path);
                    $this->$write_dir = null;
                    continue;
                }
            }

            if (!is_writable($path))
            {
                try
                {
                    // We can try to fix permissions if we own the file
                    Path::makeWritable($path);
                }
                catch (PermissionError $e)
                {
                    $this->$write_dir = null;
                    if ($this->cli)
                        WF::debug("Failed to get write access to: %s", $e->getMessage());
                }
            }
        }
        $this->path_checked = true;
        return true;
    }