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