public function stat() {
    $prefix = $this->prefix;
    if (StringUtil::endsWith($prefix, parent::DELIMITER)) {
      $prefix = substr($prefix, 0, strlen($prefix) - 1);
    }

    if (ini_get("google_app_engine.enable_gcs_stat_cache") &&
        $this->tryGetFromStatCache($stat_result)) {
      return $stat_result;
    }

    if (isset($prefix)) {
      $result = $this->headObject($prefix);
      if ($result !== false) {
        $mode = parent::S_IFREG;
        $mtime = $result['mtime'];
        $size = $result['size'];
      } else {
        // Object doesn't exisit, check and see if it's a directory.
        do {
          $results = $this->listBucket($prefix);
          if (false === $results) {
            return false;
          }
          // If there are no results then we're done
          if (empty($results)) {
            return false;
          }
          // If there is an entry that contains object_name_$folder$ or
          // object_name/ then we have a 'directory'.
          $object_name_folder = $prefix . parent::FOLDER_SUFFIX;
          $object_name_delimiter = $prefix . parent::DELIMITER;
          foreach ($results as $result) {
            if ($result['name'] === $object_name_folder ||
                $result['name'] === $object_name_delimiter) {
              $mode = parent::S_IFDIR;
              break;
            }
          }
        } while (!isset($mode) && isset($this->next_marker));
      }
    } else {
      // We are now just checking that the bucket exists, as there was no
      // object prefix supplied
      $results = $this->listBucket();
      if ($results !== false) {
        $mode = parent::S_IFDIR;
      } else {
        return false;
      }
    }
    // If mode is not set, then there was no object that matched the criteria.
    if (!isset($mode)) {
      return false;
    }
    // If the app could stat the file, then it must be readable. As different
    // PHP internal APIs check the access mode, we'll set them all to readable.
    $mode |= parent::S_IRUSR | parent::S_IRGRP | parent::S_IROTH;

    if ($this->isBucketWritable($this->bucket_name)) {
      $mode |= parent::S_IWUSR | parent::S_IWGRP | parent::S_IWOTH;
    }

    $stat_args["mode"] = $mode;
    if (isset($mtime)) {
      $unix_time = strtotime($mtime);
      if ($unix_time !== false) {
        $stat_args["mtime"] = $unix_time;
      }
    }

    if (isset($size)) {
      $stat_args["size"] = intval($size);
    }
    $stat_result = $this->createStatArray($stat_args);
    $this->addToStatCache($stat_result);
    return $stat_result;
  }
public function stat() {
    $prefix = $this->prefix;
    if (StringUtil::endsWith($prefix, parent::DELIMITER)) {
      $prefix = substr($prefix, 0, strlen($prefix) - 1);
    }

    if (ini_get("google_app_engine.enable_gcs_stat_cache") &&
        $this->tryGetFromStatCache($stat_result)) {
      return $stat_result;
    }

    if (isset($prefix)) {
      $result = $this->headObject($prefix);
      if ($result !== false) {
        $mode = parent::S_IFREG;
        $mtime = $result['mtime'];
        $size = $result['size'];
      } else {
        // Object doesn't exisit, check and see if it's a directory.
        do {
          $results = $this->listBucket($prefix);
          if (false === $results) {
            return false;
          }
          // If there are no results then we're done
          if (empty($results)) {
            return false;
          }
          // If there is an entry that contains object_name_$folder$ or
          // object_name/ then we have a 'directory'.
          $object_name_folder = $prefix . parent::FOLDER_SUFFIX;
          $object_name_delimiter = $prefix . parent::DELIMITER;
          foreach ($results as $result) {
            if ($result['name'] === $object_name_folder ||
                $result['name'] === $object_name_delimiter) {
              $mode = parent::S_IFDIR;
              break;
            }
          }
        } while (!isset($mode) && isset($this->next_marker));
      }
    } else {
      // We are now just checking that the bucket exists, as there was no
      // object prefix supplied
      $results = $this->listBucket();
      if ($results !== false) {
        $mode = parent::S_IFDIR;
      } else {
        return false;
      }
    }
    // If mode is not set, then there was no object that matched the criteria.
    if (!isset($mode)) {
      return false;
    }
    // If the app could stat the file, then it must be readable. As different
    // PHP internal APIs check the access mode, we'll set them all to readable.
    $mode |= parent::S_IRUSR | parent::S_IRGRP | parent::S_IROTH;

    if ($this->isBucketWritable($this->bucket_name)) {
      $mode |= parent::S_IWUSR | parent::S_IWGRP | parent::S_IWOTH;
    }

    $stat_args["mode"] = $mode;
    if (isset($mtime)) {
      $unix_time = strtotime($mtime);
      if ($unix_time !== false) {
        $stat_args["mtime"] = $unix_time;
      }
    }

    if (isset($size)) {
      $stat_args["size"] = intval($size);
    }
    $stat_result = $this->createStatArray($stat_args);
    $this->addToStatCache($stat_result);
    return $stat_result;
  }
public function stat ( ) { $ prefix = $ this -> prefix ; if ( StringUtil :: endsWith ( $ prefix , parent :: DELIMITER ) ) { $ prefix = substr ( $ prefix , 0 , strlen ( $ prefix ) - 1 ) ; } if ( ini_get ( "google_app_engine.enable_gcs_stat_cache" ) && $ this -> tryGetFromStatCache ( $ stat_result ) ) { return $ stat_result ; } if ( isset ( $ prefix ) ) { $ result = $ this -> headObject ( $ prefix ) ; if ( $ result !== false ) { $ mode = parent :: S_IFREG ; $ mtime = $ result [ 'mtime' ] ; $ size = $ result [ 'size' ] ; } else { // Object doesn't exisit, check and see if it's a directory. do { $ results = $ this -> listBucket ( $ prefix ) ; if ( false === $ results ) { return false ; } // If there are no results then we're done if ( empty ( $ results ) ) { return false ; } // If there is an entry that contains object_name_$folder$ or // object_name/ then we have a 'directory'. $ object_name_folder = $ prefix . parent :: FOLDER_SUFFIX ; $ object_name_delimiter = $ prefix . parent :: DELIMITER ; foreach ( $ results as $ result ) { if ( $ result [ 'name' ] === $ object_name_folder || $ result [ 'name' ] === $ object_name_delimiter ) { $ mode = parent :: S_IFDIR ; break ; } } } while ( ! isset ( $ mode ) && isset ( $ this -> next_marker ) ) ; } } else { // We are now just checking that the bucket exists, as there was no // object prefix supplied $ results = $ this -> listBucket ( ) ; if ( $ results !== false ) { $ mode = parent :: S_IFDIR ; } else { return false ; } } // If mode is not set, then there was no object that matched the criteria. if ( ! isset ( $ mode ) ) { return false ; } // If the app could stat the file, then it must be readable. As different // PHP internal APIs check the access mode, we'll set them all to readable. $ mode |= parent :: S_IRUSR | parent :: S_IRGRP | parent :: S_IROTH ; if ( $ this -> isBucketWritable ( $ this -> bucket_name ) ) { $ mode |= parent :: S_IWUSR | parent :: S_IWGRP | parent :: S_IWOTH ; } $ stat_args [ "mode" ] = $ mode ; if ( isset ( $ mtime ) ) { $ unix_time = strtotime ( $ mtime ) ; if ( $ unix_time !== false ) { $ stat_args [ "mtime" ] = $ unix_time ; } } if ( isset ( $ size ) ) { $ stat_args [ "size" ] = intval ( $ size ) ; } $ stat_result = $ this -> createStatArray ( $ stat_args ) ; $ this -> addToStatCache ( $ stat_result ) ; return $ stat_result ; }
The stat function uses GET requests to the bucket to try and determine if
the object is a 'file' or a 'directory', by listing the contents of the
bucket and then matching the results against the supplied object name.

If a file ends with "/ then Google Cloud Console will show it as a 'folder'
in the UI tool, so we consider an object that ends in "/" as a directory
as well. For backward compatibility, we also treat files with the
"_$folder$" suffix as folders.
The stat function uses GET requests to the bucket to try and determine if the object is a file or a directory by listing the contents of the bucket and then matching the results against the supplied object name .