Add useful macros for widget type cast.
[midnight-commander.git] / src / filemanager / achown.c
blob53fa3a64ff0b1757e7d2a9f370c8ef29a1f3a710
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 WDialog *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 (WDialog * h)
284 print_flags ();
285 chown_info_update ();
286 send_message (h->current->data, NULL, MSG_FOCUS, 0, NULL);
289 /* --------------------------------------------------------------------------------------------- */
291 static cb_ret_t
292 chl_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data)
294 switch (msg)
296 case MSG_KEY:
297 switch (parm)
299 case KEY_LEFT:
300 case KEY_RIGHT:
302 WDialog *h = DIALOG (w);
304 h->ret_value = parm;
305 dlg_stop (h);
309 default:
310 return dlg_default_callback (w, sender, msg, parm, data);
314 /* --------------------------------------------------------------------------------------------- */
316 static void
317 do_enter_key (WDialog * h, int f_pos)
319 WDialog *chl_dlg;
320 WListbox *chl_list;
321 struct passwd *chl_pass;
322 struct group *chl_grp;
323 int fe;
324 int lxx, lyy, b_pos;
325 gboolean chl_end, is_owner;
326 const char *title;
327 int result;
331 is_owner = (f_pos == 3);
332 title = is_owner ? _("owner") : _("group");
334 lxx = (COLS - 74) / 2 + (is_owner ? 35 : 53);
335 lyy = (LINES - 13) / 2;
336 chl_end = FALSE;
338 chl_dlg =
339 create_dlg (TRUE, lyy, lxx, 13, 17, dialog_colors, chl_callback, NULL,
340 "[Advanced Chown]", title, DLG_COMPACT);
342 /* get new listboxes */
343 chl_list = listbox_new (1, 1, 11, 15, FALSE, NULL);
344 listbox_add_item (chl_list, LISTBOX_APPEND_AT_END, 0, "<Unknown>", NULL);
345 if (is_owner)
347 /* get and put user names in the listbox */
348 setpwent ();
349 while ((chl_pass = getpwent ()) != NULL)
350 listbox_add_item (chl_list, LISTBOX_APPEND_SORTED, 0, chl_pass->pw_name, NULL);
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 endgrent ();
361 fe = listbox_search_text (chl_list, get_group (sf_stat->st_gid));
364 listbox_select_entry (chl_list, fe);
366 b_pos = chl_list->pos;
367 add_widget (chl_dlg, chl_list);
369 result = run_dlg (chl_dlg);
371 if (b_pos != chl_list->pos)
373 gboolean ok = FALSE;
374 char *text;
376 listbox_get_current (chl_list, &text, NULL);
377 if (is_owner)
379 chl_pass = getpwnam (text);
380 if (chl_pass != NULL)
382 ok = TRUE;
383 sf_stat->st_uid = chl_pass->pw_uid;
386 else
388 chl_grp = getgrnam (text);
389 if (chl_grp != NULL)
391 sf_stat->st_gid = chl_grp->gr_gid;
392 ok = TRUE;
395 if (ok)
397 ch_flags[f_pos + 6] = '+';
398 update_ownership ();
400 dlg_focus (h);
401 if (ok)
402 print_flags ();
404 if (result == KEY_LEFT)
406 if (!is_owner)
407 chl_end = TRUE;
408 dlg_one_up (ch_dlg);
409 f_pos--;
411 else if (result == KEY_RIGHT)
413 if (is_owner)
414 chl_end = TRUE;
415 dlg_one_down (ch_dlg);
416 f_pos++;
418 /* Here we used to redraw the window */
419 destroy_dlg (chl_dlg);
421 while (chl_end);
424 /* --------------------------------------------------------------------------------------------- */
426 static void
427 chown_refresh (void)
429 dlg_default_repaint (ch_dlg);
431 tty_setcolor (COLOR_NORMAL);
433 widget_move (ch_dlg, BY - 1, 8);
434 tty_print_string (_("owner"));
435 widget_move (ch_dlg, BY - 1, 16);
436 tty_print_string (_("group"));
437 widget_move (ch_dlg, BY - 1, 24);
438 tty_print_string (_("other"));
440 widget_move (ch_dlg, BY - 1, 35);
441 tty_print_string (_("owner"));
442 widget_move (ch_dlg, BY - 1, 53);
443 tty_print_string (_("group"));
445 widget_move (ch_dlg, BY + 1, 3);
446 tty_print_string (_("Flag"));
448 print_flags ();
451 /* --------------------------------------------------------------------------------------------- */
453 static void
454 b_setpos (int f_pos)
456 b_att[0]->hotpos = -1;
457 b_att[1]->hotpos = -1;
458 b_att[2]->hotpos = -1;
459 b_att[f_pos]->hotpos = (flag_pos % 3);
462 /* --------------------------------------------------------------------------------------------- */
464 static cb_ret_t
465 advanced_chown_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data)
467 WDialog *h = DIALOG (w);
468 int i;
469 int f_pos;
470 unsigned int id;
472 id = dlg_get_current_widget_id (h);
474 for (i = 0; i < BUTTONS_PERM; i++)
475 if (chown_advanced_but[i].id == id)
476 break;
478 f_pos = i;
479 i = 0;
481 switch (msg)
483 case MSG_DRAW:
484 chown_refresh ();
485 chown_info_update ();
486 return MSG_HANDLED;
488 case MSG_POST_KEY:
489 if (f_pos < 3)
490 b_setpos (f_pos);
491 return MSG_HANDLED;
493 case MSG_FOCUS:
494 if (f_pos < 3)
496 if ((flag_pos / 3) != f_pos)
497 flag_pos = f_pos * 3;
498 b_setpos (f_pos);
500 else if (f_pos < BUTTONS_PERM)
501 flag_pos = f_pos + 6;
502 return MSG_HANDLED;
504 case MSG_KEY:
505 switch (parm)
507 case XCTRL ('b'):
508 case KEY_LEFT:
509 if (f_pos < BUTTONS_PERM)
510 return (dec_flag_pos (f_pos));
511 break;
513 case XCTRL ('f'):
514 case KEY_RIGHT:
515 if (f_pos < BUTTONS_PERM)
516 return (inc_flag_pos (f_pos));
517 break;
519 case ' ':
520 if (f_pos < 3)
521 return MSG_HANDLED;
522 break;
524 case '\n':
525 case KEY_ENTER:
526 if (f_pos <= 2 || f_pos >= BUTTONS_PERM)
527 break;
528 do_enter_key (h, f_pos);
529 return MSG_HANDLED;
531 case ALT ('x'):
532 i++;
534 case ALT ('w'):
535 i++;
537 case ALT ('r'):
538 parm = i + 3;
539 for (i = 0; i < 3; i++)
540 ch_flags[i * 3 + parm - 3] = (x_toggle & (1 << parm)) ? '-' : '+';
541 x_toggle ^= (1 << parm);
542 update_mode (h);
543 dlg_broadcast_msg (h, MSG_DRAW);
544 send_message (h->current->data, NULL, MSG_FOCUS, 0, NULL);
545 break;
547 case XCTRL ('x'):
548 i++;
550 case XCTRL ('w'):
551 i++;
553 case XCTRL ('r'):
554 parm = i;
555 for (i = 0; i < 3; i++)
556 ch_flags[i * 3 + parm] = (x_toggle & (1 << parm)) ? '-' : '+';
557 x_toggle ^= (1 << parm);
558 update_mode (h);
559 dlg_broadcast_msg (h, MSG_DRAW);
560 send_message (h->current->data, NULL, MSG_FOCUS, 0, NULL);
561 break;
563 case 'x':
564 i++;
566 case 'w':
567 i++;
569 case 'r':
570 if (f_pos > 2)
571 break;
572 flag_pos = f_pos * 3 + i; /* (strchr(ch_perm,parm)-ch_perm); */
573 if (BUTTON (h->current->data)->text.start[(flag_pos % 3)] == '-')
574 ch_flags[flag_pos] = '+';
575 else
576 ch_flags[flag_pos] = '-';
577 update_mode (h);
578 break;
580 case '4':
581 i++;
583 case '2':
584 i++;
586 case '1':
587 if (f_pos <= 2)
589 flag_pos = i + f_pos * 3;
590 ch_flags[flag_pos] = '=';
591 update_mode (h);
593 break;
595 case '-':
596 if (f_pos > 2)
597 break;
599 case '*':
600 if (parm == '*')
601 parm = '=';
603 case '=':
604 case '+':
605 if (f_pos <= 4)
607 ch_flags[flag_pos] = parm;
608 update_mode (h);
609 send_message (h, sender, MSG_KEY, KEY_RIGHT, NULL);
610 if (flag_pos > 8 || (flag_pos % 3) == 0)
611 dlg_one_down (h);
613 break;
615 return MSG_NOT_HANDLED;
617 default:
618 return dlg_default_callback (w, sender, msg, parm, data);
622 /* --------------------------------------------------------------------------------------------- */
624 static void
625 init_chown_advanced (void)
627 int i;
628 int dlg_h = 12;
629 int dlg_w = 74;
630 int y;
632 static gboolean i18n = FALSE;
634 if (!i18n)
636 for (i = BUTTONS_PERM; i < BUTTONS; i++)
638 #ifdef ENABLE_NLS
639 chown_advanced_but[i].text = _(chown_advanced_but[i].text);
640 #endif /* ENABLE_NLS */
642 chown_advanced_but[i].len = str_term_width1 (chown_advanced_but[i].text) + 3;
643 if (chown_advanced_but[i].flags == DEFPUSH_BUTTON)
644 chown_advanced_but[i].len += 2; /* "<>" */
647 i18n = TRUE;
650 do_refresh ();
652 sf_stat = g_new (struct stat, 1);
653 current_file = 0;
654 end_chown = need_update = FALSE;
655 single_set = (current_panel->marked < 2);
656 memset (ch_flags, '=', 11);
657 flag_pos = 0;
658 x_toggle = 070;
660 if (!single_set)
661 dlg_h += 2;
663 ch_dlg =
664 create_dlg (TRUE, 0, 0, dlg_h, dlg_w, dialog_colors, advanced_chown_callback, NULL,
665 "[Advanced Chown]", _("Chown advanced command"), DLG_CENTER);
668 l_filename = label_new (2, 3, "");
669 add_widget (ch_dlg, l_filename);
671 add_widget (ch_dlg, hline_new (3, -1, -1));
673 #define XTRACT(i,y) y, BX+chown_advanced_but[i].x, \
674 chown_advanced_but[i].ret_cmd, chown_advanced_but[i].flags, \
675 (chown_advanced_but[i].text), NULL
676 b_att[0] = button_new (XTRACT (0, BY));
677 chown_advanced_but[0].id = add_widget (ch_dlg, b_att[0]);
678 b_att[1] = button_new (XTRACT (1, BY));
679 chown_advanced_but[1].id = add_widget (ch_dlg, b_att[1]);
680 b_att[2] = button_new (XTRACT (2, BY));
681 chown_advanced_but[2].id = add_widget (ch_dlg, b_att[2]);
682 b_user = button_new (XTRACT (3, BY));
683 chown_advanced_but[3].id = add_widget (ch_dlg, b_user);
684 b_group = button_new (XTRACT (4, BY));
685 chown_advanced_but[4].id = add_widget (ch_dlg, b_group);
686 #undef XTRACT
688 l_mode = label_new (BY + 2, 3, "");
689 add_widget (ch_dlg, l_mode);
691 y = BY + 3;
692 if (!single_set)
694 i = BUTTONS_PERM;
695 add_widget (ch_dlg, hline_new (y++, -1, -1));
696 chown_advanced_but[i].id = add_widget (ch_dlg,
697 button_new (y,
698 WIDGET (ch_dlg)->cols / 2 -
699 chown_advanced_but[i].len,
700 chown_advanced_but[i].ret_cmd,
701 chown_advanced_but[i].flags,
702 chown_advanced_but[i].text, NULL));
703 i++;
704 chown_advanced_but[i].id = add_widget (ch_dlg,
705 button_new (y, WIDGET (ch_dlg)->cols / 2 + 1,
706 chown_advanced_but[i].ret_cmd,
707 chown_advanced_but[i].flags,
708 chown_advanced_but[i].text, NULL));
709 y++;
712 i = BUTTONS_PERM + 2;
713 add_widget (ch_dlg, hline_new (y++, -1, -1));
714 chown_advanced_but[i].id = add_widget (ch_dlg,
715 button_new (y,
716 WIDGET (ch_dlg)->cols / 2 -
717 chown_advanced_but[i].len,
718 chown_advanced_but[i].ret_cmd,
719 chown_advanced_but[i].flags,
720 chown_advanced_but[i].text, NULL));
721 i++;
722 chown_advanced_but[i].id = add_widget (ch_dlg,
723 button_new (y, WIDGET (ch_dlg)->cols / 2 + 1,
724 chown_advanced_but[i].ret_cmd,
725 chown_advanced_but[i].flags,
726 chown_advanced_but[i].text, NULL));
728 dlg_select_widget (b_att[0]);
731 /* --------------------------------------------------------------------------------------------- */
733 static void
734 chown_advanced_done (void)
736 g_free (sf_stat);
737 if (need_update)
738 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
739 repaint_screen ();
742 /* --------------------------------------------------------------------------------------------- */
744 #if 0
745 static void
746 do_chown (uid_t u, gid_t g)
748 chown (current_panel->dir.list[current_file].fname, u, g);
749 file_mark (current_panel, current_file, 0);
751 #endif
753 /* --------------------------------------------------------------------------------------------- */
755 static char *
756 next_file (void)
758 while (!current_panel->dir.list[current_file].f.marked)
759 current_file++;
761 return current_panel->dir.list[current_file].fname;
764 /* --------------------------------------------------------------------------------------------- */
766 static void
767 apply_advanced_chowns (struct stat *sf)
769 vfs_path_t *vpath;
770 char *lc_fname;
771 gid_t a_gid = sf->st_gid;
772 uid_t a_uid = sf->st_uid;
774 lc_fname = current_panel->dir.list[current_file].fname;
775 vpath = vfs_path_from_str (lc_fname);
776 need_update = end_chown = TRUE;
777 if (mc_chmod (vpath, get_mode ()) == -1)
778 message (D_ERROR, MSG_ERROR, _("Cannot chmod \"%s\"\n%s"),
779 lc_fname, unix_error_string (errno));
780 /* call mc_chown only, if mc_chmod didn't fail */
781 else if (mc_chown (vpath, (ch_flags[9] == '+') ? sf->st_uid : (uid_t) - 1,
782 (ch_flags[10] == '+') ? sf->st_gid : (gid_t) - 1) == -1)
783 message (D_ERROR, MSG_ERROR, _("Cannot chown \"%s\"\n%s"),
784 lc_fname, unix_error_string (errno));
785 do_file_mark (current_panel, current_file, 0);
786 vfs_path_free (vpath);
790 lc_fname = next_file ();
791 vpath = vfs_path_from_str (lc_fname);
793 if (mc_stat (vpath, sf) != 0)
795 vfs_path_free (vpath);
796 break;
799 ch_cmode = sf->st_mode;
801 if (mc_chmod (vpath, get_mode ()) == -1)
802 message (D_ERROR, MSG_ERROR, _("Cannot chmod \"%s\"\n%s"),
803 lc_fname, unix_error_string (errno));
804 /* call mc_chown only, if mc_chmod didn't fail */
805 else if (mc_chown (vpath, (ch_flags[9] == '+') ? a_uid : (uid_t) - 1,
806 (ch_flags[10] == '+') ? a_gid : (gid_t) - 1) == -1)
807 message (D_ERROR, MSG_ERROR, _("Cannot chown \"%s\"\n%s"),
808 lc_fname, unix_error_string (errno));
810 do_file_mark (current_panel, current_file, 0);
811 vfs_path_free (vpath);
813 while (current_panel->marked != 0);
816 /* --------------------------------------------------------------------------------------------- */
817 /*** public functions ****************************************************************************/
818 /* --------------------------------------------------------------------------------------------- */
820 void
821 chown_advanced_cmd (void)
823 /* Number of files at startup */
824 int files_on_begin;
826 files_on_begin = max (1, current_panel->marked);
829 { /* do while any files remaining */
830 int file_idx;
831 char buffer[BUF_MEDIUM];
832 vfs_path_t *vpath;
833 int result;
835 init_chown_advanced ();
837 if (current_panel->marked)
838 fname = next_file (); /* next marked file */
839 else
840 fname = selection (current_panel)->fname; /* single file */
841 vpath = vfs_path_from_str (fname);
843 if (mc_stat (vpath, sf_stat) != 0)
844 { /* get status of file */
845 destroy_dlg (ch_dlg);
846 vfs_path_free (vpath);
847 break;
850 ch_cmode = sf_stat->st_mode;
852 file_idx = files_on_begin == 1 ? 1 : (files_on_begin - current_panel->marked + 1);
853 g_snprintf (buffer, sizeof (buffer), "%s (%d/%d)",
854 str_fit_to_term (fname, WIDGET(ch_dlg)->cols - 20, J_LEFT_FIT),
855 file_idx, files_on_begin);
856 label_set_text (l_filename, buffer);
857 chown_refresh ();
858 update_ownership ();
860 result = run_dlg (ch_dlg);
862 switch (result)
864 case B_CANCEL:
865 end_chown = TRUE;
866 break;
868 case B_ENTER:
869 need_update = TRUE;
870 if (mc_chmod (vpath, get_mode ()) == -1)
871 message (D_ERROR, MSG_ERROR, _("Cannot chmod \"%s\"\n%s"),
872 fname, unix_error_string (errno));
873 /* call mc_chown only, if mc_chmod didn't fail */
874 else if (mc_chown
875 (vpath, (ch_flags[9] == '+') ? sf_stat->st_uid : (uid_t) - 1,
876 (ch_flags[10] == '+') ? sf_stat->st_gid : (gid_t) - 1) == -1)
877 message (D_ERROR, MSG_ERROR, _("Cannot chown \"%s\"\n%s"), fname,
878 unix_error_string (errno));
879 break;
881 case B_SETALL:
882 apply_advanced_chowns (sf_stat);
883 break;
885 case B_SKIP:
886 break;
889 if (current_panel->marked && result != B_CANCEL)
891 do_file_mark (current_panel, current_file, 0);
892 need_update = TRUE;
894 destroy_dlg (ch_dlg);
895 vfs_path_free (vpath);
897 while (current_panel->marked && !end_chown);
899 chown_advanced_done ();
902 /* --------------------------------------------------------------------------------------------- */