static GFileInfo *
g_local_file_enumerator_next_file (GFileEnumerator  *enumerator,
				   GCancellable     *cancellable,
				   GError          **error)
{
  GLocalFileEnumerator *local = G_LOCAL_FILE_ENUMERATOR (enumerator);
  const char *filename;
  char *path;
  GFileInfo *info;
  GError *my_error;
  GFileType file_type;

  if (!local->got_parent_info)
    {
      _g_local_file_info_get_parent_info (local->filename, local->matcher, &local->parent_info);
      local->got_parent_info = TRUE;
    }

 next_file:

#ifdef USE_GDIR
  filename = g_dir_read_name (local->dir);
  file_type = G_FILE_TYPE_UNKNOWN;
#else
  filename = next_file_helper (local, &file_type);
#endif

  if (filename == NULL)
    return NULL;

  my_error = NULL;
  path = g_build_filename (local->filename, filename, NULL);
  if (file_type == G_FILE_TYPE_UNKNOWN ||
      (file_type == G_FILE_TYPE_SYMBOLIC_LINK && !(local->flags & G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS)))
    {
      info = _g_local_file_info_get (filename, path,
                                     local->matcher,
                                     local->flags,
                                     &local->parent_info,
                                     &my_error); 
    }
  else
    {
      info = _g_local_file_info_get (filename, path,
                                     local->reduced_matcher,
                                     local->flags,
                                     &local->parent_info,
                                     &my_error); 
      if (info)
        {
          _g_local_file_info_get_nostat (info, filename, path, local->matcher);
          g_file_info_set_file_type (info, file_type);
          if (file_type == G_FILE_TYPE_SYMBOLIC_LINK)
            g_file_info_set_is_symlink (info, TRUE);
        }
    }
  g_free (path);

  if (info == NULL)
    {
      /* Failed to get info */
      /* If the file does not exist there might have been a race where
       * the file was removed between the readdir and the stat, so we
       * ignore the file. */
      if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
	{
	  g_error_free (my_error);
	  goto next_file;
	}
      else
	g_propagate_error (error, my_error);
    }

  return info;
}
Beispiel #2
0
static gboolean
g_vfs_ftp_dir_cache_funcs_process (GInputStream *        stream,
                                   int                   debug_id,
                                   const GVfsFtpFile *   dir,
                                   GVfsFtpDirCacheEntry *entry,
                                   gboolean              is_unix,
                                   GCancellable *        cancellable,
                                   GError **             error)
{
  struct list_state state = { NULL, };
  GDataInputStream *data;
  GFileInfo *info;
  int type;
  GVfsFtpFile *file;
  char *line, *s;
  gsize length;

  /* protect against code reorg - in current code, error never is NULL */
  g_assert (error != NULL);
  g_assert (*error == NULL);

  data = g_data_input_stream_new (stream);
  /* we use LF only, because the mozilla code can handle lines ending in CR */
  g_data_input_stream_set_newline_type (data, G_DATA_STREAM_NEWLINE_TYPE_LF);
  while ((line = g_data_input_stream_read_line (data, &length, cancellable, error)))
    {
      struct list_result result = { 0, };
      GFileType file_type = G_FILE_TYPE_UNKNOWN;
      GTimeVal tv = { 0, 0 };

      /* strip trailing \r - ParseFTPList only removes it if the line ends in \r\n,
       * but we stripped the \n already.
       */
      if (length > 0 && line[length - 1] == '\r')
        line[--length] = '\0';

      g_debug ("<<%2d <<  %s\n", debug_id, line);
      type = ParseFTPList (line, &state, &result);
      if (type != 'd' && type != 'f' && type != 'l')
        {
          g_free (line);
          continue;
        }

      /* don't list . and .. directories
       * Let's hope they're not important files on some ftp servers
       */
      if (result.fe_fnlen == 1 &&
          result.fe_fname[0] == '.')
        {
          g_free (line);
          continue;
        }
      if (result.fe_fnlen == 2 &&
          result.fe_fname[0] == '.' &&
          result.fe_fname[1] == '.')
        {
          g_free (line);
          continue;
        }

      s = g_strndup (result.fe_fname, result.fe_fnlen);
      file = g_vfs_ftp_file_new_child  (dir, s, NULL);
      g_free (s);
      if (file == NULL)
        {
          g_debug ("# invalid filename, skipping");
          g_free (line);
          continue;
        }

      info = g_file_info_new ();

      s = g_path_get_basename (g_vfs_ftp_file_get_gvfs_path (file));
      g_file_info_set_name (info, s);
      g_free (s);

      if (type == 'l')
        {
          char *link;

          link = g_strndup (result.fe_lname, result.fe_lnlen);
          g_file_info_set_symlink_target (info, link);
          g_file_info_set_is_symlink (info, TRUE);
          g_free (link);
        }

      g_file_info_set_size (info, g_ascii_strtoull (result.fe_size, NULL, 10));

      /* If unix format then parse the attributes */
      if (state.lstyle == 'U')
        {
          char file_mode[10], uid[64], gid[64];
          guint32 mode;

          /* POSIX ls -l form: mode, links, owner, group */
          if (sscanf(line, "%10c %*u %63s %63s", file_mode, uid, gid) == 3)
            {
              if (g_vfs_ftp_parse_mode (file_mode, &mode, &file_type))
                {
                  g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE, mode);
                  g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER, uid);
                  g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_GROUP, gid);
                }
            }
          else
            g_debug ("# unknown listing format\n");
        }

      if (file_type == G_FILE_TYPE_UNKNOWN)
        {
          file_type = type == 'f' ? G_FILE_TYPE_REGULAR :
                      type == 'l' ? G_FILE_TYPE_SYMBOLIC_LINK :
                      G_FILE_TYPE_DIRECTORY;
        }

      gvfs_file_info_populate_default (info,
                                       g_vfs_ftp_file_get_gvfs_path (file),
                                       file_type);

      if (is_unix)
        g_file_info_set_is_hidden (info, result.fe_fnlen > 0 &&
                                         result.fe_fname[0] == '.');

      /* Workaround:
       * result.fetime.tm_year contains actual year instead of offset-from-1900,
       * which mktime expects.
       */
      if (result.fe_time.tm_year >= 1900)
              result.fe_time.tm_year -= 1900;

      tv.tv_sec = mktime (&result.fe_time);
      if (tv.tv_sec != -1)
        g_file_info_set_modification_time (info, &tv);

      g_vfs_ftp_dir_cache_entry_add (entry, file, info);
      g_free (line);
    }

  g_object_unref (data);
  return *error != NULL;
}