2 Chown-advanced command -- for the Midnight Commander
4 Copyright (C) 1994-2024
5 Free Software Foundation, Inc.
7 This file is part of the Midnight Commander.
9 The Midnight Commander is free software: you can redistribute it
10 and/or modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation, either version 3 of the License,
12 or (at your option) any later version.
14 The Midnight Commander is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 * \brief Source: Contains functions for advanced chowning
34 #include <sys/types.h>
38 #include "lib/global.h"
40 #include "lib/tty/tty.h"
41 #include "lib/tty/key.h" /* XCTRL and ALT macros */
43 #include "lib/vfs/vfs.h"
44 #include "lib/strutil.h"
46 #include "lib/widget.h"
48 #include "cmd.h" /* advanced_chown_cmd() */
50 /*** global variables ****************************************************************************/
52 /*** file scope macro definitions ****************************************************************/
58 #define BUTTONS_PERM 5
60 #define B_SETALL B_USER
61 #define B_SKIP (B_USER + 1)
63 /*** file scope type declarations ****************************************************************/
65 /*** forward declarations (file scope functions) *************************************************/
67 /*** file scope variables ************************************************************************/
77 } advanced_chown_but
[BUTTONS
] = {
79 { 0, B_ENTER
, NARROW_BUTTON
, 3, 0, " " },
80 { 0, B_ENTER
, NARROW_BUTTON
, 11, 0, " " },
81 { 0, B_ENTER
, NARROW_BUTTON
, 19, 0, " " },
82 { 0, B_ENTER
, NARROW_BUTTON
, 29, 0, "" },
83 { 0, B_ENTER
, NARROW_BUTTON
, 47, 0, "" },
85 { 0, B_SETALL
, NORMAL_BUTTON
, 0, 0, N_("Set &all") },
86 { 0, B_SKIP
, NORMAL_BUTTON
, 0, 0, N_("S&kip") },
87 { 0, B_ENTER
, DEFPUSH_BUTTON
, 0, 0, N_("&Set") },
88 { 0, B_CANCEL
, NORMAL_BUTTON
, 0, 0, N_("&Cancel") }
92 static int current_file
;
93 static gboolean ignore_all
;
95 static WButton
*b_att
[3]; /* permission */
96 static WButton
*b_user
, *b_group
; /* owner */
97 static WLabel
*l_filename
;
98 static WLabel
*l_mode
;
102 static char ch_flags
[11];
103 static const char ch_perm
[] = "rwx";
104 static mode_t ch_cmode
;
105 static struct stat sf_stat
;
107 /* --------------------------------------------------------------------------------------------- */
108 /*** file scope functions ************************************************************************/
109 /* --------------------------------------------------------------------------------------------- */
112 advanced_chown_init (void)
114 static gboolean i18n
= FALSE
;
122 for (i
= BUTTONS_PERM
; i
< BUTTONS
; i
++)
125 advanced_chown_but
[i
].text
= _(advanced_chown_but
[i
].text
);
126 #endif /* ENABLE_NLS */
128 advanced_chown_but
[i
].len
= str_term_width1 (advanced_chown_but
[i
].text
) + 3;
129 if (advanced_chown_but
[i
].flags
== DEFPUSH_BUTTON
)
130 advanced_chown_but
[i
].len
+= 2; /* "<>" */
135 /* --------------------------------------------------------------------------------------------- */
143 return MSG_NOT_HANDLED
;
148 return flag_pos
% 3 == 0 ? MSG_NOT_HANDLED
: MSG_HANDLED
;
151 /* --------------------------------------------------------------------------------------------- */
159 return MSG_NOT_HANDLED
;
164 return (flag_pos
+ 1) % 3 == 0 ? MSG_NOT_HANDLED
: MSG_HANDLED
;
167 /* --------------------------------------------------------------------------------------------- */
170 set_perm_by_flags (char *s
, int f_p
)
174 for (i
= 0; i
< 3; i
++)
176 if (ch_flags
[f_p
+ i
] == '+')
178 else if (ch_flags
[f_p
+ i
] == '-')
181 s
[i
] = (ch_cmode
& (1 << (8 - f_p
- i
))) != 0 ? ch_perm
[i
] : '-';
185 /* --------------------------------------------------------------------------------------------- */
188 get_perm (char *s
, int base
)
192 m
|= (s
[0] == '-') ? 0 :
193 ((s
[0] == '+') ? (mode_t
) (1 << (base
+ 2)) : (1 << (base
+ 2)) & ch_cmode
);
195 m
|= (s
[1] == '-') ? 0 :
196 ((s
[1] == '+') ? (mode_t
) (1 << (base
+ 1)) : (1 << (base
+ 1)) & ch_cmode
);
198 m
|= (s
[2] == '-') ? 0 : ((s
[2] == '+') ? (mode_t
) (1 << base
) : (1 << base
) & ch_cmode
);
203 /* --------------------------------------------------------------------------------------------- */
210 m
= ch_cmode
^ (ch_cmode
& 0777);
211 m
|= get_perm (ch_flags
, 6);
212 m
|= get_perm (ch_flags
+ 3, 3);
213 m
|= get_perm (ch_flags
+ 6, 0);
218 /* --------------------------------------------------------------------------------------------- */
221 update_permissions (void)
223 set_perm_by_flags (b_att
[0]->text
.start
, 0);
224 set_perm_by_flags (b_att
[1]->text
.start
, 3);
225 set_perm_by_flags (b_att
[2]->text
.start
, 6);
228 /* --------------------------------------------------------------------------------------------- */
231 update_ownership (void)
233 button_set_text (b_user
, get_owner (sf_stat
.st_uid
));
234 button_set_text (b_group
, get_group (sf_stat
.st_gid
));
237 /* --------------------------------------------------------------------------------------------- */
240 print_flags (const WDialog
*h
)
244 tty_setcolor (COLOR_NORMAL
);
246 for (i
= 0; i
< 3; i
++)
248 widget_gotoyx (h
, BY
+ 1, advanced_chown_but
[0].x
+ 6 + i
);
249 tty_print_char (ch_flags
[i
]);
252 for (i
= 0; i
< 3; i
++)
254 widget_gotoyx (h
, BY
+ 1, advanced_chown_but
[1].x
+ 6 + i
);
255 tty_print_char (ch_flags
[i
+ 3]);
258 for (i
= 0; i
< 3; i
++)
260 widget_gotoyx (h
, BY
+ 1, advanced_chown_but
[2].x
+ 6 + i
);
261 tty_print_char (ch_flags
[i
+ 6]);
264 update_permissions ();
266 for (i
= 0; i
< 15; i
++)
268 widget_gotoyx (h
, BY
+ 1, advanced_chown_but
[3].x
+ 6 + i
);
269 tty_print_char (ch_flags
[9]);
271 for (i
= 0; i
< 15; i
++)
273 widget_gotoyx (h
, BY
+ 1, advanced_chown_but
[4].x
+ 6 + i
);
274 tty_print_char (ch_flags
[10]);
278 /* --------------------------------------------------------------------------------------------- */
281 advanced_chown_refresh (const WDialog
*h
)
283 tty_setcolor (COLOR_NORMAL
);
285 widget_gotoyx (h
, BY
- 1, advanced_chown_but
[0].x
+ 5);
286 tty_print_string (_("owner"));
287 widget_gotoyx (h
, BY
- 1, advanced_chown_but
[1].x
+ 5);
288 tty_print_string (_("group"));
289 widget_gotoyx (h
, BY
- 1, advanced_chown_but
[2].x
+ 5);
290 tty_print_string (_("other"));
292 widget_gotoyx (h
, BY
- 1, advanced_chown_but
[3].x
+ 5);
293 tty_print_string (_("owner"));
294 widget_gotoyx (h
, BY
- 1, advanced_chown_but
[4].x
+ 5);
295 tty_print_string (_("group"));
297 widget_gotoyx (h
, BY
+ 1, 3);
298 tty_print_string (_("Flag"));
302 /* --------------------------------------------------------------------------------------------- */
305 advanced_chown_info_update (void)
308 label_set_textv (l_mode
, _("Permissions (octal): %o"), get_mode ());
311 update_permissions ();
314 /* --------------------------------------------------------------------------------------------- */
317 update_mode (WGroup
*g
)
319 print_flags (DIALOG (g
));
320 advanced_chown_info_update ();
321 widget_set_state (WIDGET (g
->current
->data
), WST_FOCUSED
, TRUE
);
324 /* --------------------------------------------------------------------------------------------- */
327 perm_button_callback (Widget
*w
, Widget
*sender
, widget_msg_t msg
, int parm
, void *data
)
329 WButton
*b
= BUTTON (w
);
330 WGroup
*g
= w
->owner
;
334 /* one of permission buttons */
337 else if (b
== b_att
[1])
339 else /* if (w == b_att [1] */
348 flag_pos
= f_pos
* 3 + b
->hotpos
;
361 flag_pos
= f_pos
* 3 + b
->hotpos
;
362 ch_flags
[flag_pos
] = parm
;
364 send_message (w
, NULL
, MSG_KEY
, KEY_RIGHT
, NULL
);
366 group_select_next_widget (g
);
374 ret
= inc_flag_pos ();
375 b
->hotpos
= flag_pos
% 3;
384 ret
= dec_flag_pos ();
385 b
->hotpos
= flag_pos
% 3;
404 flag_pos
= f_pos
* 3 + i
;
405 if (b
->text
.start
[flag_pos
% 3] == '-')
406 ch_flags
[flag_pos
] = '+';
408 ch_flags
[flag_pos
] = '-';
409 update_mode (w
->owner
);
422 flag_pos
= f_pos
* 3 + i
;
423 ch_flags
[flag_pos
] = '=';
430 /* continue key handling in the dialog level */
431 return MSG_NOT_HANDLED
;
434 return button_default_callback (w
, sender
, msg
, parm
, data
);
438 /* --------------------------------------------------------------------------------------------- */
441 perm_button_mouse_callback (Widget
*w
, mouse_msg_t msg
, mouse_event_t
*event
)
446 /* place cursor on flag that is being modified */
447 BUTTON (w
)->hotpos
= CLAMP (event
->x
- 1, 0, 2);
451 button_mouse_default_callback (w
, msg
, event
);
456 /* --------------------------------------------------------------------------------------------- */
459 perm_button_new (int y
, int x
, int action
, button_flags_t flags
, const char *text
,
465 /* create base button using native API */
466 b
= button_new (y
, x
, action
, flags
, text
, callback
);
469 /* we don't want HOTKEY */
470 widget_want_hotkey (w
, FALSE
);
472 w
->callback
= perm_button_callback
;
473 w
->mouse_callback
= perm_button_mouse_callback
;
478 /* --------------------------------------------------------------------------------------------- */
481 chl_callback (Widget
*w
, Widget
*sender
, widget_msg_t msg
, int parm
, void *data
)
491 WDialog
*h
= DIALOG (w
);
503 return dlg_default_callback (w
, sender
, msg
, parm
, data
);
507 /* --------------------------------------------------------------------------------------------- */
510 user_group_button_cb (WButton
*button
, int action
)
512 Widget
*w
= WIDGET (button
);
518 if (button
== b_user
)
519 f_pos
= BUTTONS_PERM
- 2;
520 else if (button
== b_group
)
521 f_pos
= BUTTONS_PERM
- 1;
523 return 0; /* do nothing */
527 WGroup
*g
= w
->owner
;
528 WDialog
*h
= DIALOG (g
);
529 Widget
*wh
= WIDGET (h
);
531 gboolean is_owner
= (f_pos
== BUTTONS_PERM
- 2);
538 struct passwd
*chl_pass
;
539 struct group
*chl_grp
;
546 lxx
= WIDGET (b_user
)->rect
.x
+ 1;
551 lxx
= WIDGET (b_group
)->rect
.x
+ 1;
555 dlg_create (TRUE
, wh
->rect
.y
- 1, lxx
, wh
->rect
.lines
+ 2, 17, WPOS_KEEP_DEFAULT
, TRUE
,
556 dialog_colors
, chl_callback
, NULL
, "[Advanced Chown]", title
);
558 /* get new listboxes */
560 listbox_new (1, 1, WIDGET (chl_dlg
)->rect
.lines
- 2, WIDGET (chl_dlg
)->rect
.cols
- 2,
562 listbox_add_item (chl_list
, LISTBOX_APPEND_AT_END
, 0, "<Unknown>", NULL
, FALSE
);
565 /* get and put user names in the listbox */
567 while ((chl_pass
= getpwent ()) != NULL
)
568 listbox_add_item (chl_list
, LISTBOX_APPEND_SORTED
, 0, chl_pass
->pw_name
, NULL
,
571 fe
= listbox_search_text (chl_list
, get_owner (sf_stat
.st_uid
));
575 /* get and put group names in the listbox */
577 while ((chl_grp
= getgrent ()) != NULL
)
578 listbox_add_item (chl_list
, LISTBOX_APPEND_SORTED
, 0, chl_grp
->gr_name
, NULL
,
581 fe
= listbox_search_text (chl_list
, get_group (sf_stat
.st_gid
));
584 listbox_set_current (chl_list
, fe
);
586 b_current
= chl_list
->current
;
587 group_add_widget (GROUP (chl_dlg
), chl_list
);
589 result
= dlg_run (chl_dlg
);
591 if (result
!= B_CANCEL
)
593 if (b_current
!= chl_list
->current
)
598 listbox_get_current (chl_list
, &text
, NULL
);
601 chl_pass
= getpwnam (text
);
602 if (chl_pass
!= NULL
)
604 sf_stat
.st_uid
= chl_pass
->pw_uid
;
610 chl_grp
= getgrnam (text
);
613 sf_stat
.st_gid
= chl_grp
->gr_gid
;
619 group_select_current_widget (g
);
622 ch_flags
[f_pos
+ 6] = '+';
624 group_select_current_widget (g
);
629 if (result
== KEY_LEFT
)
633 group_select_prev_widget (g
);
636 else if (result
== KEY_RIGHT
)
640 group_select_next_widget (g
);
645 /* Here we used to redraw the window */
646 widget_destroy (WIDGET (chl_dlg
));
653 /* --------------------------------------------------------------------------------------------- */
656 advanced_chown_bg_callback (Widget
*w
, Widget
*sender
, widget_msg_t msg
, int parm
, void *data
)
661 frame_callback (w
, NULL
, MSG_DRAW
, 0, NULL
);
662 advanced_chown_refresh (DIALOG (w
->owner
));
663 advanced_chown_info_update ();
667 return frame_callback (w
, sender
, msg
, parm
, data
);
671 /* --------------------------------------------------------------------------------------------- */
674 advanced_chown_callback (Widget
*w
, Widget
*sender
, widget_msg_t msg
, int parm
, void *data
)
676 WGroup
*g
= GROUP (w
);
694 for (i
= 0; i
< 3; i
++)
695 ch_flags
[i
* 3 + parm
- 3] = (x_toggle
& (1 << parm
)) ? '-' : '+';
696 x_toggle
^= (1 << parm
);
711 for (i
= 0; i
< 3; i
++)
712 ch_flags
[i
* 3 + parm
] = (x_toggle
& (1 << parm
)) ? '-' : '+';
713 x_toggle
^= (1 << parm
);
721 return MSG_NOT_HANDLED
;
724 return dlg_default_callback (w
, sender
, msg
, parm
, data
);
728 /* --------------------------------------------------------------------------------------------- */
731 advanced_chown_dlg_create (WPanel
*panel
)
741 memset (ch_flags
, '=', 11);
745 single_set
= (panel
->marked
< 2);
750 dlg_create (TRUE
, 0, 0, lines
, cols
, WPOS_CENTER
, FALSE
, dialog_colors
,
751 advanced_chown_callback
, NULL
, "[Advanced Chown]", _("Chown advanced command"));
752 ch_grp
= GROUP (ch_dlg
);
754 /* draw background */
755 ch_dlg
->bg
->callback
= advanced_chown_bg_callback
;
757 l_filename
= label_new (2, 3, NULL
);
758 group_add_widget (ch_grp
, l_filename
);
760 group_add_widget (ch_grp
, hline_new (3, -1, -1));
762 #define XTRACT(i,y,cb) y, BX+advanced_chown_but[i].x, \
763 advanced_chown_but[i].ret_cmd, advanced_chown_but[i].flags, \
764 (advanced_chown_but[i].text), cb
765 b_att
[0] = perm_button_new (XTRACT (0, BY
, NULL
));
766 advanced_chown_but
[0].id
= group_add_widget (ch_grp
, b_att
[0]);
767 b_att
[1] = perm_button_new (XTRACT (1, BY
, NULL
));
768 advanced_chown_but
[1].id
= group_add_widget (ch_grp
, b_att
[1]);
769 b_att
[2] = perm_button_new (XTRACT (2, BY
, NULL
));
770 advanced_chown_but
[2].id
= group_add_widget (ch_grp
, b_att
[2]);
771 b_user
= button_new (XTRACT (3, BY
, user_group_button_cb
));
772 advanced_chown_but
[3].id
= group_add_widget (ch_grp
, b_user
);
773 b_group
= button_new (XTRACT (4, BY
, user_group_button_cb
));
774 advanced_chown_but
[4].id
= group_add_widget (ch_grp
, b_group
);
776 l_mode
= label_new (BY
+ 2, 3, NULL
);
777 group_add_widget (ch_grp
, l_mode
);
783 group_add_widget (ch_grp
, hline_new (y
++, -1, -1));
784 advanced_chown_but
[i
].id
= group_add_widget (ch_grp
,
786 WIDGET (ch_dlg
)->rect
.cols
/ 2 -
787 advanced_chown_but
[i
].len
,
788 advanced_chown_but
[i
].ret_cmd
,
789 advanced_chown_but
[i
].flags
,
790 advanced_chown_but
[i
].text
, NULL
));
792 advanced_chown_but
[i
].id
= group_add_widget (ch_grp
,
794 WIDGET (ch_dlg
)->rect
.cols
/ 2 + 1,
795 advanced_chown_but
[i
].ret_cmd
,
796 advanced_chown_but
[i
].flags
,
797 advanced_chown_but
[i
].text
, NULL
));
801 i
= BUTTONS_PERM
+ 2;
802 group_add_widget (ch_grp
, hline_new (y
++, -1, -1));
803 advanced_chown_but
[i
].id
= group_add_widget (ch_grp
,
805 WIDGET (ch_dlg
)->rect
.cols
/ 2 -
806 advanced_chown_but
[i
].len
,
807 advanced_chown_but
[i
].ret_cmd
,
808 advanced_chown_but
[i
].flags
,
809 advanced_chown_but
[i
].text
, NULL
));
811 advanced_chown_but
[i
].id
= group_add_widget (ch_grp
,
812 button_new (y
, WIDGET (ch_dlg
)->rect
.cols
/ 2 + 1,
813 advanced_chown_but
[i
].ret_cmd
,
814 advanced_chown_but
[i
].flags
,
815 advanced_chown_but
[i
].text
, NULL
));
817 widget_select (WIDGET (b_att
[0]));
822 /* --------------------------------------------------------------------------------------------- */
825 advanced_chown_done (gboolean need_update
)
828 update_panels (UP_OPTIMIZE
, UP_KEEPSEL
);
832 /* --------------------------------------------------------------------------------------------- */
834 static const GString
*
835 next_file (const WPanel
*panel
)
837 while (panel
->dir
.list
[current_file
].f
.marked
== 0)
840 return panel
->dir
.list
[current_file
].fname
;
843 /* --------------------------------------------------------------------------------------------- */
846 try_advanced_chown (const vfs_path_t
*p
, mode_t m
, uid_t u
, gid_t g
)
849 const char *fname
= NULL
;
851 while ((chmod_result
= mc_chmod (p
, m
)) == -1 && !ignore_all
)
853 int my_errno
= errno
;
858 fname
= x_basename (vfs_path_as_str (p
));
859 msg
= g_strdup_printf (_("Cannot chmod \"%s\"\n%s"), fname
, unix_error_string (my_errno
));
861 query_dialog (MSG_ERROR
, msg
, D_ERROR
, 4, _("&Ignore"), _("Ignore &all"), _("&Retry"),
868 /* call mc_chown() only, if mc_chmod() didn't fail */
873 /* call mc_chown() only, if mc_chmod() didn't fail */
877 /* retry chmod of this file */
882 /* stop remain files processing */
887 /* call mc_chown() only, if mc_chmod didn't fail */
888 while (chmod_result
!= -1 && mc_chown (p
, u
, g
) == -1 && !ignore_all
)
890 int my_errno
= errno
;
895 fname
= x_basename (vfs_path_as_str (p
));
896 msg
= g_strdup_printf (_("Cannot chown \"%s\"\n%s"), fname
, unix_error_string (my_errno
));
898 query_dialog (MSG_ERROR
, msg
, D_ERROR
, 4, _("&Ignore"), _("Ignore &all"), _("&Retry"),
914 /* retry chown of this file */
919 /* stop remain files processing */
928 /* --------------------------------------------------------------------------------------------- */
931 do_advanced_chown (WPanel
*panel
, const vfs_path_t
*p
, mode_t m
, uid_t u
, gid_t g
)
935 ret
= try_advanced_chown (p
, m
, u
, g
);
937 do_file_mark (panel
, current_file
, 0);
942 /* --------------------------------------------------------------------------------------------- */
945 apply_advanced_chowns (WPanel
*panel
, vfs_path_t
*vpath
, struct stat
*sf
)
947 gid_t a_gid
= sf
->st_gid
;
948 uid_t a_uid
= sf
->st_uid
;
951 if (!do_advanced_chown (panel
, vpath
, get_mode (),
952 (ch_flags
[9] == '+') ? a_uid
: (uid_t
) (-1),
953 (ch_flags
[10] == '+') ? a_gid
: (gid_t
) (-1)))
958 const GString
*fname
;
960 fname
= next_file (panel
);
961 vpath
= vfs_path_from_str (fname
->str
);
962 ok
= (mc_stat (vpath
, sf
) == 0);
966 /* if current file was deleted outside mc -- try next file */
967 /* decrease panel->marked */
968 do_file_mark (panel
, current_file
, 0);
975 ch_cmode
= sf
->st_mode
;
977 ok
= do_advanced_chown (panel
, vpath
, get_mode (),
978 (ch_flags
[9] == '+') ? a_uid
: (uid_t
) (-1),
979 (ch_flags
[10] == '+') ? a_gid
: (gid_t
) (-1));
982 vfs_path_free (vpath
, TRUE
);
984 while (ok
&& panel
->marked
!= 0);
987 /* --------------------------------------------------------------------------------------------- */
988 /*** public functions ****************************************************************************/
989 /* --------------------------------------------------------------------------------------------- */
992 advanced_chown_cmd (WPanel
*panel
)
994 gboolean need_update
;
997 /* Number of files at startup */
1000 files_on_begin
= MAX (1, panel
->marked
);
1002 advanced_chown_init ();
1008 { /* do while any files remaining */
1011 const GString
*fname
;
1017 need_update
= FALSE
;
1020 if (panel
->marked
!= 0)
1021 fname
= next_file (panel
); /* next marked file */
1023 fname
= panel_current_entry (panel
)->fname
; /* single file */
1025 vpath
= vfs_path_from_str (fname
->str
);
1027 if (mc_stat (vpath
, &sf_stat
) != 0)
1029 vfs_path_free (vpath
, TRUE
);
1033 ch_cmode
= sf_stat
.st_mode
;
1035 ch_dlg
= advanced_chown_dlg_create (panel
);
1037 file_idx
= files_on_begin
== 1 ? 1 : (files_on_begin
- panel
->marked
+ 1);
1038 label_set_textv (l_filename
, "%s (%d/%d)",
1039 str_fit_to_term (fname
->str
, WIDGET (ch_dlg
)->rect
.cols
- 20, J_LEFT_FIT
),
1040 file_idx
, files_on_begin
);
1041 update_ownership ();
1043 result
= dlg_run (ch_dlg
);
1053 uid_t uid
= ch_flags
[9] == '+' ? sf_stat
.st_uid
: (uid_t
) (-1);
1054 gid_t gid
= ch_flags
[10] == '+' ? sf_stat
.st_gid
: (gid_t
) (-1);
1056 if (panel
->marked
<= 1)
1058 /* single or last file */
1059 if (mc_chmod (vpath
, get_mode ()) == -1)
1060 message (D_ERROR
, MSG_ERROR
, _("Cannot chmod \"%s\"\n%s"),
1061 fname
->str
, unix_error_string (errno
));
1062 /* call mc_chown only, if mc_chmod didn't fail */
1063 else if (mc_chown (vpath
, uid
, gid
) == -1)
1064 message (D_ERROR
, MSG_ERROR
, _("Cannot chown \"%s\"\n%s"), fname
->str
,
1065 unix_error_string (errno
));
1069 else if (!try_advanced_chown (vpath
, get_mode (), uid
, gid
))
1071 /* stop multiple files processing */
1081 apply_advanced_chowns (panel
, vpath
, &sf_stat
);
1091 if (panel
->marked
!= 0 && result
!= B_CANCEL
)
1093 do_file_mark (panel
, current_file
, 0);
1097 vfs_path_free (vpath
, TRUE
);
1099 widget_destroy (WIDGET (ch_dlg
));
1101 while (panel
->marked
!= 0 && !end_chown
);
1103 advanced_chown_done (need_update
);
1106 /* --------------------------------------------------------------------------------------------- */