gboolean handle_path (const char *path, struct stat * buf1, int *link_to_dir, int *stale_link) { vfs_path_t *vpath; if (DIR_IS_DOT (path) || DIR_IS_DOTDOT (path)) return FALSE; vpath = vfs_path_from_str (path); if (mc_lstat (vpath, buf1) == -1) { vfs_path_free (vpath); return FALSE; } if (S_ISDIR (buf1->st_mode)) tree_store_mark_checked (path); /* A link to a file or a directory? */ *link_to_dir = 0; *stale_link = 0; if (S_ISLNK (buf1->st_mode)) { struct stat buf2; if (mc_stat (vpath, &buf2) == 0) *link_to_dir = S_ISDIR (buf2.st_mode) != 0; else *stale_link = 1; } vfs_path_free (vpath); return TRUE; }
static int handle_dirent (dir_list * list, const char *fltr, struct dirent *dp, struct stat *buf1, int next_free, int *link_to_dir, int *stale_link) { vfs_path_t *vpath; if (dp->d_name[0] == '.' && dp->d_name[1] == 0) return 0; if (dp->d_name[0] == '.' && dp->d_name[1] == '.' && dp->d_name[2] == 0) return 0; if (!panels_options.show_dot_files && (dp->d_name[0] == '.')) return 0; if (!panels_options.show_backups && dp->d_name[NLENGTH (dp) - 1] == '~') return 0; vpath = vfs_path_from_str (dp->d_name); if (mc_lstat (vpath, buf1) == -1) { /* * lstat() fails - such entries should be identified by * buf1->st_mode being 0. * It happens on QNX Neutrino for /fs/cd0 if no CD is inserted. */ memset (buf1, 0, sizeof (*buf1)); } if (S_ISDIR (buf1->st_mode)) tree_store_mark_checked (dp->d_name); /* A link to a file or a directory? */ *link_to_dir = 0; *stale_link = 0; if (S_ISLNK (buf1->st_mode)) { struct stat buf2; if (mc_stat (vpath, &buf2) == 0) *link_to_dir = S_ISDIR (buf2.st_mode) != 0; else *stale_link = 1; } vfs_path_free (vpath); if (!(S_ISDIR (buf1->st_mode) || *link_to_dir) && (fltr != NULL) && !mc_search (fltr, dp->d_name, MC_SEARCH_T_GLOB)) return 0; /* Need to grow the *list? */ if (next_free == list->size && !grow_list (list)) return -1; return 1; }
static gboolean handle_dirent (struct dirent *dp, const char *fltr, struct stat *buf1, int *link_to_dir, int *stale_link) { vfs_path_t *vpath; if (DIR_IS_DOT (dp->d_name) || DIR_IS_DOTDOT (dp->d_name)) return FALSE; if (!panels_options.show_dot_files && (dp->d_name[0] == '.')) return FALSE; if (!panels_options.show_backups && dp->d_name[strlen (dp->d_name) - 1] == '~') return FALSE; vpath = vfs_path_from_str (dp->d_name); if (mc_lstat (vpath, buf1) == -1) { /* * lstat() fails - such entries should be identified by * buf1->st_mode being 0. * It happens on QNX Neutrino for /fs/cd0 if no CD is inserted. */ memset (buf1, 0, sizeof (*buf1)); } if (S_ISDIR (buf1->st_mode)) tree_store_mark_checked (dp->d_name); /* A link to a file or a directory? */ *link_to_dir = 0; *stale_link = 0; if (S_ISLNK (buf1->st_mode)) { struct stat buf2; if (mc_stat (vpath, &buf2) == 0) *link_to_dir = S_ISDIR (buf2.st_mode) != 0; else *stale_link = 1; } vfs_path_free (vpath); return (S_ISDIR (buf1->st_mode) || *link_to_dir != 0 || fltr == NULL || mc_search (fltr, NULL, dp->d_name, MC_SEARCH_T_GLOB)); }
int handle_path (dir_list * list, const char *path, struct stat *buf1, int next_free, int *link_to_dir, int *stale_link) { vfs_path_t *vpath; if (path[0] == '.' && path[1] == 0) return 0; if (path[0] == '.' && path[1] == '.' && path[2] == 0) return 0; vpath = vfs_path_from_str (path); if (mc_lstat (vpath, buf1) == -1) { vfs_path_free (vpath); return 0; } if (S_ISDIR (buf1->st_mode)) tree_store_mark_checked (path); /* A link to a file or a directory? */ *link_to_dir = 0; *stale_link = 0; if (S_ISLNK (buf1->st_mode)) { struct stat buf2; if (mc_stat (vpath, &buf2) == 0) *link_to_dir = S_ISDIR (buf2.st_mode) != 0; else *stale_link = 1; } vfs_path_free (vpath); /* Need to grow the *list? */ if (next_free == list->size && !grow_list (list)) return -1; return 1; }
static char * resolve_symlinks (const vfs_path_t * vpath) { char *p, *p2; char *buf, *buf2, *q, *r, c; struct stat mybuf; if (vpath->relative) return NULL; p = p2 = g_strdup (vfs_path_as_str (vpath)); r = buf = g_malloc (MC_MAXPATHLEN); buf2 = g_malloc (MC_MAXPATHLEN); *r++ = PATH_SEP; *r = 0; do { q = strchr (p + 1, PATH_SEP); if (!q) { q = strchr (p + 1, 0); if (q == p + 1) break; } c = *q; *q = 0; if (mc_lstat (vpath, &mybuf) < 0) { MC_PTR_FREE (buf); goto ret; } if (!S_ISLNK (mybuf.st_mode)) strcpy (r, p + 1); else { int len; len = mc_readlink (vpath, buf2, MC_MAXPATHLEN - 1); if (len < 0) { MC_PTR_FREE (buf); goto ret; } buf2[len] = 0; if (IS_PATH_SEP (*buf2)) strcpy (buf, buf2); else strcpy (r, buf2); } canonicalize_pathname (buf); r = strchr (buf, 0); if (*r == '\0' || !IS_PATH_SEP (r[-1])) /* FIXME: this condition is always true because r points to the EOL */ { *r++ = PATH_SEP; *r = '\0'; } *q = c; p = q; } while (c != '\0'); if (*buf == '\0') strcpy (buf, PATH_SEP_STR); else if (IS_PATH_SEP (r[-1]) && r != buf + 1) r[-1] = '\0'; ret: g_free (buf2); g_free (p2); return buf; }
/* Bring this item's structure uptodate. * 'parent' is optional; it saves one stat() for directories. */ void diritem_restat(const guchar *path, DirItem *item, struct stat *parent) { struct stat info; if (item->_image) { g_object_unref(item->_image); item->_image = NULL; } item->flags = 0; item->mime_type = NULL; if (mc_lstat(path, &info) == -1) { item->lstat_errno = errno; item->base_type = TYPE_ERROR; item->size = 0; item->mode = 0; item->mtime = item->ctime = item->atime = 0; item->uid = (uid_t) -1; item->gid = (gid_t) -1; } else { guchar *target_path; item->lstat_errno = 0; item->size = info.st_size; item->mode = info.st_mode; item->atime = info.st_atime; item->ctime = info.st_ctime; item->mtime = info.st_mtime; item->uid = info.st_uid; item->gid = info.st_gid; if (ABOUT_NOW(item->mtime) || ABOUT_NOW(item->ctime)) item->flags |= ITEM_FLAG_RECENT; if (xattr_have(path)) item->flags |= ITEM_FLAG_HAS_XATTR; item->label = xlabel_get(path); if (S_ISLNK(info.st_mode)) { if (mc_stat(path, &info)) item->base_type = TYPE_ERROR; else item->base_type = mode_to_base_type(info.st_mode); item->flags |= ITEM_FLAG_SYMLINK; target_path = pathdup(path); } else { item->base_type = mode_to_base_type(info.st_mode); target_path = (guchar *) path; } if (item->base_type == TYPE_DIRECTORY) { if (mount_is_mounted(target_path, &info, target_path == path ? parent : NULL)) item->flags |= ITEM_FLAG_MOUNT_POINT | ITEM_FLAG_MOUNTED; else if (g_hash_table_lookup(fstab_mounts, target_path)) item->flags |= ITEM_FLAG_MOUNT_POINT; } if (path != target_path) g_free(target_path); } if (item->base_type == TYPE_DIRECTORY) { /* KRJW: info.st_uid will be the uid of the dir, regardless * of whether `path' is a dir or a symlink to one. Note that * if path is a symlink to a dir, item->uid will be the uid * of the *symlink*, but we really want the uid of the dir * to which the symlink points. */ examine_dir(path, item, &info); } else if (item->base_type == TYPE_FILE) { if (item->flags & ITEM_FLAG_SYMLINK) { guchar *link_path; link_path = pathdup(path); item->mime_type = type_from_path(link_path ? link_path : path); g_free(link_path); } else item->mime_type = type_from_path(path); /* Note: for symlinks we need the mode of the target */ if (info.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { /* Note that the flag is set for ALL executable * files, but the mime_type must also be executable * for clicking on the file to run it. */ item->flags |= ITEM_FLAG_EXEC_FILE; if (item->mime_type == NULL || item->mime_type == application_octet_stream) { item->mime_type = application_executable; } else if (item->mime_type == text_plain && !strchr(item->leafname, '.')) { item->mime_type = application_x_shellscript; } } else if (item->mime_type == application_x_desktop) { item->flags |= ITEM_FLAG_EXEC_FILE; } if (!item->mime_type) item->mime_type = text_plain; check_globicon(path, item); if (item->mime_type == application_x_desktop && item->_image == NULL) { item->_image = g_fscache_lookup(desktop_icon_cache, path); } } else check_globicon(path, item); if (!item->mime_type) item->mime_type = mime_type_from_base_type(item->base_type); }
/* Fill in more details of the DirItem for a directory item. * - Looks for an image (but maybe still NULL on error) * - Updates ITEM_FLAG_APPDIR * * link_target contains stat info for the link target for symlinks (or for the * item itself if not a link). */ static void examine_dir(const guchar *path, DirItem *item, struct stat *link_target) { struct stat info; static GString *tmp = NULL; uid_t uid = link_target->st_uid; if (!tmp) tmp = g_string_new(NULL); check_globicon(path, item); if (item->flags & ITEM_FLAG_MOUNT_POINT) { item->mime_type = inode_mountpoint; return; /* Try to avoid automounter problems */ } if (link_target->st_mode & S_IWOTH) return; /* Don't trust world-writable dirs */ /* Finding the icon: * * - If it contains a .DirIcon then that's the icon * - If it contains an AppRun then it's an application * - If it contains an AppRun but no .DirIcon then try to * use AppIcon.xpm as the icon. * * .DirIcon and AppRun must have the same owner as the * directory itself, to prevent abuse of /tmp, etc. * For symlinks, we want the symlink's owner. */ g_string_printf(tmp, "%s/.DirIcon", path); if (item->_image) goto no_diricon; /* Already got an icon */ if (mc_lstat(tmp->str, &info) != 0 || info.st_uid != uid) goto no_diricon; /* Missing, or wrong owner */ if (S_ISLNK(info.st_mode) && mc_stat(tmp->str, &info) != 0) goto no_diricon; /* Bad symlink */ if (info.st_size > MAX_ICON_SIZE || !S_ISREG(info.st_mode)) goto no_diricon; /* Too big, or non-regular file */ /* Try to load image; may still get NULL... */ item->_image = g_fscache_lookup(pixmap_cache, tmp->str); no_diricon: /* Try to find AppRun... */ g_string_truncate(tmp, tmp->len - 8); g_string_append(tmp, "AppRun"); if (mc_lstat(tmp->str, &info) != 0 || info.st_uid != uid) goto out; /* Missing, or wrong owner */ if (!(info.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) goto out; /* Not executable */ item->flags |= ITEM_FLAG_APPDIR; /* Try to load AppIcon.xpm... */ if (item->_image) goto out; /* Already got an icon */ g_string_truncate(tmp, tmp->len - 3); g_string_append(tmp, "Icon.xpm"); /* Note: since AppRun is valid we don't need to check AppIcon.xpm * so carefully. */ if (mc_stat(tmp->str, &info) != 0) goto out; /* Missing, or broken symlink */ if (info.st_size > MAX_ICON_SIZE || !S_ISREG(info.st_mode)) goto out; /* Too big, or non-regular file */ /* Try to load image; may still get NULL... */ item->_image = g_fscache_lookup(pixmap_cache, tmp->str); out: if ((item->flags & ITEM_FLAG_APPDIR) && !item->_image) { /* This is an application without an icon */ item->_image = im_appdir; g_object_ref(item->_image); } }
static char * resolve_symlinks (const char *path) { char *buf, *buf2, *q, *r, c; int len; struct stat mybuf; const char *p; if (*path != PATH_SEP) return NULL; r = buf = g_malloc (MC_MAXPATHLEN); buf2 = g_malloc (MC_MAXPATHLEN); *r++ = PATH_SEP; *r = 0; p = path; for (;;) { q = strchr (p + 1, PATH_SEP); if (!q) { q = strchr (p + 1, 0); if (q == p + 1) break; } c = *q; *q = 0; if (mc_lstat (path, &mybuf) < 0) { g_free (buf); g_free (buf2); *q = c; return NULL; } if (!S_ISLNK (mybuf.st_mode)) strcpy (r, p + 1); else { len = mc_readlink (path, buf2, MC_MAXPATHLEN - 1); if (len < 0) { g_free (buf); g_free (buf2); *q = c; return NULL; } buf2[len] = 0; if (*buf2 == PATH_SEP) strcpy (buf, buf2); else strcpy (r, buf2); } canonicalize_pathname (buf); r = strchr (buf, 0); if (!*r || *(r - 1) != PATH_SEP) { *r++ = PATH_SEP; *r = 0; } *q = c; p = q; if (!c) break; } if (!*buf) strcpy (buf, PATH_SEP_STR); else if (*(r - 1) == PATH_SEP && r != buf + 1) *(r - 1) = 0; g_free (buf2); return buf; }