achown.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727
  1. /* Chown-advanced command -- for the Midnight Commander
  2. Copyright (C) 1994, 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
  3. 2005, 2007 Free Software Foundation, Inc.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  15. */
  16. /** \file achown.c
  17. * \brief Source: Contains functions for advanced chowning
  18. */
  19. #include <config.h>
  20. #include <errno.h>
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <sys/types.h>
  24. #include <sys/stat.h>
  25. #include <unistd.h>
  26. #include <pwd.h>
  27. #include <grp.h>
  28. #include "global.h"
  29. #include "../src/tty/tty.h"
  30. #include "../src/tty/key.h" /* XCTRL and ALT macros */
  31. #include "../src/skin/skin.h"
  32. #include "dialog.h"
  33. #include "widget.h"
  34. #include "wtools.h" /* For init_box_colors() */
  35. #include "strutil.h"
  36. #include "dir.h"
  37. #include "panel.h" /* Needed for the externs */
  38. #include "chmod.h"
  39. #include "main.h" /* update_panels() */
  40. #include "layout.h" /* repaint_screen() */
  41. #include "achown.h"
  42. #define BX 5
  43. #define BY 6
  44. #define TX 50
  45. #define TY 2
  46. #define BUTTONS 9
  47. #define B_SETALL B_USER
  48. #define B_SKIP (B_USER + 1)
  49. #define B_OWN (B_USER + 3)
  50. #define B_GRP (B_USER + 4)
  51. #define B_OTH (B_USER + 5)
  52. #define B_OUSER (B_USER + 6)
  53. #define B_OGROUP (B_USER + 7)
  54. static struct Dlg_head *ch_dlg;
  55. static struct {
  56. int ret_cmd, flags, y, x;
  57. const char *text;
  58. } chown_advanced_but [BUTTONS] = {
  59. { B_CANCEL, NORMAL_BUTTON, 4, 53, N_("&Cancel") },
  60. { B_ENTER, DEFPUSH_BUTTON,4, 40, N_("&Set") },
  61. { B_SKIP, NORMAL_BUTTON, 4, 23, N_("S&kip") },
  62. { B_SETALL, NORMAL_BUTTON, 4, 0, N_("Set &all")},
  63. { B_ENTER, NARROW_BUTTON, 0, 47, ""},
  64. { B_ENTER, NARROW_BUTTON, 0, 29, ""},
  65. { B_ENTER, NARROW_BUTTON, 0, 19, " "},
  66. { B_ENTER, NARROW_BUTTON, 0, 11, " "},
  67. { B_ENTER, NARROW_BUTTON, 0, 3, " "}
  68. };
  69. static WButton *b_att[3]; /* permission */
  70. static WButton *b_user, *b_group; /* owner */
  71. static int files_on_begin; /* Number of files at startup */
  72. static int flag_pos;
  73. static int x_toggle;
  74. static char ch_flags[11];
  75. static const char ch_perm[] = "rwx";
  76. static mode_t ch_cmode;
  77. static struct stat *sf_stat;
  78. static int need_update;
  79. static int end_chown;
  80. static int current_file;
  81. static int single_set;
  82. static char *fname;
  83. static void update_ownership (void)
  84. {
  85. button_set_text (b_user, get_owner (sf_stat->st_uid));
  86. button_set_text (b_group, get_group (sf_stat->st_gid));
  87. }
  88. static cb_ret_t inc_flag_pos (int f_pos)
  89. {
  90. if (flag_pos == 10) {
  91. flag_pos = 0;
  92. return MSG_NOT_HANDLED;
  93. }
  94. flag_pos++;
  95. if (!(flag_pos % 3) || f_pos > 2)
  96. return MSG_NOT_HANDLED;
  97. return MSG_HANDLED;
  98. }
  99. static cb_ret_t dec_flag_pos (int f_pos)
  100. {
  101. if (!flag_pos) {
  102. flag_pos = 10;
  103. return MSG_NOT_HANDLED;
  104. }
  105. flag_pos--;
  106. if (!((flag_pos + 1) % 3) || f_pos > 2)
  107. return MSG_NOT_HANDLED;
  108. return MSG_HANDLED;
  109. }
  110. static void set_perm_by_flags (char *s, int f_p)
  111. {
  112. int i;
  113. for (i = 0; i < 3; i++) {
  114. if (ch_flags[f_p + i] == '+')
  115. s[i] = ch_perm[i];
  116. else if (ch_flags[f_p + i] == '-')
  117. s[i] = '-';
  118. else
  119. s[i] = (ch_cmode & (1 << (8 - f_p - i))) ? ch_perm[i] : '-';
  120. }
  121. }
  122. static void update_permissions (void)
  123. {
  124. set_perm_by_flags (b_att[0]->text.start, 0);
  125. set_perm_by_flags (b_att[1]->text.start, 3);
  126. set_perm_by_flags (b_att[2]->text.start, 6);
  127. }
  128. static mode_t get_perm (char *s, int base)
  129. {
  130. mode_t m;
  131. m = 0;
  132. m |= (s[0] == '-') ? 0 :
  133. ((s[0] == '+') ? (mode_t)(1 << (base + 2)) : (1 << (base + 2)) & ch_cmode);
  134. m |= (s[1] == '-') ? 0 :
  135. ((s[1] == '+') ? (mode_t)(1 << (base + 1)) : (1 << (base + 1)) & ch_cmode);
  136. m |= (s[2] == '-') ? 0 :
  137. ((s[2] == '+') ? (mode_t)(1 << base) : (1 << base) & ch_cmode);
  138. return m;
  139. }
  140. static mode_t get_mode (void)
  141. {
  142. mode_t m;
  143. m = ch_cmode ^ (ch_cmode & 0777);
  144. m |= get_perm (ch_flags, 6);
  145. m |= get_perm (ch_flags + 3, 3);
  146. m |= get_perm (ch_flags + 6, 0);
  147. return m;
  148. }
  149. static void print_flags (void)
  150. {
  151. int i;
  152. tty_setcolor (COLOR_NORMAL);
  153. for (i = 0; i < 3; i++){
  154. dlg_move (ch_dlg, BY+1, 9+i);
  155. tty_print_char (ch_flags [i]);
  156. }
  157. for (i = 0; i < 3; i++){
  158. dlg_move (ch_dlg, BY + 1, 17 + i);
  159. tty_print_char (ch_flags [i+3]);
  160. }
  161. for (i = 0; i < 3; i++){
  162. dlg_move (ch_dlg, BY + 1, 25 + i);
  163. tty_print_char (ch_flags [i+6]);
  164. }
  165. update_permissions ();
  166. for (i = 0; i < 15; i++){
  167. dlg_move (ch_dlg, BY+1, 35+i);
  168. tty_print_char (ch_flags[9]);
  169. }
  170. for (i = 0; i < 15; i++){
  171. dlg_move (ch_dlg, BY + 1, 53 + i);
  172. tty_print_char (ch_flags[10]);
  173. }
  174. }
  175. static void update_mode (Dlg_head * h)
  176. {
  177. print_flags ();
  178. tty_setcolor (COLOR_NORMAL);
  179. dlg_move (h, BY + 2, 9);
  180. tty_printf ("%12o", get_mode ());
  181. send_message (h->current, WIDGET_FOCUS, 0);
  182. }
  183. static cb_ret_t
  184. chl_callback (Dlg_head *h, dlg_msg_t msg, int parm)
  185. {
  186. switch (msg) {
  187. case DLG_KEY:
  188. switch (parm) {
  189. case KEY_LEFT:
  190. case KEY_RIGHT:
  191. h->ret_value = parm;
  192. dlg_stop (h);
  193. }
  194. default:
  195. return default_dlg_callback (h, msg, parm);
  196. }
  197. }
  198. static void
  199. do_enter_key (Dlg_head * h, int f_pos)
  200. {
  201. Dlg_head *chl_dlg;
  202. WListbox *chl_list;
  203. struct passwd *chl_pass;
  204. struct group *chl_grp;
  205. WLEntry *fe;
  206. int lxx, lyy, chl_end, b_pos;
  207. int is_owner;
  208. const char *title;
  209. do {
  210. is_owner = (f_pos == 3);
  211. title = is_owner ? _("owner") : _("group");
  212. lxx = (COLS - 74) / 2 + (is_owner ? 35 : 53);
  213. lyy = (LINES - 13) / 2;
  214. chl_end = 0;
  215. chl_dlg =
  216. create_dlg (lyy, lxx, 13, 17, dialog_colors, chl_callback,
  217. "[Advanced Chown]", title, DLG_COMPACT | DLG_REVERSE);
  218. /* get new listboxes */
  219. chl_list = listbox_new (1, 1, 11, 15, NULL);
  220. listbox_add_item (chl_list, LISTBOX_APPEND_AT_END, 0,
  221. "<Unknown>", NULL);
  222. if (is_owner) {
  223. /* get and put user names in the listbox */
  224. setpwent ();
  225. while ((chl_pass = getpwent ())) {
  226. listbox_add_item (chl_list, LISTBOX_APPEND_SORTED, 0,
  227. chl_pass->pw_name, NULL);
  228. }
  229. endpwent ();
  230. fe = listbox_search_text (chl_list,
  231. get_owner (sf_stat->st_uid));
  232. } else {
  233. /* get and put group names in the listbox */
  234. setgrent ();
  235. while ((chl_grp = getgrent ())) {
  236. listbox_add_item (chl_list, LISTBOX_APPEND_SORTED, 0,
  237. chl_grp->gr_name, NULL);
  238. }
  239. endgrent ();
  240. fe = listbox_search_text (chl_list,
  241. get_group (sf_stat->st_gid));
  242. }
  243. if (fe)
  244. listbox_select_entry (chl_list, fe);
  245. b_pos = chl_list->pos;
  246. add_widget (chl_dlg, chl_list);
  247. run_dlg (chl_dlg);
  248. if (b_pos != chl_list->pos) {
  249. int ok = 0;
  250. if (is_owner) {
  251. chl_pass = getpwnam (chl_list->current->text);
  252. if (chl_pass) {
  253. ok = 1;
  254. sf_stat->st_uid = chl_pass->pw_uid;
  255. }
  256. } else {
  257. chl_grp = getgrnam (chl_list->current->text);
  258. if (chl_grp) {
  259. sf_stat->st_gid = chl_grp->gr_gid;
  260. ok = 1;
  261. }
  262. }
  263. if (ok) {
  264. ch_flags[f_pos + 6] = '+';
  265. update_ownership ();
  266. }
  267. dlg_focus (h);
  268. if (ok)
  269. print_flags ();
  270. }
  271. if (chl_dlg->ret_value == KEY_LEFT) {
  272. if (!is_owner)
  273. chl_end = 1;
  274. dlg_one_up (ch_dlg);
  275. f_pos--;
  276. } else if (chl_dlg->ret_value == KEY_RIGHT) {
  277. if (is_owner)
  278. chl_end = 1;
  279. dlg_one_down (ch_dlg);
  280. f_pos++;
  281. }
  282. /* Here we used to redraw the window */
  283. destroy_dlg (chl_dlg);
  284. } while (chl_end);
  285. }
  286. static void chown_refresh (void)
  287. {
  288. common_dialog_repaint (ch_dlg);
  289. tty_setcolor (COLOR_NORMAL);
  290. dlg_move (ch_dlg, BY - 1, 8);
  291. tty_print_string (_("owner"));
  292. dlg_move (ch_dlg, BY - 1, 16);
  293. tty_print_string (_("group"));
  294. dlg_move (ch_dlg, BY - 1, 24);
  295. tty_print_string (_("other"));
  296. dlg_move (ch_dlg, BY - 1, 35);
  297. tty_print_string (_("owner"));
  298. dlg_move (ch_dlg, BY - 1, 53);
  299. tty_print_string (_("group"));
  300. dlg_move (ch_dlg, 3, 4);
  301. tty_print_string (_("On"));
  302. dlg_move (ch_dlg, BY + 1, 4);
  303. tty_print_string (_("Flag"));
  304. dlg_move (ch_dlg, BY + 2, 4);
  305. tty_print_string (_("Mode"));
  306. if (!single_set){
  307. dlg_move (ch_dlg, 3, 54);
  308. tty_printf (_("%6d of %d"),
  309. files_on_begin - (current_panel->marked) + 1,
  310. files_on_begin);
  311. }
  312. print_flags ();
  313. }
  314. static void chown_info_update (void)
  315. {
  316. /* display file info */
  317. tty_setcolor (COLOR_NORMAL);
  318. /* name && mode */
  319. dlg_move (ch_dlg, 3, 8);
  320. tty_print_string (str_fit_to_term (fname, 45, J_LEFT_FIT));
  321. dlg_move (ch_dlg, BY + 2, 9);
  322. tty_printf ("%12o", get_mode ());
  323. /* permissions */
  324. update_permissions ();
  325. }
  326. static void b_setpos (int f_pos) {
  327. b_att[0]->hotpos=-1;
  328. b_att[1]->hotpos=-1;
  329. b_att[2]->hotpos=-1;
  330. b_att[f_pos]->hotpos = (flag_pos % 3);
  331. }
  332. static cb_ret_t
  333. advanced_chown_callback (Dlg_head *h, dlg_msg_t msg, int parm)
  334. {
  335. int i = 0, f_pos = BUTTONS - h->current->dlg_id - single_set - 1;
  336. switch (msg) {
  337. case DLG_DRAW:
  338. chown_refresh ();
  339. chown_info_update ();
  340. return MSG_HANDLED;
  341. case DLG_POST_KEY:
  342. if (f_pos < 3)
  343. b_setpos (f_pos);
  344. return MSG_HANDLED;
  345. case DLG_FOCUS:
  346. if (f_pos < 3) {
  347. if ((flag_pos / 3) != f_pos)
  348. flag_pos = f_pos * 3;
  349. b_setpos (f_pos);
  350. } else if (f_pos < 5)
  351. flag_pos = f_pos + 6;
  352. return MSG_HANDLED;
  353. case DLG_KEY:
  354. switch (parm) {
  355. case XCTRL ('b'):
  356. case KEY_LEFT:
  357. if (f_pos < 5)
  358. return (dec_flag_pos (f_pos));
  359. break;
  360. case XCTRL ('f'):
  361. case KEY_RIGHT:
  362. if (f_pos < 5)
  363. return (inc_flag_pos (f_pos));
  364. break;
  365. case ' ':
  366. if (f_pos < 3)
  367. return MSG_HANDLED;
  368. break;
  369. case '\n':
  370. case KEY_ENTER:
  371. if (f_pos <= 2 || f_pos >= 5)
  372. break;
  373. do_enter_key (h, f_pos);
  374. return MSG_HANDLED;
  375. case ALT ('x'):
  376. i++;
  377. case ALT ('w'):
  378. i++;
  379. case ALT ('r'):
  380. parm = i + 3;
  381. for (i = 0; i < 3; i++)
  382. ch_flags[i * 3 + parm - 3] =
  383. (x_toggle & (1 << parm)) ? '-' : '+';
  384. x_toggle ^= (1 << parm);
  385. update_mode (h);
  386. dlg_broadcast_msg (h, WIDGET_DRAW, 0);
  387. send_message (h->current, WIDGET_FOCUS, 0);
  388. break;
  389. case XCTRL ('x'):
  390. i++;
  391. case XCTRL ('w'):
  392. i++;
  393. case XCTRL ('r'):
  394. parm = i;
  395. for (i = 0; i < 3; i++)
  396. ch_flags[i * 3 + parm] =
  397. (x_toggle & (1 << parm)) ? '-' : '+';
  398. x_toggle ^= (1 << parm);
  399. update_mode (h);
  400. dlg_broadcast_msg (h, WIDGET_DRAW, 0);
  401. send_message (h->current, WIDGET_FOCUS, 0);
  402. break;
  403. case 'x':
  404. i++;
  405. case 'w':
  406. i++;
  407. case 'r':
  408. if (f_pos > 2)
  409. break;
  410. flag_pos = f_pos * 3 + i; /* (strchr(ch_perm,parm)-ch_perm); */
  411. if (((WButton *) h->current)->text.start[(flag_pos % 3)] ==
  412. '-')
  413. ch_flags[flag_pos] = '+';
  414. else
  415. ch_flags[flag_pos] = '-';
  416. update_mode (h);
  417. break;
  418. case '4':
  419. i++;
  420. case '2':
  421. i++;
  422. case '1':
  423. if (f_pos > 2)
  424. break;
  425. flag_pos = i + f_pos * 3;
  426. ch_flags[flag_pos] = '=';
  427. update_mode (h);
  428. break;
  429. case '-':
  430. if (f_pos > 2)
  431. break;
  432. case '*':
  433. if (parm == '*')
  434. parm = '=';
  435. case '=':
  436. case '+':
  437. if (f_pos > 4)
  438. break;
  439. ch_flags[flag_pos] = parm;
  440. update_mode (h);
  441. advanced_chown_callback (h, DLG_KEY, KEY_RIGHT);
  442. if (flag_pos > 8 || !(flag_pos % 3))
  443. dlg_one_down (h);
  444. break;
  445. }
  446. return MSG_NOT_HANDLED;
  447. default:
  448. return default_dlg_callback (h, msg, parm);
  449. }
  450. }
  451. static void
  452. init_chown_advanced (void)
  453. {
  454. int i;
  455. enum { dlg_h = 13, dlg_w = 74, n_elem = 4 };
  456. #ifdef ENABLE_NLS
  457. static int i18n_len = 0;
  458. if (i18n_len == 0) {
  459. int dx, cx;
  460. for (i = 0 ; i < n_elem ; i++) {
  461. chown_advanced_but[i].text = _(chown_advanced_but[i].text);
  462. i18n_len += str_term_width1 (chown_advanced_but[i].text) + 3;
  463. if (DEFPUSH_BUTTON == chown_advanced_but[i].flags)
  464. i18n_len += 2; /* "<>" */
  465. }
  466. cx = dx = (dlg_w - i18n_len - 2) / (n_elem + 1);
  467. /* Reversed order */
  468. for (i = n_elem - 1; i >= 0; i--) {
  469. chown_advanced_but[i].x = cx;
  470. cx += str_term_width1 (chown_advanced_but[i].text) + 3 + dx;
  471. }
  472. }
  473. #endif /* ENABLE_NLS */
  474. sf_stat = g_new (struct stat, 1);
  475. do_refresh ();
  476. end_chown = need_update = current_file = 0;
  477. single_set = (current_panel->marked < 2) ? 2 : 0;
  478. memset (ch_flags, '=', 11);
  479. flag_pos = 0;
  480. x_toggle = 070;
  481. ch_dlg =
  482. create_dlg (0, 0, dlg_h, dlg_w, dialog_colors, advanced_chown_callback,
  483. "[Advanced Chown]", _(" Chown advanced command "),
  484. DLG_CENTER | DLG_REVERSE);
  485. #define XTRACT(i) BY+chown_advanced_but[i].y, BX+chown_advanced_but[i].x, \
  486. chown_advanced_but[i].ret_cmd, chown_advanced_but[i].flags, \
  487. (chown_advanced_but[i].text), 0
  488. for (i = 0; i < BUTTONS - 5; i++)
  489. if (!single_set || i < 2)
  490. add_widget (ch_dlg, button_new (XTRACT (i)));
  491. b_att[0] = button_new (XTRACT (8));
  492. b_att[1] = button_new (XTRACT (7));
  493. b_att[2] = button_new (XTRACT (6));
  494. b_user = button_new (XTRACT (5));
  495. b_group = button_new (XTRACT (4));
  496. add_widget (ch_dlg, b_group);
  497. add_widget (ch_dlg, b_user);
  498. add_widget (ch_dlg, b_att[2]);
  499. add_widget (ch_dlg, b_att[1]);
  500. add_widget (ch_dlg, b_att[0]);
  501. }
  502. static void
  503. chown_advanced_done (void)
  504. {
  505. g_free (sf_stat);
  506. if (need_update)
  507. update_panels (UP_OPTIMIZE, UP_KEEPSEL);
  508. repaint_screen ();
  509. }
  510. #if 0
  511. static void do_chown (uid_t u, gid_t g)
  512. {
  513. chown (current_panel->dir.list[current_file].fname, u, g);
  514. file_mark (current_panel, current_file, 0);
  515. }
  516. #endif
  517. static char *next_file (void)
  518. {
  519. while (!current_panel->dir.list[current_file].f.marked)
  520. current_file++;
  521. return current_panel->dir.list[current_file].fname;
  522. }
  523. static void apply_advanced_chowns (struct stat *sf)
  524. {
  525. char *fname;
  526. gid_t a_gid = sf->st_gid;
  527. uid_t a_uid = sf->st_uid;
  528. fname = current_panel->dir.list[current_file].fname;
  529. need_update = end_chown = 1;
  530. if (mc_chmod (fname, get_mode ()) == -1)
  531. message (D_ERROR, MSG_ERROR, _(" Cannot chmod \"%s\" \n %s "),
  532. fname, unix_error_string (errno));
  533. /* call mc_chown only, if mc_chmod didn't fail */
  534. else if (mc_chown (fname, (ch_flags[9] == '+') ? sf->st_uid : (uid_t) -1,
  535. (ch_flags[10] == '+') ? sf->st_gid : (gid_t) -1) == -1)
  536. message (D_ERROR, MSG_ERROR, _(" Cannot chown \"%s\" \n %s "),
  537. fname, unix_error_string (errno));
  538. do_file_mark (current_panel, current_file, 0);
  539. do {
  540. fname = next_file ();
  541. if (mc_stat (fname, sf) != 0)
  542. break;
  543. ch_cmode = sf->st_mode;
  544. if (mc_chmod (fname, get_mode ()) == -1)
  545. message (D_ERROR, MSG_ERROR, _(" Cannot chmod \"%s\" \n %s "),
  546. fname, unix_error_string (errno));
  547. /* call mc_chown only, if mc_chmod didn't fail */
  548. else if (mc_chown (fname, (ch_flags[9] == '+') ? a_uid : (uid_t) -1,
  549. (ch_flags[10] == '+') ? a_gid : (gid_t) -1) == -1)
  550. message (D_ERROR, MSG_ERROR, _(" Cannot chown \"%s\" \n %s "),
  551. fname, unix_error_string (errno));
  552. do_file_mark (current_panel, current_file, 0);
  553. } while (current_panel->marked);
  554. }
  555. void
  556. chown_advanced_cmd (void)
  557. {
  558. files_on_begin = current_panel->marked;
  559. do { /* do while any files remaining */
  560. init_chown_advanced ();
  561. if (current_panel->marked)
  562. fname = next_file (); /* next marked file */
  563. else
  564. fname = selection (current_panel)->fname; /* single file */
  565. if (mc_stat (fname, sf_stat) != 0) { /* get status of file */
  566. destroy_dlg (ch_dlg);
  567. break;
  568. }
  569. ch_cmode = sf_stat->st_mode;
  570. chown_refresh ();
  571. update_ownership ();
  572. /* game can begin */
  573. run_dlg (ch_dlg);
  574. switch (ch_dlg->ret_value) {
  575. case B_CANCEL:
  576. end_chown = 1;
  577. break;
  578. case B_ENTER:
  579. need_update = 1;
  580. if (mc_chmod (fname, get_mode ()) == -1)
  581. message (D_ERROR, MSG_ERROR, _(" Cannot chmod \"%s\" \n %s "),
  582. fname, unix_error_string (errno));
  583. /* call mc_chown only, if mc_chmod didn't fail */
  584. else if (mc_chown (fname, (ch_flags[9] == '+') ? sf_stat->st_uid : (uid_t) -1,
  585. (ch_flags[10] == '+') ? sf_stat->st_gid : (gid_t) -1) == -1)
  586. message (D_ERROR, MSG_ERROR, _(" Cannot chown \"%s\" \n %s "),
  587. fname, unix_error_string (errno));
  588. break;
  589. case B_SETALL:
  590. apply_advanced_chowns (sf_stat);
  591. break;
  592. case B_SKIP:
  593. break;
  594. }
  595. if (current_panel->marked && ch_dlg->ret_value != B_CANCEL) {
  596. do_file_mark (current_panel, current_file, 0);
  597. need_update = 1;
  598. }
  599. destroy_dlg (ch_dlg);
  600. } while (current_panel->marked && !end_chown);
  601. chown_advanced_done ();
  602. }