This source file includes following definitions.
- advanced_chown_init
- inc_flag_pos
- dec_flag_pos
- set_perm_by_flags
- get_perm
- get_mode
- update_permissions
- update_ownership
- print_flags
- advanced_chown_refresh
- advanced_chown_info_update
- update_mode
- perm_button_callback
- perm_button_mouse_callback
- perm_button_new
- chl_callback
- user_group_button_cb
- advanced_chown_bg_callback
- advanced_chown_callback
- advanced_chown_dlg_create
- advanced_chown_done
- try_advanced_chown
- do_advanced_chown
- apply_advanced_chowns
- advanced_chown_cmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 #include <config.h>
28
29 #include <errno.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <pwd.h>
33 #include <grp.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37
38 #include "lib/global.h"
39
40 #include "lib/tty/tty.h"
41 #include "lib/tty/key.h"
42 #include "lib/skin.h"
43 #include "lib/vfs/vfs.h"
44 #include "lib/strutil.h"
45 #include "lib/util.h"
46 #include "lib/widget.h"
47
48 #include "cmd.h"
49
50
51
52
53
54 #define BX 5
55 #define BY 5
56
57 #define BUTTONS 9
58 #define BUTTONS_PERM 5
59
60 #define B_SETALL B_USER
61 #define B_SKIP (B_USER + 1)
62
63
64
65
66
67
68
69 static struct
70 {
71 unsigned long id;
72 int ret_cmd;
73 button_flags_t flags;
74 int x;
75 int len;
76 const char *text;
77 } advanced_chown_but[BUTTONS] = {
78
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, "" },
84
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") }
89
90 };
91
92 static int current_file;
93 static gboolean ignore_all;
94
95 static WButton *b_att[3];
96 static WButton *b_user, *b_group;
97 static WLabel *l_filename;
98 static WLabel *l_mode;
99
100 static int flag_pos;
101 static int x_toggle;
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;
106
107
108
109
110
111 static void
112 advanced_chown_init (void)
113 {
114 static gboolean i18n = FALSE;
115 int i;
116
117 if (i18n)
118 return;
119
120 i18n = TRUE;
121
122 for (i = BUTTONS_PERM; i < BUTTONS; i++)
123 {
124 #ifdef ENABLE_NLS
125 advanced_chown_but[i].text = _(advanced_chown_but[i].text);
126 #endif
127
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;
131 }
132
133 }
134
135
136
137 static cb_ret_t
138 inc_flag_pos (void)
139 {
140 if (flag_pos == 10)
141 {
142 flag_pos = 0;
143 return MSG_NOT_HANDLED;
144 }
145
146 flag_pos++;
147
148 return flag_pos % 3 == 0 ? MSG_NOT_HANDLED : MSG_HANDLED;
149 }
150
151
152
153 static cb_ret_t
154 dec_flag_pos (void)
155 {
156 if (flag_pos == 0)
157 {
158 flag_pos = 10;
159 return MSG_NOT_HANDLED;
160 }
161
162 flag_pos--;
163
164 return (flag_pos + 1) % 3 == 0 ? MSG_NOT_HANDLED : MSG_HANDLED;
165 }
166
167
168
169 static void
170 set_perm_by_flags (char *s, int f_p)
171 {
172 int i;
173
174 for (i = 0; i < 3; i++)
175 {
176 if (ch_flags[f_p + i] == '+')
177 s[i] = ch_perm[i];
178 else if (ch_flags[f_p + i] == '-')
179 s[i] = '-';
180 else
181 s[i] = (ch_cmode & (1 << (8 - f_p - i))) != 0 ? ch_perm[i] : '-';
182 }
183 }
184
185
186
187 static mode_t
188 get_perm (char *s, int base)
189 {
190 mode_t m = 0;
191
192 m |= (s[0] == '-') ? 0 :
193 ((s[0] == '+') ? (mode_t) (1 << (base + 2)) : (1 << (base + 2)) & ch_cmode);
194
195 m |= (s[1] == '-') ? 0 :
196 ((s[1] == '+') ? (mode_t) (1 << (base + 1)) : (1 << (base + 1)) & ch_cmode);
197
198 m |= (s[2] == '-') ? 0 : ((s[2] == '+') ? (mode_t) (1 << base) : (1 << base) & ch_cmode);
199
200 return m;
201 }
202
203
204
205 static mode_t
206 get_mode (void)
207 {
208 mode_t m;
209
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);
214
215 return m;
216 }
217
218
219
220 static void
221 update_permissions (void)
222 {
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);
226 }
227
228
229
230 static void
231 update_ownership (void)
232 {
233 button_set_text (b_user, get_owner (sf_stat.st_uid));
234 button_set_text (b_group, get_group (sf_stat.st_gid));
235 }
236
237
238
239 static void
240 print_flags (const WDialog *h)
241 {
242 int i;
243
244 tty_setcolor (COLOR_NORMAL);
245
246 for (i = 0; i < 3; i++)
247 {
248 widget_gotoyx (h, BY + 1, advanced_chown_but[0].x + 6 + i);
249 tty_print_char (ch_flags[i]);
250 }
251
252 for (i = 0; i < 3; i++)
253 {
254 widget_gotoyx (h, BY + 1, advanced_chown_but[1].x + 6 + i);
255 tty_print_char (ch_flags[i + 3]);
256 }
257
258 for (i = 0; i < 3; i++)
259 {
260 widget_gotoyx (h, BY + 1, advanced_chown_but[2].x + 6 + i);
261 tty_print_char (ch_flags[i + 6]);
262 }
263
264 update_permissions ();
265
266 for (i = 0; i < 15; i++)
267 {
268 widget_gotoyx (h, BY + 1, advanced_chown_but[3].x + 6 + i);
269 tty_print_char (ch_flags[9]);
270 }
271 for (i = 0; i < 15; i++)
272 {
273 widget_gotoyx (h, BY + 1, advanced_chown_but[4].x + 6 + i);
274 tty_print_char (ch_flags[10]);
275 }
276 }
277
278
279
280 static void
281 advanced_chown_refresh (const WDialog *h)
282 {
283 tty_setcolor (COLOR_NORMAL);
284
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"));
291
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"));
296
297 widget_gotoyx (h, BY + 1, 3);
298 tty_print_string (_("Flag"));
299 print_flags (h);
300 }
301
302
303
304 static void
305 advanced_chown_info_update (void)
306 {
307
308 label_set_textv (l_mode, _("Permissions (octal): %o"), get_mode ());
309
310
311 update_permissions ();
312 }
313
314
315
316 static void
317 update_mode (WGroup *g)
318 {
319 print_flags (DIALOG (g));
320 advanced_chown_info_update ();
321 widget_set_state (WIDGET (g->current->data), WST_FOCUSED, TRUE);
322 }
323
324
325
326 static cb_ret_t
327 perm_button_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
328 {
329 WButton *b = BUTTON (w);
330 WGroup *g = w->owner;
331 int i = 0;
332 int f_pos;
333
334
335 if (b == b_att[0])
336 f_pos = 0;
337 else if (b == b_att[1])
338 f_pos = 1;
339 else
340 f_pos = 2;
341
342 switch (msg)
343 {
344 case MSG_FOCUS:
345 if (b->hotpos == -1)
346 b->hotpos = 0;
347
348 flag_pos = f_pos * 3 + b->hotpos;
349 return MSG_HANDLED;
350
351 case MSG_KEY:
352 switch (parm)
353 {
354 case '*':
355 parm = '=';
356 MC_FALLTHROUGH;
357
358 case '-':
359 case '=':
360 case '+':
361 flag_pos = f_pos * 3 + b->hotpos;
362 ch_flags[flag_pos] = parm;
363 update_mode (g);
364 send_message (w, NULL, MSG_KEY, KEY_RIGHT, NULL);
365 if (b->hotpos == 2)
366 group_select_next_widget (g);
367 break;
368
369 case XCTRL ('f'):
370 case KEY_RIGHT:
371 {
372 cb_ret_t ret;
373
374 ret = inc_flag_pos ();
375 b->hotpos = flag_pos % 3;
376 return ret;
377 }
378
379 case XCTRL ('b'):
380 case KEY_LEFT:
381 {
382 cb_ret_t ret;
383
384 ret = dec_flag_pos ();
385 b->hotpos = flag_pos % 3;
386 return ret;
387 }
388
389 case 'x':
390 i++;
391 MC_FALLTHROUGH;
392
393 case 'w':
394 i++;
395 MC_FALLTHROUGH;
396
397 case 'r':
398 b->hotpos = i;
399 MC_FALLTHROUGH;
400
401 case ' ':
402 i = b->hotpos;
403
404 flag_pos = f_pos * 3 + i;
405 if (b->text.start[flag_pos % 3] == '-')
406 ch_flags[flag_pos] = '+';
407 else
408 ch_flags[flag_pos] = '-';
409 update_mode (w->owner);
410 break;
411
412 case '4':
413 i++;
414 MC_FALLTHROUGH;
415
416 case '2':
417 i++;
418 MC_FALLTHROUGH;
419
420 case '1':
421 b->hotpos = i;
422 flag_pos = f_pos * 3 + i;
423 ch_flags[flag_pos] = '=';
424 update_mode (g);
425 break;
426
427 default:
428 break;
429 }
430
431 return MSG_NOT_HANDLED;
432
433 default:
434 return button_default_callback (w, sender, msg, parm, data);
435 }
436 }
437
438
439
440 static void
441 perm_button_mouse_callback (Widget *w, mouse_msg_t msg, mouse_event_t *event)
442 {
443 switch (msg)
444 {
445 case MSG_MOUSE_DOWN:
446
447 BUTTON (w)->hotpos = CLAMP (event->x - 1, 0, 2);
448 MC_FALLTHROUGH;
449
450 default:
451 button_mouse_default_callback (w, msg, event);
452 break;
453 }
454 }
455
456
457
458 static WButton *
459 perm_button_new (int y, int x, int action, button_flags_t flags, const char *text,
460 bcback_fn callback)
461 {
462 WButton *b;
463 Widget *w;
464
465
466 b = button_new (y, x, action, flags, text, callback);
467 w = WIDGET (b);
468
469
470 widget_want_hotkey (w, FALSE);
471
472 w->callback = perm_button_callback;
473 w->mouse_callback = perm_button_mouse_callback;
474
475 return b;
476 }
477
478
479
480 static cb_ret_t
481 chl_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
482 {
483 switch (msg)
484 {
485 case MSG_KEY:
486 switch (parm)
487 {
488 case KEY_LEFT:
489 case KEY_RIGHT:
490 {
491 WDialog *h = DIALOG (w);
492
493 h->ret_value = parm;
494 dlg_close (h);
495 }
496 break;
497 default:
498 break;
499 }
500 MC_FALLTHROUGH;
501
502 default:
503 return dlg_default_callback (w, sender, msg, parm, data);
504 }
505 }
506
507
508
509 static int
510 user_group_button_cb (WButton *button, int action)
511 {
512 Widget *w = WIDGET (button);
513 int f_pos;
514 gboolean chl_end;
515
516 (void) action;
517
518 if (button == b_user)
519 f_pos = BUTTONS_PERM - 2;
520 else if (button == b_group)
521 f_pos = BUTTONS_PERM - 1;
522 else
523 return 0;
524
525 do
526 {
527 WGroup *g = w->owner;
528 WDialog *h = DIALOG (g);
529 Widget *wh = WIDGET (h);
530
531 gboolean is_owner = (f_pos == BUTTONS_PERM - 2);
532 const char *title;
533 int lxx, b_current;
534 WDialog *chl_dlg;
535 WListbox *chl_list;
536 int result;
537 int fe;
538 struct passwd *chl_pass;
539 struct group *chl_grp;
540
541 chl_end = FALSE;
542
543 if (is_owner)
544 {
545 title = _("owner");
546 lxx = WIDGET (b_user)->rect.x + 1;
547 }
548 else
549 {
550 title = _("group");
551 lxx = WIDGET (b_group)->rect.x + 1;
552 }
553
554 chl_dlg =
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);
557
558
559 chl_list =
560 listbox_new (1, 1, WIDGET (chl_dlg)->rect.lines - 2, WIDGET (chl_dlg)->rect.cols - 2,
561 FALSE, NULL);
562 listbox_add_item (chl_list, LISTBOX_APPEND_AT_END, 0, "<Unknown>", NULL, FALSE);
563 if (is_owner)
564 {
565
566 setpwent ();
567 while ((chl_pass = getpwent ()) != NULL)
568 listbox_add_item (chl_list, LISTBOX_APPEND_SORTED, 0, chl_pass->pw_name, NULL,
569 FALSE);
570 endpwent ();
571 fe = listbox_search_text (chl_list, get_owner (sf_stat.st_uid));
572 }
573 else
574 {
575
576 setgrent ();
577 while ((chl_grp = getgrent ()) != NULL)
578 listbox_add_item (chl_list, LISTBOX_APPEND_SORTED, 0, chl_grp->gr_name, NULL,
579 FALSE);
580 endgrent ();
581 fe = listbox_search_text (chl_list, get_group (sf_stat.st_gid));
582 }
583
584 listbox_set_current (chl_list, fe);
585
586 b_current = chl_list->current;
587 group_add_widget (GROUP (chl_dlg), chl_list);
588
589 result = dlg_run (chl_dlg);
590
591 if (result != B_CANCEL)
592 {
593 if (b_current != chl_list->current)
594 {
595 gboolean ok = FALSE;
596 char *text;
597
598 listbox_get_current (chl_list, &text, NULL);
599 if (is_owner)
600 {
601 chl_pass = getpwnam (text);
602 if (chl_pass != NULL)
603 {
604 sf_stat.st_uid = chl_pass->pw_uid;
605 ok = TRUE;
606 }
607 }
608 else
609 {
610 chl_grp = getgrnam (text);
611 if (chl_grp != NULL)
612 {
613 sf_stat.st_gid = chl_grp->gr_gid;
614 ok = TRUE;
615 }
616 }
617
618 if (!ok)
619 group_select_current_widget (g);
620 else
621 {
622 ch_flags[f_pos + 6] = '+';
623 update_ownership ();
624 group_select_current_widget (g);
625 print_flags (h);
626 }
627 }
628
629 if (result == KEY_LEFT)
630 {
631 if (!is_owner)
632 chl_end = TRUE;
633 group_select_prev_widget (g);
634 f_pos--;
635 }
636 else if (result == KEY_RIGHT)
637 {
638 if (is_owner)
639 chl_end = TRUE;
640 group_select_next_widget (g);
641 f_pos++;
642 }
643 }
644
645
646 widget_destroy (WIDGET (chl_dlg));
647 }
648 while (chl_end);
649
650 return 0;
651 }
652
653
654
655 static cb_ret_t
656 advanced_chown_bg_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
657 {
658 switch (msg)
659 {
660 case MSG_DRAW:
661 frame_callback (w, NULL, MSG_DRAW, 0, NULL);
662 advanced_chown_refresh (DIALOG (w->owner));
663 advanced_chown_info_update ();
664 return MSG_HANDLED;
665
666 default:
667 return frame_callback (w, sender, msg, parm, data);
668 }
669 }
670
671
672
673 static cb_ret_t
674 advanced_chown_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
675 {
676 WGroup *g = GROUP (w);
677 int i = 0;
678
679 switch (msg)
680 {
681 case MSG_KEY:
682 switch (parm)
683 {
684 case ALT ('x'):
685 i++;
686 MC_FALLTHROUGH;
687
688 case ALT ('w'):
689 i++;
690 MC_FALLTHROUGH;
691
692 case ALT ('r'):
693 parm = i + 3;
694 for (i = 0; i < 3; i++)
695 ch_flags[i * 3 + parm - 3] = (x_toggle & (1 << parm)) ? '-' : '+';
696 x_toggle ^= (1 << parm);
697 update_mode (g);
698 widget_draw (w);
699 break;
700
701 case XCTRL ('x'):
702 i++;
703 MC_FALLTHROUGH;
704
705 case XCTRL ('w'):
706 i++;
707 MC_FALLTHROUGH;
708
709 case XCTRL ('r'):
710 parm = i;
711 for (i = 0; i < 3; i++)
712 ch_flags[i * 3 + parm] = (x_toggle & (1 << parm)) ? '-' : '+';
713 x_toggle ^= (1 << parm);
714 update_mode (g);
715 widget_draw (w);
716 break;
717
718 default:
719 break;
720 }
721 return MSG_NOT_HANDLED;
722
723 default:
724 return dlg_default_callback (w, sender, msg, parm, data);
725 }
726 }
727
728
729
730 static WDialog *
731 advanced_chown_dlg_create (WPanel *panel)
732 {
733 gboolean single_set;
734 WDialog *ch_dlg;
735 WGroup *ch_grp;
736 int lines = 12;
737 int cols = 74;
738 int i;
739 int y;
740
741 memset (ch_flags, '=', 11);
742 flag_pos = 0;
743 x_toggle = 070;
744
745 single_set = (panel->marked < 2);
746 if (!single_set)
747 lines += 2;
748
749 ch_dlg =
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);
753
754
755 ch_dlg->bg->callback = advanced_chown_bg_callback;
756
757 l_filename = label_new (2, 3, NULL);
758 group_add_widget (ch_grp, l_filename);
759
760 group_add_widget (ch_grp, hline_new (3, -1, -1));
761
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);
775
776 l_mode = label_new (BY + 2, 3, NULL);
777 group_add_widget (ch_grp, l_mode);
778
779 y = BY + 3;
780 if (!single_set)
781 {
782 i = BUTTONS_PERM;
783 group_add_widget (ch_grp, hline_new (y++, -1, -1));
784 advanced_chown_but[i].id = group_add_widget (ch_grp,
785 button_new (y,
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));
791 i++;
792 advanced_chown_but[i].id = group_add_widget (ch_grp,
793 button_new (y,
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));
798 y++;
799 }
800
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,
804 button_new (y,
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));
810 i++;
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));
816
817 widget_select (WIDGET (b_att[0]));
818
819 return ch_dlg;
820 }
821
822
823
824 static void
825 advanced_chown_done (gboolean need_update)
826 {
827 if (need_update)
828 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
829 repaint_screen ();
830 }
831
832
833
834 static gboolean
835 try_advanced_chown (const vfs_path_t *p, mode_t m, uid_t u, gid_t g)
836 {
837 int chmod_result;
838 const char *fname = NULL;
839
840 while ((chmod_result = mc_chmod (p, m)) == -1 && !ignore_all)
841 {
842 int my_errno = errno;
843 int result;
844 char *msg;
845
846 if (fname == NULL)
847 fname = x_basename (vfs_path_as_str (p));
848 msg = g_strdup_printf (_("Cannot chmod \"%s\"\n%s"), fname, unix_error_string (my_errno));
849 result =
850 query_dialog (MSG_ERROR, msg, D_ERROR, 4, _("&Ignore"), _("Ignore &all"), _("&Retry"),
851 _("&Cancel"));
852 g_free (msg);
853
854 switch (result)
855 {
856 case 0:
857
858 return TRUE;
859
860 case 1:
861 ignore_all = TRUE;
862
863 return TRUE;
864
865 case 2:
866
867 break;
868
869 case 3:
870 default:
871
872 return FALSE;
873 }
874 }
875
876
877 while (chmod_result != -1 && mc_chown (p, u, g) == -1 && !ignore_all)
878 {
879 int my_errno = errno;
880 int result;
881 char *msg;
882
883 if (fname == NULL)
884 fname = x_basename (vfs_path_as_str (p));
885 msg = g_strdup_printf (_("Cannot chown \"%s\"\n%s"), fname, unix_error_string (my_errno));
886 result =
887 query_dialog (MSG_ERROR, msg, D_ERROR, 4, _("&Ignore"), _("Ignore &all"), _("&Retry"),
888 _("&Cancel"));
889 g_free (msg);
890
891 switch (result)
892 {
893 case 0:
894
895 return TRUE;
896
897 case 1:
898 ignore_all = TRUE;
899
900 return TRUE;
901
902 case 2:
903
904 break;
905
906 case 3:
907 default:
908
909 return FALSE;
910 }
911 }
912
913 return TRUE;
914
915 }
916
917
918
919 static gboolean
920 do_advanced_chown (WPanel *panel, const vfs_path_t *p, mode_t m, uid_t u, gid_t g)
921 {
922 gboolean ret;
923
924 ret = try_advanced_chown (p, m, u, g);
925
926 do_file_mark (panel, current_file, 0);
927
928 return ret;
929 }
930
931
932
933 static void
934 apply_advanced_chowns (WPanel *panel, vfs_path_t *vpath, struct stat *sf)
935 {
936 gid_t a_gid = sf->st_gid;
937 uid_t a_uid = sf->st_uid;
938 gboolean ok;
939
940 if (!do_advanced_chown (panel, vpath, get_mode (),
941 (ch_flags[9] == '+') ? a_uid : (uid_t) (-1),
942 (ch_flags[10] == '+') ? a_gid : (gid_t) (-1)))
943 return;
944
945 do
946 {
947 const GString *fname;
948
949 fname = panel_find_marked_file (panel, ¤t_file);
950 vpath = vfs_path_from_str (fname->str);
951 ok = (mc_stat (vpath, sf) == 0);
952
953 if (!ok)
954 {
955
956
957 do_file_mark (panel, current_file, 0);
958
959
960 ok = TRUE;
961 }
962 else
963 {
964 ch_cmode = sf->st_mode;
965
966 ok = do_advanced_chown (panel, vpath, get_mode (),
967 (ch_flags[9] == '+') ? a_uid : (uid_t) (-1),
968 (ch_flags[10] == '+') ? a_gid : (gid_t) (-1));
969 }
970
971 vfs_path_free (vpath, TRUE);
972 }
973 while (ok && panel->marked != 0);
974 }
975
976
977
978
979
980 void
981 advanced_chown_cmd (WPanel *panel)
982 {
983 gboolean need_update;
984 gboolean end_chown;
985
986
987 int files_on_begin;
988
989 files_on_begin = MAX (1, panel->marked);
990
991 advanced_chown_init ();
992
993 current_file = 0;
994 ignore_all = FALSE;
995
996 do
997 {
998 vfs_path_t *vpath;
999 WDialog *ch_dlg;
1000 const GString *fname;
1001 int result;
1002 int file_idx;
1003
1004 do_refresh ();
1005
1006 need_update = FALSE;
1007 end_chown = FALSE;
1008
1009 fname = panel_get_marked_file (panel, ¤t_file);
1010 if (fname == NULL)
1011 break;
1012
1013 vpath = vfs_path_from_str (fname->str);
1014
1015 if (mc_stat (vpath, &sf_stat) != 0)
1016 {
1017 vfs_path_free (vpath, TRUE);
1018 break;
1019 }
1020
1021 ch_cmode = sf_stat.st_mode;
1022
1023 ch_dlg = advanced_chown_dlg_create (panel);
1024
1025 file_idx = files_on_begin == 1 ? 1 : (files_on_begin - panel->marked + 1);
1026 label_set_textv (l_filename, "%s (%d/%d)",
1027 str_fit_to_term (fname->str, WIDGET (ch_dlg)->rect.cols - 20, J_LEFT_FIT),
1028 file_idx, files_on_begin);
1029 update_ownership ();
1030
1031 result = dlg_run (ch_dlg);
1032
1033 switch (result)
1034 {
1035 case B_CANCEL:
1036 end_chown = TRUE;
1037 break;
1038
1039 case B_ENTER:
1040 {
1041 uid_t uid = ch_flags[9] == '+' ? sf_stat.st_uid : (uid_t) (-1);
1042 gid_t gid = ch_flags[10] == '+' ? sf_stat.st_gid : (gid_t) (-1);
1043
1044 if (panel->marked <= 1)
1045 {
1046
1047 if (mc_chmod (vpath, get_mode ()) == -1)
1048 message (D_ERROR, MSG_ERROR, _("Cannot chmod \"%s\"\n%s"),
1049 fname->str, unix_error_string (errno));
1050
1051 else if (mc_chown (vpath, uid, gid) == -1)
1052 message (D_ERROR, MSG_ERROR, _("Cannot chown \"%s\"\n%s"), fname->str,
1053 unix_error_string (errno));
1054
1055 end_chown = TRUE;
1056 }
1057 else if (!try_advanced_chown (vpath, get_mode (), uid, gid))
1058 {
1059
1060 result = B_CANCEL;
1061 end_chown = TRUE;
1062 }
1063
1064 need_update = TRUE;
1065 break;
1066 }
1067
1068 case B_SETALL:
1069 apply_advanced_chowns (panel, vpath, &sf_stat);
1070 need_update = TRUE;
1071 end_chown = TRUE;
1072 break;
1073
1074 case B_SKIP:
1075 default:
1076 break;
1077 }
1078
1079 if (panel->marked != 0 && result != B_CANCEL)
1080 {
1081 do_file_mark (panel, current_file, 0);
1082 need_update = TRUE;
1083 }
1084
1085 vfs_path_free (vpath, TRUE);
1086
1087 widget_destroy (WIDGET (ch_dlg));
1088 }
1089 while (panel->marked != 0 && !end_chown);
1090
1091 advanced_chown_done (need_update);
1092 }
1093
1094