all suggestion by it@li.org committed
[midnight-commander.git] / os2 / chmod.os2.c
blob0669012840cb443df154f7ecbaa0eefbffbd6379
1 /* Chmod command for OS/2 operating system
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2 of the License, or
6 (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.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 #include <config.h>
20 #ifndef __os2__
21 #error This file is for the OS/2 operating system.
22 #else
24 #define INCL_DOSFILEMGR
25 #include <os2.h>
26 #include <string.h>
27 #include <stdio.h>
28 /* for chmod and stat */
29 #include <io.h>
30 #include <sys\types.h>
31 #include <sys\stat.h>
32 #include "tty.h"
33 #include "mad.h"
34 #include "util.h"
35 #include "win.h"
36 #include "color.h"
37 #include "dlg.h"
38 #include "widget.h"
39 #include "dialog.h" /* For do_refresh() */
41 #include "dir.h"
42 #include "panel.h" /* Needed for the externs */
43 #include "file.h"
44 #include "main.h"
45 #include "chmod.h"
46 #include "achown.h"
47 #include "chown.h"
49 static int single_set;
50 struct Dlg_head *ch_dlg;
52 #define PX 5
53 #define PY 2
55 #define FX 40
56 #define FY 2
58 #define BX 6
59 #define BY 17
61 #define TX 40
62 #define TY 12
64 #define PERMISSIONS 4
65 #define BUTTONS 6
67 #define B_MARKED B_USER
68 #define B_ALL B_USER+1
69 #define B_SETMRK B_USER+2
70 #define B_CLRMRK B_USER+3
72 int mode_change, need_update;
73 int c_file, end_chmod;
75 umode_t and_mask, or_mask, c_stat;
76 char *c_fname, *c_fown, *c_fgrp, *c_fperm;
77 int c_fsize;
79 static WLabel *statl;
80 static int normal_color;
81 static int title_color;
82 static int selection_color;
84 /* bsedos.h */
85 struct {
86 mode_t mode;
87 char *text;
88 int selected;
89 WCheck *check;
90 } check_perm[PERMISSIONS] = {
93 FILE_ARCHIVED, "Archive", 0, 0,
96 FILE_READONLY, "Read Only", 0, 0,
99 FILE_HIDDEN, "Hidden", 0, 0,
102 FILE_SYSTEM, "System", 0, 0,
106 struct {
107 int ret_cmd, flags, y, x;
108 char *text;
109 } chmod_but[BUTTONS] = {
112 B_CANCEL, NORMAL_BUTTON, 2, 33, "&Cancel",
115 B_ENTER, DEFPUSH_BUTTON, 2, 17, "&Set",
118 B_CLRMRK, NORMAL_BUTTON, 0, 42, "C&lear marked",
121 B_SETMRK, NORMAL_BUTTON, 0, 27, "S&et marked",
124 B_MARKED, NORMAL_BUTTON, 0, 12, "&Marked all",
127 B_ALL, NORMAL_BUTTON, 0, 0, "Set &all",
132 static void mk_chmod (char *filename, ULONG st);
135 static void chmod_toggle_select (void)
137 int Id = ch_dlg->current->dlg_id - BUTTONS + single_set * 2;
139 attrset (normal_color);
140 check_perm[Id].selected ^= 1;
142 dlg_move (ch_dlg, PY + PERMISSIONS - Id, PX + 1);
143 addch ((check_perm[Id].selected) ? '*' : ' ');
144 dlg_move (ch_dlg, PY + PERMISSIONS - Id, PX + 3);
147 static void chmod_refresh (void)
149 attrset (normal_color);
150 dlg_erase (ch_dlg);
152 draw_box (ch_dlg, 1, 2, 20 - single_set, 66);
153 draw_box (ch_dlg, PY, PX, PERMISSIONS + 2, 33);
154 draw_box (ch_dlg, FY, FX, 10, 25);
156 dlg_move (ch_dlg, FY + 1, FX + 2);
157 addstr ("Name");
158 dlg_move (ch_dlg, FY + 3, FX + 2);
159 addstr ("Permissions (Octal)");
160 dlg_move (ch_dlg, FY + 5, FX + 2);
161 addstr ("Owner name");
162 dlg_move (ch_dlg, FY + 7, FX + 2);
163 addstr ("Group name");
165 attrset (title_color);
166 dlg_move (ch_dlg, 1, 28);
167 addstr (" Chmod command ");
168 dlg_move (ch_dlg, PY, PX + 1);
169 addstr (" Permission ");
170 dlg_move (ch_dlg, FY, FX + 1);
171 addstr (" File ");
173 attrset (selection_color);
175 dlg_move (ch_dlg, TY, TX);
176 addstr ("Use SPACE to change");
177 dlg_move (ch_dlg, TY + 1, TX);
178 addstr ("an option, ARROW KEYS");
179 dlg_move (ch_dlg, TY + 2, TX);
180 addstr ("to move between options");
181 dlg_move (ch_dlg, TY + 3, TX);
182 addstr ("and T or INS to mark");
185 static int chmod_callback (Dlg_head *h, int Par, int Msg)
187 char buffer [10];
189 switch (Msg) {
190 case DLG_ACTION:
191 if (Par >= BUTTONS - single_set * 2){
192 c_stat ^= check_perm[Par - BUTTONS + single_set * 2].mode;
193 sprintf (buffer, "%o", c_stat);
194 label_set_text (statl, buffer);
195 chmod_toggle_select ();
196 mode_change = 1;
198 break;
200 case DLG_KEY:
201 if ((Par == 'T' || Par == 't' || Par == KEY_IC) &&
202 ch_dlg->current->dlg_id >= BUTTONS - single_set * 2) {
203 chmod_toggle_select ();
204 if (Par == KEY_IC)
205 dlg_one_down (ch_dlg);
206 return 1;
208 break;
209 #ifndef HAVE_X
210 case DLG_DRAW:
211 chmod_refresh ();
212 break;
213 #endif
215 return 0;
218 static void init_chmod (void)
220 int i;
222 do_refresh ();
223 end_chmod = c_file = need_update = 0;
224 single_set = (cpanel->marked < 2) ? 2 : 0;
226 if (use_colors){
227 normal_color = COLOR_NORMAL;
228 title_color = COLOR_HOT_NORMAL;
229 selection_color = COLOR_NORMAL;
230 } else {
231 normal_color = NORMAL_COLOR;
232 title_color = SELECTED_COLOR;
233 selection_color = SELECTED_COLOR;
236 ch_dlg = create_dlg (0, 0, 22 - single_set, 70, dialog_colors,
237 chmod_callback, "[Chmod]", "chmod", DLG_CENTER);
239 x_set_dialog_title (ch_dlg, "Chmod command");
241 #define XTRACT(i) BY+chmod_but[i].y-single_set, BX+chmod_but[i].x, \
242 chmod_but[i].ret_cmd, chmod_but[i].flags, chmod_but[i].text, 0, 0, NULL
244 tk_new_frame (ch_dlg, "b.");
245 for (i = 0; i < BUTTONS; i++) {
246 if (i == 2 && single_set)
247 break;
248 else
249 add_widgetl (ch_dlg, button_new (XTRACT (i)), XV_WLAY_RIGHTOF);
253 #define XTRACT2(i) 0, check_perm [i].text, NULL
254 tk_new_frame (ch_dlg, "c.");
255 for (i = 0; i < PERMISSIONS; i++) {
256 check_perm[i].check = check_new (PY + (PERMISSIONS - i), PX + 2,
257 XTRACT2 (i));
258 add_widget (ch_dlg, check_perm[i].check);
262 int stat_file (char *filename, struct stat *st)
264 HFILE fHandle = 0L;
265 ULONG fInfoLevel = 1; /* 1st Level Info: Standard attributs */
266 FILESTATUS3 fInfoBuf;
267 ULONG fInfoBufSize;
268 ULONG fAction = 0;
269 APIRET rc;
271 fInfoBufSize = sizeof(FILESTATUS3);
272 rc = DosOpen((PSZ) filename,
273 &fHandle,
274 &fAction,
275 (ULONG) 0,
276 FILE_NORMAL,
277 OPEN_ACTION_OPEN_IF_EXISTS,
278 (OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE),
279 (PEAOP2) NULL);
280 if (rc != 0) {
281 return 0;
284 rc = DosQueryFileInfo(fHandle, fInfoLevel, &fInfoBuf, fInfoBufSize);
285 DosClose(fHandle);
286 if (rc != 0) {
287 return 0; /* error ! */
288 } else {
289 st->st_mode = fInfoBuf.attrFile;
292 if (st->st_mode & FILE_DIRECTORY)
293 return 0;
294 return 1;
297 static void chmod_done (void)
299 if (need_update)
300 update_panels (UP_OPTIMIZE, UP_KEEPSEL, UP_KEEPSEL);
301 repaint_screen ();
304 char *next_file (void)
306 while (!cpanel->dir.list[c_file].f.marked)
307 c_file++;
309 return cpanel->dir.list[c_file].fname;
312 static int os2_chmod (char *filename, ULONG st)
314 HFILE fHandle = 0L;
315 ULONG fInfoLevel = 1; /* 1st Level Info: Standard attributs */
316 FILESTATUS3 fInfoBuf;
317 ULONG fInfoBufSize;
318 ULONG fAction = 0L;
319 APIRET rc;
321 fInfoBufSize = sizeof(FILESTATUS3);
322 rc = DosOpen((PSZ) filename,
323 &fHandle,
324 &fAction,
325 (ULONG) 0,
326 FILE_NORMAL,
327 OPEN_ACTION_OPEN_IF_EXISTS,
328 (OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE),
329 0L);
330 if (rc != 0) {
331 return rc;
334 rc = DosQueryFileInfo(fHandle, fInfoLevel, &fInfoBuf, fInfoBufSize);
335 if (rc!=0) {
336 DosClose(fHandle);
337 return rc;
339 fInfoBuf.attrFile = st;
340 rc = DosSetFileInfo(fHandle, fInfoLevel, &fInfoBuf, fInfoBufSize);
341 rc = DosClose(fHandle);
342 return rc;
345 static void do_chmod (struct stat *sf)
347 HFILE fHandle = 0L;
348 ULONG fInfoLevel = 1; /* 1st Level Info: Standard attributs */
349 FILESTATUS3 fInfoBuf;
350 ULONG fInfoBufSize;
351 ULONG fAction = 0;
352 EAOP2 fEaop;
353 APIRET rc;
355 sf->st_mode &= and_mask;
356 sf->st_mode |= or_mask;
358 mk_chmod(cpanel->dir.list[c_file].fname, sf->st_mode);
360 do_file_mark (cpanel, c_file, 0);
361 return;
364 static void mk_chmod (char *filename, ULONG st)
366 int rc;
367 int fileMode = 0;
369 if (st & FILE_READONLY) {
370 // READONLY set
371 fileMode |= S_IREAD;
372 os2_chmod(filename, st);
373 } else {
374 fileMode |= (S_IWRITE | S_IREAD);
375 rc = chmod(filename, fileMode);
376 // Then set the other flags
377 os2_chmod(filename, st);
379 return;
383 static void apply_mask (struct stat *sf)
385 char *fname;
387 need_update = end_chmod = 1;
388 do_chmod (sf);
390 do {
391 fname = next_file ();
392 if (!stat_file (fname, sf))
393 return;
394 c_stat = sf->st_mode;
396 do_chmod (sf);
397 } while (cpanel->marked);
400 void chmod_cmd (void)
402 char buffer [10];
403 char *fname;
404 int i;
405 struct stat sf_stat;
407 do { /* do while any files remaining */
408 init_chmod ();
409 if (cpanel->marked)
410 fname = next_file (); /* next marked file */
411 else
412 fname = selection (cpanel)->fname; /* single file */
414 if (!stat_file (fname, &sf_stat)) /* get status of file */
415 break;
417 c_stat = sf_stat.st_mode;
418 mode_change = 0; /* clear changes flag */
420 /* set check buttons */
421 for (i = 0; i < PERMISSIONS; i++){
422 check_perm[i].check->state = (c_stat & check_perm[i].mode) ? 1 : 0;
423 check_perm[i].selected = 0;
426 tk_new_frame (ch_dlg, "l.");
427 /* Set the labels */
428 c_fname = name_trunc (fname, 21);
429 add_widget (ch_dlg, label_new (FY+2, FX+2, c_fname, NULL));
430 c_fown = name_trunc (get_owner (sf_stat.st_uid), 21);
431 add_widget (ch_dlg, label_new (FY+6, FX+2, c_fown, NULL));
432 c_fgrp = name_trunc (get_group (sf_stat.st_gid), 21);
433 add_widget (ch_dlg, label_new (FY+8, FX+2, c_fgrp, NULL));
434 sprintf (buffer, "%o", c_stat);
435 statl = label_new (FY+4, FX+2, buffer, NULL);
436 add_widget (ch_dlg, statl);
437 tk_end_frame ();
439 run_dlg (ch_dlg); /* retrieve an action */
441 /* do action */
442 switch (ch_dlg->ret_value){
443 case B_ENTER:
444 if (mode_change)
445 mk_chmod (fname, c_stat); /*.ado */
446 need_update = 1;
447 break;
449 case B_CANCEL:
450 end_chmod = 1;
451 break;
453 case B_ALL:
454 case B_MARKED:
455 and_mask = or_mask = 0;
456 and_mask = ~and_mask;
458 for (i = 0; i < PERMISSIONS; i++) {
459 if (check_perm[i].selected || ch_dlg->ret_value == B_ALL)
460 if (check_perm[i].check->state & C_BOOL)
461 or_mask |= check_perm[i].mode;
462 else
463 and_mask &= ~check_perm[i].mode;
466 apply_mask (&sf_stat);
467 break;
469 case B_SETMRK:
470 and_mask = or_mask = 0;
471 and_mask = ~and_mask;
473 for (i = 0; i < PERMISSIONS; i++) {
474 if (check_perm[i].selected)
475 or_mask |= check_perm[i].mode;
478 apply_mask (&sf_stat);
479 break;
480 case B_CLRMRK:
481 and_mask = or_mask = 0;
482 and_mask = ~and_mask;
484 for (i = 0; i < PERMISSIONS; i++) {
485 if (check_perm[i].selected)
486 and_mask &= ~check_perm[i].mode;
489 apply_mask (&sf_stat);
490 break;
493 if (cpanel->marked && ch_dlg->ret_value!=B_CANCEL) {
494 do_file_mark (cpanel, c_file, 0);
495 need_update = 1;
497 destroy_dlg (ch_dlg);
498 } while (cpanel->marked && !end_chmod);
499 chmod_done ();
502 #endif /*__os2__*/