Build "Advanced chown command" dialog in normal order.
[midnight-commander.git] / src / filemanager / achown.c
blob4f56776149ff4e5adb9650d537cfb21d16bfaa68
1 /*
2 Chown-advanced command -- for the Midnight Commander
4 Copyright (C) 1994, 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
5 2005, 2007, 2011
6 The Free Software Foundation, Inc.
8 This file is part of the Midnight Commander.
10 The Midnight Commander is free software: you can redistribute it
11 and/or modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation, either version 3 of the License,
13 or (at your option) any later version.
15 The Midnight Commander is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 /** \file achown.c
25 * \brief Source: Contains functions for advanced chowning
28 #include <config.h>
30 #include <errno.h>
31 #include <stdio.h>
32 #include <string.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37 #include <pwd.h>
38 #include <grp.h>
40 #include "lib/global.h"
42 #include "lib/tty/tty.h"
43 #include "lib/tty/key.h" /* XCTRL and ALT macros */
44 #include "lib/skin.h"
45 #include "lib/strutil.h"
46 #include "lib/vfs/vfs.h"
47 #include "lib/util.h"
48 #include "lib/widget.h"
50 #include "dir.h"
51 #include "midnight.h" /* current_panel */
52 #include "chmod.h"
54 #include "achown.h"
56 /*** global variables ****************************************************************************/
58 /*** file scope macro definitions ****************************************************************/
60 #define BX 5
61 #define BY 5
63 #define BUTTONS 9
64 #define BUTTONS_PERM 5
66 #define B_SETALL B_USER
67 #define B_SKIP (B_USER + 1)
68 #define B_OWN (B_USER + 3)
69 #define B_GRP (B_USER + 4)
70 #define B_OTH (B_USER + 5)
71 #define B_OUSER (B_USER + 6)
72 #define B_OGROUP (B_USER + 7)
74 /*** file scope type declarations ****************************************************************/
76 /*** file scope variables ************************************************************************/
78 static struct Dlg_head *ch_dlg;
80 static struct
82 unsigned long id;
83 int ret_cmd, flags, x, len;
84 const char *text;
85 } chown_advanced_but[BUTTONS] =
87 /* *INDENT-OFF* */
88 { 0, B_ENTER, NARROW_BUTTON, 3, 0, " "},
89 { 0, B_ENTER, NARROW_BUTTON, 11, 0, " "},
90 { 0, B_ENTER, NARROW_BUTTON, 19, 0, " "},
91 { 0, B_ENTER, NARROW_BUTTON, 29, 0, ""},
92 { 0, B_ENTER, NARROW_BUTTON, 47, 0, ""},
94 { 0, B_SETALL, NORMAL_BUTTON, 0, 0, N_("Set &all")},
95 { 0, B_SKIP, NORMAL_BUTTON, 0, 0, N_("S&kip") },
96 { 0, B_ENTER, DEFPUSH_BUTTON, 0, 0, N_("&Set") },
97 { 0, B_CANCEL, NORMAL_BUTTON, 0, 0, N_("&Cancel") }
98 /* *INDENT-ON* */
101 static WButton *b_att[3]; /* permission */
102 static WButton *b_user, *b_group; /* owner */
103 static WLabel *l_filename;
104 static WLabel *l_mode;
106 static int flag_pos;
107 static int x_toggle;
108 static char ch_flags[11];
109 static const char ch_perm[] = "rwx";
110 static mode_t ch_cmode;
111 static struct stat *sf_stat;
112 static gboolean need_update = FALSE;
113 static gboolean end_chown = FALSE;
114 static int current_file;
115 static gboolean single_set = FALSE;
116 static char *fname;
118 /* --------------------------------------------------------------------------------------------- */
119 /*** file scope functions ************************************************************************/
120 /* --------------------------------------------------------------------------------------------- */
122 static void
123 update_ownership (void)
125 button_set_text (b_user, get_owner (sf_stat->st_uid));
126 button_set_text (b_group, get_group (sf_stat->st_gid));
129 /* --------------------------------------------------------------------------------------------- */
131 static cb_ret_t
132 inc_flag_pos (int f_pos)
134 if (flag_pos == 10)
136 flag_pos = 0;
137 return MSG_NOT_HANDLED;
139 flag_pos++;
140 if ((flag_pos % 3) == 0 || f_pos > 2)
141 return MSG_NOT_HANDLED;
142 return MSG_HANDLED;
145 /* --------------------------------------------------------------------------------------------- */
147 static cb_ret_t
148 dec_flag_pos (int f_pos)
150 if (flag_pos == 0)
152 flag_pos = 10;
153 return MSG_NOT_HANDLED;
155 flag_pos--;
156 if (((flag_pos + 1) % 3) == 0 || f_pos > 2)
157 return MSG_NOT_HANDLED;
158 return MSG_HANDLED;
161 /* --------------------------------------------------------------------------------------------- */
163 static void
164 set_perm_by_flags (char *s, int f_p)
166 int i;
168 for (i = 0; i < 3; i++)
170 if (ch_flags[f_p + i] == '+')
171 s[i] = ch_perm[i];
172 else if (ch_flags[f_p + i] == '-')
173 s[i] = '-';
174 else
175 s[i] = (ch_cmode & (1 << (8 - f_p - i))) ? ch_perm[i] : '-';
179 /* --------------------------------------------------------------------------------------------- */
181 static void
182 update_permissions (void)
184 set_perm_by_flags (b_att[0]->text.start, 0);
185 set_perm_by_flags (b_att[1]->text.start, 3);
186 set_perm_by_flags (b_att[2]->text.start, 6);
189 /* --------------------------------------------------------------------------------------------- */
191 static mode_t
192 get_perm (char *s, int base)
194 mode_t m;
196 m = 0;
197 m |= (s[0] == '-') ? 0 :
198 ((s[0] == '+') ? (mode_t) (1 << (base + 2)) : (1 << (base + 2)) & ch_cmode);
200 m |= (s[1] == '-') ? 0 :
201 ((s[1] == '+') ? (mode_t) (1 << (base + 1)) : (1 << (base + 1)) & ch_cmode);
203 m |= (s[2] == '-') ? 0 : ((s[2] == '+') ? (mode_t) (1 << base) : (1 << base) & ch_cmode);
205 return m;
208 /* --------------------------------------------------------------------------------------------- */
210 static mode_t
211 get_mode (void)
213 mode_t m;
215 m = ch_cmode ^ (ch_cmode & 0777);
216 m |= get_perm (ch_flags, 6);
217 m |= get_perm (ch_flags + 3, 3);
218 m |= get_perm (ch_flags + 6, 0);
220 return m;
223 /* --------------------------------------------------------------------------------------------- */
225 static void
226 print_flags (void)
228 int i;
230 tty_setcolor (COLOR_NORMAL);
232 for (i = 0; i < 3; i++)
234 widget_move (ch_dlg, BY + 1, 9 + i);
235 tty_print_char (ch_flags[i]);
238 for (i = 0; i < 3; i++)
240 widget_move (ch_dlg, BY + 1, 17 + i);
241 tty_print_char (ch_flags[i + 3]);
244 for (i = 0; i < 3; i++)
246 widget_move (ch_dlg, BY + 1, 25 + i);
247 tty_print_char (ch_flags[i + 6]);
250 update_permissions ();
252 for (i = 0; i < 15; i++)
254 widget_move (ch_dlg, BY + 1, 35 + i);
255 tty_print_char (ch_flags[9]);
257 for (i = 0; i < 15; i++)
259 widget_move (ch_dlg, BY + 1, 53 + i);
260 tty_print_char (ch_flags[10]);
264 /* --------------------------------------------------------------------------------------------- */
266 static void
267 chown_info_update (void)
269 char buffer[BUF_SMALL];
271 /* mode */
272 g_snprintf (buffer, sizeof (buffer), "Permissions (octal): %o", get_mode ());
273 label_set_text (l_mode, buffer);
275 /* permissions */
276 update_permissions ();
279 /* --------------------------------------------------------------------------------------------- */
281 static void
282 update_mode (Dlg_head * h)
284 print_flags ();
285 chown_info_update ();
286 send_message (WIDGET (h->current->data), NULL, WIDGET_FOCUS, 0, NULL);
289 /* --------------------------------------------------------------------------------------------- */
291 static cb_ret_t
292 chl_callback (Dlg_head * h, Widget * sender, dlg_msg_t msg, int parm, void *data)
294 switch (msg)
296 case DLG_KEY:
297 switch (parm)
299 case KEY_LEFT:
300 case KEY_RIGHT:
301 h->ret_value = parm;
302 dlg_stop (h);
305 default:
306 return default_dlg_callback (h, sender, msg, parm, data);
310 /* --------------------------------------------------------------------------------------------- */
312 static void
313 do_enter_key (Dlg_head * h, int f_pos)
315 Dlg_head *chl_dlg;
316 WListbox *chl_list;
317 struct passwd *chl_pass;
318 struct group *chl_grp;
319 int fe;
320 int lxx, lyy, b_pos;
321 gboolean chl_end, is_owner;
322 const char *title;
323 int result;
327 is_owner = (f_pos == 3);
328 title = is_owner ? _("owner") : _("group");
330 lxx = (COLS - 74) / 2 + (is_owner ? 35 : 53);
331 lyy = (LINES - 13) / 2;
332 chl_end = FALSE;
334 chl_dlg =
335 create_dlg (TRUE, lyy, lxx, 13, 17, dialog_colors, chl_callback, NULL,
336 "[Advanced Chown]", title, DLG_COMPACT);
338 /* get new listboxes */
339 chl_list = listbox_new (1, 1, 11, 15, FALSE, NULL);
340 listbox_add_item (chl_list, LISTBOX_APPEND_AT_END, 0, "<Unknown>", NULL);
341 if (is_owner)
343 /* get and put user names in the listbox */
344 setpwent ();
345 while ((chl_pass = getpwent ()) != NULL)
346 listbox_add_item (chl_list, LISTBOX_APPEND_SORTED, 0, chl_pass->pw_name, NULL);
347 endpwent ();
348 fe = listbox_search_text (chl_list, get_owner (sf_stat->st_uid));
350 else
352 /* get and put group names in the listbox */
353 setgrent ();
354 while ((chl_grp = getgrent ()) != NULL)
355 listbox_add_item (chl_list, LISTBOX_APPEND_SORTED, 0, chl_grp->gr_name, NULL);
356 endgrent ();
357 fe = listbox_search_text (chl_list, get_group (sf_stat->st_gid));
360 listbox_select_entry (chl_list, fe);
362 b_pos = chl_list->pos;
363 add_widget (chl_dlg, chl_list);
365 result = run_dlg (chl_dlg);
367 if (b_pos != chl_list->pos)
369 gboolean ok = FALSE;
370 char *text;
372 listbox_get_current (chl_list, &text, NULL);
373 if (is_owner)
375 chl_pass = getpwnam (text);
376 if (chl_pass != NULL)
378 ok = TRUE;
379 sf_stat->st_uid = chl_pass->pw_uid;
382 else
384 chl_grp = getgrnam (text);
385 if (chl_grp != NULL)
387 sf_stat->st_gid = chl_grp->gr_gid;
388 ok = TRUE;
391 if (ok)
393 ch_flags[f_pos + 6] = '+';
394 update_ownership ();
396 dlg_focus (h);
397 if (ok)
398 print_flags ();
400 if (result == KEY_LEFT)
402 if (!is_owner)
403 chl_end = TRUE;
404 dlg_one_up (ch_dlg);
405 f_pos--;
407 else if (result == KEY_RIGHT)
409 if (is_owner)
410 chl_end = TRUE;
411 dlg_one_down (ch_dlg);
412 f_pos++;
414 /* Here we used to redraw the window */
415 destroy_dlg (chl_dlg);
417 while (chl_end);
420 /* --------------------------------------------------------------------------------------------- */
422 static void
423 chown_refresh (void)
425 common_dialog_repaint (ch_dlg);
427 tty_setcolor (COLOR_NORMAL);
429 widget_move (ch_dlg, BY - 1, 8);
430 tty_print_string (_("owner"));
431 widget_move (ch_dlg, BY - 1, 16);
432 tty_print_string (_("group"));
433 widget_move (ch_dlg, BY - 1, 24);
434 tty_print_string (_("other"));
436 widget_move (ch_dlg, BY - 1, 35);
437 tty_print_string (_("owner"));
438 widget_move (ch_dlg, BY - 1, 53);
439 tty_print_string (_("group"));
441 widget_move (ch_dlg, BY + 1, 3);
442 tty_print_string (_("Flag"));
444 print_flags ();
447 /* --------------------------------------------------------------------------------------------- */
449 static void
450 b_setpos (int f_pos)
452 b_att[0]->hotpos = -1;
453 b_att[1]->hotpos = -1;
454 b_att[2]->hotpos = -1;
455 b_att[f_pos]->hotpos = (flag_pos % 3);
458 /* --------------------------------------------------------------------------------------------- */
460 static cb_ret_t
461 advanced_chown_callback (Dlg_head * h, Widget * sender, dlg_msg_t msg, int parm, void *data)
463 int i;
464 int f_pos;
465 unsigned int id;
467 id = dlg_get_current_widget_id (h);
469 for (i = 0; i < BUTTONS_PERM; i++)
470 if (chown_advanced_but[i].id == id)
471 break;
473 f_pos = i;
474 i = 0;
476 switch (msg)
478 case DLG_DRAW:
479 chown_refresh ();
480 chown_info_update ();
481 return MSG_HANDLED;
483 case DLG_POST_KEY:
484 if (f_pos < 3)
485 b_setpos (f_pos);
486 return MSG_HANDLED;
488 case DLG_FOCUS:
489 if (f_pos < 3)
491 if ((flag_pos / 3) != f_pos)
492 flag_pos = f_pos * 3;
493 b_setpos (f_pos);
495 else if (f_pos < BUTTONS_PERM)
496 flag_pos = f_pos + 6;
497 return MSG_HANDLED;
499 case DLG_KEY:
500 switch (parm)
502 case XCTRL ('b'):
503 case KEY_LEFT:
504 if (f_pos < BUTTONS_PERM)
505 return (dec_flag_pos (f_pos));
506 break;
508 case XCTRL ('f'):
509 case KEY_RIGHT:
510 if (f_pos < BUTTONS_PERM)
511 return (inc_flag_pos (f_pos));
512 break;
514 case ' ':
515 if (f_pos < 3)
516 return MSG_HANDLED;
517 break;
519 case '\n':
520 case KEY_ENTER:
521 if (f_pos <= 2 || f_pos >= BUTTONS_PERM)
522 break;
523 do_enter_key (h, f_pos);
524 return MSG_HANDLED;
526 case ALT ('x'):
527 i++;
529 case ALT ('w'):
530 i++;
532 case ALT ('r'):
533 parm = i + 3;
534 for (i = 0; i < 3; i++)
535 ch_flags[i * 3 + parm - 3] = (x_toggle & (1 << parm)) ? '-' : '+';
536 x_toggle ^= (1 << parm);
537 update_mode (h);
538 dlg_broadcast_msg (h, WIDGET_DRAW, FALSE);
539 send_message (WIDGET (h->current->data), NULL, WIDGET_FOCUS, 0, NULL);
540 break;
542 case XCTRL ('x'):
543 i++;
545 case XCTRL ('w'):
546 i++;
548 case XCTRL ('r'):
549 parm = i;
550 for (i = 0; i < 3; i++)
551 ch_flags[i * 3 + parm] = (x_toggle & (1 << parm)) ? '-' : '+';
552 x_toggle ^= (1 << parm);
553 update_mode (h);
554 dlg_broadcast_msg (h, WIDGET_DRAW, FALSE);
555 send_message (WIDGET (h->current->data), NULL, WIDGET_FOCUS, 0, NULL);
556 break;
558 case 'x':
559 i++;
561 case 'w':
562 i++;
564 case 'r':
565 if (f_pos > 2)
566 break;
567 flag_pos = f_pos * 3 + i; /* (strchr(ch_perm,parm)-ch_perm); */
568 if (((WButton *) h->current->data)->text.start[(flag_pos % 3)] == '-')
569 ch_flags[flag_pos] = '+';
570 else
571 ch_flags[flag_pos] = '-';
572 update_mode (h);
573 break;
575 case '4':
576 i++;
578 case '2':
579 i++;
581 case '1':
582 if (f_pos <= 2)
584 flag_pos = i + f_pos * 3;
585 ch_flags[flag_pos] = '=';
586 update_mode (h);
588 break;
590 case '-':
591 if (f_pos > 2)
592 break;
594 case '*':
595 if (parm == '*')
596 parm = '=';
598 case '=':
599 case '+':
600 if (f_pos <= 4)
602 ch_flags[flag_pos] = parm;
603 update_mode (h);
604 advanced_chown_callback (h, sender, DLG_KEY, KEY_RIGHT, NULL);
605 if (flag_pos > 8 || (flag_pos % 3) == 0)
606 dlg_one_down (h);
608 break;
610 return MSG_NOT_HANDLED;
612 default:
613 return default_dlg_callback (h, sender, msg, parm, data);
617 /* --------------------------------------------------------------------------------------------- */
619 static void
620 init_chown_advanced (void)
622 int i;
623 int dlg_h = 12;
624 int dlg_w = 74;
625 int y;
627 static gboolean i18n = FALSE;
629 if (!i18n)
631 for (i = BUTTONS_PERM; i < BUTTONS; i++)
633 #ifdef ENABLE_NLS
634 chown_advanced_but[i].text = _(chown_advanced_but[i].text);
635 #endif /* ENABLE_NLS */
637 chown_advanced_but[i].len = str_term_width1 (chown_advanced_but[i].text) + 3;
638 if (chown_advanced_but[i].flags == DEFPUSH_BUTTON)
639 chown_advanced_but[i].len += 2; /* "<>" */
642 i18n = TRUE;
645 do_refresh ();
647 sf_stat = g_new (struct stat, 1);
648 current_file = 0;
649 end_chown = need_update = FALSE;
650 single_set = (current_panel->marked < 2);
651 memset (ch_flags, '=', 11);
652 flag_pos = 0;
653 x_toggle = 070;
655 if (!single_set)
656 dlg_h += 2;
658 ch_dlg =
659 create_dlg (TRUE, 0, 0, dlg_h, dlg_w, dialog_colors, advanced_chown_callback, NULL,
660 "[Advanced Chown]", _("Chown advanced command"), DLG_CENTER);
663 l_filename = label_new (2, 3, "");
664 add_widget (ch_dlg, l_filename);
666 add_widget (ch_dlg, hline_new (3, -1, -1));
668 #define XTRACT(i,y) y, BX+chown_advanced_but[i].x, \
669 chown_advanced_but[i].ret_cmd, chown_advanced_but[i].flags, \
670 (chown_advanced_but[i].text), NULL
671 b_att[0] = button_new (XTRACT (0, BY));
672 chown_advanced_but[0].id = add_widget (ch_dlg, b_att[0]);
673 b_att[1] = button_new (XTRACT (1, BY));
674 chown_advanced_but[1].id = add_widget (ch_dlg, b_att[1]);
675 b_att[2] = button_new (XTRACT (2, BY));
676 chown_advanced_but[2].id = add_widget (ch_dlg, b_att[2]);
677 b_user = button_new (XTRACT (3, BY));
678 chown_advanced_but[3].id = add_widget (ch_dlg, b_user);
679 b_group = button_new (XTRACT (4, BY));
680 chown_advanced_but[4].id = add_widget (ch_dlg, b_group);
681 #undef XTRACT
683 l_mode = label_new (BY + 2, 3, "");
684 add_widget (ch_dlg, l_mode);
686 y = BY + 3;
687 if (!single_set)
689 i = BUTTONS_PERM;
690 add_widget (ch_dlg, hline_new (y++, -1, -1));
691 chown_advanced_but[i].id = add_widget (ch_dlg,
692 button_new (y,
693 WIDGET (ch_dlg)->cols / 2 -
694 chown_advanced_but[i].len,
695 chown_advanced_but[i].ret_cmd,
696 chown_advanced_but[i].flags,
697 chown_advanced_but[i].text, NULL));
698 i++;
699 chown_advanced_but[i].id = add_widget (ch_dlg,
700 button_new (y, WIDGET (ch_dlg)->cols / 2 + 1,
701 chown_advanced_but[i].ret_cmd,
702 chown_advanced_but[i].flags,
703 chown_advanced_but[i].text, NULL));
704 y++;
707 i = BUTTONS_PERM + 2;
708 add_widget (ch_dlg, hline_new (y++, -1, -1));
709 chown_advanced_but[i].id = add_widget (ch_dlg,
710 button_new (y,
711 WIDGET (ch_dlg)->cols / 2 -
712 chown_advanced_but[i].len,
713 chown_advanced_but[i].ret_cmd,
714 chown_advanced_but[i].flags,
715 chown_advanced_but[i].text, NULL));
716 i++;
717 chown_advanced_but[i].id = add_widget (ch_dlg,
718 button_new (y, WIDGET (ch_dlg)->cols / 2 + 1,
719 chown_advanced_but[i].ret_cmd,
720 chown_advanced_but[i].flags,
721 chown_advanced_but[i].text, NULL));
723 dlg_select_widget (b_att[0]);
726 /* --------------------------------------------------------------------------------------------- */
728 static void
729 chown_advanced_done (void)
731 g_free (sf_stat);
732 if (need_update)
733 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
734 repaint_screen ();
737 /* --------------------------------------------------------------------------------------------- */
739 #if 0
740 static void
741 do_chown (uid_t u, gid_t g)
743 chown (current_panel->dir.list[current_file].fname, u, g);
744 file_mark (current_panel, current_file, 0);
746 #endif
748 /* --------------------------------------------------------------------------------------------- */
750 static char *
751 next_file (void)
753 while (!current_panel->dir.list[current_file].f.marked)
754 current_file++;
756 return current_panel->dir.list[current_file].fname;
759 /* --------------------------------------------------------------------------------------------- */
761 static void
762 apply_advanced_chowns (struct stat *sf)
764 vfs_path_t *vpath;
765 char *lc_fname;
766 gid_t a_gid = sf->st_gid;
767 uid_t a_uid = sf->st_uid;
769 lc_fname = current_panel->dir.list[current_file].fname;
770 vpath = vfs_path_from_str (lc_fname);
771 need_update = end_chown = TRUE;
772 if (mc_chmod (vpath, get_mode ()) == -1)
773 message (D_ERROR, MSG_ERROR, _("Cannot chmod \"%s\"\n%s"),
774 lc_fname, unix_error_string (errno));
775 /* call mc_chown only, if mc_chmod didn't fail */
776 else if (mc_chown (vpath, (ch_flags[9] == '+') ? sf->st_uid : (uid_t) - 1,
777 (ch_flags[10] == '+') ? sf->st_gid : (gid_t) - 1) == -1)
778 message (D_ERROR, MSG_ERROR, _("Cannot chown \"%s\"\n%s"),
779 lc_fname, unix_error_string (errno));
780 do_file_mark (current_panel, current_file, 0);
781 vfs_path_free (vpath);
785 lc_fname = next_file ();
786 vpath = vfs_path_from_str (lc_fname);
788 if (mc_stat (vpath, sf) != 0)
790 vfs_path_free (vpath);
791 break;
794 ch_cmode = sf->st_mode;
796 if (mc_chmod (vpath, get_mode ()) == -1)
797 message (D_ERROR, MSG_ERROR, _("Cannot chmod \"%s\"\n%s"),
798 lc_fname, unix_error_string (errno));
799 /* call mc_chown only, if mc_chmod didn't fail */
800 else if (mc_chown (vpath, (ch_flags[9] == '+') ? a_uid : (uid_t) - 1,
801 (ch_flags[10] == '+') ? a_gid : (gid_t) - 1) == -1)
802 message (D_ERROR, MSG_ERROR, _("Cannot chown \"%s\"\n%s"),
803 lc_fname, unix_error_string (errno));
805 do_file_mark (current_panel, current_file, 0);
806 vfs_path_free (vpath);
808 while (current_panel->marked != 0);
811 /* --------------------------------------------------------------------------------------------- */
812 /*** public functions ****************************************************************************/
813 /* --------------------------------------------------------------------------------------------- */
815 void
816 chown_advanced_cmd (void)
818 /* Number of files at startup */
819 int files_on_begin;
821 files_on_begin = max (1, current_panel->marked);
824 { /* do while any files remaining */
825 int file_idx;
826 char buffer[BUF_MEDIUM];
827 vfs_path_t *vpath;
828 int result;
830 init_chown_advanced ();
832 if (current_panel->marked)
833 fname = next_file (); /* next marked file */
834 else
835 fname = selection (current_panel)->fname; /* single file */
836 vpath = vfs_path_from_str (fname);
838 if (mc_stat (vpath, sf_stat) != 0)
839 { /* get status of file */
840 destroy_dlg (ch_dlg);
841 vfs_path_free (vpath);
842 break;
845 ch_cmode = sf_stat->st_mode;
847 file_idx = files_on_begin == 1 ? 1 : (files_on_begin - current_panel->marked + 1);
848 g_snprintf (buffer, sizeof (buffer), "%s (%d/%d)",
849 str_fit_to_term (fname, WIDGET(ch_dlg)->cols - 20, J_LEFT_FIT),
850 file_idx, files_on_begin);
851 label_set_text (l_filename, buffer);
852 chown_refresh ();
853 update_ownership ();
855 result = run_dlg (ch_dlg);
857 switch (result)
859 case B_CANCEL:
860 end_chown = TRUE;
861 break;
863 case B_ENTER:
864 need_update = TRUE;
865 if (mc_chmod (vpath, get_mode ()) == -1)
866 message (D_ERROR, MSG_ERROR, _("Cannot chmod \"%s\"\n%s"),
867 fname, unix_error_string (errno));
868 /* call mc_chown only, if mc_chmod didn't fail */
869 else if (mc_chown
870 (vpath, (ch_flags[9] == '+') ? sf_stat->st_uid : (uid_t) - 1,
871 (ch_flags[10] == '+') ? sf_stat->st_gid : (gid_t) - 1) == -1)
872 message (D_ERROR, MSG_ERROR, _("Cannot chown \"%s\"\n%s"), fname,
873 unix_error_string (errno));
874 break;
876 case B_SETALL:
877 apply_advanced_chowns (sf_stat);
878 break;
880 case B_SKIP:
881 break;
884 if (current_panel->marked && result != B_CANCEL)
886 do_file_mark (current_panel, current_file, 0);
887 need_update = TRUE;
889 destroy_dlg (ch_dlg);
890 vfs_path_free (vpath);
892 while (current_panel->marked && !end_chown);
894 chown_advanced_done ();
897 /* --------------------------------------------------------------------------------------------- */