Rename WDialog APIs:
[midnight-commander.git] / src / filemanager / achown.c
blobfa708938bee7018542211749409fed6efb932b63
1 /*
2 Chown-advanced command -- for the Midnight Commander
4 Copyright (C) 1994-2016
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/>.
23 /** \file achown.c
24 * \brief Source: Contains functions for advanced chowning
27 #include <config.h>
29 #include <errno.h>
30 #include <stdio.h>
31 #include <string.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <unistd.h>
36 #include <pwd.h>
37 #include <grp.h>
39 #include "lib/global.h"
41 #include "lib/tty/tty.h"
42 #include "lib/tty/key.h" /* XCTRL and ALT macros */
43 #include "lib/skin.h"
44 #include "lib/strutil.h"
45 #include "lib/vfs/vfs.h"
46 #include "lib/util.h"
47 #include "lib/widget.h"
49 #include "dir.h"
50 #include "midnight.h" /* current_panel */
51 #include "chmod.h"
53 #include "achown.h"
55 /*** global variables ****************************************************************************/
57 /*** file scope macro definitions ****************************************************************/
59 #define BX 5
60 #define BY 5
62 #define BUTTONS 9
63 #define BUTTONS_PERM 5
65 #define B_SETALL B_USER
66 #define B_SKIP (B_USER + 1)
68 /*** file scope type declarations ****************************************************************/
70 /*** file scope variables ************************************************************************/
72 static WDialog *ch_dlg;
74 static struct
76 unsigned long id;
77 int ret_cmd;
78 button_flags_t flags;
79 int x, len;
80 const char *text;
81 } chown_advanced_but[BUTTONS] =
83 /* *INDENT-OFF* */
84 { 0, B_ENTER, NARROW_BUTTON, 3, 0, " "},
85 { 0, B_ENTER, NARROW_BUTTON, 11, 0, " "},
86 { 0, B_ENTER, NARROW_BUTTON, 19, 0, " "},
87 { 0, B_ENTER, NARROW_BUTTON, 29, 0, ""},
88 { 0, B_ENTER, NARROW_BUTTON, 47, 0, ""},
90 { 0, B_SETALL, NORMAL_BUTTON, 0, 0, N_("Set &all")},
91 { 0, B_SKIP, NORMAL_BUTTON, 0, 0, N_("S&kip") },
92 { 0, B_ENTER, DEFPUSH_BUTTON, 0, 0, N_("&Set") },
93 { 0, B_CANCEL, NORMAL_BUTTON, 0, 0, N_("&Cancel") }
94 /* *INDENT-ON* */
97 static WButton *b_att[3]; /* permission */
98 static WButton *b_user, *b_group; /* owner */
99 static WLabel *l_filename;
100 static WLabel *l_mode;
102 static int flag_pos;
103 static int x_toggle;
104 static char ch_flags[11];
105 static const char ch_perm[] = "rwx";
106 static mode_t ch_cmode;
107 static struct stat *sf_stat;
108 static gboolean need_update = FALSE;
109 static gboolean end_chown = FALSE;
110 static int current_file;
111 static gboolean single_set = FALSE;
112 static char *fname;
114 /* --------------------------------------------------------------------------------------------- */
115 /*** file scope functions ************************************************************************/
116 /* --------------------------------------------------------------------------------------------- */
118 static void
119 update_ownership (void)
121 button_set_text (b_user, get_owner (sf_stat->st_uid));
122 button_set_text (b_group, get_group (sf_stat->st_gid));
125 /* --------------------------------------------------------------------------------------------- */
127 static cb_ret_t
128 inc_flag_pos (int f_pos)
130 if (flag_pos == 10)
132 flag_pos = 0;
133 return MSG_NOT_HANDLED;
135 flag_pos++;
136 if ((flag_pos % 3) == 0 || f_pos > 2)
137 return MSG_NOT_HANDLED;
138 return MSG_HANDLED;
141 /* --------------------------------------------------------------------------------------------- */
143 static cb_ret_t
144 dec_flag_pos (int f_pos)
146 if (flag_pos == 0)
148 flag_pos = 10;
149 return MSG_NOT_HANDLED;
151 flag_pos--;
152 if (((flag_pos + 1) % 3) == 0 || f_pos > 2)
153 return MSG_NOT_HANDLED;
154 return MSG_HANDLED;
157 /* --------------------------------------------------------------------------------------------- */
159 static void
160 set_perm_by_flags (char *s, int f_p)
162 int i;
164 for (i = 0; i < 3; i++)
166 if (ch_flags[f_p + i] == '+')
167 s[i] = ch_perm[i];
168 else if (ch_flags[f_p + i] == '-')
169 s[i] = '-';
170 else
171 s[i] = (ch_cmode & (1 << (8 - f_p - i))) ? ch_perm[i] : '-';
175 /* --------------------------------------------------------------------------------------------- */
177 static void
178 update_permissions (void)
180 set_perm_by_flags (b_att[0]->text.start, 0);
181 set_perm_by_flags (b_att[1]->text.start, 3);
182 set_perm_by_flags (b_att[2]->text.start, 6);
185 /* --------------------------------------------------------------------------------------------- */
187 static mode_t
188 get_perm (char *s, int base)
190 mode_t m;
192 m = 0;
193 m |= (s[0] == '-') ? 0 :
194 ((s[0] == '+') ? (mode_t) (1 << (base + 2)) : (1 << (base + 2)) & ch_cmode);
196 m |= (s[1] == '-') ? 0 :
197 ((s[1] == '+') ? (mode_t) (1 << (base + 1)) : (1 << (base + 1)) & ch_cmode);
199 m |= (s[2] == '-') ? 0 : ((s[2] == '+') ? (mode_t) (1 << base) : (1 << base) & ch_cmode);
201 return m;
204 /* --------------------------------------------------------------------------------------------- */
206 static mode_t
207 get_mode (void)
209 mode_t m;
211 m = ch_cmode ^ (ch_cmode & 0777);
212 m |= get_perm (ch_flags, 6);
213 m |= get_perm (ch_flags + 3, 3);
214 m |= get_perm (ch_flags + 6, 0);
216 return m;
219 /* --------------------------------------------------------------------------------------------- */
221 static void
222 print_flags (void)
224 int i;
226 tty_setcolor (COLOR_NORMAL);
228 for (i = 0; i < 3; i++)
230 widget_move (ch_dlg, BY + 1, 9 + i);
231 tty_print_char (ch_flags[i]);
234 for (i = 0; i < 3; i++)
236 widget_move (ch_dlg, BY + 1, 17 + i);
237 tty_print_char (ch_flags[i + 3]);
240 for (i = 0; i < 3; i++)
242 widget_move (ch_dlg, BY + 1, 25 + i);
243 tty_print_char (ch_flags[i + 6]);
246 update_permissions ();
248 for (i = 0; i < 15; i++)
250 widget_move (ch_dlg, BY + 1, 35 + i);
251 tty_print_char (ch_flags[9]);
253 for (i = 0; i < 15; i++)
255 widget_move (ch_dlg, BY + 1, 53 + i);
256 tty_print_char (ch_flags[10]);
260 /* --------------------------------------------------------------------------------------------- */
262 static void
263 chown_info_update (void)
265 char buffer[BUF_SMALL];
267 /* mode */
268 g_snprintf (buffer, sizeof (buffer), "Permissions (octal): %o", get_mode ());
269 label_set_text (l_mode, buffer);
271 /* permissions */
272 update_permissions ();
275 /* --------------------------------------------------------------------------------------------- */
277 static void
278 update_mode (WDialog * h)
280 print_flags ();
281 chown_info_update ();
282 widget_set_state (WIDGET (h->current->data), WST_FOCUSED, TRUE);
285 /* --------------------------------------------------------------------------------------------- */
287 static cb_ret_t
288 chl_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data)
290 switch (msg)
292 case MSG_KEY:
293 switch (parm)
295 case KEY_LEFT:
296 case KEY_RIGHT:
298 WDialog *h = DIALOG (w);
300 h->ret_value = parm;
301 dlg_stop (h);
303 default:
304 break;
307 default:
308 return dlg_default_callback (w, sender, msg, parm, data);
312 /* --------------------------------------------------------------------------------------------- */
314 static void
315 do_enter_key (WDialog * h, int f_pos)
317 WListbox *chl_list;
318 struct passwd *chl_pass;
319 struct group *chl_grp;
320 int fe;
321 gboolean chl_end, is_owner;
325 int result;
326 WDialog *chl_dlg;
327 const char *title;
328 int lxx, lyy, b_pos;
330 is_owner = (f_pos == 3);
331 title = is_owner ? _("owner") : _("group");
333 lxx = (COLS - 74) / 2 + (is_owner ? 35 : 53);
334 lyy = (LINES - 13) / 2;
335 chl_end = FALSE;
337 chl_dlg =
338 dlg_create (TRUE, lyy, lxx, 13, 17, WPOS_KEEP_DEFAULT, TRUE, dialog_colors,
339 chl_callback, NULL, "[Advanced Chown]", title);
341 /* get new listboxes */
342 chl_list = listbox_new (1, 1, 11, 15, FALSE, NULL);
343 listbox_add_item (chl_list, LISTBOX_APPEND_AT_END, 0, "<Unknown>", NULL, FALSE);
344 if (is_owner)
346 /* get and put user names in the listbox */
347 setpwent ();
348 while ((chl_pass = getpwent ()) != NULL)
349 listbox_add_item (chl_list, LISTBOX_APPEND_SORTED, 0, chl_pass->pw_name, NULL,
350 FALSE);
351 endpwent ();
352 fe = listbox_search_text (chl_list, get_owner (sf_stat->st_uid));
354 else
356 /* get and put group names in the listbox */
357 setgrent ();
358 while ((chl_grp = getgrent ()) != NULL)
359 listbox_add_item (chl_list, LISTBOX_APPEND_SORTED, 0, chl_grp->gr_name, NULL,
360 FALSE);
361 endgrent ();
362 fe = listbox_search_text (chl_list, get_group (sf_stat->st_gid));
365 listbox_select_entry (chl_list, fe);
367 b_pos = chl_list->pos;
368 add_widget (chl_dlg, chl_list);
370 result = dlg_run (chl_dlg);
372 if (result != B_CANCEL)
374 if (b_pos != chl_list->pos)
376 gboolean ok = FALSE;
377 char *text;
379 listbox_get_current (chl_list, &text, NULL);
380 if (is_owner)
382 chl_pass = getpwnam (text);
383 if (chl_pass != NULL)
385 ok = TRUE;
386 sf_stat->st_uid = chl_pass->pw_uid;
389 else
391 chl_grp = getgrnam (text);
392 if (chl_grp != NULL)
394 sf_stat->st_gid = chl_grp->gr_gid;
395 ok = TRUE;
398 if (ok)
400 ch_flags[f_pos + 6] = '+';
401 update_ownership ();
403 dlg_focus (h);
404 if (ok)
405 print_flags ();
407 if (result == KEY_LEFT)
409 if (!is_owner)
410 chl_end = TRUE;
411 dlg_select_prev_widget (ch_dlg);
412 f_pos--;
414 else if (result == KEY_RIGHT)
416 if (is_owner)
417 chl_end = TRUE;
418 dlg_select_next_widget (ch_dlg);
419 f_pos++;
423 /* Here we used to redraw the window */
424 dlg_destroy (chl_dlg);
426 while (chl_end);
429 /* --------------------------------------------------------------------------------------------- */
431 static void
432 chown_refresh (void)
434 dlg_default_repaint (ch_dlg);
436 tty_setcolor (COLOR_NORMAL);
438 widget_move (ch_dlg, BY - 1, 8);
439 tty_print_string (_("owner"));
440 widget_move (ch_dlg, BY - 1, 16);
441 tty_print_string (_("group"));
442 widget_move (ch_dlg, BY - 1, 24);
443 tty_print_string (_("other"));
445 widget_move (ch_dlg, BY - 1, 35);
446 tty_print_string (_("owner"));
447 widget_move (ch_dlg, BY - 1, 53);
448 tty_print_string (_("group"));
450 widget_move (ch_dlg, BY + 1, 3);
451 tty_print_string (_("Flag"));
453 print_flags ();
456 /* --------------------------------------------------------------------------------------------- */
458 static void
459 b_setpos (int f_pos)
461 b_att[0]->hotpos = -1;
462 b_att[1]->hotpos = -1;
463 b_att[2]->hotpos = -1;
464 b_att[f_pos]->hotpos = (flag_pos % 3);
467 /* --------------------------------------------------------------------------------------------- */
469 static cb_ret_t
470 advanced_chown_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data)
472 WDialog *h = DIALOG (w);
473 int i;
474 int f_pos;
475 unsigned long id;
477 id = dlg_get_current_widget_id (h);
479 for (i = 0; i < BUTTONS_PERM; i++)
480 if (chown_advanced_but[i].id == id)
481 break;
483 f_pos = i;
484 i = 0;
486 switch (msg)
488 case MSG_DRAW:
489 chown_refresh ();
490 chown_info_update ();
491 return MSG_HANDLED;
493 case MSG_POST_KEY:
494 if (f_pos < 3)
495 b_setpos (f_pos);
496 return MSG_HANDLED;
498 case MSG_FOCUS:
499 if (f_pos < 3)
501 if ((flag_pos / 3) != f_pos)
502 flag_pos = f_pos * 3;
503 b_setpos (f_pos);
505 else if (f_pos < BUTTONS_PERM)
506 flag_pos = f_pos + 6;
507 return MSG_HANDLED;
509 case MSG_KEY:
510 switch (parm)
512 case XCTRL ('b'):
513 case KEY_LEFT:
514 if (f_pos < BUTTONS_PERM)
515 return (dec_flag_pos (f_pos));
516 break;
518 case XCTRL ('f'):
519 case KEY_RIGHT:
520 if (f_pos < BUTTONS_PERM)
521 return (inc_flag_pos (f_pos));
522 break;
524 case ' ':
525 if (f_pos < 3)
526 return MSG_HANDLED;
527 break;
529 case '\n':
530 case KEY_ENTER:
531 if (f_pos <= 2 || f_pos >= BUTTONS_PERM)
532 break;
533 do_enter_key (h, f_pos);
534 return MSG_HANDLED;
536 case ALT ('x'):
537 i++;
539 case ALT ('w'):
540 i++;
542 case ALT ('r'):
543 parm = i + 3;
544 for (i = 0; i < 3; i++)
545 ch_flags[i * 3 + parm - 3] = (x_toggle & (1 << parm)) ? '-' : '+';
546 x_toggle ^= (1 << parm);
547 update_mode (h);
548 dlg_broadcast_msg (h, MSG_DRAW);
549 widget_set_state (WIDGET (h->current->data), WST_FOCUSED, TRUE);
550 break;
552 case XCTRL ('x'):
553 i++;
555 case XCTRL ('w'):
556 i++;
558 case XCTRL ('r'):
559 parm = i;
560 for (i = 0; i < 3; i++)
561 ch_flags[i * 3 + parm] = (x_toggle & (1 << parm)) ? '-' : '+';
562 x_toggle ^= (1 << parm);
563 update_mode (h);
564 dlg_broadcast_msg (h, MSG_DRAW);
565 widget_set_state (WIDGET (h->current->data), WST_FOCUSED, TRUE);
566 break;
568 case 'x':
569 i++;
571 case 'w':
572 i++;
574 case 'r':
575 if (f_pos > 2)
576 break;
577 flag_pos = f_pos * 3 + i; /* (strchr(ch_perm,parm)-ch_perm); */
578 if (BUTTON (h->current->data)->text.start[(flag_pos % 3)] == '-')
579 ch_flags[flag_pos] = '+';
580 else
581 ch_flags[flag_pos] = '-';
582 update_mode (h);
583 break;
585 case '4':
586 i++;
588 case '2':
589 i++;
591 case '1':
592 if (f_pos <= 2)
594 flag_pos = i + f_pos * 3;
595 ch_flags[flag_pos] = '=';
596 update_mode (h);
598 break;
600 case '-':
601 if (f_pos > 2)
602 break;
604 case '*':
605 if (parm == '*')
606 parm = '=';
608 case '=':
609 case '+':
610 if (f_pos <= 4)
612 ch_flags[flag_pos] = parm;
613 update_mode (h);
614 send_message (h, sender, MSG_KEY, KEY_RIGHT, NULL);
615 if (flag_pos > 8 || (flag_pos % 3) == 0)
616 dlg_select_next_widget (h);
618 break;
620 default:
621 break;
623 return MSG_NOT_HANDLED;
625 default:
626 return dlg_default_callback (w, sender, msg, parm, data);
630 /* --------------------------------------------------------------------------------------------- */
632 static void
633 init_chown_advanced (void)
635 int i;
636 int dlg_h = 12;
637 int dlg_w = 74;
638 int y;
640 static gboolean i18n = FALSE;
642 if (!i18n)
644 for (i = BUTTONS_PERM; i < BUTTONS; i++)
646 #ifdef ENABLE_NLS
647 chown_advanced_but[i].text = _(chown_advanced_but[i].text);
648 #endif /* ENABLE_NLS */
650 chown_advanced_but[i].len = str_term_width1 (chown_advanced_but[i].text) + 3;
651 if (chown_advanced_but[i].flags == DEFPUSH_BUTTON)
652 chown_advanced_but[i].len += 2; /* "<>" */
655 i18n = TRUE;
658 do_refresh ();
660 sf_stat = g_new (struct stat, 1);
661 current_file = 0;
662 end_chown = need_update = FALSE;
663 single_set = (current_panel->marked < 2);
664 memset (ch_flags, '=', 11);
665 flag_pos = 0;
666 x_toggle = 070;
668 if (!single_set)
669 dlg_h += 2;
671 ch_dlg =
672 dlg_create (TRUE, 0, 0, dlg_h, dlg_w, WPOS_CENTER, FALSE, dialog_colors,
673 advanced_chown_callback, NULL, "[Advanced Chown]", _("Chown advanced command"));
676 l_filename = label_new (2, 3, "");
677 add_widget (ch_dlg, l_filename);
679 add_widget (ch_dlg, hline_new (3, -1, -1));
681 #define XTRACT(i,y) y, BX+chown_advanced_but[i].x, \
682 chown_advanced_but[i].ret_cmd, chown_advanced_but[i].flags, \
683 (chown_advanced_but[i].text), NULL
684 b_att[0] = button_new (XTRACT (0, BY));
685 chown_advanced_but[0].id = add_widget (ch_dlg, b_att[0]);
686 b_att[1] = button_new (XTRACT (1, BY));
687 chown_advanced_but[1].id = add_widget (ch_dlg, b_att[1]);
688 b_att[2] = button_new (XTRACT (2, BY));
689 chown_advanced_but[2].id = add_widget (ch_dlg, b_att[2]);
690 b_user = button_new (XTRACT (3, BY));
691 chown_advanced_but[3].id = add_widget (ch_dlg, b_user);
692 b_group = button_new (XTRACT (4, BY));
693 chown_advanced_but[4].id = add_widget (ch_dlg, b_group);
694 #undef XTRACT
696 l_mode = label_new (BY + 2, 3, "");
697 add_widget (ch_dlg, l_mode);
699 y = BY + 3;
700 if (!single_set)
702 i = BUTTONS_PERM;
703 add_widget (ch_dlg, hline_new (y++, -1, -1));
704 chown_advanced_but[i].id = add_widget (ch_dlg,
705 button_new (y,
706 WIDGET (ch_dlg)->cols / 2 -
707 chown_advanced_but[i].len,
708 chown_advanced_but[i].ret_cmd,
709 chown_advanced_but[i].flags,
710 chown_advanced_but[i].text, NULL));
711 i++;
712 chown_advanced_but[i].id = add_widget (ch_dlg,
713 button_new (y, WIDGET (ch_dlg)->cols / 2 + 1,
714 chown_advanced_but[i].ret_cmd,
715 chown_advanced_but[i].flags,
716 chown_advanced_but[i].text, NULL));
717 y++;
720 i = BUTTONS_PERM + 2;
721 add_widget (ch_dlg, hline_new (y++, -1, -1));
722 chown_advanced_but[i].id = add_widget (ch_dlg,
723 button_new (y,
724 WIDGET (ch_dlg)->cols / 2 -
725 chown_advanced_but[i].len,
726 chown_advanced_but[i].ret_cmd,
727 chown_advanced_but[i].flags,
728 chown_advanced_but[i].text, NULL));
729 i++;
730 chown_advanced_but[i].id = add_widget (ch_dlg,
731 button_new (y, WIDGET (ch_dlg)->cols / 2 + 1,
732 chown_advanced_but[i].ret_cmd,
733 chown_advanced_but[i].flags,
734 chown_advanced_but[i].text, NULL));
736 dlg_select_widget (b_att[0]);
739 /* --------------------------------------------------------------------------------------------- */
741 static void
742 chown_advanced_done (void)
744 g_free (sf_stat);
745 if (need_update)
746 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
747 repaint_screen ();
750 /* --------------------------------------------------------------------------------------------- */
752 #if 0
753 static void
754 do_chown (uid_t u, gid_t g)
756 chown (current_panel->dir.list[current_file].fname, u, g);
757 file_mark (current_panel, current_file, 0);
759 #endif
761 /* --------------------------------------------------------------------------------------------- */
763 static char *
764 next_file (void)
766 while (!current_panel->dir.list[current_file].f.marked)
767 current_file++;
769 return current_panel->dir.list[current_file].fname;
772 /* --------------------------------------------------------------------------------------------- */
774 static void
775 apply_advanced_chowns (struct stat *sf)
777 vfs_path_t *vpath;
778 char *lc_fname;
779 gid_t a_gid = sf->st_gid;
780 uid_t a_uid = sf->st_uid;
782 lc_fname = current_panel->dir.list[current_file].fname;
783 vpath = vfs_path_from_str (lc_fname);
784 need_update = end_chown = TRUE;
785 if (mc_chmod (vpath, get_mode ()) == -1)
786 message (D_ERROR, MSG_ERROR, _("Cannot chmod \"%s\"\n%s"),
787 lc_fname, unix_error_string (errno));
788 /* call mc_chown only, if mc_chmod didn't fail */
789 else if (mc_chown (vpath, (ch_flags[9] == '+') ? sf->st_uid : (uid_t) (-1),
790 (ch_flags[10] == '+') ? sf->st_gid : (gid_t) (-1)) == -1)
791 message (D_ERROR, MSG_ERROR, _("Cannot chown \"%s\"\n%s"),
792 lc_fname, unix_error_string (errno));
793 do_file_mark (current_panel, current_file, 0);
794 vfs_path_free (vpath);
798 lc_fname = next_file ();
799 vpath = vfs_path_from_str (lc_fname);
801 if (mc_stat (vpath, sf) != 0)
803 vfs_path_free (vpath);
804 break;
807 ch_cmode = sf->st_mode;
809 if (mc_chmod (vpath, get_mode ()) == -1)
810 message (D_ERROR, MSG_ERROR, _("Cannot chmod \"%s\"\n%s"),
811 lc_fname, unix_error_string (errno));
812 /* call mc_chown only, if mc_chmod didn't fail */
813 else if (mc_chown (vpath, (ch_flags[9] == '+') ? a_uid : (uid_t) (-1),
814 (ch_flags[10] == '+') ? a_gid : (gid_t) (-1)) == -1)
815 message (D_ERROR, MSG_ERROR, _("Cannot chown \"%s\"\n%s"),
816 lc_fname, unix_error_string (errno));
818 do_file_mark (current_panel, current_file, 0);
819 vfs_path_free (vpath);
821 while (current_panel->marked != 0);
824 /* --------------------------------------------------------------------------------------------- */
825 /*** public functions ****************************************************************************/
826 /* --------------------------------------------------------------------------------------------- */
828 void
829 chown_advanced_cmd (void)
831 /* Number of files at startup */
832 int files_on_begin;
834 files_on_begin = MAX (1, current_panel->marked);
837 { /* do while any files remaining */
838 int file_idx;
839 char buffer[BUF_MEDIUM];
840 vfs_path_t *vpath;
841 int result;
843 init_chown_advanced ();
845 if (current_panel->marked)
846 fname = next_file (); /* next marked file */
847 else
848 fname = selection (current_panel)->fname; /* single file */
849 vpath = vfs_path_from_str (fname);
851 if (mc_stat (vpath, sf_stat) != 0)
852 { /* get status of file */
853 dlg_destroy (ch_dlg);
854 vfs_path_free (vpath);
855 break;
858 ch_cmode = sf_stat->st_mode;
860 file_idx = files_on_begin == 1 ? 1 : (files_on_begin - current_panel->marked + 1);
861 g_snprintf (buffer, sizeof (buffer), "%s (%d/%d)",
862 str_fit_to_term (fname, WIDGET (ch_dlg)->cols - 20, J_LEFT_FIT),
863 file_idx, files_on_begin);
864 label_set_text (l_filename, buffer);
865 chown_refresh ();
866 update_ownership ();
868 result = dlg_run (ch_dlg);
870 switch (result)
872 case B_CANCEL:
873 end_chown = TRUE;
874 break;
876 case B_ENTER:
877 need_update = TRUE;
878 if (mc_chmod (vpath, get_mode ()) == -1)
879 message (D_ERROR, MSG_ERROR, _("Cannot chmod \"%s\"\n%s"),
880 fname, unix_error_string (errno));
881 /* call mc_chown only, if mc_chmod didn't fail */
882 else if (mc_chown
883 (vpath, (ch_flags[9] == '+') ? sf_stat->st_uid : (uid_t) (-1),
884 (ch_flags[10] == '+') ? sf_stat->st_gid : (gid_t) (-1)) == -1)
885 message (D_ERROR, MSG_ERROR, _("Cannot chown \"%s\"\n%s"), fname,
886 unix_error_string (errno));
887 break;
889 case B_SETALL:
890 apply_advanced_chowns (sf_stat);
891 break;
893 case B_SKIP:
894 default:
895 break;
898 if (current_panel->marked && result != B_CANCEL)
900 do_file_mark (current_panel, current_file, 0);
901 need_update = TRUE;
903 dlg_destroy (ch_dlg);
904 vfs_path_free (vpath);
906 while (current_panel->marked && !end_chown);
908 chown_advanced_done ();
911 /* --------------------------------------------------------------------------------------------- */