dosutils: align Novell-compatible tests and stage NCOPY work
Update the DOS utilities and test suite with the current Novell comparison state. Validated/updated tool behavior: - improve CREATOR output by showing Novell-style attribute and rights masks - extend FLAGDIR handling with old NCP22 directory attribute read/write fallback paths - expand NDIR Novell-style formatting, filtering, /SUB handling, date output, DI/RI attribute display and richer metadata collection - adjust REVOKE output/grammar, recursive /SUBDIRECTORIES behavior and trustee update/delete paths to better match Novell tools - adjust SLIST header/output behavior for logged-in and logged-out cases - update README status to reflect the currently green/tested tools Test-suite changes: - add/refresh Novell comparison tests for CREATOR, NDIR, REVOKE and SLIST - update NCOPY tests and collection scripts for the current investigation state - refresh per-tool README files and top-level test documentation - keep MAP documented as still separately open NCOPY: - add the current NCOPY implementation and experimental NCP74/server-side-copy scaffolding - build ncopy.c so it stays compile-tested - keep NCOPY disabled in the NET multicall dispatch for now because the server-side-copy/open-handle path is still unsafe and needs further analysis Build: - include ncopy.c in the DOS utility build - drop the temporary MARS_DOSUTILS_VERSION define wiring from CMake
This commit is contained in:
304
flagdir.c
304
flagdir.c
@@ -3,6 +3,7 @@
|
||||
#include "net.h"
|
||||
#include "c32ncp.h"
|
||||
#include <dos.h>
|
||||
#include <direct.h>
|
||||
|
||||
#define FD_NWFA_H 0x00000002UL
|
||||
#define FD_NWFA_SY 0x00000004UL
|
||||
@@ -11,6 +12,8 @@
|
||||
#define FD_NWFA_DI 0x00040000UL
|
||||
|
||||
#define FD_DIR_BITS (FD_NWFA_H | FD_NWFA_SY | FD_NWFA_P | FD_NWFA_RI | FD_NWFA_DI)
|
||||
#define FD_DM_ATTRIBUTES 0x00000002UL
|
||||
|
||||
|
||||
#ifndef _A_RDONLY
|
||||
#define _A_RDONLY 0x01
|
||||
@@ -28,6 +31,223 @@
|
||||
#define _A_ARCH 0x20
|
||||
#endif
|
||||
|
||||
|
||||
static void fd_put_dword_lh(uint8 *p, uint32 v)
|
||||
{
|
||||
p[0] = (uint8)(v & 0xff);
|
||||
p[1] = (uint8)((v >> 8) & 0xff);
|
||||
p[2] = (uint8)((v >> 16) & 0xff);
|
||||
p[3] = (uint8)((v >> 24) & 0xff);
|
||||
}
|
||||
|
||||
static uint32 fd_get_dword_lh(uint8 *p)
|
||||
{
|
||||
return((uint32)p[0] |
|
||||
((uint32)p[1] << 8) |
|
||||
((uint32)p[2] << 16) |
|
||||
((uint32)p[3] << 24));
|
||||
}
|
||||
|
||||
static int fd_copy_ncp22_name(uint8 *dst, char *src, uint8 *len_out)
|
||||
{
|
||||
char tmp[260];
|
||||
int len;
|
||||
|
||||
if (!dst || !len_out)
|
||||
return(-1);
|
||||
if (!src)
|
||||
src = "";
|
||||
|
||||
tool_upcopy(tmp, src, sizeof(tmp));
|
||||
if (strchr(tmp, '\\') || strchr(tmp, '/') || strchr(tmp, ':'))
|
||||
return(-1);
|
||||
|
||||
len = strlen(tmp);
|
||||
if (len < 1 || len > 12)
|
||||
return(-1);
|
||||
|
||||
memcpy(dst, tmp, len);
|
||||
*len_out = (uint8)len;
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int fd_ncp22_1e_obtain_attrs(char *name, uint32 *attrs)
|
||||
{
|
||||
struct {
|
||||
uint16 len;
|
||||
uint8 func;
|
||||
uint8 dirhandle;
|
||||
uint8 search_attributes;
|
||||
uint8 searchsequence[4];
|
||||
uint8 namlen;
|
||||
uint8 name[12];
|
||||
} req;
|
||||
struct {
|
||||
uint16 len;
|
||||
uint8 data[128];
|
||||
} repl;
|
||||
uint8 connid = 0;
|
||||
uint8 dhandle = 0;
|
||||
uint8 namlen = 0;
|
||||
|
||||
if (tool_current_dhandle(&connid, &dhandle))
|
||||
return(-1);
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
memset(&repl, 0, sizeof(repl));
|
||||
|
||||
if (fd_copy_ncp22_name(req.name, name, &namlen))
|
||||
return(-1);
|
||||
|
||||
req.func = 0x1e; /* Scan directory */
|
||||
req.dirhandle = dhandle;
|
||||
req.search_attributes = 0x16; /* hidden/system/subdir */
|
||||
U32_TO_BE32(0xffffffffUL, req.searchsequence);
|
||||
req.namlen = namlen;
|
||||
req.len = (uint16)(1 + 1 + 1 + 4 + 1 + namlen);
|
||||
repl.len = sizeof(repl.data);
|
||||
|
||||
neterrno = Net_Call(0xE200, &req, &repl);
|
||||
if (neterrno)
|
||||
return(-1);
|
||||
|
||||
/* NCP22/30 Scan Directory returns attributes at offset 8. */
|
||||
if (attrs)
|
||||
*attrs = fd_get_dword_lh(repl.data + 8);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int fd_ncp22_25_modify_attrs(char *name, uint32 attrs)
|
||||
{
|
||||
struct {
|
||||
uint16 len;
|
||||
uint8 func;
|
||||
uint8 dirhandle;
|
||||
uint8 search_attributes;
|
||||
uint8 searchsequence[4];
|
||||
uint8 change_bits[4];
|
||||
uint8 subdir[4];
|
||||
uint8 attributes[4];
|
||||
uint8 uniqueid;
|
||||
uint8 flags;
|
||||
uint8 namespace;
|
||||
uint8 namlen;
|
||||
uint8 name[12];
|
||||
uint8 rest[104];
|
||||
} req;
|
||||
struct {
|
||||
uint16 len;
|
||||
} repl;
|
||||
uint8 connid = 0;
|
||||
uint8 dhandle = 0;
|
||||
|
||||
if (tool_current_dhandle(&connid, &dhandle))
|
||||
return(-1);
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
memset(&repl, 0, sizeof(repl));
|
||||
|
||||
req.func = 0x25; /* Set directory/file information */
|
||||
req.dirhandle = dhandle;
|
||||
req.search_attributes = 0x16; /* hidden/system/subdir */
|
||||
U32_TO_BE32(0xffffffffUL, req.searchsequence);
|
||||
U32_TO_32(FD_DM_ATTRIBUTES, req.change_bits);
|
||||
fd_put_dword_lh(req.attributes, attrs);
|
||||
|
||||
if (fd_copy_ncp22_name(req.name, name, &req.namlen))
|
||||
return(-1);
|
||||
|
||||
req.len = sizeof(req) - sizeof(req.len);
|
||||
|
||||
neterrno = Net_Call(0xE200, &req, &repl);
|
||||
if (neterrno)
|
||||
return(-1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static char *fd_last_sep(char *s)
|
||||
{
|
||||
char *last = NULL;
|
||||
char *p;
|
||||
|
||||
for (p = s; *p; p++) {
|
||||
if (*p == '\\' || *p == '/' || *p == ':')
|
||||
last = p;
|
||||
}
|
||||
|
||||
return(last);
|
||||
}
|
||||
|
||||
static void fd_split_pattern(char *pattern, char *parent, int parent_size,
|
||||
char *leaf, int leaf_size)
|
||||
{
|
||||
char temp[260];
|
||||
char *sep;
|
||||
int plen;
|
||||
|
||||
parent[0] = '\0';
|
||||
leaf[0] = '\0';
|
||||
|
||||
strmaxcpy(temp, pattern, sizeof(temp) - 1);
|
||||
sep = fd_last_sep(temp);
|
||||
|
||||
if (!sep) {
|
||||
strmaxcpy(leaf, temp, leaf_size - 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (*(sep + 1))
|
||||
strmaxcpy(leaf, sep + 1, leaf_size - 1);
|
||||
else
|
||||
strmaxcpy(leaf, "*.*", leaf_size - 1);
|
||||
|
||||
plen = (int)(sep - temp);
|
||||
if (*sep == ':' && (*(sep + 1) == '\\' || *(sep + 1) == '/'))
|
||||
plen += 2;
|
||||
else if (*sep == ':' || *sep == '\\' || *sep == '/')
|
||||
plen += 1;
|
||||
|
||||
if (plen >= parent_size)
|
||||
plen = parent_size - 1;
|
||||
|
||||
memcpy(parent, temp, plen);
|
||||
parent[plen] = '\0';
|
||||
}
|
||||
|
||||
static int fd_enter_parent(char *pattern, char *leaf, int leaf_size,
|
||||
char *oldcwd, int oldcwd_size)
|
||||
{
|
||||
char parent[260];
|
||||
|
||||
oldcwd[0] = '\0';
|
||||
fd_split_pattern(pattern, parent, sizeof(parent), leaf, leaf_size);
|
||||
|
||||
if (!leaf[0])
|
||||
strmaxcpy(leaf, "*.*", leaf_size - 1);
|
||||
|
||||
if (!parent[0])
|
||||
return(0);
|
||||
|
||||
if (!getcwd(oldcwd, oldcwd_size))
|
||||
oldcwd[0] = '\0';
|
||||
|
||||
if (chdir(parent)) {
|
||||
if (oldcwd[0])
|
||||
chdir(oldcwd);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void fd_leave_parent(char *oldcwd)
|
||||
{
|
||||
if (oldcwd[0])
|
||||
chdir(oldcwd);
|
||||
}
|
||||
|
||||
static int fd_current_display_path(uint8 dhandle, char *out, int max)
|
||||
{
|
||||
char path[260];
|
||||
@@ -97,7 +317,7 @@ static void fd_print_attrs(uint32 attrs)
|
||||
int any = 0;
|
||||
|
||||
if (!(attrs & FD_DIR_BITS)) {
|
||||
fprintf(stdout, "Normal\n");
|
||||
fprintf(stdout, "Normal \n");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -122,20 +342,50 @@ static void fd_print_attrs(uint32 attrs)
|
||||
any = 1;
|
||||
}
|
||||
|
||||
fprintf(stdout, "\n");
|
||||
fprintf(stdout, " \n");
|
||||
}
|
||||
|
||||
static void fd_display_header(char *path)
|
||||
{
|
||||
char up[260];
|
||||
char prefix[90];
|
||||
|
||||
tool_upcopy(up, path, sizeof(up));
|
||||
char prefix[260];
|
||||
char header[300];
|
||||
int len;
|
||||
char *p;
|
||||
|
||||
if (tool_current_prefix(prefix, sizeof(prefix)))
|
||||
prefix[0] = '\0';
|
||||
|
||||
fprintf(stdout, "%s%s \n", prefix, up);
|
||||
tool_upcopy(up, path, sizeof(up));
|
||||
|
||||
/* fd_process_one() enters the parent directory before displaying the
|
||||
* entry. Use the current NetWare prefix plus the leaf/relative name,
|
||||
* not the original F:\... argument, otherwise the drive-qualified path is
|
||||
* appended to the already changed current directory.
|
||||
*/
|
||||
strmaxcpy(header, prefix, sizeof(header) - 1);
|
||||
if (!tool_is_current_path(up) && up[0]) {
|
||||
len = strlen(header);
|
||||
if (len > 0 && header[len - 1] != ':' &&
|
||||
header[len - 1] != '\\' && header[len - 1] != '/') {
|
||||
if (len < (int)sizeof(header) - 1) {
|
||||
header[len++] = '\\';
|
||||
header[len] = '\0';
|
||||
}
|
||||
}
|
||||
if ((int)(strlen(header) + strlen(up)) < (int)sizeof(header) - 1)
|
||||
strcat(header, up);
|
||||
}
|
||||
|
||||
/* Novell FLAGDIR displays SERVER/SYS: and uses / as path separator in
|
||||
* the header line.
|
||||
*/
|
||||
for (p = header; *p; p++) {
|
||||
if (*p == '\\')
|
||||
*p = '/';
|
||||
}
|
||||
|
||||
fprintf(stdout, "%s \n", header);
|
||||
}
|
||||
|
||||
static void fd_display_row(char *name, uint32 attrs)
|
||||
@@ -169,6 +419,9 @@ static int fd_is_directory(char *path)
|
||||
|
||||
static int fd_obtain(char *path, uint8 dhandle, uint32 *attrs)
|
||||
{
|
||||
if (!fd_ncp22_1e_obtain_attrs(path, attrs))
|
||||
return(0);
|
||||
|
||||
if (c32_ncp87_obtain_rim_attributes(path, (uint16)dhandle,
|
||||
attrs, NULL, NULL, NULL) == 0)
|
||||
return(0);
|
||||
@@ -177,6 +430,9 @@ static int fd_obtain(char *path, uint8 dhandle, uint32 *attrs)
|
||||
|
||||
static int fd_modify(char *path, uint8 dhandle, uint32 attrs)
|
||||
{
|
||||
if (!fd_ncp22_25_modify_attrs(path, attrs))
|
||||
return(0);
|
||||
|
||||
if (c32_ncp87_modify_dos_attributes(path, (uint16)dhandle, attrs,
|
||||
NULL, NULL, NULL) == 0)
|
||||
return(0);
|
||||
@@ -187,16 +443,35 @@ static int fd_process_one(char *path, char *display_path, uint8 dhandle,
|
||||
uint32 setbits, uint32 clearbits,
|
||||
int have_change, int show_header)
|
||||
{
|
||||
char leaf[260];
|
||||
char oldcwd[260];
|
||||
char *ncp_path;
|
||||
char *check_path;
|
||||
uint32 attrs;
|
||||
uint32 newattrs;
|
||||
int rc = 0;
|
||||
|
||||
if (!fd_is_directory(path)) {
|
||||
fprintf(stderr, "Directory %s not found.\n", path);
|
||||
return(1);
|
||||
oldcwd[0] = '\0';
|
||||
leaf[0] = '\0';
|
||||
|
||||
if (!tool_is_current_path(path)) {
|
||||
if (fd_enter_parent(path, leaf, sizeof(leaf), oldcwd, sizeof(oldcwd))) {
|
||||
fprintf(stderr, "Directory %s not found.\n", path);
|
||||
return(1);
|
||||
}
|
||||
check_path = leaf;
|
||||
ncp_path = leaf;
|
||||
} else {
|
||||
check_path = path;
|
||||
ncp_path = "";
|
||||
}
|
||||
|
||||
ncp_path = tool_is_current_path(path) ? "" : path;
|
||||
if (!fd_is_directory(check_path)) {
|
||||
fd_display_header(ncp_path[0] ? ncp_path : path);
|
||||
fprintf(stdout, "Directory %s not found.", ncp_path[0] ? ncp_path : path);
|
||||
fd_leave_parent(oldcwd);
|
||||
return(1);
|
||||
}
|
||||
|
||||
if (fd_obtain(ncp_path, dhandle, &attrs)) {
|
||||
if (tool_is_current_path(path) && display_path && !display_path[0] &&
|
||||
@@ -204,6 +479,7 @@ static int fd_process_one(char *path, char *display_path, uint8 dhandle,
|
||||
attrs = 0;
|
||||
} else {
|
||||
fprintf(stderr, "Unable to get directory attributes.\n");
|
||||
fd_leave_parent(oldcwd);
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
@@ -213,6 +489,7 @@ static int fd_process_one(char *path, char *display_path, uint8 dhandle,
|
||||
if (newattrs != attrs) {
|
||||
if (fd_modify(ncp_path, dhandle, newattrs)) {
|
||||
fprintf(stderr, "Unable to change attributes.\n");
|
||||
fd_leave_parent(oldcwd);
|
||||
return(1);
|
||||
}
|
||||
attrs = newattrs;
|
||||
@@ -221,11 +498,12 @@ static int fd_process_one(char *path, char *display_path, uint8 dhandle,
|
||||
}
|
||||
|
||||
if (show_header)
|
||||
fd_display(display_path, attrs);
|
||||
fd_display(ncp_path[0] ? ncp_path : display_path, attrs);
|
||||
else
|
||||
fd_display_row(display_path, attrs);
|
||||
fd_display_row(ncp_path[0] ? ncp_path : display_path, attrs);
|
||||
|
||||
return(0);
|
||||
fd_leave_parent(oldcwd);
|
||||
return(rc);
|
||||
}
|
||||
|
||||
static int fd_process_wild(char *spec, uint8 dhandle,
|
||||
|
||||
Reference in New Issue
Block a user