r845: Require AppRun to be executable before showing a directory as an
[rox-filer.git] / ROX-Filer / src / diritem.c
blob716e380f4e323803af6cd40ca0faf630e058c785
1 /*
2 * $Id$
4 * Copyright (C) 2001, the ROX-Filer team.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
18 * Place, Suite 330, Boston, MA 02111-1307 USA
21 /* diritem.c - get details about files */
23 /* Don't load icons larger than 400K (this is rather excessive, basically
24 * we just want to stop people crashing the filer with huge icons).
26 #define MAX_ICON_SIZE (400 * 1024)
28 #include "config.h"
30 #include <gtk/gtk.h>
31 #include <errno.h>
32 #include <stdio.h>
33 #include <string.h>
35 #include "global.h"
37 #include "diritem.h"
38 #include "support.h"
39 #include "gui_support.h"
40 #include "mount.h"
41 #include "pixmaps.h"
42 #include "type.h"
43 #include "usericons.h"
44 #include "options.h"
46 static gboolean o_ignore_exec = FALSE;
48 /* Static prototypes */
49 static void set_ignore_exec(guchar *new);
52 /****************************************************************
53 * EXTERNAL INTERFACE *
54 ****************************************************************/
56 void diritem_init(void)
58 option_add_int("display_ignore_exec", o_ignore_exec, set_ignore_exec);
60 read_globicons();
63 /* Bring this item's structure uptodate.
64 * Use diritem_stat() instead the first time to initialise the item.
66 void diritem_restat(guchar *path, DirItem *item, gboolean make_thumb)
68 struct stat info;
70 if (item->image)
72 pixmap_unref(item->image);
73 item->image = NULL;
75 item->flags = 0;
76 item->mime_type = NULL;
78 if (mc_lstat(path, &info) == -1)
80 item->lstat_errno = errno;
81 item->base_type = TYPE_ERROR;
82 item->size = 0;
83 item->mode = 0;
84 item->mtime = item->ctime = item->atime = 0;
85 item->uid = (uid_t) -1;
86 item->gid = (gid_t) -1;
88 else
90 item->lstat_errno = 0;
91 item->size = info.st_size;
92 item->mode = info.st_mode;
93 item->atime = info.st_atime;
94 item->ctime = info.st_ctime;
95 item->mtime = info.st_mtime;
96 item->uid = info.st_uid;
97 item->gid = info.st_gid;
99 if (S_ISLNK(info.st_mode))
101 if (mc_stat(path, &info))
102 item->base_type = TYPE_ERROR;
103 else
104 item->base_type =
105 mode_to_base_type(info.st_mode);
107 item->flags |= ITEM_FLAG_SYMLINK;
109 else
111 item->base_type = mode_to_base_type(info.st_mode);
113 if (item->base_type == TYPE_DIRECTORY)
115 if (mount_is_mounted(path))
116 item->flags |= ITEM_FLAG_MOUNT_POINT
117 | ITEM_FLAG_MOUNTED;
118 else if (g_hash_table_lookup(fstab_mounts,
119 path))
120 item->flags |= ITEM_FLAG_MOUNT_POINT;
125 if (item->base_type == TYPE_DIRECTORY &&
126 !(item->flags & ITEM_FLAG_MOUNT_POINT))
128 uid_t uid = info.st_uid;
129 int path_len;
130 guchar *tmp;
131 struct stat icon;
133 check_globicon(path, item);
135 /* It's a directory:
137 * - If it contains a .DirIcon.png then that's the icon
138 * - If it contains an AppRun then it's an application
139 * - If it contains an AppRun but no .DirIcon then try to
140 * use AppIcon.xpm as the icon.
142 * .DirIcon.png and AppRun must have the same owner as the
143 * directory itself, to prevent abuse of /tmp, etc.
144 * For symlinks, we want the symlink's owner.
147 path_len = strlen(path);
148 /* (sizeof(string) includes \0) */
149 tmp = g_malloc(path_len + sizeof("/.DirIcon.png"));
151 /* Try to find .DirIcon.png... */
152 sprintf(tmp, "%s/%s", path, ".DirIcon.png");
153 if (mc_lstat(tmp, &info) == 0 && info.st_uid == uid)
155 if (info.st_size > MAX_ICON_SIZE ||
156 !S_ISREG(info.st_mode))
158 /* Don't let nasty files cause us trouble */
159 /* (Note: slight race here) */
160 item->image = im_appdir;
161 pixmap_ref(item->image);
163 else
164 item->image = g_fscache_lookup(pixmap_cache,
165 tmp);
168 /* Try to find AppRun... */
169 strcpy(tmp + path_len + 1, "AppRun");
170 if (mc_lstat(tmp, &info) == 0 && info.st_uid == uid &&
171 info.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))
172 item->flags |= ITEM_FLAG_APPDIR;
174 /* Are we still missing an icon for this app? */
175 if (item->flags & ITEM_FLAG_APPDIR && !item->image)
177 strcpy(tmp + path_len + 4, "Icon.xpm");
179 if (mc_lstat(tmp, &icon) == 0 &&
180 S_ISREG(icon.st_mode) &&
181 icon.st_size <= MAX_ICON_SIZE)
183 item->image = g_fscache_lookup(pixmap_cache,
184 tmp);
187 if (!item->image)
189 item->image = im_appdir;
190 pixmap_ref(item->image);
194 g_free(tmp);
196 else if (item->base_type == TYPE_FILE)
198 /* Type determined from path before checking for executables
199 * because some mounts show everything as executable and we
200 * still want to use the file name to set the mime type.
202 item->mime_type = type_from_path(path);
204 /* Note: for symlinks we need the mode of the target */
205 if (info.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))
207 /* Note that the flag is set for ALL executable
208 * files, but the mime_type is only special_exec
209 * if the file doesn't have a known extension when
210 * that option is in force.
212 item->flags |= ITEM_FLAG_EXEC_FILE;
214 if (!o_ignore_exec)
215 item->mime_type = &special_exec;
218 if (!item->mime_type)
219 item->mime_type = item->flags & ITEM_FLAG_EXEC_FILE
220 ? &special_exec
221 : &text_plain;
223 if (make_thumb)
224 item->image = g_fscache_lookup(pixmap_cache, path);
225 else
226 item->image = g_fscache_lookup_full(pixmap_cache,
227 path,
228 FSCACHE_LOOKUP_ONLY_NEW);
229 if (!item->image)
230 check_globicon(path, item);
232 else
233 check_globicon(path, item);
236 if (!item->mime_type)
237 item->mime_type = mime_type_from_base_type(item->base_type);
239 if (!item->image)
241 if (item->base_type == TYPE_ERROR)
243 item->image = im_error;
244 pixmap_ref(im_error);
246 else
247 item->image = type_to_icon(item->mime_type);
251 /* Fill in the item structure with the appropriate details.
252 * 'leafname' field is set to NULL; text_width is unset.
254 void diritem_stat(guchar *path, DirItem *item, gboolean make_thumb)
256 item->leafname = NULL;
257 item->may_delete = FALSE;
258 item->image = NULL;
260 diritem_restat(path, item, make_thumb);
263 /* Frees all fields in the icon, but does not free the icon structure
264 * itself (because it might be part of a larger structure).
266 void diritem_clear(DirItem *item)
268 g_return_if_fail(item != NULL);
270 pixmap_unref(item->image);
271 g_free(item->leafname);
274 static void set_ignore_exec(guchar *new)
276 o_ignore_exec = atoi(new);