1 /* -*- Mode: C; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 3 -*- */
2 
3 /*
4  * gtk_prop.c
5  *
6  * Copyright (C) 1999 Rasca, Berlin
7  * EMail: thron@gmx.de
8  *
9  * Olivier Fourdan (fourdan@xfce.org)
10  * Heavily modified as part of the Xfce project (http://www.xfce.org)
11  *
12  * 2001/11/13
13  * Takuro Ashie (ashie@homa.ne.jp)
14  * Modified as part of GImageView project
15  *    (http://gtkmmviewer.sourceforge.net)
16  *
17  * This program is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License as published by
19  * the Free Software Foundation; either version 2 of the License, or
20  * (at your option) any later version.
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, write to the Free Software
29  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30  *
31  * $Id: gtk_prop.c,v 1.12 2004/09/21 08:44:32 makeinu Exp $
32  */
33 
34 #ifdef HAVE_CONFIG_H
35 #  include "config.h"
36 #endif
37 
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <unistd.h>
41 #include <string.h>
42 #include <time.h>
43 #include <grp.h>
44 #include <pwd.h>
45 #include <sys/stat.h>
46 #include <sys/wait.h>
47 #include <gtk/gtk.h>
48 #include <gdk/gdkkeysyms.h>
49 #include "intl.h"
50 #include "gtk_prop.h"
51 
52 #ifdef DMALLOC
53 #  include "dmalloc.h"
54 #endif
55 
56 /* FIXME? */
57 #include "prefs.h"
58 #include "charset.h"
59 /* END FIXME? */
60 
61 
62 #define box_pack_start(box,w) \
63 	gtk_box_pack_start(GTK_BOX(box),w,TRUE,FALSE,0)
64 #define box_pack_end(box,w) \
65 	gtk_box_pack_end(GTK_BOX(box),w,TRUE,FALSE,0)
66 
67 #define X_PAD 8
68 #define Y_PAD 1
69 #define TBL_XOPT GTK_EXPAND
70 
71 typedef struct
72 {
73    GtkWidget *top;
74    GtkWidget *user;
75    GtkWidget *group;
76    fprop *prop;
77    int result;
78    int type;
79 } dlg;
80 
81 static dlg dl;
82 
83 
84 /*
85  */
86 static GtkWidget *
label_new(const char * text,GtkJustification j_type)87 label_new (const char *text, GtkJustification j_type)
88 {
89    GtkWidget *label;
90    label = gtk_label_new (text);
91    gtk_label_set_justify (GTK_LABEL (label), j_type);
92    gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
93    /* j_type == GTK_JUSTIFY_RIGHT? 1.0 : 0.0, 0.5); */
94    return (label);
95 }
96 
97 
98 /*
99  */
100 static void
on_cancel(GtkWidget * btn,gpointer * data)101 on_cancel (GtkWidget * btn, gpointer * data)
102 {
103    if ((int) ((long) data) != DLG_RC_DESTROY) {
104       dl.result = (int) ((long) data);
105       gtk_widget_destroy (dl.top);
106    }
107    gtk_main_quit ();
108 }
109 
110 
111 /*
112  */
113 static void
on_ok(GtkWidget * ok,gpointer * data)114 on_ok (GtkWidget * ok, gpointer * data)
115 {
116    const char *val;
117    struct passwd *pw;
118    struct group *gr;
119 
120    val = gtk_entry_get_text (GTK_ENTRY (dl.user));
121    if (val) {
122       pw = getpwnam (val);
123       if (pw) {
124          dl.prop->uid = pw->pw_uid;
125       }
126    }
127    val = gtk_entry_get_text (GTK_ENTRY (dl.group));
128    if (val) {
129       gr = getgrnam (val);
130       if (gr) {
131          dl.prop->gid = gr->gr_gid;
132       }
133    }
134    gtk_widget_destroy (dl.top);
135 
136    dl.result = (int) ((long) data);
137    gtk_main_quit ();
138 }
139 
140 
141 /*
142  */
143 static void
cb_perm(GtkWidget * toggle,void * data)144 cb_perm (GtkWidget * toggle, void *data)
145 {
146    int bit = (int) ((long) data);
147    if (GTK_TOGGLE_BUTTON (toggle)->active)
148       dl.prop->mode |= (mode_t) bit;
149    else
150       dl.prop->mode &= (mode_t) ~ bit;
151 }
152 
153 
154 /*
155  */
156 static gint
on_key_press(GtkWidget * w,GdkEventKey * event,void * data)157 on_key_press (GtkWidget * w, GdkEventKey * event, void *data)
158 {
159    if (event->keyval == GDK_Escape) {
160       on_cancel ((GtkWidget *) data, (gpointer) ((long) DLG_RC_CANCEL));
161       return (TRUE);
162    }
163    return (FALSE);
164 }
165 
166 
167 /*
168  * create a modal dialog for properties and handle it
169  */
170 gint
dlg_prop(const gchar * path,fprop * prop,gint flags)171 dlg_prop (const gchar *path, fprop * prop, gint flags)
172 {
173    GtkWidget *ok = NULL, *cancel = NULL, *label, *skip, *all, *notebook, *table;
174    GtkWidget *owner[4], *perm[15], *info[12];
175    struct tm *t;
176    struct passwd *pw;
177    struct group *gr;
178    char buf[PATH_MAX + 1];
179    GList *g_user = NULL;
180    GList *g_group = NULL, *g_tmp;
181    int n, len;
182 #ifndef LINE_MAX
183 #define LINE_MAX	1024
184 #endif
185    char line[LINE_MAX + 1];
186 
187 
188    dl.result = 0;
189    dl.prop = prop;
190    dl.top = gtk_dialog_new ();
191    gtk_window_set_title (GTK_WINDOW (dl.top), _("Properties"));
192    gtk_signal_connect (GTK_OBJECT (dl.top), "destroy",
193                        GTK_SIGNAL_FUNC (on_cancel),
194                        (gpointer) ((long) DLG_RC_DESTROY));
195    gtk_window_set_modal (GTK_WINDOW (dl.top), TRUE);
196    gtk_window_set_position (GTK_WINDOW (dl.top), GTK_WIN_POS_MOUSE);
197 
198    notebook = gtk_notebook_new ();
199    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dl.top)->vbox), notebook,
200                        TRUE, TRUE, 0);
201 
202    /* ok and cancel buttons */
203    ok = gtk_button_new_with_label (_("Ok"));
204    cancel = gtk_button_new_with_label (_("Cancel"));
205 
206    GTK_WIDGET_SET_FLAGS (ok, GTK_CAN_DEFAULT);
207    GTK_WIDGET_SET_FLAGS (cancel, GTK_CAN_DEFAULT);
208 
209    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dl.top)->action_area), ok,
210                        TRUE, FALSE, 0);
211    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dl.top)->action_area),
212                        cancel, TRUE, FALSE, 0);
213 
214    gtk_signal_connect (GTK_OBJECT (ok), "clicked",
215                        GTK_SIGNAL_FUNC (on_ok),
216                        (gpointer) ((long) DLG_RC_OK));
217    gtk_signal_connect (GTK_OBJECT (cancel), "clicked",
218                        GTK_SIGNAL_FUNC (on_cancel),
219                        (gpointer) ((long) DLG_RC_CANCEL));
220    gtk_widget_grab_default (ok);
221 
222    if (flags & GTK_PROP_MULTI) {
223       skip = gtk_button_new_with_label (_("Skip"));
224       all = gtk_button_new_with_label (_("All"));
225       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dl.top)->action_area), skip,
226                           TRUE, FALSE, 0);
227       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dl.top)->action_area), all,
228                           TRUE, FALSE, 0);
229       gtk_signal_connect (GTK_OBJECT (skip), "clicked",
230                           GTK_SIGNAL_FUNC (on_cancel),
231                           (gpointer) ((long) DLG_RC_SKIP));
232       gtk_signal_connect (GTK_OBJECT (all), "clicked",
233                           GTK_SIGNAL_FUNC (on_ok),
234                           (gpointer) ((long) DLG_RC_ALL));
235       GTK_WIDGET_SET_FLAGS (skip, GTK_CAN_DEFAULT);
236       GTK_WIDGET_SET_FLAGS (all, GTK_CAN_DEFAULT);
237    }
238 
239 
240    /* date and size page */
241    label = gtk_label_new (_("Info"));
242    table = gtk_table_new (6, 2, FALSE);
243    gtk_notebook_append_page (GTK_NOTEBOOK (notebook), table, label);
244 
245    n = 0;
246    info[n] = label_new (_("Name :"), GTK_JUSTIFY_RIGHT);
247    gtk_table_attach (GTK_TABLE (table), info[n], 0, 1, n, n + 1, TBL_XOPT, 0, X_PAD, Y_PAD);
248    {
249       gchar *path_internal;
250       path_internal = charset_to_internal (path,
251                                            conf.charset_filename,
252                                            conf.charset_auto_detect_fn,
253                                            conf.charset_filename_mode);
254       info[n + 1] = label_new (path_internal, GTK_JUSTIFY_LEFT);
255       g_free (path_internal);
256    }
257    gtk_table_attach (GTK_TABLE (table), info[n + 1], 1, 2, n, n + 1, TBL_XOPT, 0, 0, 0);
258    n += 2;
259 
260    if (!(flags & GTK_PROP_NOT_DETECT_TYPE)) {
261       pid_t pid;
262       int out_fd[2];
263 
264       if (pipe (out_fd) == 0) {
265          pid = fork ();
266          if (pid > 0) {
267             char *p;
268 
269             close (out_fd[1]);
270             len = read (out_fd[0], line, LINE_MAX);
271             if (n > 0) {
272                line[len] = '\0';
273                len = strlen(line);
274                if (line[len - 1] == '\n')
275                   line[len - 1] = '\0';
276             }
277             waitpid (pid, NULL, WUNTRACED);
278             close (out_fd[0]);
279 
280             if ((p = strstr (line, ": ")) != NULL) {
281                p += 2;
282                info[n + 1] = label_new (p, GTK_JUSTIFY_LEFT);
283                info[n] = label_new (_("Type :"), GTK_JUSTIFY_RIGHT);
284                gtk_table_attach (GTK_TABLE (table), info[n], 0, 1, n, n + 1,
285                                  TBL_XOPT, 0, X_PAD, Y_PAD);
286                gtk_table_attach (GTK_TABLE (table), info[n + 1], 1, 2, n, n + 1,
287                                  TBL_XOPT, 0, 0, 0);
288                n += 2;
289             }
290          } else if (pid == 0) {
291             gchar **argv = g_new0 (gchar *, 1);
292 
293             argv[0] = g_strdup ("file");
294             argv[1] = g_strdup (path);
295             argv[2] = NULL;
296 
297             close (out_fd[0]);
298             dup2 (out_fd[1], STDOUT_FILENO);
299 
300             execvp (argv[0], argv);
301          }
302       }
303    }
304 
305    sprintf (buf, _("%ld Bytes"), (unsigned long) prop->size);
306    info[n + 1] = label_new (buf, GTK_JUSTIFY_LEFT);
307    info[n] = label_new (_("Size :"), GTK_JUSTIFY_RIGHT);
308    gtk_table_attach (GTK_TABLE (table), info[n], 0, 1, n, n + 1,
309                      TBL_XOPT, 0, X_PAD, Y_PAD);
310    gtk_table_attach (GTK_TABLE (table), info[n + 1], 1, 2, n, n + 1,
311                      TBL_XOPT, 0, 0, 0);
312    n += 2;
313 
314    t = localtime (&prop->atime);
315    sprintf (buf, "%04d/%02d/%02d  %02d:%02d",
316             t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
317             t->tm_hour, t->tm_min);
318    info[n + 1] = gtk_label_new (buf);
319    info[n] = gtk_label_new (_("Access Time :"));
320    gtk_table_attach (GTK_TABLE (table), info[n], 0, 1, n, n + 1,
321                      TBL_XOPT, 0, X_PAD, Y_PAD);
322    gtk_table_attach (GTK_TABLE (table), info[n + 1], 1, 2, n, n + 1,
323                      TBL_XOPT, 0, 0, 0);
324    n += 2;
325 
326    t = localtime (&prop->mtime);
327    sprintf (buf, "%02d/%02d/%02d  %02d:%02d",
328             t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
329             t->tm_hour, t->tm_min);
330    info[n + 1] = gtk_label_new (buf);
331    info[n] = gtk_label_new (_("Modification Time :"));
332    gtk_table_attach (GTK_TABLE (table), info[n], 0, 1, n, n + 1,
333                      TBL_XOPT, 0, X_PAD, Y_PAD);
334    gtk_table_attach (GTK_TABLE (table), info[n + 1], 1, 2, n, n + 1,
335                      TBL_XOPT, 0, 0, 0);
336    n += 2;
337 
338    t = localtime (&prop->ctime);
339    sprintf (buf, "%04d/%02d/%02d  %02d:%02d",
340             t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
341             t->tm_hour, t->tm_min);
342    info[n + 1] = gtk_label_new (buf);
343    info[n] = gtk_label_new (_("Change Time :"));
344    gtk_table_attach (GTK_TABLE (table), info[n], 0, 1, n, n + 1,
345                      TBL_XOPT, 0, X_PAD, Y_PAD);
346    gtk_table_attach (GTK_TABLE (table), info[n + 1], 1, 2, n, n + 1,
347                      TBL_XOPT, 0, 0, 0);
348    n += 2;
349 
350    /* permissions page */
351    if (!(flags & GTK_PROP_STALE_LINK)) {
352       label = gtk_label_new (_("Permissions"));
353       table = gtk_table_new (3, 5, FALSE);
354       gtk_notebook_append_page (GTK_NOTEBOOK (notebook), table, label);
355 
356       perm[0] = gtk_label_new (_("Owner :"));
357       perm[1] = gtk_check_button_new_with_label (_("Read"));
358       if (prop->mode & S_IRUSR)
359          gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (perm[1]), 1);
360       gtk_signal_connect (GTK_OBJECT (perm[1]), "clicked",
361                           GTK_SIGNAL_FUNC (cb_perm),
362                           (gpointer) ((long) S_IRUSR));
363       perm[2] = gtk_check_button_new_with_label (_("Write"));
364       if (prop->mode & S_IWUSR)
365          gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (perm[2]), 1);
366       gtk_signal_connect (GTK_OBJECT (perm[2]), "clicked",
367                           GTK_SIGNAL_FUNC (cb_perm),
368                           (gpointer) ((long) S_IWUSR));
369       perm[3] = gtk_check_button_new_with_label (_("Execute"));
370       if (prop->mode & S_IXUSR)
371          gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (perm[3]), 1);
372       gtk_signal_connect (GTK_OBJECT (perm[3]), "clicked",
373                           GTK_SIGNAL_FUNC (cb_perm),
374                           (gpointer) ((long) S_IXUSR));
375       perm[4] = gtk_check_button_new_with_label (_("Set UID"));
376       if (prop->mode & S_ISUID)
377          gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (perm[4]), 1);
378       gtk_signal_connect (GTK_OBJECT (perm[4]), "clicked",
379                           GTK_SIGNAL_FUNC (cb_perm),
380                           (gpointer) ((long) S_ISUID));
381 
382       gtk_table_attach (GTK_TABLE (table), perm[0], 0, 1, 0, 1, 0, 0, X_PAD, 0);
383       gtk_table_attach (GTK_TABLE (table), perm[1], 1, 2, 0, 1, 0, 0, X_PAD, 0);
384       gtk_table_attach (GTK_TABLE (table), perm[2], 2, 3, 0, 1, 0, 0, X_PAD, 0);
385       gtk_table_attach (GTK_TABLE (table), perm[3], 3, 4, 0, 1, 0, 0, X_PAD, 0);
386       gtk_table_attach (GTK_TABLE (table), perm[4], 4, 5, 0, 1, 0, 0, X_PAD, 0);
387 
388       perm[5] = gtk_label_new (_("Group :"));
389       perm[6] = gtk_check_button_new_with_label (_("Read"));
390       if (prop->mode & S_IRGRP)
391          gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (perm[6]), 1);
392       gtk_signal_connect (GTK_OBJECT (perm[6]), "clicked",
393                           GTK_SIGNAL_FUNC (cb_perm),
394                           (gpointer) ((long) S_IRGRP));
395       perm[7] = gtk_check_button_new_with_label (_("Write"));
396       if (prop->mode & S_IWGRP)
397          gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (perm[7]), 1);
398       gtk_signal_connect (GTK_OBJECT (perm[7]), "clicked",
399                           GTK_SIGNAL_FUNC (cb_perm),
400                           (gpointer) ((long) S_IWGRP));
401       perm[8] = gtk_check_button_new_with_label (_("Execute"));
402       if (prop->mode & S_IXGRP)
403          gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (perm[8]), 1);
404       gtk_signal_connect (GTK_OBJECT (perm[8]), "clicked",
405                           GTK_SIGNAL_FUNC (cb_perm),
406                           (gpointer) ((long) S_IXGRP));
407       perm[9] = gtk_check_button_new_with_label (_("Set GID"));
408       if (prop->mode & S_ISGID)
409          gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (perm[9]), 1);
410       gtk_signal_connect (GTK_OBJECT (perm[9]), "clicked",
411                           GTK_SIGNAL_FUNC (cb_perm),
412                           (gpointer) ((long) S_ISGID));
413       gtk_table_attach (GTK_TABLE (table), perm[5], 0, 1, 1, 2, 0, 0, X_PAD, 0);
414       gtk_table_attach (GTK_TABLE (table), perm[6], 1, 2, 1, 2, 0, 0, X_PAD, 0);
415       gtk_table_attach (GTK_TABLE (table), perm[7], 2, 3, 1, 2, 0, 0, X_PAD, 0);
416       gtk_table_attach (GTK_TABLE (table), perm[8], 3, 4, 1, 2, 0, 0, X_PAD, 0);
417       gtk_table_attach (GTK_TABLE (table), perm[9], 4, 5, 1, 2, 0, 0, X_PAD, 0);
418 
419       perm[10] = gtk_label_new (_("Other :"));
420       perm[11] = gtk_check_button_new_with_label (_("Read"));
421       if (prop->mode & S_IROTH)
422          gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (perm[11]), 1);
423       gtk_signal_connect (GTK_OBJECT (perm[11]), "clicked",
424                           GTK_SIGNAL_FUNC (cb_perm),
425                           (gpointer) ((long) S_IROTH));
426       perm[12] = gtk_check_button_new_with_label (_("Write"));
427       if (prop->mode & S_IWOTH)
428          gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (perm[12]), 1);
429       gtk_signal_connect (GTK_OBJECT (perm[12]), "clicked",
430                           GTK_SIGNAL_FUNC (cb_perm),
431                           (gpointer) ((long) S_IWOTH));
432       perm[13] = gtk_check_button_new_with_label (_("Execute"));
433       if (prop->mode & S_IXOTH)
434          gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (perm[13]), 1);
435       gtk_signal_connect (GTK_OBJECT (perm[13]), "clicked",
436                           GTK_SIGNAL_FUNC (cb_perm),
437                           (gpointer) ((long) S_IXOTH));
438       perm[14] = gtk_check_button_new_with_label (_("Sticky"));
439       if (prop->mode & S_ISVTX)
440          gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (perm[14]), 1);
441       gtk_signal_connect (GTK_OBJECT (perm[14]), "clicked",
442                           GTK_SIGNAL_FUNC (cb_perm),
443                           (gpointer) ((long) S_ISVTX));
444       gtk_table_attach (GTK_TABLE (table), perm[10], 0, 1, 2, 3, 0, 0, X_PAD, 0);
445       gtk_table_attach (GTK_TABLE (table), perm[11], 1, 2, 2, 3, 0, 0, X_PAD, 0);
446       gtk_table_attach (GTK_TABLE (table), perm[12], 2, 3, 2, 3, 0, 0, X_PAD, 0);
447       gtk_table_attach (GTK_TABLE (table), perm[13], 3, 4, 2, 3, 0, 0, X_PAD, 0);
448       gtk_table_attach (GTK_TABLE (table), perm[14], 4, 5, 2, 3, 0, 0, X_PAD, 0);
449    }
450 
451    if (flags & GTK_PROP_EDITABLE) {
452       gint i, n_perms;
453       n_perms = sizeof (perm) / sizeof (GtkWidget *);
454       for (i = 0; i < n_perms; i++) {
455          gtk_widget_set_sensitive (perm[i], FALSE);
456       }
457    }
458 
459    /* owner/group page */
460    while ((pw = getpwent ()) != NULL) {
461       g_user = g_list_append (g_user, g_strdup (pw->pw_name));
462    }
463    g_user = g_list_sort (g_user, (GCompareFunc) strcmp);
464    endpwent ();
465 
466    while ((gr = getgrent ()) != NULL) {
467       g_group = g_list_append (g_group, g_strdup (gr->gr_name));
468    }
469    endgrent ();
470    g_group = g_list_sort (g_group, (GCompareFunc) strcmp);
471 
472    label = gtk_label_new (_("Owner"));
473    table = gtk_table_new (2, 2, FALSE);
474    gtk_notebook_append_page (GTK_NOTEBOOK (notebook), table, label);
475 
476    pw = getpwuid (prop->uid);
477    sprintf (buf, "%s", pw ? pw->pw_name : _("unknown"));
478    owner[1] = gtk_combo_new ();
479    dl.user = GTK_WIDGET (GTK_COMBO (owner[1])->entry);
480    if (g_user)
481       gtk_combo_set_popdown_strings (GTK_COMBO (owner[1]), g_user);
482    gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (owner[1])->entry), buf);
483    owner[0] = label_new (_("Owner :"), GTK_JUSTIFY_RIGHT);
484    gtk_table_attach (GTK_TABLE (table), owner[0], 0, 1, 0, 1, 0, 0, X_PAD, Y_PAD);
485    gtk_table_attach (GTK_TABLE (table), owner[1], 1, 2, 0, 1, 0, 0, X_PAD, 0);
486 
487    gr = getgrgid (prop->gid);
488    sprintf (buf, "%s", gr ? gr->gr_name : _("unknown"));
489    owner[3] = gtk_combo_new ();
490    dl.group = GTK_WIDGET (GTK_COMBO (owner[3])->entry);
491    if (g_group)
492       gtk_combo_set_popdown_strings (GTK_COMBO (owner[3]), g_group);
493    gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (owner[3])->entry), buf);
494    owner[2] = label_new (_("Group :"), GTK_JUSTIFY_RIGHT);
495    gtk_table_attach (GTK_TABLE (table), owner[2], 0, 1, 1, 2, 0, 0, X_PAD, Y_PAD);
496    gtk_table_attach (GTK_TABLE (table), owner[3], 1, 2, 1, 2, 0, 0, X_PAD, 0);
497 
498    if (flags & GTK_PROP_EDITABLE) {
499       gint i, n_owners;
500       n_owners = sizeof (owner) / sizeof (GtkWidget *);
501       for (i = 0; i < n_owners; i++) {
502          gtk_widget_set_sensitive (owner[i], FALSE);
503       }
504    }
505 
506    gtk_signal_connect (GTK_OBJECT (dl.top), "key_press_event",
507                        GTK_SIGNAL_FUNC (on_key_press),
508                        (gpointer) cancel);
509    gtk_widget_show_all (dl.top);
510 
511    gtk_main ();
512 
513    /* free the lists */
514    g_tmp = g_user;
515    while (g_tmp) {
516       g_free (g_tmp->data);
517       g_tmp = g_tmp->next;
518    }
519    g_list_free (g_user);
520    g_tmp = g_group;
521    while (g_tmp) {
522       g_free (g_tmp->data);
523       g_tmp = g_tmp->next;
524    }
525    g_list_free (g_group);
526    return (dl.result);
527 }
528 
529 
530 gboolean
dlg_prop_from_image_info(GimvImageInfo * info,gint flags)531 dlg_prop_from_image_info (GimvImageInfo *info, gint flags)
532 {
533    fprop prop;
534    gint rc = DLG_RC_CANCEL;
535    const gchar *path;
536    gboolean retval = FALSE;
537 
538    g_return_val_if_fail (info, FALSE);
539 
540    path = gimv_image_info_get_path (info);
541 
542    prop.mode  = info->st.st_mode;
543    prop.uid   = info->st.st_uid;
544    prop.gid   = info->st.st_gid;
545    prop.ctime = info->st.st_ctime;
546    prop.mtime = info->st.st_mtime;
547    prop.atime = info->st.st_atime;
548    prop.size  = info->st.st_size;
549 
550    rc = dlg_prop (path, &prop, 0);
551 
552    switch (rc) {
553    case DLG_RC_OK:
554    case DLG_RC_ALL:
555       if (prop.mode != info->st.st_mode) {
556          chmod (path, prop.mode);
557          retval = TRUE;
558       }
559       if ((prop.uid != info->st.st_uid) || (prop.gid != info->st.st_gid)) {
560          chown (path, prop.uid, prop.gid);
561          retval = TRUE;
562       }
563    default:
564       break;
565    }
566 
567    return retval;
568 }
569