dosutils: add RIGHTS and finish Novell-style display fixes
- add RIGHTS as a new multi-call DOS utility - implement Client32 NCP87 effective-rights query helper - map NCP effective-rights bits to Novell RIGHTS display order - keep legacy directory-handle based rights lookup as fallback - match Novell RIGHTS output for directories and files more closely - remove hardcoded MARS/SYS and SYS display fallbacks from RIGHTS/FLAGDIR - derive display prefixes from the active network drive where available - adjust FLAGDIR output formatting to match Novell field alignment - keep FLAG and SLIST unchanged after checking for hardcoded prefixes
This commit is contained in:
@@ -55,6 +55,7 @@ if(MARS_NWE_BUILD_DOSUTILS)
|
||||
slist.c
|
||||
flag.c
|
||||
flagdir.c
|
||||
rights.c
|
||||
c32ncp.c
|
||||
nwcrypt.c
|
||||
nwdebug.c
|
||||
|
||||
27
README.md
27
README.md
@@ -40,6 +40,7 @@ Still to validate or continue:
|
||||
- Server listing through `SLIST`
|
||||
- File attribute management through `FLAG`
|
||||
- Directory attribute management through `FLAGDIR`
|
||||
- Effective rights display through `RIGHTS`
|
||||
- Optional mars_nwe debug control hooks
|
||||
- Developer diagnostics through `TESTS`
|
||||
|
||||
@@ -63,6 +64,7 @@ The current command dispatcher includes these built-ins:
|
||||
- `SLIST`
|
||||
- `FLAG`
|
||||
- `FLAGDIR`
|
||||
- `RIGHTS`
|
||||
- `DEBUG`
|
||||
- `ECHO`
|
||||
- `CD`
|
||||
@@ -114,6 +116,7 @@ This path is currently used by:
|
||||
|
||||
- `FLAG`
|
||||
- `FLAGDIR`
|
||||
- `RIGHTS`
|
||||
|
||||
The old `Net_Call` / INT 21h requester path is kept as a fallback where appropriate, but Client32 is now preferred for the validated FLAG-family operations.
|
||||
|
||||
@@ -363,6 +366,30 @@ MARS/SYS:UDIR
|
||||
|
||||
`Private` is intentionally rejected for the current NetWare 386-style path.
|
||||
|
||||
|
||||
### `RIGHTS`
|
||||
|
||||
Display effective NetWare rights for a file or directory.
|
||||
|
||||
Typical usage:
|
||||
|
||||
```text
|
||||
RIGHTS [path]
|
||||
```
|
||||
|
||||
Supported in this first version:
|
||||
|
||||
- directory paths
|
||||
- file paths, using the parent directory rights for the first read-only implementation
|
||||
- Novell-like display of the effective rights mask
|
||||
|
||||
Rights are shown in the traditional order:
|
||||
|
||||
```text
|
||||
S R W C E M F A
|
||||
Supervisor, Read, Write, Create, Erase, Modify, File scan, Access Control
|
||||
```
|
||||
|
||||
### `DEBUG`
|
||||
|
||||
Set mars_nwe debug levels for selected server-side modules.
|
||||
|
||||
173
c32ncp.c
173
c32ncp.c
@@ -97,6 +97,85 @@ static UI c32_build_handle_path(uint8 *buf, uint8 dhandle,
|
||||
return(used);
|
||||
}
|
||||
|
||||
|
||||
static UI c32_build_handle_path_from_dos_path(uint8 *buf, uint8 dhandle,
|
||||
uint16 dirbase, uint8 style,
|
||||
const char *dospath)
|
||||
{
|
||||
uint8 *p;
|
||||
uint8 *countp;
|
||||
int count = 0;
|
||||
const char *s;
|
||||
UI used;
|
||||
|
||||
memset(buf, 0, 0x140);
|
||||
|
||||
if (dhandle) {
|
||||
c32_put_word_lh(buf + 1, (uint16)dhandle);
|
||||
c32_put_word_lh(buf + 3, dirbase);
|
||||
buf[5] = style;
|
||||
} else {
|
||||
buf[5] = 0xff;
|
||||
}
|
||||
|
||||
p = buf + 6;
|
||||
countp = p++;
|
||||
|
||||
s = dospath;
|
||||
if (!s) s = "";
|
||||
|
||||
/*
|
||||
* DOS tools mostly pass relative paths against the current directory
|
||||
* handle. Accept simple DOS decoration here so RIGHTS can pass "." or
|
||||
* ".\\UDIR\\FILE" without constructing path components in the caller.
|
||||
*/
|
||||
if (s[0] && s[1] == ':')
|
||||
s += 2;
|
||||
|
||||
while (*s == '\\' || *s == '/')
|
||||
s++;
|
||||
|
||||
while (*s && p < buf + 0x138 && count < 32) {
|
||||
const char *start;
|
||||
int len;
|
||||
|
||||
while (*s == '\\' || *s == '/')
|
||||
s++;
|
||||
|
||||
if (*s == '.'
|
||||
&& (s[1] == '\0' || s[1] == '\\' || s[1] == '/')) {
|
||||
s++;
|
||||
continue;
|
||||
}
|
||||
|
||||
start = s;
|
||||
while (*s && *s != '\\' && *s != '/')
|
||||
s++;
|
||||
|
||||
len = (int)(s - start);
|
||||
if (len <= 0)
|
||||
continue;
|
||||
|
||||
if (len > 255)
|
||||
len = 255;
|
||||
|
||||
if (p + 1 + len >= buf + 0x138)
|
||||
break;
|
||||
|
||||
*p++ = (uint8)len;
|
||||
memcpy(p, start, len);
|
||||
p += len;
|
||||
count++;
|
||||
}
|
||||
|
||||
*countp = (uint8)count;
|
||||
|
||||
used = (UI)(p - buf);
|
||||
c32_put_word_lh(buf + 0x13c, used);
|
||||
return(used);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Current verified Client32 path for mars-nwe DOS utilities:
|
||||
*
|
||||
@@ -307,3 +386,97 @@ int c32_ncp87_modify_dos_attributes(char *name,
|
||||
}
|
||||
|
||||
|
||||
int c32_ncp87_get_effective_rights(const char *path_name,
|
||||
uint16 dir_handle,
|
||||
uint16 *rights_out,
|
||||
uint16 *actual_out,
|
||||
uint16 *handle_lo_out,
|
||||
uint16 *handle_hi_out)
|
||||
{
|
||||
uint16 handle_lo, handle_hi;
|
||||
uint8 hdr[16];
|
||||
uint8 path[0x140];
|
||||
uint8 rep0[0x20];
|
||||
uint8 rep1[0x20];
|
||||
uint8 rawout[32];
|
||||
uint16 raw_ret_ax, raw_ret_dx;
|
||||
uint16 actual_lo;
|
||||
uint16 rights0;
|
||||
uint16 rights4;
|
||||
UI path_len;
|
||||
int rc;
|
||||
|
||||
if (!rights_out)
|
||||
return(1);
|
||||
|
||||
*rights_out = 0;
|
||||
if (actual_out) *actual_out = 0;
|
||||
if (handle_lo_out) *handle_lo_out = 0;
|
||||
if (handle_hi_out) *handle_hi_out = 0;
|
||||
|
||||
rc = c32_get_ncp_handle(&handle_lo, &handle_hi);
|
||||
if (rc)
|
||||
return(10 + rc);
|
||||
|
||||
/*
|
||||
* NCP 87 subfunction 29: Get effective rights.
|
||||
*
|
||||
* This mirrors ncpfs ncp_get_eff_directory_rights():
|
||||
* byte 29
|
||||
* byte source namespace
|
||||
* byte target namespace
|
||||
* word search attributes, little endian
|
||||
* dword reserved, zero
|
||||
* handle/path
|
||||
*
|
||||
* Reply is a little-endian word with NCP rights bits.
|
||||
*/
|
||||
memset(hdr, 0, sizeof(hdr));
|
||||
hdr[0] = 29;
|
||||
hdr[1] = 0; /* source namespace DOS */
|
||||
hdr[2] = 0; /* target namespace DOS */
|
||||
c32_put_word_lh(hdr + 3, 0x0006); /* SA_ALL */
|
||||
c32_put_dword_lh(hdr + 5, 0L); /* reserved */
|
||||
|
||||
path_len = c32_build_handle_path_from_dos_path(path, (uint8)dir_handle,
|
||||
0, 0, path_name);
|
||||
|
||||
memset(rep0, 0, sizeof(rep0));
|
||||
memset(rep1, 0, sizeof(rep1));
|
||||
memset(rawout, 0, sizeof(rawout));
|
||||
|
||||
C32_NCP87_Raw5_Probe(handle_lo, handle_hi,
|
||||
hdr, 9,
|
||||
path, path_len,
|
||||
rep0, sizeof(rep0),
|
||||
rep1, sizeof(rep1),
|
||||
rawout);
|
||||
|
||||
raw_ret_ax = c32_get_word_lh(rawout + 14);
|
||||
raw_ret_dx = c32_get_word_lh(rawout + 16);
|
||||
actual_lo = c32_get_word_lh(rawout + 18);
|
||||
|
||||
if (actual_out) *actual_out = actual_lo;
|
||||
if (handle_lo_out) *handle_lo_out = handle_lo;
|
||||
if (handle_hi_out) *handle_hi_out = handle_hi;
|
||||
|
||||
if (raw_ret_ax != 0 || raw_ret_dx != 0)
|
||||
return(20);
|
||||
|
||||
rights0 = c32_get_word_lh(rep0 + 0);
|
||||
rights4 = c32_get_word_lh(rep0 + 4);
|
||||
|
||||
/*
|
||||
* Most NCP replies start at REP0+0. The existing RIM_ATTRIBUTES helper
|
||||
* found attributes at REP0+4 on Client32. Accept the +4 location only
|
||||
* if +0 is empty, so restricted rights value 0 still works when +4 is
|
||||
* also zero.
|
||||
*/
|
||||
if (rights0 == 0 && rights4 != 0)
|
||||
rights0 = rights4;
|
||||
|
||||
*rights_out = rights0;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
7
c32ncp.h
7
c32ncp.h
@@ -19,4 +19,11 @@ int c32_ncp87_modify_dos_attributes(char *name,
|
||||
uint16 *handle_lo_out,
|
||||
uint16 *handle_hi_out);
|
||||
|
||||
int c32_ncp87_get_effective_rights(const char *path,
|
||||
uint16 dir_handle,
|
||||
uint16 *rights_out,
|
||||
uint16 *actual_out,
|
||||
uint16 *handle_lo_out,
|
||||
uint16 *handle_hi_out);
|
||||
|
||||
#endif
|
||||
|
||||
73
flagdir.c
73
flagdir.c
@@ -75,6 +75,61 @@ static int fd_current_dhandle(uint8 *dhandle)
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
static int fd_current_prefix(char *out, int max)
|
||||
{
|
||||
uint8 connid = 0;
|
||||
uint8 dhandle = 0;
|
||||
uint8 flags = 0;
|
||||
int drive;
|
||||
char server[52];
|
||||
char path[260];
|
||||
char volume[32];
|
||||
char *p;
|
||||
int i = 0;
|
||||
|
||||
if (!out || max < 8)
|
||||
return(-1);
|
||||
|
||||
out[0] = '\0';
|
||||
|
||||
drive = fd_get_current_drive();
|
||||
if (get_drive_info((uint8)drive, &connid, &dhandle, &flags))
|
||||
return(-1);
|
||||
|
||||
if (!connid || (flags & 0x80))
|
||||
return(-1);
|
||||
|
||||
server[0] = '\0';
|
||||
if (get_fs_name(connid, server))
|
||||
server[0] = '\0';
|
||||
|
||||
path[0] = '\0';
|
||||
if (get_dir_path(dhandle, path) || !path[0])
|
||||
return(-1);
|
||||
|
||||
p = strchr(path, ':');
|
||||
if (!p)
|
||||
return(-1);
|
||||
|
||||
while (path + i < p && i < (int)sizeof(volume) - 1) {
|
||||
volume[i] = path[i];
|
||||
i++;
|
||||
}
|
||||
volume[i] = '\0';
|
||||
|
||||
if (!volume[0])
|
||||
return(-1);
|
||||
|
||||
if (server[0])
|
||||
sprintf(out, "%s/%s:", server, volume);
|
||||
else
|
||||
sprintf(out, "%s:", volume);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
static void fd_help(void)
|
||||
{
|
||||
fprintf(stdout, "386 Usage: Flagdir [path [option...]]\n");
|
||||
@@ -118,17 +173,13 @@ static void fd_display(char *path, uint32 attrs)
|
||||
|
||||
fd_upcopy(up, path, sizeof(up));
|
||||
|
||||
/*
|
||||
* Novell FLAGDIR style:
|
||||
*
|
||||
* MARS/SYS:UDIR
|
||||
* UDIR System Hidden ...
|
||||
*
|
||||
* For now we match the tested MARS/SYS: environment used by PUBLIC/NPUBLIC.
|
||||
* The NCP logic is independent from this cosmetic header.
|
||||
*/
|
||||
fprintf(stdout, "MARS/SYS:%s\n", up);
|
||||
fprintf(stdout, " %-10s ", up);
|
||||
{
|
||||
char prefix[90];
|
||||
if (fd_current_prefix(prefix, sizeof(prefix)))
|
||||
prefix[0] = '\0';
|
||||
fprintf(stdout, "%s%s \n", prefix, up);
|
||||
}
|
||||
fprintf(stdout, " %-12.12s ", up);
|
||||
|
||||
if (!(attrs & FD_DIR_BITS)) {
|
||||
fprintf(stdout, "Normal\n");
|
||||
|
||||
1
net.c
1
net.c
@@ -36,6 +36,7 @@ static struct s_net_functions {
|
||||
{"LOGOUT", "logout from server", func_logout , 0},
|
||||
{"FLAG", "display or modify file attributes", func_flag , 0},
|
||||
{"FLAGDIR","display or modify directory attributes",func_flagdir, 0},
|
||||
{"RIGHTS", "display effective file/directory rights",func_rights, 0},
|
||||
{"SLIST", "list servers", func_slist , 0},
|
||||
{"PASSWD", "change password", func_passwd , 0},
|
||||
#if 1
|
||||
|
||||
1
net.h
1
net.h
@@ -255,6 +255,7 @@ extern int func_capture(int argc, char *argv[], int mode);
|
||||
/* flag.c */
|
||||
extern int func_flag (int argc, char *argv[], int mode);
|
||||
extern int func_flagdir(int argc, char *argv[], int mode);
|
||||
extern int func_rights (int argc, char *argv[], int mode);
|
||||
|
||||
|
||||
extern int ncp_17_37(uint32 last_id, uint16 objtyp, uint8 *pattern,
|
||||
|
||||
408
rights.c
Normal file
408
rights.c
Normal file
@@ -0,0 +1,408 @@
|
||||
/* rights.c - Novell RIGHTS-like DOS utility, read-only v4 */
|
||||
|
||||
#include "net.h"
|
||||
#include "c32ncp.h"
|
||||
#include <dos.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef S_IFDIR
|
||||
#define S_IFDIR 0040000
|
||||
#endif
|
||||
|
||||
#define NW_RIGHT_S 0x01
|
||||
#define NW_RIGHT_R 0x02
|
||||
#define NW_RIGHT_W 0x04
|
||||
#define NW_RIGHT_C 0x08
|
||||
#define NW_RIGHT_E 0x10
|
||||
#define NW_RIGHT_M 0x20
|
||||
#define NW_RIGHT_F 0x40
|
||||
#define NW_RIGHT_A 0x80
|
||||
|
||||
/* NCP effective-rights bits returned by NCP87 subfunction 29. */
|
||||
#define NCP_RIGHT_READ 0x0001
|
||||
#define NCP_RIGHT_WRITE 0x0002
|
||||
#define NCP_RIGHT_OPEN 0x0004
|
||||
#define NCP_RIGHT_CREATE 0x0008
|
||||
#define NCP_RIGHT_DELETE 0x0010
|
||||
#define NCP_RIGHT_OWNER 0x0020
|
||||
#define NCP_RIGHT_SEARCH 0x0040
|
||||
#define NCP_RIGHT_MODIFY 0x0080
|
||||
#define NCP_RIGHT_SUPER 0x0100
|
||||
|
||||
static uint8 rights_map_ncp_mask(uint16 ncp_rights);
|
||||
|
||||
|
||||
static int rights_same(char *a, char *b)
|
||||
{
|
||||
while (*a || *b) {
|
||||
int ca = *a++;
|
||||
int cb = *b++;
|
||||
if (ca >= 'a' && ca <= 'z') ca -= 32;
|
||||
if (cb >= 'a' && cb <= 'z') cb -= 32;
|
||||
if (ca != cb) return(0);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int rights_is_help(char *s)
|
||||
{
|
||||
if (!s) return(0);
|
||||
return(rights_same(s, "/?") || rights_same(s, "-?") || rights_same(s, "?"));
|
||||
}
|
||||
|
||||
static void rights_usage(void)
|
||||
{
|
||||
fprintf(stdout, "Usage: RIGHTS [path]\n\n");
|
||||
fprintf(stdout, "Rights = All | Supervisor | Read | Write | Create | Erase\n");
|
||||
fprintf(stdout, " Modify | File scan | Access Control\n");
|
||||
}
|
||||
|
||||
static int rights_get_current_drive(void)
|
||||
{
|
||||
REGS regs;
|
||||
|
||||
regs.h.ah = 0x19;
|
||||
int86(0x21, ®s, ®s);
|
||||
return((int)regs.h.al);
|
||||
}
|
||||
|
||||
static int rights_current_dhandle(uint8 *connid, uint8 *dhandle)
|
||||
{
|
||||
uint8 flags = 0;
|
||||
int drive = rights_get_current_drive();
|
||||
|
||||
if (get_drive_info((uint8)drive, connid, dhandle, &flags))
|
||||
return(-1);
|
||||
|
||||
if (!*connid || (flags & 0x80))
|
||||
return(-1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int rights_is_current_path(char *path)
|
||||
{
|
||||
if (!path || !*path) return(1);
|
||||
if (rights_same(path, ".")) return(1);
|
||||
if (rights_same(path, ".\\")) return(1);
|
||||
if (rights_same(path, "./")) return(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void rights_upcopy(char *dst, char *src, int max)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if (!src) src = "";
|
||||
|
||||
while (*src && i < max - 1) {
|
||||
char c = *src++;
|
||||
if (c == '/') c = '\\';
|
||||
if (c >= 'a' && c <= 'z') c -= 32;
|
||||
dst[i++] = c;
|
||||
}
|
||||
dst[i] = 0;
|
||||
}
|
||||
|
||||
static void rights_parent_path(char *dst, char *src, int max)
|
||||
{
|
||||
char tmp[260];
|
||||
char *p;
|
||||
|
||||
rights_upcopy(tmp, src, sizeof(tmp));
|
||||
|
||||
p = strrchr(tmp, '\\');
|
||||
if (!p) p = strrchr(tmp, ':');
|
||||
|
||||
if (!p) {
|
||||
dst[0] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
if (*p == ':') {
|
||||
p++;
|
||||
*p = '\0';
|
||||
} else {
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
strmaxcpy(dst, tmp, max - 1);
|
||||
}
|
||||
|
||||
static int rights_path_is_dir(char *path)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (rights_is_current_path(path))
|
||||
return(1);
|
||||
|
||||
if (stat(path, &st) == 0) {
|
||||
if (st.st_mode & S_IFDIR)
|
||||
return(1);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
static int rights_current_prefix(char *out, int max)
|
||||
{
|
||||
uint8 connid = 0;
|
||||
uint8 dhandle = 0;
|
||||
uint8 flags = 0;
|
||||
int drive;
|
||||
char server[52];
|
||||
char dpath[260];
|
||||
char volume[32];
|
||||
char *p;
|
||||
int i = 0;
|
||||
|
||||
if (!out || max < 8)
|
||||
return(-1);
|
||||
|
||||
out[0] = '\0';
|
||||
|
||||
drive = rights_get_current_drive();
|
||||
if (get_drive_info((uint8)drive, &connid, &dhandle, &flags))
|
||||
return(-1);
|
||||
|
||||
if (!connid || (flags & 0x80))
|
||||
return(-1);
|
||||
|
||||
server[0] = '\0';
|
||||
if (get_fs_name(connid, server))
|
||||
server[0] = '\0';
|
||||
|
||||
dpath[0] = '\0';
|
||||
if (get_dir_path(dhandle, dpath) || !dpath[0])
|
||||
return(-1);
|
||||
|
||||
p = strchr(dpath, ':');
|
||||
if (!p)
|
||||
return(-1);
|
||||
|
||||
while (dpath + i < p && i < (int)sizeof(volume) - 1) {
|
||||
volume[i] = dpath[i];
|
||||
i++;
|
||||
}
|
||||
volume[i] = '\0';
|
||||
|
||||
if (!volume[0])
|
||||
return(-1);
|
||||
|
||||
if (server[0])
|
||||
sprintf(out, "%s/%s:", server, volume);
|
||||
else
|
||||
sprintf(out, "%s:", volume);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
static void rights_make_header_path(char *out, char *path)
|
||||
{
|
||||
char up[260];
|
||||
char prefix[90];
|
||||
|
||||
if (rights_current_prefix(prefix, sizeof(prefix)))
|
||||
prefix[0] = '\0';
|
||||
|
||||
if (rights_is_current_path(path)) {
|
||||
strcpy(out, prefix);
|
||||
return;
|
||||
}
|
||||
|
||||
rights_upcopy(up, path, sizeof(up));
|
||||
strcpy(out, prefix);
|
||||
strcat(out, up);
|
||||
}
|
||||
|
||||
static int rights_effective_mask(char *path, int is_dir, uint8 *mask)
|
||||
{
|
||||
uint8 connid = 0;
|
||||
uint8 dhandle = 0;
|
||||
uint8 eff = 0;
|
||||
char usepath[260];
|
||||
int newhandle;
|
||||
uint16 ncp_rights = 0;
|
||||
|
||||
if (mask) *mask = 0;
|
||||
|
||||
if (rights_current_dhandle(&connid, &dhandle))
|
||||
return(-1);
|
||||
|
||||
/*
|
||||
* Prefer the explicit Client32 NCP87 effective-rights request. This is
|
||||
* the DOS Client32 equivalent of ncpfs ncp_get_eff_directory_rights().
|
||||
* It works for both files and directories, so pass the requested path
|
||||
* itself instead of mapping files to their parent directory.
|
||||
*/
|
||||
if (!c32_ncp87_get_effective_rights(rights_is_current_path(path) ? "" : path,
|
||||
(uint16)dhandle,
|
||||
&ncp_rights,
|
||||
NULL, NULL, NULL)) {
|
||||
if (mask) *mask = rights_map_ncp_mask(ncp_rights);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fallback for older requesters/paths: allocate a temporary directory
|
||||
* handle and use the returned old-style effective-rights byte.
|
||||
* This cannot directly target a file, so files are mapped to their parent.
|
||||
*/
|
||||
if (rights_is_current_path(path)) {
|
||||
usepath[0] = '\0';
|
||||
} else if (is_dir) {
|
||||
rights_upcopy(usepath, path, sizeof(usepath));
|
||||
} else {
|
||||
rights_parent_path(usepath, path, sizeof(usepath));
|
||||
}
|
||||
|
||||
newhandle = alloc_temp_dir_handle(dhandle, usepath, 0, &eff);
|
||||
if (newhandle < 0) {
|
||||
if (usepath[0]) {
|
||||
int subdir = 1;
|
||||
int r = ncp_16_02(dhandle, (uint8 *)usepath, &subdir,
|
||||
NULL, NULL, NULL);
|
||||
if (r >= 0) {
|
||||
eff = (uint8)r;
|
||||
} else {
|
||||
return(-1);
|
||||
}
|
||||
} else {
|
||||
eff = 0xff;
|
||||
}
|
||||
} else {
|
||||
dealloc_dir_handle(newhandle);
|
||||
}
|
||||
|
||||
if (mask) *mask = eff;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
static uint8 rights_map_ncp_mask(uint16 ncp_rights)
|
||||
{
|
||||
uint8 mask = 0;
|
||||
|
||||
if (ncp_rights & NCP_RIGHT_SUPER) mask |= NW_RIGHT_S;
|
||||
if (ncp_rights & NCP_RIGHT_READ) mask |= NW_RIGHT_R;
|
||||
if (ncp_rights & NCP_RIGHT_WRITE) mask |= NW_RIGHT_W;
|
||||
if (ncp_rights & NCP_RIGHT_CREATE) mask |= NW_RIGHT_C;
|
||||
if (ncp_rights & NCP_RIGHT_DELETE) mask |= NW_RIGHT_E;
|
||||
if (ncp_rights & NCP_RIGHT_MODIFY) mask |= NW_RIGHT_M;
|
||||
if (ncp_rights & NCP_RIGHT_SEARCH) mask |= NW_RIGHT_F;
|
||||
if (ncp_rights & NCP_RIGHT_OWNER) mask |= NW_RIGHT_A;
|
||||
|
||||
return(mask);
|
||||
}
|
||||
|
||||
|
||||
static void rights_mask_string(uint8 mask, char *out)
|
||||
{
|
||||
out[0] = (mask & NW_RIGHT_S) ? 'S' : '-';
|
||||
out[1] = (mask & NW_RIGHT_R) ? 'R' : '-';
|
||||
out[2] = (mask & NW_RIGHT_W) ? 'W' : '-';
|
||||
out[3] = (mask & NW_RIGHT_C) ? 'C' : '-';
|
||||
out[4] = (mask & NW_RIGHT_E) ? 'E' : '-';
|
||||
out[5] = (mask & NW_RIGHT_M) ? 'M' : '-';
|
||||
out[6] = (mask & NW_RIGHT_F) ? 'F' : '-';
|
||||
out[7] = (mask & NW_RIGHT_A) ? 'A' : '-';
|
||||
out[8] = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* Novell RIGHTS layout:
|
||||
* - lines with star: two leading blanks, star, blank, text
|
||||
* - lines without star: four leading blanks, text
|
||||
* Keep the right-column letter at a fixed-ish DOS-screen position.
|
||||
*/
|
||||
static void rights_print_line(int have, int star, char *text, char letter)
|
||||
{
|
||||
(void)have;
|
||||
|
||||
if (star)
|
||||
fprintf(stdout, " * %-43s(%c)\n", text, letter);
|
||||
else
|
||||
fprintf(stdout, " %-43s(%c)\n", text, letter);
|
||||
}
|
||||
|
||||
static void rights_display(char *path, int is_dir, uint8 mask)
|
||||
{
|
||||
char hdr[300];
|
||||
char mstr[10];
|
||||
|
||||
rights_make_header_path(hdr, path);
|
||||
rights_mask_string(mask, mstr);
|
||||
|
||||
fprintf(stdout, "%s\n", hdr);
|
||||
|
||||
if (is_dir)
|
||||
fprintf(stdout, "Your Effective Rights for this directory are [%s]\n", mstr);
|
||||
else
|
||||
fprintf(stdout, "Your Effective Rights for this file are [%s]\n", mstr);
|
||||
|
||||
if (is_dir) {
|
||||
rights_print_line(mask & NW_RIGHT_S, 0, "You have Supervisor Rights to Directory.", 'S');
|
||||
rights_print_line(mask & NW_RIGHT_R, 1, "May Read from File.", 'R');
|
||||
rights_print_line(mask & NW_RIGHT_W, 1, "May Write to File.", 'W');
|
||||
rights_print_line(mask & NW_RIGHT_C, 0, "May Create Subdirectories and Files.", 'C');
|
||||
rights_print_line(mask & NW_RIGHT_E, 0, "May Erase Directory.", 'E');
|
||||
rights_print_line(mask & NW_RIGHT_M, 0, "May Modify Directory.", 'M');
|
||||
rights_print_line(mask & NW_RIGHT_F, 0, "May Scan for Files.", 'F');
|
||||
rights_print_line(mask & NW_RIGHT_A, 0, "May Change Access Control.", 'A');
|
||||
|
||||
fprintf(stdout, "\n");
|
||||
fprintf(stdout, " * Has no effect on directory.\n\n");
|
||||
fprintf(stdout, " Entries in Directory May Inherit [%s] rights.\n", mstr);
|
||||
if (mask == 0xff)
|
||||
fprintf(stdout, " You have ALL RIGHTS to Directory Entry.\n");
|
||||
} else {
|
||||
rights_print_line(mask & NW_RIGHT_S, 0, "You have Supervisor Rights to File.", 'S');
|
||||
rights_print_line(mask & NW_RIGHT_R, 0, "May Read from File.", 'R');
|
||||
rights_print_line(mask & NW_RIGHT_W, 0, "May Write to File.", 'W');
|
||||
rights_print_line(mask & NW_RIGHT_C, 1, "May Create Subdirectories and Files.", 'C');
|
||||
rights_print_line(mask & NW_RIGHT_E, 0, "May Erase File.", 'E');
|
||||
rights_print_line(mask & NW_RIGHT_M, 0, "May Modify File.", 'M');
|
||||
rights_print_line(mask & NW_RIGHT_F, 0, "May Scan for File.", 'F');
|
||||
rights_print_line(mask & NW_RIGHT_A, 0, "May Change Access Control.", 'A');
|
||||
|
||||
fprintf(stdout, "\n");
|
||||
fprintf(stdout, " * Create is necessary to salvage a file that has been deleted.\n\n");
|
||||
if (mask == 0xff)
|
||||
fprintf(stdout, " You have ALL RIGHTS to Directory Entry.\n");
|
||||
}
|
||||
}
|
||||
|
||||
int func_rights(int argc, char *argv[], int mode)
|
||||
{
|
||||
char *path = ".";
|
||||
uint8 mask = 0;
|
||||
int is_dir;
|
||||
|
||||
(void)mode;
|
||||
|
||||
if (argc > 2) {
|
||||
rights_usage();
|
||||
return(1);
|
||||
}
|
||||
|
||||
if (argc == 2) {
|
||||
if (rights_is_help(argv[1])) {
|
||||
rights_usage();
|
||||
return(0);
|
||||
}
|
||||
path = argv[1];
|
||||
}
|
||||
|
||||
is_dir = rights_path_is_dir(path);
|
||||
|
||||
if (rights_effective_mask(path, is_dir, &mask)) {
|
||||
fprintf(stdout, "Specified path not locatable.\n");
|
||||
return(1);
|
||||
}
|
||||
|
||||
rights_display(path, is_dir, mask);
|
||||
return(0);
|
||||
}
|
||||
4
teste.c
4
teste.c
@@ -22,11 +22,11 @@ int main()
|
||||
close(fd);
|
||||
_chmod(fn, 1, _chmod(fn, 0) | 0x80 );
|
||||
stat(fn, &stbuff);
|
||||
printf("Filesize <20>ber stat =%ld\n", stbuff.st_size);
|
||||
printf("Filesize <20>ber stat =%ld\n", stbuff.st_size);
|
||||
fd = open(fn, O_RDWR | O_BINARY |O_DENYNONE);
|
||||
|
||||
offset = lseek(fd, 0L, SEEK_END);
|
||||
printf("Filesize <20>ber lseek =%ld\n", offset);
|
||||
printf("Filesize <20>ber lseek =%ld\n", offset);
|
||||
write(fd, buff, strlen(buff));
|
||||
|
||||
lseek(fd, 0L, SEEK_SET);
|
||||
|
||||
Reference in New Issue
Block a user