This source file includes following definitions.
- chown_init
- chown_refresh
- chown_bg_callback
- chown_buttons_create
- chown_dlg_create
- chown_done
- try_chown
- do_chown
- apply_chowns
- 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/skin.h"
42 #include "lib/vfs/vfs.h"
43 #include "lib/strutil.h"
44 #include "lib/util.h"
45 #include "lib/widget.h"
46
47 #include "src/setup.h"
48 #include "src/util.h"
49
50 #include "cmd.h"
51
52
53
54
55
56 #define GH 12
57 #define GW 21
58
59 #define BUTTONS 5
60
61 #define B_SETALL B_USER
62 #define B_SETUSR (B_USER + 1)
63 #define B_SETGRP (B_USER + 2)
64
65 #define LABELS 5
66
67 #define chown_label(n, txt) label_set_text (chown_label[n].l, txt)
68
69
70
71
72
73
74
75 static struct
76 {
77 int ret_cmd;
78 button_flags_t flags;
79 int y;
80 const char *text;
81 WButton *button;
82 } chown_but[BUTTONS] = {
83 { B_SETALL, NORMAL_BUTTON, 5, N_ ("Set &all"), NULL },
84 { B_SETGRP, NORMAL_BUTTON, 5, N_ ("Set &groups"), NULL },
85 { B_SETUSR, NORMAL_BUTTON, 5, N_ ("Set &users"), NULL },
86 { B_ENTER, DEFPUSH_BUTTON, 3, N_ ("&Set"), NULL },
87 { B_CANCEL, NORMAL_BUTTON, 3, N_ ("&Cancel"), NULL },
88 };
89
90 static struct
91 {
92 int y;
93 WLabel *l;
94 } chown_label[LABELS] = {
95 { 4, NULL }, { 6, NULL }, { 8, NULL }, { 10, NULL }, { 12, NULL },
96 };
97
98 static int current_file;
99 static gboolean ignore_all;
100
101 static WListbox *l_user, *l_group;
102
103
104
105
106
107 static void
108 chown_init (void)
109 {
110 static gboolean i18n = FALSE;
111
112 if (i18n)
113 return;
114
115 i18n = TRUE;
116
117 #ifdef ENABLE_NLS
118 for (int i = 0; i < BUTTONS; i++)
119 chown_but[i].text = _ (chown_but[i].text);
120 #endif
121 }
122
123
124
125 static void
126 chown_refresh (const Widget *h)
127 {
128 int y = 3;
129 int x = 7 + GW * 2;
130
131 tty_setcolor (COLOR_NORMAL);
132
133 widget_gotoyx (h, y + 0, x);
134 tty_print_string (_ ("Name"));
135 widget_gotoyx (h, y + 2, x);
136 tty_print_string (_ ("Owner name"));
137 widget_gotoyx (h, y + 4, x);
138 tty_print_string (_ ("Group name"));
139 widget_gotoyx (h, y + 6, x);
140 tty_print_string (_ ("Size"));
141 widget_gotoyx (h, y + 8, x);
142 tty_print_string (_ ("Permission"));
143 }
144
145
146
147 static cb_ret_t
148 chown_bg_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
149 {
150 switch (msg)
151 {
152 case MSG_DRAW:
153 frame_callback (w, NULL, MSG_DRAW, 0, NULL);
154 chown_refresh (WIDGET (w->owner));
155 return MSG_HANDLED;
156
157 default:
158 return frame_callback (w, sender, msg, parm, data);
159 }
160 }
161
162
163
164 static void
165 chown_buttons_create (WGroup *g, const int first, const int last)
166 {
167 int i;
168 int blen = 0;
169 int x;
170
171 const int y = WIDGET (g)->rect.lines - chown_but[first].y;
172
173 group_add_widget (g, hline_new (y - 1, -1, -1));
174
175 for (i = first; i <= last; i++)
176 {
177 chown_but[i].button =
178 button_new (y, 1, chown_but[i].ret_cmd, chown_but[i].flags, chown_but[i].text, NULL);
179 blen += button_get_width (chown_but[i].button) + 1;
180 group_add_widget (g, chown_but[i].button);
181 }
182
183 x = WIDGET (g)->rect.x + (WIDGET (g)->rect.cols - blen) / 2;
184
185 for (i = first; i <= last; i++)
186 {
187 WIDGET (chown_but[i].button)->rect.x = x;
188 x += button_get_width (chown_but[i].button) + 1;
189 }
190 }
191
192
193
194 static WDialog *
195 chown_dlg_create (WPanel *panel)
196 {
197 int single_set;
198 WDialog *ch_dlg;
199 WGroup *g;
200 int lines, cols;
201 struct passwd *l_pass;
202 struct group *l_grp;
203
204 single_set = (panel->marked < 2) ? 3 : 0;
205 lines = GH + 4 + (single_set != 0 ? 2 : 4);
206 cols = GW * 3 + 2 + 6;
207
208 ch_dlg = dlg_create (TRUE, 0, 0, lines, cols, WPOS_CENTER, FALSE, dialog_colors, NULL, NULL,
209 "[Chown]", _ ("Chown command"));
210 g = GROUP (ch_dlg);
211
212
213 ch_dlg->bg->callback = chown_bg_callback;
214
215 group_add_widget (g, groupbox_new (2, 3, GH, GW, _ ("User name")));
216 l_user = listbox_new (3, 4, GH - 2, GW - 2, FALSE, NULL);
217 group_add_widget (g, l_user);
218
219 listbox_add_item (l_user, LISTBOX_APPEND_AT_END, 0, _ ("<Unknown user>"), NULL, FALSE);
220
221 setpwent ();
222 while ((l_pass = getpwent ()) != NULL)
223 listbox_add_item (l_user, LISTBOX_APPEND_SORTED, 0, l_pass->pw_name, NULL, FALSE);
224 endpwent ();
225
226 group_add_widget (g, groupbox_new (2, 4 + GW, GH, GW, _ ("Group name")));
227 l_group = listbox_new (3, 5 + GW, GH - 2, GW - 2, FALSE, NULL);
228 group_add_widget (g, l_group);
229
230 listbox_add_item (l_group, LISTBOX_APPEND_AT_END, 0, _ ("<Unknown group>"), NULL, FALSE);
231
232 setgrent ();
233 while ((l_grp = getgrent ()) != NULL)
234 listbox_add_item (l_group, LISTBOX_APPEND_SORTED, 0, l_grp->gr_name, NULL, FALSE);
235 endgrent ();
236
237 group_add_widget (g, groupbox_new (2, 5 + GW * 2, GH, GW, _ ("File")));
238
239 for (int i = 0; i < LABELS; i++)
240 {
241 chown_label[i].l = label_new (chown_label[i].y, 7 + GW * 2, NULL);
242 group_add_widget (g, chown_label[i].l);
243 }
244
245 if (single_set == 0)
246 chown_buttons_create (g, 0, BUTTONS - 3);
247
248 chown_buttons_create (g, BUTTONS - 2, BUTTONS - 1);
249
250
251 widget_select (WIDGET (l_user));
252
253 return ch_dlg;
254 }
255
256
257
258 static void
259 chown_done (gboolean need_update)
260 {
261 if (need_update)
262 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
263 repaint_screen ();
264 }
265
266
267
268 static gboolean
269 try_chown (const vfs_path_t *p, uid_t u, gid_t g)
270 {
271 const char *fname = NULL;
272
273 while (mc_chown (p, u, g) == -1 && !ignore_all)
274 {
275 int my_errno = errno;
276
277 if (fname == NULL)
278 fname = x_basename (vfs_path_as_str (p));
279
280 errno = my_errno;
281
282 switch (file_error (NULL, TRUE, _ ("Cannot chown\n%sn%s"), fname))
283 {
284 case FILE_IGNORE:
285
286 return TRUE;
287
288 case FILE_IGNORE_ALL:
289 ignore_all = TRUE;
290
291 return TRUE;
292
293 case FILE_RETRY:
294
295 break;
296
297 case FILE_ABORT:
298 default:
299
300 return FALSE;
301 }
302 }
303
304 return TRUE;
305 }
306
307
308
309 static gboolean
310 do_chown (WPanel *panel, const vfs_path_t *p, uid_t u, gid_t g)
311 {
312 gboolean ret;
313
314 ret = try_chown (p, u, g);
315
316 do_file_mark (panel, current_file, 0);
317
318 return ret;
319 }
320
321
322
323 static void
324 apply_chowns (WPanel *panel, vfs_path_t *vpath, uid_t u, gid_t g)
325 {
326 gboolean ok;
327
328 if (!do_chown (panel, vpath, u, g))
329 return;
330
331 do
332 {
333 const GString *fname;
334 struct stat sf;
335
336 fname = panel_find_marked_file (panel, ¤t_file);
337 vpath = vfs_path_from_str (fname->str);
338 ok = (mc_stat (vpath, &sf) == 0);
339
340 if (!ok)
341 {
342
343
344 do_file_mark (panel, current_file, 0);
345
346
347 ok = TRUE;
348 }
349 else
350 ok = do_chown (panel, vpath, u, g);
351
352 vfs_path_free (vpath, TRUE);
353 }
354 while (ok && panel->marked != 0);
355 }
356
357
358
359
360
361 void
362 chown_cmd (WPanel *panel)
363 {
364 gboolean need_update;
365 gboolean end_chown;
366
367 chown_init ();
368
369 current_file = 0;
370 ignore_all = FALSE;
371
372 do
373 {
374 vfs_path_t *vpath;
375 WDialog *ch_dlg;
376 struct stat sf_stat;
377 const GString *fname;
378 int result;
379 char buffer[BUF_TINY];
380 uid_t new_user = (uid_t) (-1);
381 gid_t new_group = (gid_t) (-1);
382
383 do_refresh ();
384
385 need_update = FALSE;
386 end_chown = FALSE;
387
388 fname = panel_get_marked_file (panel, ¤t_file);
389 if (fname == NULL)
390 break;
391
392 vpath = vfs_path_from_str (fname->str);
393
394 if (mc_stat (vpath, &sf_stat) != 0)
395 {
396 vfs_path_free (vpath, TRUE);
397 break;
398 }
399
400 ch_dlg = chown_dlg_create (panel);
401
402
403 listbox_set_current (l_user, listbox_search_text (l_user, get_owner (sf_stat.st_uid)));
404 listbox_set_current (l_group, listbox_search_text (l_group, get_group (sf_stat.st_gid)));
405
406 chown_label (0, str_trunc (fname->str, GW - 4));
407 chown_label (1, str_trunc (get_owner (sf_stat.st_uid), GW - 4));
408 chown_label (2, str_trunc (get_group (sf_stat.st_gid), GW - 4));
409 size_trunc_len (buffer, GW - 4, sf_stat.st_size, 0, panels_options.kilobyte_si);
410 chown_label (3, buffer);
411 chown_label (4, string_perm (sf_stat.st_mode));
412
413 result = dlg_run (ch_dlg);
414
415 switch (result)
416 {
417 case B_CANCEL:
418 end_chown = TRUE;
419 break;
420
421 case B_ENTER:
422 case B_SETALL:
423 {
424 struct group *grp;
425 struct passwd *user;
426 char *text;
427
428 listbox_get_current (l_group, &text, NULL);
429 grp = getgrnam (text);
430 if (grp != NULL)
431 new_group = grp->gr_gid;
432 listbox_get_current (l_user, &text, NULL);
433 user = getpwnam (text);
434 if (user != NULL)
435 new_user = user->pw_uid;
436 if (result == B_ENTER)
437 {
438 if (panel->marked <= 1)
439 {
440
441 if (mc_chown (vpath, new_user, new_group) == -1)
442 file_error_message (_ ("Cannot chown\n%s"), fname->str);
443 end_chown = TRUE;
444 }
445 else if (!try_chown (vpath, new_user, new_group))
446 {
447
448 result = B_CANCEL;
449 end_chown = TRUE;
450 }
451 }
452 else
453 {
454 apply_chowns (panel, vpath, new_user, new_group);
455 end_chown = TRUE;
456 }
457
458 need_update = TRUE;
459 break;
460 }
461
462 case B_SETUSR:
463 {
464 struct passwd *user;
465 char *text;
466
467 listbox_get_current (l_user, &text, NULL);
468 user = getpwnam (text);
469 if (user != NULL)
470 {
471 new_user = user->pw_uid;
472 apply_chowns (panel, vpath, new_user, new_group);
473 need_update = TRUE;
474 end_chown = TRUE;
475 }
476 break;
477 }
478
479 case B_SETGRP:
480 {
481 struct group *grp;
482 char *text;
483
484 listbox_get_current (l_group, &text, NULL);
485 grp = getgrnam (text);
486 if (grp != NULL)
487 {
488 new_group = grp->gr_gid;
489 apply_chowns (panel, vpath, new_user, new_group);
490 need_update = TRUE;
491 end_chown = TRUE;
492 }
493 break;
494 }
495
496 default:
497 break;
498 }
499
500 if (panel->marked != 0 && result != B_CANCEL)
501 {
502 do_file_mark (panel, current_file, 0);
503 need_update = TRUE;
504 }
505
506 vfs_path_free (vpath, TRUE);
507
508 widget_destroy (WIDGET (ch_dlg));
509 }
510 while (panel->marked != 0 && !end_chown);
511
512 chown_done (need_update);
513 }
514
515