2 Chown 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/>.
24 * \brief Source: chown command
34 #include <sys/types.h>
38 #include "lib/global.h"
40 #include "lib/tty/tty.h"
42 #include "lib/vfs/vfs.h"
43 #include "lib/strutil.h"
45 #include "lib/widget.h"
47 #include "src/setup.h" /* panels_options */
49 /* Needed for the extern declarations of integer parameters */
51 #include "midnight.h" /* current_panel */
55 /*** global variables ****************************************************************************/
57 /*** file scope macro definitions ****************************************************************/
64 #define B_SETALL B_USER
65 #define B_SETUSR (B_USER + 1)
66 #define B_SETGRP (B_USER + 2)
70 #define chown_label(n,txt) label_set_text (chown_label [n].l, txt)
72 /*** file scope type declarations ****************************************************************/
74 /*** file scope variables ************************************************************************/
76 static int need_update
, end_chown
;
77 static int current_file
;
78 static int single_set
;
79 static WListbox
*l_user
, *l_group
;
88 } chown_but
[BUTTONS
] = {
89 { B_SETALL
, NORMAL_BUTTON
, 5, 0, N_("Set &all") },
90 { B_SETGRP
, NORMAL_BUTTON
, 5, 0, N_("Set &groups") },
91 { B_SETUSR
, NORMAL_BUTTON
, 5, 0, N_("Set &users") },
92 { B_ENTER
, DEFPUSH_BUTTON
, 3, 0, N_("&Set") },
93 { B_CANCEL
, NORMAL_BUTTON
, 3, 0, N_("&Cancel") },
96 /* summary length of three buttons */
102 } chown_label
[LABELS
] = {
111 /* --------------------------------------------------------------------------------------------- */
112 /*** file scope functions ************************************************************************/
113 /* --------------------------------------------------------------------------------------------- */
118 static gboolean i18n
= FALSE
;
127 for (i
= 0; i
< BUTTONS
; i
++)
128 chown_but
[i
].text
= _(chown_but
[i
].text
);
129 #endif /* ENABLE_NLS */
131 for (i
= 0; i
< BUTTONS
; i
++)
133 chown_but
[i
].len
= str_term_width1 (chown_but
[i
].text
) + 3; /* [], spaces and w/o & */
134 if (chown_but
[i
].flags
== DEFPUSH_BUTTON
)
135 chown_but
[i
].len
+= 2; /* <> */
138 blen
+= chown_but
[i
].len
;
144 /* --------------------------------------------------------------------------------------------- */
147 chown_refresh (WDialog
* h
)
150 const int x
= 7 + GW
* 2;
152 dlg_default_repaint (h
);
154 tty_setcolor (COLOR_NORMAL
);
156 widget_move (h
, y
+ 0, x
);
157 tty_print_string (_("Name"));
158 widget_move (h
, y
+ 2, x
);
159 tty_print_string (_("Owner name"));
160 widget_move (h
, y
+ 4, x
);
161 tty_print_string (_("Group name"));
162 widget_move (h
, y
+ 6, x
);
163 tty_print_string (_("Size"));
164 widget_move (h
, y
+ 8, x
);
165 tty_print_string (_("Permission"));
168 /* --------------------------------------------------------------------------------------------- */
173 while (!current_panel
->dir
.list
[current_file
].f
.marked
)
176 return current_panel
->dir
.list
[current_file
].fname
;
179 /* --------------------------------------------------------------------------------------------- */
182 chown_callback (Widget
* w
, Widget
* sender
, widget_msg_t msg
, int parm
, void *data
)
187 chown_refresh (DIALOG (w
));
191 return dlg_default_callback (w
, sender
, msg
, parm
, data
);
195 /* --------------------------------------------------------------------------------------------- */
203 struct passwd
*l_pass
;
209 end_chown
= need_update
= current_file
= 0;
210 single_set
= (current_panel
->marked
< 2) ? 3 : 0;
212 cols
= GW
* 3 + 2 + 6;
213 lines
= GH
+ 4 + (single_set
? 2 : 4);
216 dlg_create (TRUE
, 0, 0, lines
, cols
, WPOS_CENTER
, FALSE
, dialog_colors
, chown_callback
,
217 NULL
, "[Chown]", _("Chown command"));
219 add_widget (ch_dlg
, groupbox_new (2, 3, GH
, GW
, _("User name")));
220 l_user
= listbox_new (3, 4, GH
- 2, GW
- 2, FALSE
, NULL
);
221 add_widget (ch_dlg
, l_user
);
222 /* add field for unknown names (numbers) */
223 listbox_add_item (l_user
, LISTBOX_APPEND_AT_END
, 0, _("<Unknown user>"), NULL
, FALSE
);
224 /* get and put user names in the listbox */
226 while ((l_pass
= getpwent ()) != NULL
)
227 listbox_add_item (l_user
, LISTBOX_APPEND_SORTED
, 0, l_pass
->pw_name
, NULL
, FALSE
);
230 add_widget (ch_dlg
, groupbox_new (2, 4 + GW
, GH
, GW
, _("Group name")));
231 l_group
= listbox_new (3, 5 + GW
, GH
- 2, GW
- 2, FALSE
, NULL
);
232 add_widget (ch_dlg
, l_group
);
233 /* add field for unknown names (numbers) */
234 listbox_add_item (l_group
, LISTBOX_APPEND_AT_END
, 0, _("<Unknown group>"), NULL
, FALSE
);
235 /* get and put group names in the listbox */
237 while ((l_grp
= getgrent ()) != NULL
)
238 listbox_add_item (l_group
, LISTBOX_APPEND_SORTED
, 0, l_grp
->gr_name
, NULL
, FALSE
);
241 add_widget (ch_dlg
, groupbox_new (2, 5 + GW
* 2, GH
, GW
, _("File")));
242 /* add widgets for the file information */
243 for (i
= 0; i
< LABELS
; i
++)
245 chown_label
[i
].l
= label_new (chown_label
[i
].y
, 7 + GW
* 2, "");
246 add_widget (ch_dlg
, chown_label
[i
].l
);
253 add_widget (ch_dlg
, hline_new (lines
- chown_but
[0].y
- 1, -1, -1));
255 y
= lines
- chown_but
[0].y
;
256 x
= (cols
- blen
) / 2;
258 for (i
= 0; i
< BUTTONS
- 2; i
++)
261 button_new (y
, x
, chown_but
[i
].ret_cmd
, chown_but
[i
].flags
,
262 chown_but
[i
].text
, NULL
));
263 x
+= chown_but
[i
].len
+ 1;
268 y
= lines
- chown_but
[i
].y
;
269 add_widget (ch_dlg
, hline_new (y
- 1, -1, -1));
271 button_new (y
, WIDGET (ch_dlg
)->cols
/ 2 - chown_but
[i
].len
, chown_but
[i
].ret_cmd
,
272 chown_but
[i
].flags
, chown_but
[i
].text
, NULL
));
275 button_new (y
, WIDGET (ch_dlg
)->cols
/ 2 + 1, chown_but
[i
].ret_cmd
,
276 chown_but
[i
].flags
, chown_but
[i
].text
, NULL
));
278 /* select first listbox */
279 widget_select (WIDGET (l_user
));
284 /* --------------------------------------------------------------------------------------------- */
290 update_panels (UP_OPTIMIZE
, UP_KEEPSEL
);
294 /* --------------------------------------------------------------------------------------------- */
297 do_chown (uid_t u
, gid_t g
)
301 vpath
= vfs_path_from_str (current_panel
->dir
.list
[current_file
].fname
);
302 if (mc_chown (vpath
, u
, g
) == -1)
303 message (D_ERROR
, MSG_ERROR
, _("Cannot chown \"%s\"\n%s"),
304 current_panel
->dir
.list
[current_file
].fname
, unix_error_string (errno
));
306 vfs_path_free (vpath
);
307 do_file_mark (current_panel
, current_file
, 0);
310 /* --------------------------------------------------------------------------------------------- */
313 apply_chowns (uid_t u
, gid_t g
)
316 need_update
= end_chown
= 1;
324 while (current_panel
->marked
);
327 /* --------------------------------------------------------------------------------------------- */
328 /*** public functions ****************************************************************************/
329 /* --------------------------------------------------------------------------------------------- */
338 char buffer
[BUF_TINY
];
343 { /* do while any files remaining */
347 ch_dlg
= init_chown ();
348 new_user
= new_group
= -1;
350 if (current_panel
->marked
)
351 fname
= next_file (); /* next marked file */
353 fname
= selection (current_panel
)->fname
; /* single file */
355 vpath
= vfs_path_from_str (fname
);
356 if (mc_stat (vpath
, &sf_stat
) != 0)
357 { /* get status of file */
358 dlg_destroy (ch_dlg
);
359 vfs_path_free (vpath
);
362 vfs_path_free (vpath
);
364 /* select in listboxes */
365 listbox_select_entry (l_user
, listbox_search_text (l_user
, get_owner (sf_stat
.st_uid
)));
366 listbox_select_entry (l_group
, listbox_search_text (l_group
, get_group (sf_stat
.st_gid
)));
368 chown_label (0, str_trunc (fname
, GW
- 4));
369 chown_label (1, str_trunc (get_owner (sf_stat
.st_uid
), GW
- 4));
370 chown_label (2, str_trunc (get_group (sf_stat
.st_gid
), GW
- 4));
371 size_trunc_len (buffer
, GW
- 4, sf_stat
.st_size
, 0, panels_options
.kilobyte_si
);
372 chown_label (3, buffer
);
373 chown_label (4, string_perm (sf_stat
.st_mode
));
375 switch (dlg_run (ch_dlg
))
386 listbox_get_current (l_user
, &text
, NULL
);
387 user
= getpwnam (text
);
390 new_user
= user
->pw_uid
;
391 apply_chowns (new_user
, new_group
);
401 listbox_get_current (l_group
, &text
, NULL
);
402 grp
= getgrnam (text
);
405 new_group
= grp
->gr_gid
;
406 apply_chowns (new_user
, new_group
);
418 listbox_get_current (l_group
, &text
, NULL
);
419 grp
= getgrnam (text
);
421 new_group
= grp
->gr_gid
;
422 listbox_get_current (l_user
, &text
, NULL
);
423 user
= getpwnam (text
);
425 new_user
= user
->pw_uid
;
426 if (ch_dlg
->ret_value
== B_ENTER
)
428 vfs_path_t
*fname_vpath
;
430 fname_vpath
= vfs_path_from_str (fname
);
432 if (mc_chown (fname_vpath
, new_user
, new_group
) == -1)
433 message (D_ERROR
, MSG_ERROR
, _("Cannot chown \"%s\"\n%s"),
434 fname
, unix_error_string (errno
));
435 vfs_path_free (fname_vpath
);
438 apply_chowns (new_user
, new_group
);
446 if (current_panel
->marked
&& ch_dlg
->ret_value
!= B_CANCEL
)
448 do_file_mark (current_panel
, current_file
, 0);
452 dlg_destroy (ch_dlg
);
454 while (current_panel
->marked
&& !end_chown
);
459 /* --------------------------------------------------------------------------------------------- */