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; }
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; }