Remove min() and max() macros. Use MIN() and MAX() macros from GLib.
[midnight-commander.git] / src / filemanager / achown.c
blob92eee9627aa63c38d88d60bb8737c0c83b091763
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)
67 #define B_OWN (B_USER + 3)
68 #define B_GRP (B_USER + 4)
69 #define B_OTH (B_USER + 5)
70 #define B_OUSER (B_USER + 6)
71 #define B_OGROUP (B_USER + 7)
73 /*** file scope type declarations ****************************************************************/
75 /*** file scope variables ************************************************************************/
77 static WDialog *ch_dlg;
79 static struct
81 unsigned long id;
82 int ret_cmd;
83 button_flags_t flags;
84 int x, len;
85 const char *text;
86 } chown_advanced_but[BUTTONS] =
88 /* *INDENT-OFF* */
89 { 0, B_ENTER, NARROW_BUTTON, 3, 0, " "},
90 { 0, B_ENTER, NARROW_BUTTON, 11, 0, " "},
91 { 0, B_ENTER, NARROW_BUTTON, 19, 0, " "},
92 { 0, B_ENTER, NARROW_BUTTON, 29, 0, ""},
93 { 0, B_ENTER, NARROW_BUTTON, 47, 0, ""},
95 { 0, B_SETALL, NORMAL_BUTTON, 0, 0, N_("Set &all")},
96 { 0, B_SKIP, NORMAL_BUTTON, 0, 0, N_("S&kip") },
97 { 0, B_ENTER, DEFPUSH_BUTTON, 0, 0, N_("&Set") },
98 { 0, B_CANCEL, NORMAL_BUTTON, 0, 0, N_("&Cancel") }
99 /* *INDENT-ON* */
102 static WButton *b_att[3]; /* permission */
103 static WButton *b_user, *b_group; /* owner */
104 static WLabel *l_filename;
105 static WLabel *l_mode;
107 static int flag_pos;
108 static int x_toggle;
109 static char ch_flags[11];
110 static const char ch_perm[] = "rwx";
111 static mode_t ch_cmode;
112 static struct stat *sf_stat;
113 static gboolean need_update = FALSE;
114 static gboolean end_chown = FALSE;
115 static int current_file;
116 static gboolean single_set = FALSE;
117 static char *fname;
119 /* --------------------------------------------------------------------------------------------- */
120 /*** file scope functions ************************************************************************/
121 /* --------------------------------------------------------------------------------------------- */
123 static void
124 update_ownership (void)
126 button_set_text (b_user, get_owner (sf_stat->st_uid));
127 button_set_text (b_group, get_group (sf_stat->st_gid));
130 /* --------------------------------------------------------------------------------------------- */
132 static cb_ret_t
133 inc_flag_pos (int f_pos)
135 if (flag_pos == 10)
137 flag_pos = 0;
138 return MSG_NOT_HANDLED;
140 flag_pos++;
141 if ((flag_pos % 3) == 0 || f_pos > 2)
142 return MSG_NOT_HANDLED;
143 return MSG_HANDLED;
146 /* --------------------------------------------------------------------------------------------- */
148 static cb_ret_t
149 dec_flag_pos (int f_pos)
151 if (flag_pos == 0)
153 flag_pos = 10;
154 return MSG_NOT_HANDLED;
156 flag_pos--;
157 if (((flag_pos + 1) % 3) == 0 || f_pos > 2)
158 return MSG_NOT_HANDLED;
159 return MSG_HANDLED;
162 /* --------------------------------------------------------------------------------------------- */
164 static void
165 set_perm_by_flags (char *s, int f_p)
167 int i;
169 for (i = 0; i < 3; i++)
171 if (ch_flags[f_p + i] == '+')
172 s[i] = ch_perm[i];
173 else if (ch_flags[f_p + i] == '-')
174 s[i] = '-';
175 else
176 s[i] = (ch_cmode & (1 << (8 - f_p - i))) ? ch_perm[i] : '-';
180 /* --------------------------------------------------------------------------------------------- */
182 static void
183 update_permissions (void)
185 set_perm_by_flags (b_att[0]->text.start, 0);
186 set_perm_by_flags (b_att[1]->text.start, 3);
187 set_perm_by_flags (b_att[2]->text.start, 6);
190 /* --------------------------------------------------------------------------------------------- */
192 static mode_t
193 get_perm (char *s, int base)
195 mode_t m;
197 m = 0;
198 m |= (s[0] == '-') ? 0 :
199 ((s[0] == '+') ? (mode_t) (1 << (base + 2)) : (1 << (base + 2)) & ch_cmode);
201 m |= (s[1] == '-') ? 0 :
202 ((s[1] == '+') ? (mode_t) (1 << (base + 1)) : (1 << (base + 1)) & ch_cmode);
204 m |= (s[2] == '-') ? 0 : ((s[2] == '+') ? (mode_t) (1 << base) : (1 << base) & ch_cmode);
206 return m;
209 /* --------------------------------------------------------------------------------------------- */
211 static mode_t
212 get_mode (void)
214 mode_t m;
216 m = ch_cmode ^ (ch_cmode & 0777);
217 m |= get_perm (ch_flags, 6);
218 m |= get_perm (ch_flags + 3, 3);
219 m |= get_perm (ch_flags + 6, 0);
221 return m;
224 /* --------------------------------------------------------------------------------------------- */
226 static void
227 print_flags (void)
229 int i;
231 tty_setcolor (COLOR_NORMAL);
233 for (i = 0; i < 3; i++)
235 widget_move (ch_dlg, BY + 1, 9 + i);
236 tty_print_char (ch_flags[i]);
239 for (i = 0; i < 3; i++)
241 widget_move (ch_dlg, BY + 1, 17 + i);
242 tty_print_char (ch_flags[i + 3]);
245 for (i = 0; i < 3; i++)
247 widget_move (ch_dlg, BY + 1, 25 + i);
248 tty_print_char (ch_flags[i + 6]);
251 update_permissions ();
253 for (i = 0; i < 15; i++)
255 widget_move (ch_dlg, BY + 1, 35 + i);
256 tty_print_char (ch_flags[9]);
258 for (i = 0; i < 15; i++)
260 widget_move (ch_dlg, BY + 1, 53 + i);
261 tty_print_char (ch_flags[10]);
265 /* --------------------------------------------------------------------------------------------- */
267 static void
268 chown_info_update (void)
270 char buffer[BUF_SMALL];
272 /* mode */
273 g_snprintf (buffer, sizeof (buffer), "Permissions (octal): %o", get_mode ());
274 label_set_text (l_mode, buffer);
276 /* permissions */
277 update_permissions ();
280 /* --------------------------------------------------------------------------------------------- */
282 static void
283 update_mode (WDialog * h)
285 print_flags ();
286 chown_info_update ();
287 send_message (h->current->data, NULL, MSG_FOCUS, 0, NULL);
290 /* --------------------------------------------------------------------------------------------- */
292 static cb_ret_t
293 chl_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data)
295 switch (msg)
297 case MSG_KEY:
298 switch (parm)
300 case KEY_LEFT:
301 case KEY_RIGHT:
303 WDialog *h = DIALOG (w);
305 h->ret_value = parm;
306 dlg_stop (h);
308 default:
309 break;
312 default:
313 return dlg_default_callback (w, sender, msg, parm, data);
317 /* --------------------------------------------------------------------------------------------- */
319 static void
320 do_enter_key (WDialog * h, int f_pos)
322 WListbox *chl_list;
323 struct passwd *chl_pass;
324 struct group *chl_grp;
325 int fe;
326 gboolean chl_end, is_owner;
330 int result;
331 WDialog *chl_dlg;
332 const char *title;
333 int lxx, lyy, b_pos;
335 is_owner = (f_pos == 3);
336 title = is_owner ? _("owner") : _("group");
338 lxx = (COLS - 74) / 2 + (is_owner ? 35 : 53);
339 lyy = (LINES - 13) / 2;
340 chl_end = FALSE;
342 chl_dlg =
343 dlg_create (TRUE, lyy, lxx, 13, 17, dialog_colors, chl_callback, NULL,
344 "[Advanced Chown]", title, DLG_COMPACT);
346 /* get new listboxes */
347 chl_list = listbox_new (1, 1, 11, 15, FALSE, NULL);
348 listbox_add_item (chl_list, LISTBOX_APPEND_AT_END, 0, "<Unknown>", NULL, FALSE);
349 if (is_owner)
351 /* get and put user names in the listbox */
352 setpwent ();
353 while ((chl_pass = getpwent ()) != NULL)
354 listbox_add_item (chl_list, LISTBOX_APPEND_SORTED, 0, chl_pass->pw_name, NULL,
355 FALSE);
356 endpwent ();
357 fe = listbox_search_text (chl_list, get_owner (sf_stat->st_uid));
359 else
361 /* get and put group names in the listbox */
362 setgrent ();
363 while ((chl_grp = getgrent ()) != NULL)
364 listbox_add_item (chl_list, LISTBOX_APPEND_SORTED, 0, chl_grp->gr_name, NULL,
365 FALSE);
366 endgrent ();
367 fe = listbox_search_text (chl_list, get_group (sf_stat->st_gid));
370 listbox_select_entry (chl_list, fe);
372 b_pos = chl_list->pos;
373 add_widget (chl_dlg, chl_list);
375 result = dlg_run (chl_dlg);
377 if (result != B_CANCEL)
379 if (b_pos != chl_list->pos)
381 gboolean ok = FALSE;
382 char *text;
384 listbox_get_current (chl_list, &text, NULL);
385 if (is_owner)
387 chl_pass = getpwnam (text);
388 if (chl_pass != NULL)
390 ok = TRUE;
391 sf_stat->st_uid = chl_pass->pw_uid;
394 else
396 chl_grp = getgrnam (text);
397 if (chl_grp != NULL)
399 sf_stat->st_gid = chl_grp->gr_gid;
400 ok = TRUE;
403 if (ok)
405 ch_flags[f_pos + 6] = '+';
406 update_ownership ();
408 dlg_focus (h);
409 if (ok)
410 print_flags ();
412 if (result == KEY_LEFT)
414 if (!is_owner)
415 chl_end = TRUE;
416 dlg_one_up (ch_dlg);
417 f_pos--;
419 else if (result == KEY_RIGHT)
421 if (is_owner)
422 chl_end = TRUE;
423 dlg_one_down (ch_dlg);
424 f_pos++;
428 /* Here we used to redraw the window */
429 dlg_destroy (chl_dlg);
431 while (chl_end);
434 /* --------------------------------------------------------------------------------------------- */
436 static void
437 chown_refresh (void)
439 dlg_default_repaint (ch_dlg);
441 tty_setcolor (COLOR_NORMAL);
443 widget_move (ch_dlg, BY - 1, 8);
444 tty_print_string (_("owner"));
445 widget_move (ch_dlg, BY - 1, 16);
446 tty_print_string (_("group"));
447 widget_move (ch_dlg, BY - 1, 24);
448 tty_print_string (_("other"));
450 widget_move (ch_dlg, BY - 1, 35);
451 tty_print_string (_("owner"));
452 widget_move (ch_dlg, BY - 1, 53);
453 tty_print_string (_("group"));
455 widget_move (ch_dlg, BY + 1, 3);
456 tty_print_string (_("Flag"));
458 print_flags ();
461 /* --------------------------------------------------------------------------------------------- */
463 static void
464 b_setpos (int f_pos)
466 b_att[0]->hotpos = -1;
467 b_att[1]->hotpos = -1;
468 b_att[2]->hotpos = -1;
469 b_att[f_pos]->hotpos = (flag_pos % 3);
472 /* --------------------------------------------------------------------------------------------- */
474 static cb_ret_t
475 advanced_chown_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data)
477 WDialog *h = DIALOG (w);
478 int i;
479 int f_pos;
480 unsigned long id;
482 id = dlg_get_current_widget_id (h);
484 for (i = 0; i < BUTTONS_PERM; i++)
485 if (chown_advanced_but[i].id == id)
486 break;
488 f_pos = i;
489 i = 0;
491 switch (msg)
493 case MSG_DRAW:
494 chown_refresh ();
495 chown_info_update ();
496 return MSG_HANDLED;
498 case MSG_POST_KEY:
499 if (f_pos < 3)
500 b_setpos (f_pos);
501 return MSG_HANDLED;
503 case MSG_FOCUS:
504 if (f_pos < 3)
506 if ((flag_pos / 3) != f_pos)
507 flag_pos = f_pos * 3;
508 b_setpos (f_pos);
510 else if (f_pos < BUTTONS_PERM)
511 flag_pos = f_pos + 6;
512 return MSG_HANDLED;
514 case MSG_KEY:
515 switch (parm)
517 case XCTRL ('b'):
518 case KEY_LEFT:
519 if (f_pos < BUTTONS_PERM)
520 return (dec_flag_pos (f_pos));
521 break;
523 case XCTRL ('f'):
524 case KEY_RIGHT:
525 if (f_pos < BUTTONS_PERM)
526 return (inc_flag_pos (f_pos));
527 break;
529 case ' ':
530 if (f_pos < 3)
531 return MSG_HANDLED;
532 break;
534 case '\n':
535 case KEY_ENTER:
536 if (f_pos <= 2 || f_pos >= BUTTONS_PERM)
537 break;
538 do_enter_key (h, f_pos);
539 return MSG_HANDLED;
541 case ALT ('x'):
542 i++;
544 case ALT ('w'):
545 i++;
547 case ALT ('r'):
548 parm = i + 3;
549 for (i = 0; i < 3; i++)
550 ch_flags[i * 3 + parm - 3] = (x_toggle & (1 << parm)) ? '-' : '+';
551 x_toggle ^= (1 << parm);
552 update_mode (h);
553 dlg_broadcast_msg (h, MSG_DRAW);
554 send_message (h->current->data, NULL, MSG_FOCUS, 0, NULL);
555 break;
557 case XCTRL ('x'):
558 i++;
560 case XCTRL ('w'):
561 i++;
563 case XCTRL ('r'):
564 parm = i;
565 for (i = 0; i < 3; i++)
566 ch_flags[i * 3 + parm] = (x_toggle & (1 << parm)) ? '-' : '+';
567 x_toggle ^= (1 << parm);
568 update_mode (h);
569 dlg_broadcast_msg (h, MSG_DRAW);
570 send_message (h->current->data, NULL, MSG_FOCUS, 0, NULL);
571 break;
573 case 'x':
574 i++;
576 case 'w':
577 i++;
579 case 'r':
580 if (f_pos > 2)
581 break;
582 flag_pos = f_pos * 3 + i; /* (strchr(ch_perm,parm)-ch_perm); */
583 if (BUTTON (h->current->data)->text.start[(flag_pos % 3)] == '-')
584 ch_flags[flag_pos] = '+';
585 else
586 ch_flags[flag_pos] = '-';
587 update_mode (h);
588 break;
590 case '4':
591 i++;
593 case '2':
594 i++;
596 case '1':
597 if (f_pos <= 2)
599 flag_pos = i + f_pos * 3;
600 ch_flags[flag_pos] = '=';
601 update_mode (h);
603 break;
605 case '-':
606 if (f_pos > 2)
607 break;
609 case '*':
610 if (parm == '*')
611 parm = '=';
613 case '=':
614 case '+':
615 if (f_pos <= 4)
617 ch_flags[flag_pos] = parm;
618 update_mode (h);
619 send_message (h, sender, MSG_KEY, KEY_RIGHT, NULL);
620 if (flag_pos > 8 || (flag_pos % 3) == 0)
621 dlg_one_down (h);
623 break;
625 default:
626 break;
628 return MSG_NOT_HANDLED;
630 default:
631 return dlg_default_callback (w, sender, msg, parm, data);
635 /* --------------------------------------------------------------------------------------------- */
637 static void
638 init_chown_advanced (void)
640 int i;
641 int dlg_h = 12;
642 int dlg_w = 74;
643 int y;
645 static gboolean i18n = FALSE;
647 if (!i18n)
649 for (i = BUTTONS_PERM; i < BUTTONS; i++)
651 #ifdef ENABLE_NLS
652 chown_advanced_but[i].text = _(chown_advanced_but[i].text);
653 #endif /* ENABLE_NLS */
655 chown_advanced_but[i].len = str_term_width1 (chown_advanced_but[i].text) + 3;
656 if (chown_advanced_but[i].flags == DEFPUSH_BUTTON)
657 chown_advanced_but[i].len += 2; /* "<>" */
660 i18n = TRUE;
663 do_refresh ();
665 sf_stat = g_new (struct stat, 1);
666 current_file = 0;
667 end_chown = need_update = FALSE;
668 single_set = (current_panel->marked < 2);
669 memset (ch_flags, '=', 11);
670 flag_pos = 0;
671 x_toggle = 070;
673 if (!single_set)
674 dlg_h += 2;
676 ch_dlg =
677 dlg_create (TRUE, 0, 0, dlg_h, dlg_w, dialog_colors, advanced_chown_callback, NULL,
678 "[Advanced Chown]", _("Chown advanced command"), DLG_CENTER);
681 l_filename = label_new (2, 3, "");
682 add_widget (ch_dlg, l_filename);
684 add_widget (ch_dlg, hline_new (3, -1, -1));
686 #define XTRACT(i,y) y, BX+chown_advanced_but[i].x, \
687 chown_advanced_but[i].ret_cmd, chown_advanced_but[i].flags, \
688 (chown_advanced_but[i].text), NULL
689 b_att[0] = button_new (XTRACT (0, BY));
690 chown_advanced_but[0].id = add_widget (ch_dlg, b_att[0]);
691 b_att[1] = button_new (XTRACT (1, BY));
692 chown_advanced_but[1].id = add_widget (ch_dlg, b_att[1]);
693 b_att[2] = button_new (XTRACT (2, BY));
694 chown_advanced_but[2].id = add_widget (ch_dlg, b_att[2]);
695 b_user = button_new (XTRACT (3, BY));
696 chown_advanced_but[3].id = add_widget (ch_dlg, b_user);
697 b_group = button_new (XTRACT (4, BY));
698 chown_advanced_but[4].id = add_widget (ch_dlg, b_group);
699 #undef XTRACT
701 l_mode = label_new (BY + 2, 3, "");
702 add_widget (ch_dlg, l_mode);
704 y = BY + 3;
705 if (!single_set)
707 i = BUTTONS_PERM;
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));
722 y++;
725 i = BUTTONS_PERM + 2;
726 add_widget (ch_dlg, hline_new (y++, -1, -1));
727 chown_advanced_but[i].id = add_widget (ch_dlg,
728 button_new (y,
729 WIDGET (ch_dlg)->cols / 2 -
730 chown_advanced_but[i].len,
731 chown_advanced_but[i].ret_cmd,
732 chown_advanced_but[i].flags,
733 chown_advanced_but[i].text, NULL));
734 i++;
735 chown_advanced_but[i].id = add_widget (ch_dlg,
736 button_new (y, WIDGET (ch_dlg)->cols / 2 + 1,
737 chown_advanced_but[i].ret_cmd,
738 chown_advanced_but[i].flags,
739 chown_advanced_but[i].text, NULL));
741 dlg_select_widget (b_att[0]);
744 /* --------------------------------------------------------------------------------------------- */
746 static void
747 chown_advanced_done (void)
749 g_free (sf_stat);
750 if (need_update)
751 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
752 repaint_screen ();
755 /* --------------------------------------------------------------------------------------------- */
757 #if 0
758 static void
759 do_chown (uid_t u, gid_t g)
761 chown (current_panel->dir.list[current_file].fname, u, g);
762 file_mark (current_panel, current_file, 0);
764 #endif
766 /* --------------------------------------------------------------------------------------------- */
768 static char *
769 next_file (void)
771 while (!current_panel->dir.list[current_file].f.marked)
772 current_file++;
774 return current_panel->dir.list[current_file].fname;
777 /* --------------------------------------------------------------------------------------------- */
779 static void
780 apply_advanced_chowns (struct stat *sf)
782 vfs_path_t *vpath;
783 char *lc_fname;
784 gid_t a_gid = sf->st_gid;
785 uid_t a_uid = sf->st_uid;
787 lc_fname = current_panel->dir.list[current_file].fname;
788 vpath = vfs_path_from_str (lc_fname);
789 need_update = end_chown = TRUE;
790 if (mc_chmod (vpath, get_mode ()) == -1)
791 message (D_ERROR, MSG_ERROR, _("Cannot chmod \"%s\"\n%s"),
792 lc_fname, unix_error_string (errno));
793 /* call mc_chown only, if mc_chmod didn't fail */
794 else if (mc_chown (vpath, (ch_flags[9] == '+') ? sf->st_uid : (uid_t) (-1),
795 (ch_flags[10] == '+') ? sf->st_gid : (gid_t) (-1)) == -1)
796 message (D_ERROR, MSG_ERROR, _("Cannot chown \"%s\"\n%s"),
797 lc_fname, unix_error_string (errno));
798 do_file_mark (current_panel, current_file, 0);
799 vfs_path_free (vpath);
803 lc_fname = next_file ();
804 vpath = vfs_path_from_str (lc_fname);
806 if (mc_stat (vpath, sf) != 0)
808 vfs_path_free (vpath);
809 break;
812 ch_cmode = sf->st_mode;
814 if (mc_chmod (vpath, get_mode ()) == -1)
815 message (D_ERROR, MSG_ERROR, _("Cannot chmod \"%s\"\n%s"),
816 lc_fname, unix_error_string (errno));
817 /* call mc_chown only, if mc_chmod didn't fail */
818 else if (mc_chown (vpath, (ch_flags[9] == '+') ? a_uid : (uid_t) (-1),
819 (ch_flags[10] == '+') ? a_gid : (gid_t) (-1)) == -1)
820 message (D_ERROR, MSG_ERROR, _("Cannot chown \"%s\"\n%s"),
821 lc_fname, unix_error_string (errno));
823 do_file_mark (current_panel, current_file, 0);
824 vfs_path_free (vpath);
826 while (current_panel->marked != 0);
829 /* --------------------------------------------------------------------------------------------- */
830 /*** public functions ****************************************************************************/
831 /* --------------------------------------------------------------------------------------------- */
833 void
834 chown_advanced_cmd (void)
836 /* Number of files at startup */
837 int files_on_begin;
839 files_on_begin = MAX (1, current_panel->marked);
842 { /* do while any files remaining */
843 int file_idx;
844 char buffer[BUF_MEDIUM];
845 vfs_path_t *vpath;
846 int result;
848 init_chown_advanced ();
850 if (current_panel->marked)
851 fname = next_file (); /* next marked file */
852 else
853 fname = selection (current_panel)->fname; /* single file */
854 vpath = vfs_path_from_str (fname);
856 if (mc_stat (vpath, sf_stat) != 0)
857 { /* get status of file */
858 dlg_destroy (ch_dlg);
859 vfs_path_free (vpath);
860 break;
863 ch_cmode = sf_stat->st_mode;
865 file_idx = files_on_begin == 1 ? 1 : (files_on_begin - current_panel->marked + 1);
866 g_snprintf (buffer, sizeof (buffer), "%s (%d/%d)",
867 str_fit_to_term (fname, WIDGET (ch_dlg)->cols - 20, J_LEFT_FIT),
868 file_idx, files_on_begin);
869 label_set_text (l_filename, buffer);
870 chown_refresh ();
871 update_ownership ();
873 result = dlg_run (ch_dlg);
875 switch (result)
877 case B_CANCEL:
878 end_chown = TRUE;
879 break;
881 case B_ENTER:
882 need_update = TRUE;
883 if (mc_chmod (vpath, get_mode ()) == -1)
884 message (D_ERROR, MSG_ERROR, _("Cannot chmod \"%s\"\n%s"),
885 fname, unix_error_string (errno));
886 /* call mc_chown only, if mc_chmod didn't fail */
887 else if (mc_chown
888 (vpath, (ch_flags[9] == '+') ? sf_stat->st_uid : (uid_t) (-1),
889 (ch_flags[10] == '+') ? sf_stat->st_gid : (gid_t) (-1)) == -1)
890 message (D_ERROR, MSG_ERROR, _("Cannot chown \"%s\"\n%s"), fname,
891 unix_error_string (errno));
892 break;
894 case B_SETALL:
895 apply_advanced_chowns (sf_stat);
896 break;
898 case B_SKIP:
899 default:
900 break;
903 if (current_panel->marked && result != B_CANCEL)
905 do_file_mark (current_panel, current_file, 0);
906 need_update = TRUE;
908 dlg_destroy (ch_dlg);
909 vfs_path_free (vpath);
911 while (current_panel->marked && !end_chown);
913 chown_advanced_done ();
916 /* --------------------------------------------------------------------------------------------- */