PageRenderTime 53ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/src/filemanager/achown.c

https://github.com/elianos/mc
C | 902 lines | 678 code | 157 blank | 67 comment | 124 complexity | daebe601359e8b370ff3f0cdd7b9dbd0 MD5 | raw file
Possible License(s): GPL-3.0
  1. /*
  2. Chown-advanced command -- for the Midnight Commander
  3. Copyright (C) 1994, 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
  4. 2005, 2007, 2011
  5. The Free Software Foundation, Inc.
  6. This file is part of the Midnight Commander.
  7. The Midnight Commander is free software: you can redistribute it
  8. and/or modify it under the terms of the GNU General Public License as
  9. published by the Free Software Foundation, either version 3 of the License,
  10. or (at your option) any later version.
  11. The Midnight Commander is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /** \file achown.c
  19. * \brief Source: Contains functions for advanced chowning
  20. */
  21. #include <config.h>
  22. #include <errno.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <sys/types.h>
  26. #include <sys/stat.h>
  27. #include <unistd.h>
  28. #include <pwd.h>
  29. #include <grp.h>
  30. #include "lib/global.h"
  31. #include "lib/tty/tty.h"
  32. #include "lib/tty/key.h" /* XCTRL and ALT macros */
  33. #include "lib/skin.h"
  34. #include "lib/strutil.h"
  35. #include "lib/vfs/vfs.h"
  36. #include "lib/util.h"
  37. #include "lib/widget.h"
  38. #include "dir.h"
  39. #include "midnight.h" /* current_panel */
  40. #include "chmod.h"
  41. #include "achown.h"
  42. /*** global variables ****************************************************************************/
  43. /*** file scope macro definitions ****************************************************************/
  44. #define BX 5
  45. #define BY 5
  46. #define BUTTONS 9
  47. #define BUTTONS_PERM 5
  48. #define B_SETALL B_USER
  49. #define B_SKIP (B_USER + 1)
  50. #define B_OWN (B_USER + 3)
  51. #define B_GRP (B_USER + 4)
  52. #define B_OTH (B_USER + 5)
  53. #define B_OUSER (B_USER + 6)
  54. #define B_OGROUP (B_USER + 7)
  55. /*** file scope type declarations ****************************************************************/
  56. /*** file scope variables ************************************************************************/
  57. static struct WDialog *ch_dlg;
  58. static struct
  59. {
  60. unsigned long id;
  61. int ret_cmd, flags, x, len;
  62. const char *text;
  63. } chown_advanced_but[BUTTONS] =
  64. {
  65. /* *INDENT-OFF* */
  66. { 0, B_ENTER, NARROW_BUTTON, 3, 0, " "},
  67. { 0, B_ENTER, NARROW_BUTTON, 11, 0, " "},
  68. { 0, B_ENTER, NARROW_BUTTON, 19, 0, " "},
  69. { 0, B_ENTER, NARROW_BUTTON, 29, 0, ""},
  70. { 0, B_ENTER, NARROW_BUTTON, 47, 0, ""},
  71. { 0, B_SETALL, NORMAL_BUTTON, 0, 0, N_("Set &all")},
  72. { 0, B_SKIP, NORMAL_BUTTON, 0, 0, N_("S&kip") },
  73. { 0, B_ENTER, DEFPUSH_BUTTON, 0, 0, N_("&Set") },
  74. { 0, B_CANCEL, NORMAL_BUTTON, 0, 0, N_("&Cancel") }
  75. /* *INDENT-ON* */
  76. };
  77. static WButton *b_att[3]; /* permission */
  78. static WButton *b_user, *b_group; /* owner */
  79. static WLabel *l_filename;
  80. static WLabel *l_mode;
  81. static int flag_pos;
  82. static int x_toggle;
  83. static char ch_flags[11];
  84. static const char ch_perm[] = "rwx";
  85. static mode_t ch_cmode;
  86. static struct stat *sf_stat;
  87. static gboolean need_update = FALSE;
  88. static gboolean end_chown = FALSE;
  89. static int current_file;
  90. static gboolean single_set = FALSE;
  91. static char *fname;
  92. /* --------------------------------------------------------------------------------------------- */
  93. /*** file scope functions ************************************************************************/
  94. /* --------------------------------------------------------------------------------------------- */
  95. static void
  96. update_ownership (void)
  97. {
  98. button_set_text (b_user, get_owner (sf_stat->st_uid));
  99. button_set_text (b_group, get_group (sf_stat->st_gid));
  100. }
  101. /* --------------------------------------------------------------------------------------------- */
  102. static cb_ret_t
  103. inc_flag_pos (int f_pos)
  104. {
  105. if (flag_pos == 10)
  106. {
  107. flag_pos = 0;
  108. return MSG_NOT_HANDLED;
  109. }
  110. flag_pos++;
  111. if ((flag_pos % 3) == 0 || f_pos > 2)
  112. return MSG_NOT_HANDLED;
  113. return MSG_HANDLED;
  114. }
  115. /* --------------------------------------------------------------------------------------------- */
  116. static cb_ret_t
  117. dec_flag_pos (int f_pos)
  118. {
  119. if (flag_pos == 0)
  120. {
  121. flag_pos = 10;
  122. return MSG_NOT_HANDLED;
  123. }
  124. flag_pos--;
  125. if (((flag_pos + 1) % 3) == 0 || f_pos > 2)
  126. return MSG_NOT_HANDLED;
  127. return MSG_HANDLED;
  128. }
  129. /* --------------------------------------------------------------------------------------------- */
  130. static void
  131. set_perm_by_flags (char *s, int f_p)
  132. {
  133. int i;
  134. for (i = 0; i < 3; i++)
  135. {
  136. if (ch_flags[f_p + i] == '+')
  137. s[i] = ch_perm[i];
  138. else if (ch_flags[f_p + i] == '-')
  139. s[i] = '-';
  140. else
  141. s[i] = (ch_cmode & (1 << (8 - f_p - i))) ? ch_perm[i] : '-';
  142. }
  143. }
  144. /* --------------------------------------------------------------------------------------------- */
  145. static void
  146. update_permissions (void)
  147. {
  148. set_perm_by_flags (b_att[0]->text.start, 0);
  149. set_perm_by_flags (b_att[1]->text.start, 3);
  150. set_perm_by_flags (b_att[2]->text.start, 6);
  151. }
  152. /* --------------------------------------------------------------------------------------------- */
  153. static mode_t
  154. get_perm (char *s, int base)
  155. {
  156. mode_t m;
  157. m = 0;
  158. m |= (s[0] == '-') ? 0 :
  159. ((s[0] == '+') ? (mode_t) (1 << (base + 2)) : (1 << (base + 2)) & ch_cmode);
  160. m |= (s[1] == '-') ? 0 :
  161. ((s[1] == '+') ? (mode_t) (1 << (base + 1)) : (1 << (base + 1)) & ch_cmode);
  162. m |= (s[2] == '-') ? 0 : ((s[2] == '+') ? (mode_t) (1 << base) : (1 << base) & ch_cmode);
  163. return m;
  164. }
  165. /* --------------------------------------------------------------------------------------------- */
  166. static mode_t
  167. get_mode (void)
  168. {
  169. mode_t m;
  170. m = ch_cmode ^ (ch_cmode & 0777);
  171. m |= get_perm (ch_flags, 6);
  172. m |= get_perm (ch_flags + 3, 3);
  173. m |= get_perm (ch_flags + 6, 0);
  174. return m;
  175. }
  176. /* --------------------------------------------------------------------------------------------- */
  177. static void
  178. print_flags (void)
  179. {
  180. int i;
  181. tty_setcolor (COLOR_NORMAL);
  182. for (i = 0; i < 3; i++)
  183. {
  184. widget_move (ch_dlg, BY + 1, 9 + i);
  185. tty_print_char (ch_flags[i]);
  186. }
  187. for (i = 0; i < 3; i++)
  188. {
  189. widget_move (ch_dlg, BY + 1, 17 + i);
  190. tty_print_char (ch_flags[i + 3]);
  191. }
  192. for (i = 0; i < 3; i++)
  193. {
  194. widget_move (ch_dlg, BY + 1, 25 + i);
  195. tty_print_char (ch_flags[i + 6]);
  196. }
  197. update_permissions ();
  198. for (i = 0; i < 15; i++)
  199. {
  200. widget_move (ch_dlg, BY + 1, 35 + i);
  201. tty_print_char (ch_flags[9]);
  202. }
  203. for (i = 0; i < 15; i++)
  204. {
  205. widget_move (ch_dlg, BY + 1, 53 + i);
  206. tty_print_char (ch_flags[10]);
  207. }
  208. }
  209. /* --------------------------------------------------------------------------------------------- */
  210. static void
  211. chown_info_update (void)
  212. {
  213. char buffer[BUF_SMALL];
  214. /* mode */
  215. g_snprintf (buffer, sizeof (buffer), "Permissions (octal): %o", get_mode ());
  216. label_set_text (l_mode, buffer);
  217. /* permissions */
  218. update_permissions ();
  219. }
  220. /* --------------------------------------------------------------------------------------------- */
  221. static void
  222. update_mode (WDialog * h)
  223. {
  224. print_flags ();
  225. chown_info_update ();
  226. send_message (h->current->data, NULL, MSG_FOCUS, 0, NULL);
  227. }
  228. /* --------------------------------------------------------------------------------------------- */
  229. static cb_ret_t
  230. chl_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data)
  231. {
  232. switch (msg)
  233. {
  234. case MSG_KEY:
  235. switch (parm)
  236. {
  237. case KEY_LEFT:
  238. case KEY_RIGHT:
  239. {
  240. WDialog *h = DIALOG (w);
  241. h->ret_value = parm;
  242. dlg_stop (h);
  243. }
  244. }
  245. default:
  246. return dlg_default_callback (w, sender, msg, parm, data);
  247. }
  248. }
  249. /* --------------------------------------------------------------------------------------------- */
  250. static void
  251. do_enter_key (WDialog * h, int f_pos)
  252. {
  253. WDialog *chl_dlg;
  254. WListbox *chl_list;
  255. struct passwd *chl_pass;
  256. struct group *chl_grp;
  257. int fe;
  258. int lxx, lyy, b_pos;
  259. gboolean chl_end, is_owner;
  260. const char *title;
  261. int result;
  262. do
  263. {
  264. is_owner = (f_pos == 3);
  265. title = is_owner ? _("owner") : _("group");
  266. lxx = (COLS - 74) / 2 + (is_owner ? 35 : 53);
  267. lyy = (LINES - 13) / 2;
  268. chl_end = FALSE;
  269. chl_dlg =
  270. create_dlg (TRUE, lyy, lxx, 13, 17, dialog_colors, chl_callback, NULL,
  271. "[Advanced Chown]", title, DLG_COMPACT);
  272. /* get new listboxes */
  273. chl_list = listbox_new (1, 1, 11, 15, FALSE, NULL);
  274. listbox_add_item (chl_list, LISTBOX_APPEND_AT_END, 0, "<Unknown>", NULL);
  275. if (is_owner)
  276. {
  277. /* get and put user names in the listbox */
  278. setpwent ();
  279. while ((chl_pass = getpwent ()) != NULL)
  280. listbox_add_item (chl_list, LISTBOX_APPEND_SORTED, 0, chl_pass->pw_name, NULL);
  281. endpwent ();
  282. fe = listbox_search_text (chl_list, get_owner (sf_stat->st_uid));
  283. }
  284. else
  285. {
  286. /* get and put group names in the listbox */
  287. setgrent ();
  288. while ((chl_grp = getgrent ()) != NULL)
  289. listbox_add_item (chl_list, LISTBOX_APPEND_SORTED, 0, chl_grp->gr_name, NULL);
  290. endgrent ();
  291. fe = listbox_search_text (chl_list, get_group (sf_stat->st_gid));
  292. }
  293. listbox_select_entry (chl_list, fe);
  294. b_pos = chl_list->pos;
  295. add_widget (chl_dlg, chl_list);
  296. result = run_dlg (chl_dlg);
  297. if (b_pos != chl_list->pos)
  298. {
  299. gboolean ok = FALSE;
  300. char *text;
  301. listbox_get_current (chl_list, &text, NULL);
  302. if (is_owner)
  303. {
  304. chl_pass = getpwnam (text);
  305. if (chl_pass != NULL)
  306. {
  307. ok = TRUE;
  308. sf_stat->st_uid = chl_pass->pw_uid;
  309. }
  310. }
  311. else
  312. {
  313. chl_grp = getgrnam (text);
  314. if (chl_grp != NULL)
  315. {
  316. sf_stat->st_gid = chl_grp->gr_gid;
  317. ok = TRUE;
  318. }
  319. }
  320. if (ok)
  321. {
  322. ch_flags[f_pos + 6] = '+';
  323. update_ownership ();
  324. }
  325. dlg_focus (h);
  326. if (ok)
  327. print_flags ();
  328. }
  329. if (result == KEY_LEFT)
  330. {
  331. if (!is_owner)
  332. chl_end = TRUE;
  333. dlg_one_up (ch_dlg);
  334. f_pos--;
  335. }
  336. else if (result == KEY_RIGHT)
  337. {
  338. if (is_owner)
  339. chl_end = TRUE;
  340. dlg_one_down (ch_dlg);
  341. f_pos++;
  342. }
  343. /* Here we used to redraw the window */
  344. destroy_dlg (chl_dlg);
  345. }
  346. while (chl_end);
  347. }
  348. /* --------------------------------------------------------------------------------------------- */
  349. static void
  350. chown_refresh (void)
  351. {
  352. dlg_default_repaint (ch_dlg);
  353. tty_setcolor (COLOR_NORMAL);
  354. widget_move (ch_dlg, BY - 1, 8);
  355. tty_print_string (_("owner"));
  356. widget_move (ch_dlg, BY - 1, 16);
  357. tty_print_string (_("group"));
  358. widget_move (ch_dlg, BY - 1, 24);
  359. tty_print_string (_("other"));
  360. widget_move (ch_dlg, BY - 1, 35);
  361. tty_print_string (_("owner"));
  362. widget_move (ch_dlg, BY - 1, 53);
  363. tty_print_string (_("group"));
  364. widget_move (ch_dlg, BY + 1, 3);
  365. tty_print_string (_("Flag"));
  366. print_flags ();
  367. }
  368. /* --------------------------------------------------------------------------------------------- */
  369. static void
  370. b_setpos (int f_pos)
  371. {
  372. b_att[0]->hotpos = -1;
  373. b_att[1]->hotpos = -1;
  374. b_att[2]->hotpos = -1;
  375. b_att[f_pos]->hotpos = (flag_pos % 3);
  376. }
  377. /* --------------------------------------------------------------------------------------------- */
  378. static cb_ret_t
  379. advanced_chown_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data)
  380. {
  381. WDialog *h = DIALOG (w);
  382. int i;
  383. int f_pos;
  384. unsigned int id;
  385. id = dlg_get_current_widget_id (h);
  386. for (i = 0; i < BUTTONS_PERM; i++)
  387. if (chown_advanced_but[i].id == id)
  388. break;
  389. f_pos = i;
  390. i = 0;
  391. switch (msg)
  392. {
  393. case MSG_DRAW:
  394. chown_refresh ();
  395. chown_info_update ();
  396. return MSG_HANDLED;
  397. case MSG_POST_KEY:
  398. if (f_pos < 3)
  399. b_setpos (f_pos);
  400. return MSG_HANDLED;
  401. case MSG_FOCUS:
  402. if (f_pos < 3)
  403. {
  404. if ((flag_pos / 3) != f_pos)
  405. flag_pos = f_pos * 3;
  406. b_setpos (f_pos);
  407. }
  408. else if (f_pos < BUTTONS_PERM)
  409. flag_pos = f_pos + 6;
  410. return MSG_HANDLED;
  411. case MSG_KEY:
  412. switch (parm)
  413. {
  414. case XCTRL ('b'):
  415. case KEY_LEFT:
  416. if (f_pos < BUTTONS_PERM)
  417. return (dec_flag_pos (f_pos));
  418. break;
  419. case XCTRL ('f'):
  420. case KEY_RIGHT:
  421. if (f_pos < BUTTONS_PERM)
  422. return (inc_flag_pos (f_pos));
  423. break;
  424. case ' ':
  425. if (f_pos < 3)
  426. return MSG_HANDLED;
  427. break;
  428. case '\n':
  429. case KEY_ENTER:
  430. if (f_pos <= 2 || f_pos >= BUTTONS_PERM)
  431. break;
  432. do_enter_key (h, f_pos);
  433. return MSG_HANDLED;
  434. case ALT ('x'):
  435. i++;
  436. case ALT ('w'):
  437. i++;
  438. case ALT ('r'):
  439. parm = i + 3;
  440. for (i = 0; i < 3; i++)
  441. ch_flags[i * 3 + parm - 3] = (x_toggle & (1 << parm)) ? '-' : '+';
  442. x_toggle ^= (1 << parm);
  443. update_mode (h);
  444. dlg_broadcast_msg (h, MSG_DRAW);
  445. send_message (h->current->data, NULL, MSG_FOCUS, 0, NULL);
  446. break;
  447. case XCTRL ('x'):
  448. i++;
  449. case XCTRL ('w'):
  450. i++;
  451. case XCTRL ('r'):
  452. parm = i;
  453. for (i = 0; i < 3; i++)
  454. ch_flags[i * 3 + parm] = (x_toggle & (1 << parm)) ? '-' : '+';
  455. x_toggle ^= (1 << parm);
  456. update_mode (h);
  457. dlg_broadcast_msg (h, MSG_DRAW);
  458. send_message (h->current->data, NULL, MSG_FOCUS, 0, NULL);
  459. break;
  460. case 'x':
  461. i++;
  462. case 'w':
  463. i++;
  464. case 'r':
  465. if (f_pos > 2)
  466. break;
  467. flag_pos = f_pos * 3 + i; /* (strchr(ch_perm,parm)-ch_perm); */
  468. if (BUTTON (h->current->data)->text.start[(flag_pos % 3)] == '-')
  469. ch_flags[flag_pos] = '+';
  470. else
  471. ch_flags[flag_pos] = '-';
  472. update_mode (h);
  473. break;
  474. case '4':
  475. i++;
  476. case '2':
  477. i++;
  478. case '1':
  479. if (f_pos <= 2)
  480. {
  481. flag_pos = i + f_pos * 3;
  482. ch_flags[flag_pos] = '=';
  483. update_mode (h);
  484. }
  485. break;
  486. case '-':
  487. if (f_pos > 2)
  488. break;
  489. case '*':
  490. if (parm == '*')
  491. parm = '=';
  492. case '=':
  493. case '+':
  494. if (f_pos <= 4)
  495. {
  496. ch_flags[flag_pos] = parm;
  497. update_mode (h);
  498. send_message (h, sender, MSG_KEY, KEY_RIGHT, NULL);
  499. if (flag_pos > 8 || (flag_pos % 3) == 0)
  500. dlg_one_down (h);
  501. }
  502. break;
  503. }
  504. return MSG_NOT_HANDLED;
  505. default:
  506. return dlg_default_callback (w, sender, msg, parm, data);
  507. }
  508. }
  509. /* --------------------------------------------------------------------------------------------- */
  510. static void
  511. init_chown_advanced (void)
  512. {
  513. int i;
  514. int dlg_h = 12;
  515. int dlg_w = 74;
  516. int y;
  517. static gboolean i18n = FALSE;
  518. if (!i18n)
  519. {
  520. for (i = BUTTONS_PERM; i < BUTTONS; i++)
  521. {
  522. #ifdef ENABLE_NLS
  523. chown_advanced_but[i].text = _(chown_advanced_but[i].text);
  524. #endif /* ENABLE_NLS */
  525. chown_advanced_but[i].len = str_term_width1 (chown_advanced_but[i].text) + 3;
  526. if (chown_advanced_but[i].flags == DEFPUSH_BUTTON)
  527. chown_advanced_but[i].len += 2; /* "<>" */
  528. }
  529. i18n = TRUE;
  530. }
  531. do_refresh ();
  532. sf_stat = g_new (struct stat, 1);
  533. current_file = 0;
  534. end_chown = need_update = FALSE;
  535. single_set = (current_panel->marked < 2);
  536. memset (ch_flags, '=', 11);
  537. flag_pos = 0;
  538. x_toggle = 070;
  539. if (!single_set)
  540. dlg_h += 2;
  541. ch_dlg =
  542. create_dlg (TRUE, 0, 0, dlg_h, dlg_w, dialog_colors, advanced_chown_callback, NULL,
  543. "[Advanced Chown]", _("Chown advanced command"), DLG_CENTER);
  544. l_filename = label_new (2, 3, "");
  545. add_widget (ch_dlg, l_filename);
  546. add_widget (ch_dlg, hline_new (3, -1, -1));
  547. #define XTRACT(i,y) y, BX+chown_advanced_but[i].x, \
  548. chown_advanced_but[i].ret_cmd, chown_advanced_but[i].flags, \
  549. (chown_advanced_but[i].text), NULL
  550. b_att[0] = button_new (XTRACT (0, BY));
  551. chown_advanced_but[0].id = add_widget (ch_dlg, b_att[0]);
  552. b_att[1] = button_new (XTRACT (1, BY));
  553. chown_advanced_but[1].id = add_widget (ch_dlg, b_att[1]);
  554. b_att[2] = button_new (XTRACT (2, BY));
  555. chown_advanced_but[2].id = add_widget (ch_dlg, b_att[2]);
  556. b_user = button_new (XTRACT (3, BY));
  557. chown_advanced_but[3].id = add_widget (ch_dlg, b_user);
  558. b_group = button_new (XTRACT (4, BY));
  559. chown_advanced_but[4].id = add_widget (ch_dlg, b_group);
  560. #undef XTRACT
  561. l_mode = label_new (BY + 2, 3, "");
  562. add_widget (ch_dlg, l_mode);
  563. y = BY + 3;
  564. if (!single_set)
  565. {
  566. i = BUTTONS_PERM;
  567. add_widget (ch_dlg, hline_new (y++, -1, -1));
  568. chown_advanced_but[i].id = add_widget (ch_dlg,
  569. button_new (y,
  570. WIDGET (ch_dlg)->cols / 2 -
  571. chown_advanced_but[i].len,
  572. chown_advanced_but[i].ret_cmd,
  573. chown_advanced_but[i].flags,
  574. chown_advanced_but[i].text, NULL));
  575. i++;
  576. chown_advanced_but[i].id = add_widget (ch_dlg,
  577. button_new (y, WIDGET (ch_dlg)->cols / 2 + 1,
  578. chown_advanced_but[i].ret_cmd,
  579. chown_advanced_but[i].flags,
  580. chown_advanced_but[i].text, NULL));
  581. y++;
  582. }
  583. i = BUTTONS_PERM + 2;
  584. add_widget (ch_dlg, hline_new (y++, -1, -1));
  585. chown_advanced_but[i].id = add_widget (ch_dlg,
  586. button_new (y,
  587. WIDGET (ch_dlg)->cols / 2 -
  588. chown_advanced_but[i].len,
  589. chown_advanced_but[i].ret_cmd,
  590. chown_advanced_but[i].flags,
  591. chown_advanced_but[i].text, NULL));
  592. i++;
  593. chown_advanced_but[i].id = add_widget (ch_dlg,
  594. button_new (y, WIDGET (ch_dlg)->cols / 2 + 1,
  595. chown_advanced_but[i].ret_cmd,
  596. chown_advanced_but[i].flags,
  597. chown_advanced_but[i].text, NULL));
  598. dlg_select_widget (b_att[0]);
  599. }
  600. /* --------------------------------------------------------------------------------------------- */
  601. static void
  602. chown_advanced_done (void)
  603. {
  604. g_free (sf_stat);
  605. if (need_update)
  606. update_panels (UP_OPTIMIZE, UP_KEEPSEL);
  607. repaint_screen ();
  608. }
  609. /* --------------------------------------------------------------------------------------------- */
  610. #if 0
  611. static void
  612. do_chown (uid_t u, gid_t g)
  613. {
  614. chown (current_panel->dir.list[current_file].fname, u, g);
  615. file_mark (current_panel, current_file, 0);
  616. }
  617. #endif
  618. /* --------------------------------------------------------------------------------------------- */
  619. static char *
  620. next_file (void)
  621. {
  622. while (!current_panel->dir.list[current_file].f.marked)
  623. current_file++;
  624. return current_panel->dir.list[current_file].fname;
  625. }
  626. /* --------------------------------------------------------------------------------------------- */
  627. static void
  628. apply_advanced_chowns (struct stat *sf)
  629. {
  630. vfs_path_t *vpath;
  631. char *lc_fname;
  632. gid_t a_gid = sf->st_gid;
  633. uid_t a_uid = sf->st_uid;
  634. lc_fname = current_panel->dir.list[current_file].fname;
  635. vpath = vfs_path_from_str (lc_fname);
  636. need_update = end_chown = TRUE;
  637. if (mc_chmod (vpath, get_mode ()) == -1)
  638. message (D_ERROR, MSG_ERROR, _("Cannot chmod \"%s\"\n%s"),
  639. lc_fname, unix_error_string (errno));
  640. /* call mc_chown only, if mc_chmod didn't fail */
  641. else if (mc_chown (vpath, (ch_flags[9] == '+') ? sf->st_uid : (uid_t) (-1),
  642. (ch_flags[10] == '+') ? sf->st_gid : (gid_t) (-1)) == -1)
  643. message (D_ERROR, MSG_ERROR, _("Cannot chown \"%s\"\n%s"),
  644. lc_fname, unix_error_string (errno));
  645. do_file_mark (current_panel, current_file, 0);
  646. vfs_path_free (vpath);
  647. do
  648. {
  649. lc_fname = next_file ();
  650. vpath = vfs_path_from_str (lc_fname);
  651. if (mc_stat (vpath, sf) != 0)
  652. {
  653. vfs_path_free (vpath);
  654. break;
  655. }
  656. ch_cmode = sf->st_mode;
  657. if (mc_chmod (vpath, get_mode ()) == -1)
  658. message (D_ERROR, MSG_ERROR, _("Cannot chmod \"%s\"\n%s"),
  659. lc_fname, unix_error_string (errno));
  660. /* call mc_chown only, if mc_chmod didn't fail */
  661. else if (mc_chown (vpath, (ch_flags[9] == '+') ? a_uid : (uid_t) (-1),
  662. (ch_flags[10] == '+') ? a_gid : (gid_t) (-1)) == -1)
  663. message (D_ERROR, MSG_ERROR, _("Cannot chown \"%s\"\n%s"),
  664. lc_fname, unix_error_string (errno));
  665. do_file_mark (current_panel, current_file, 0);
  666. vfs_path_free (vpath);
  667. }
  668. while (current_panel->marked != 0);
  669. }
  670. /* --------------------------------------------------------------------------------------------- */
  671. /*** public functions ****************************************************************************/
  672. /* --------------------------------------------------------------------------------------------- */
  673. void
  674. chown_advanced_cmd (void)
  675. {
  676. /* Number of files at startup */
  677. int files_on_begin;
  678. files_on_begin = max (1, current_panel->marked);
  679. do
  680. { /* do while any files remaining */
  681. int file_idx;
  682. char buffer[BUF_MEDIUM];
  683. vfs_path_t *vpath;
  684. int result;
  685. init_chown_advanced ();
  686. if (current_panel->marked)
  687. fname = next_file (); /* next marked file */
  688. else
  689. fname = selection (current_panel)->fname; /* single file */
  690. vpath = vfs_path_from_str (fname);
  691. if (mc_stat (vpath, sf_stat) != 0)
  692. { /* get status of file */
  693. destroy_dlg (ch_dlg);
  694. vfs_path_free (vpath);
  695. break;
  696. }
  697. ch_cmode = sf_stat->st_mode;
  698. file_idx = files_on_begin == 1 ? 1 : (files_on_begin - current_panel->marked + 1);
  699. g_snprintf (buffer, sizeof (buffer), "%s (%d/%d)",
  700. str_fit_to_term (fname, WIDGET (ch_dlg)->cols - 20, J_LEFT_FIT),
  701. file_idx, files_on_begin);
  702. label_set_text (l_filename, buffer);
  703. chown_refresh ();
  704. update_ownership ();
  705. result = run_dlg (ch_dlg);
  706. switch (result)
  707. {
  708. case B_CANCEL:
  709. end_chown = TRUE;
  710. break;
  711. case B_ENTER:
  712. need_update = TRUE;
  713. if (mc_chmod (vpath, get_mode ()) == -1)
  714. message (D_ERROR, MSG_ERROR, _("Cannot chmod \"%s\"\n%s"),
  715. fname, unix_error_string (errno));
  716. /* call mc_chown only, if mc_chmod didn't fail */
  717. else if (mc_chown
  718. (vpath, (ch_flags[9] == '+') ? sf_stat->st_uid : (uid_t) (-1),
  719. (ch_flags[10] == '+') ? sf_stat->st_gid : (gid_t) (-1)) == -1)
  720. message (D_ERROR, MSG_ERROR, _("Cannot chown \"%s\"\n%s"), fname,
  721. unix_error_string (errno));
  722. break;
  723. case B_SETALL:
  724. apply_advanced_chowns (sf_stat);
  725. break;
  726. case B_SKIP:
  727. break;
  728. }
  729. if (current_panel->marked && result != B_CANCEL)
  730. {
  731. do_file_mark (current_panel, current_file, 0);
  732. need_update = TRUE;
  733. }
  734. destroy_dlg (ch_dlg);
  735. vfs_path_free (vpath);
  736. }
  737. while (current_panel->marked && !end_chown);
  738. chown_advanced_done ();
  739. }
  740. /* --------------------------------------------------------------------------------------------- */