diff --git a/CMakeLists.txt b/CMakeLists.txt index 00a42ad..101a7b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,12 +10,6 @@ option(MAINTAINER_BUILD "Enable maintainer-only DOS tool helpers and diagnostics" OFF) -if(DEFINED MARS_NWE_VERSION_BASE) - set(MARS_DOSUTILS_VERSION "${MARS_NWE_VERSION_BASE}") -else() - set(MARS_DOSUTILS_VERSION "0.99") -endif() - set(MARS_DOSUTILS_LEGACY_NET_EXE "${CMAKE_CURRENT_SOURCE_DIR}/netold.exe" CACHE FILEPATH "Legacy/pre-Client32 DOS net.exe used by default for legacy command names" @@ -55,6 +49,7 @@ set(MARS_DOSUTILS_NEW_ONLY_TOOLS ndir creator whoami + ncopy ) if(MARS_NWE_BUILD_DOSUTILS) @@ -83,6 +78,7 @@ if(MARS_NWE_BUILD_DOSUTILS) capture.c creator.c whoami.c + ncopy.c ) add_custom_command( @@ -104,7 +100,7 @@ if(MARS_NWE_BUILD_DOSUTILS) set(obj "${CMAKE_CURRENT_BINARY_DIR}/${obj_name}.obj") list(APPEND DOSUTILS_OBJECTS "${obj}") - set(DOSUTILS_WCL_DEFS -dMARS_DOSUTILS_VERSION=\"${MARS_DOSUTILS_VERSION}\") + set(DOSUTILS_WCL_DEFS) if(MAINTAINER_BUILD) list(APPEND DOSUTILS_WCL_DEFS -dMAINTAINER_BUILD) endif() diff --git a/README.md b/README.md index af035ca..cdd4025 100644 --- a/README.md +++ b/README.md @@ -11,27 +11,37 @@ The command dispatcher lives in `net.c`, and the install rules deploy the same b ## Current status -The tree is a modernization of the historical mars_nwe DOS utilities. It still keeps the original Borland-era style and APIs where useful, but now also has an Open Watcom/CMake build path and working DOS Client32 support for the FLAG-family and trustee/right tools. +The tree is a modernization of the historical mars_nwe DOS utilities. It still +keeps the original Borland-era style and APIs where useful, but now also has an +Open Watcom/CMake build path and working DOS Client32 support for the +Novell-compatible comparison tests. -Validated recently: +Recently validated with byte-for-byte Novell comparison tests or equivalent +readback tests: -- `FLAG` file attribute read/modify through DOS Client32 -- `FLAGDIR` directory attribute read/modify through DOS Client32 -- `RIGHTS` effective-rights display through Client32 NCP87 -- `GRANT` trustee assignment for users and groups -- `REVOKE` trustee-right removal for users and groups -- `REMOVE` trustee deletion for users and groups -- Novell-tool comparison for `FLAG`, including `ALL`, `N`, `RO`, `RW`, high bits, and display layout -- Novell-tool comparison for `FLAGDIR`, including `Normal`, `System`, `Hidden`, `DeleteInhibit`, `Purge`, `RenameInhibit`, and combined attributes -- Novell-tool comparison for `RIGHTS`, `GRANT`, `REVOKE`, and `REMOVE` -- CMake/Open Watcom build using binary-directory object files, so `.obj`/`.o` files are no longer written into the source tree +- `CREATOR` metadata/xattr readback, including readable attribute and rights-mask output +- `FLAG` file attribute display and modification, including high NetWare bits such as DI/RI +- `FLAGDIR` directory attribute display and modification +- `GRANT` trustee assignment matrix and normal-user rights readback +- `NDIR` directory listing, filters, `/DATES`, `/RIGHTS`, `/SUB`, DI/RI display and user-context readback +- `REMOVE` trustee deletion matrix and normal-user rights readback +- `REVOKE` trustee-right removal matrix and normal-user rights readback +- `RIGHTS` effective-rights display +- `SLIST` server listing while logged in and while logged out from `SYS:LOGIN` +- `WHOAMI` option/output comparison +- maintainer baseline for `LOGIN`/`LOGOUT` + +The DOS test suite is documented in [`test/README.md`](test/README.md). Each +feature directory also contains its own README with run instructions and result +layout. Still to validate or continue: -- DOSX/VLM/NETX fallback behavior for `FLAG` and `FLAGDIR` -- More complex `FLAGDIR` paths beyond the simple mapped-directory cases already tested +- full `PUBLIC\MAP` comparison against Novell `MAP` beyond the current MAP baseline/semantics test +- DOSX/VLM/NETX fallback behavior where relevant - OS/2 requester/tool behavior -- Additional Novell-like utilities such as `NDIR`, `PURGE`, and `SALVAGE` +- additional Novell-like utilities such as `PURGE` and `SALVAGE` +- further MARS-NWE server-side NCP endpoint coverage where newer tests expose gaps ## Features diff --git a/c32ncp.c b/c32ncp.c index d910f05..e594a71 100644 --- a/c32ncp.c +++ b/c32ncp.c @@ -241,6 +241,200 @@ int c32_get_ncp_handle(uint16 *handle_lo, uint16 *handle_hi) return(0); } + +static void c32_copy_open_reply_to_handle6(C32_NWFILE_HANDLE6 *dst, + const uint8 *src) +{ + /* + * NCP 74 File Server Copy and NCP 66 Close File both take a six-byte + * server file handle. Client32's NCP87 Open/Create reply supplies that + * six-byte handle at the start of the first reply fragment; the following + * bytes are OpenCreateAction and Reserved. + * + * The previous patch only copied four bytes and zero-filled h[4..5]. That + * is enough to create a visible zero-length target file, but it is not the + * handle that NCP74/NCP66 own. The bad close leaves Client32/MARS seeing + * the target as still open, so the fallback DOS/requester open reports + * "File in use during a file open" for every file. + */ + memset(dst->h, 0, sizeof(dst->h)); + memcpy(dst->h, src, 6); +} + +int c32_ncp87_open_create_file(const char *path_name, + uint16 dir_handle, + uint8 open_create_mode, + uint32 create_attrs, + uint16 desired_access, + uint16 search_attrs, + C32_NWFILE_HANDLE6 *handle_out, + uint32 *file_size_out, + uint8 *open_create_action_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[0x180]; + uint8 rep1[0x40]; + uint8 rawout[32]; + uint16 raw_ret_ax, raw_ret_dx; + uint16 actual_lo; + UI path_len; + int rc; + + if (handle_out) + memset(handle_out, 0, sizeof(*handle_out)); + if (file_size_out) *file_size_out = 0; + if (open_create_action_out) *open_create_action_out = 0; + if (actual_out) *actual_out = 0; + if (handle_lo_out) *handle_lo_out = 0; + if (handle_hi_out) *handle_hi_out = 0; + + if (!path_name || !handle_out) + return(1); + + rc = c32_get_ncp_handle(&handle_lo, &handle_hi); + if (rc) + return(10 + rc); + + /* + * NCP 87 subfunction 1: Open/Create File or Subdirectory. + * + * Request payload after the NCP87 subfunction byte: + * byte NameSpace (0 = DOS) + * byte OpenCreateMode (OPEN/TRUNCATE/CREATE bits) + * word SearchAttributes (Lo-Hi) + * dword ReturnInfoMask (Lo-Hi) + * dword CreateAttributes (Lo-Hi) + * word DesiredAccessRights (Lo-Hi) + * NWHandlePathStruct + * + * Existing C32_NCP87_Raw5_Probe users in this file send the subfunction + * header as fragment 0 and the NWHandlePathStruct as fragment 1. + */ + memset(hdr, 0, sizeof(hdr)); + hdr[0] = 1; /* NCP87 subfunction 1 */ + hdr[1] = 0; /* DOS namespace */ + hdr[2] = open_create_mode; + c32_put_word_lh(hdr + 3, search_attrs); + c32_put_dword_lh(hdr + 5, 0x00000FFFUL); /* RIM_ALL, keeps size handy */ + c32_put_dword_lh(hdr + 9, create_attrs); + c32_put_word_lh(hdr + 13, desired_access); + + 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, 15, + 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); + + c32_copy_open_reply_to_handle6(handle_out, rep0 + 0); + + if (open_create_action_out) + *open_create_action_out = rep0[6]; + + /* NetWareInfoStruct follows FileHandle[6]/OpenCreateAction/Reserved. */ + if (file_size_out) + *file_size_out = c32_get_dword_lh(rep0 + 8 + 10); + + return(0); +} + +int c32_ncp74_file_server_copy(const C32_NWFILE_HANDLE6 *src, + const C32_NWFILE_HANDLE6 *dst, + uint32 src_offset, + uint32 dst_offset, + uint32 count, + uint32 *copied_out) +{ + struct { + uint16 len; + uint8 reserved; + uint8 src_handle[6]; + uint8 dst_handle[6]; + uint8 src_offset[4]; + uint8 dst_offset[4]; + uint8 count[4]; + } req; + struct { + uint16 len; + uint8 copied[4]; + } repl; + + if (copied_out) + *copied_out = 0; + if (!src || !dst) + return(1); + + memset(&req, 0, sizeof(req)); + memset(&repl, 0, sizeof(repl)); + + memcpy(req.src_handle, src->h, 6); + memcpy(req.dst_handle, dst->h, 6); + c32_put_dword_hl(req.src_offset, src_offset); + c32_put_dword_hl(req.dst_offset, dst_offset); + c32_put_dword_hl(req.count, count); + req.len = 1 + 6 + 6 + 4 + 4 + 4; + repl.len = 4; + + neterrno = Net_Call(0xF24A, &req, &repl); + if (neterrno) + return(-neterrno); + + if (copied_out) + *copied_out = c32_get_dword_hl(repl.copied); + + return(0); +} + +int c32_ncp66_close_file(const C32_NWFILE_HANDLE6 *handle) +{ + struct { + uint8 len; + uint8 reserved; + uint8 handle[6]; + } req; + struct { uint8 len; } repl; + + if (!handle) + return(1); + + memset(&req, 0, sizeof(req)); + memset(&repl, 0, sizeof(repl)); + + memcpy(req.handle, handle->h, 6); + req.len = 1 + 6; + repl.len = 0; + + neterrno = Net_Call(0xF242, &req, &repl); + if (neterrno) + return(-neterrno); + + return(0); +} + + int c32_ncp87_obtain_rim_attributes(const char *name, uint16 dir_handle, uint32 *attr_out, diff --git a/c32ncp.h b/c32ncp.h index 4b9ef7e..71340ae 100644 --- a/c32ncp.h +++ b/c32ncp.h @@ -4,6 +4,44 @@ #define C32NCP_H int c32_get_ncp_handle(uint16 *handle_lo, uint16 *handle_hi); + +typedef struct c32_nwfile_handle6 { + uint8 h[6]; +} C32_NWFILE_HANDLE6; + +#define C32_OC_MODE_OPEN 0x01 +#define C32_OC_MODE_TRUNCATE 0x02 +#define C32_OC_MODE_CREATE 0x08 + +#define C32_DAR_READ 0x0001 +#define C32_DAR_WRITE 0x0002 +#define C32_DAR_DENY_READ 0x0004 +#define C32_DAR_DENY_WRITE 0x0008 +#define C32_DAR_COMPAT 0x0010 + +int c32_ncp87_open_create_file(const char *path_name, + uint16 dir_handle, + uint8 open_create_mode, + uint32 create_attrs, + uint16 desired_access, + uint16 search_attrs, + C32_NWFILE_HANDLE6 *handle_out, + uint32 *file_size_out, + uint8 *open_create_action_out, + uint16 *actual_out, + uint16 *handle_lo_out, + uint16 *handle_hi_out); + +int c32_ncp74_file_server_copy(const C32_NWFILE_HANDLE6 *src, + const C32_NWFILE_HANDLE6 *dst, + uint32 src_offset, + uint32 dst_offset, + uint32 count, + uint32 *copied_out); + +int c32_ncp66_close_file(const C32_NWFILE_HANDLE6 *handle); + + int c32_ncp87_obtain_rim_attributes(const char *name, uint16 dir_handle, uint32 *attr_out, diff --git a/creator.c b/creator.c index 45a2515..03953d8 100644 --- a/creator.c +++ b/creator.c @@ -21,6 +21,34 @@ #define BINDERY_USER 0x0001 #define BINDERY_GROUP 0x0002 +#ifndef _A_RDONLY +#define _A_RDONLY 0x01 +#endif +#ifndef _A_HIDDEN +#define _A_HIDDEN 0x02 +#endif +#ifndef _A_SYSTEM +#define _A_SYSTEM 0x04 +#endif +#ifndef _A_SUBDIR +#define _A_SUBDIR 0x10 +#endif +#ifndef _A_ARCH +#define _A_ARCH 0x20 +#endif + +#define CREATOR_ATTR_RENAME_INHIBIT 0x00020000UL +#define CREATOR_ATTR_DELETE_INHIBIT 0x00040000UL + +#define CREATOR_RIGHT_S 0x01 +#define CREATOR_RIGHT_R 0x02 +#define CREATOR_RIGHT_W 0x04 +#define CREATOR_RIGHT_C 0x08 +#define CREATOR_RIGHT_E 0x10 +#define CREATOR_RIGHT_M 0x20 +#define CREATOR_RIGHT_F 0x40 +#define CREATOR_RIGHT_A 0x80 + static void creator_usage(void) { fprintf(stdout, "Usage:\n"); @@ -366,10 +394,53 @@ static int set_info(uint8 dhandle, char *name, uint32 bits, return(0); } + +static void creator_attr_string(uint32 attr, char *out) +{ + out[0] = '['; + out[1] = 'R'; + out[2] = (attr & _A_RDONLY) ? 'o' : 'w'; + out[3] = '-'; + out[4] = (attr & _A_ARCH) ? 'A' : '-'; + out[5] = '-'; + out[6] = (attr & _A_HIDDEN) ? 'H' : '-'; + if (attr & _A_SYSTEM) { + out[7] = 'S'; + out[8] = 'y'; + } else { + out[7] = '-'; + out[8] = '-'; + } + memset(out + 9, '-', 8); + out[17] = (attr & CREATOR_ATTR_DELETE_INHIBIT) ? 'D' : '-'; + out[18] = (attr & CREATOR_ATTR_RENAME_INHIBIT) ? 'R' : '-'; + out[19] = ']'; + out[20] = '\0'; +} + +static void creator_rights_string(uint16 rights, char *out) +{ + uint8 old = (uint8)rights; + + out[0] = '['; + out[1] = (old & CREATOR_RIGHT_S) ? 'S' : '-'; + out[2] = (old & CREATOR_RIGHT_R) ? 'R' : '-'; + out[3] = (old & CREATOR_RIGHT_W) ? 'W' : '-'; + out[4] = (old & CREATOR_RIGHT_C) ? 'C' : '-'; + out[5] = (old & CREATOR_RIGHT_E) ? 'E' : '-'; + out[6] = (old & CREATOR_RIGHT_M) ? 'M' : '-'; + out[7] = (old & CREATOR_RIGHT_F) ? 'F' : '-'; + out[8] = (old & CREATOR_RIGHT_A) ? 'A' : '-'; + out[9] = ']'; + out[10] = '\0'; +} + static int show_info(char *name, uint8 dhandle) { C32_NDIR_INFO info; int rc; + char attr_text[24]; + char rights_text[12]; memset(&info, 0, sizeof(info)); rc = c32_ncp87_obtain_ndir_info(tool_is_current_path(name) ? "" : name, @@ -381,8 +452,11 @@ static int show_info(char *name, uint8 dhandle) return(rc); } + creator_attr_string(info.attributes, attr_text); + creator_rights_string(info.inherited_rights, rights_text); + fprintf(stdout, "File: %s\n", name); - fprintf(stdout, "Attributes: 0x%08lX\n", (unsigned long)info.attributes); + fprintf(stdout, "Attributes: %s (0x%08lX)\n", attr_text, (unsigned long)info.attributes); fprintf(stdout, "Create: "); print_dos_date(info.creation_date); fprintf(stdout, " "); print_dos_time(info.creation_time); fprintf(stdout, " creator=0x%08lX\n", (unsigned long)info.creator_id); @@ -393,7 +467,7 @@ static int show_info(char *name, uint8 dhandle) fprintf(stdout, " "); print_dos_time(info.archive_time); fprintf(stdout, " archiver=0x%08lX\n", (unsigned long)info.archiver_id); fprintf(stdout, "Access date: "); print_dos_date(info.last_access_date); - fprintf(stdout, "\nRights mask: 0x%04X\n", (unsigned)info.inherited_rights); + fprintf(stdout, "\nRights mask: %s (0x%04X)\n", rights_text, (unsigned)info.inherited_rights); return(0); } diff --git a/flagdir.c b/flagdir.c index 2e5436f..9dc52c4 100644 --- a/flagdir.c +++ b/flagdir.c @@ -3,6 +3,7 @@ #include "net.h" #include "c32ncp.h" #include +#include #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, diff --git a/ncopy.c b/ncopy.c new file mode 100644 index 0000000..b4ef4cc --- /dev/null +++ b/ncopy.c @@ -0,0 +1,1696 @@ +/* ncopy.c - Novell NCOPY-like DOS utility, first implementation + * + * Prefer NetWare server-side copy through the DOS requester + * NWFileServerFileCopy wrapper (INT 21h AH=F3). A small DOS read/write path + * remains as fallback for non-NetWare paths or requester failures. + */ + +#include "net.h" +#include "c32ncp.h" +#include +#include +#include +#include +#include +#include +#include + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +#ifndef _A_NORMAL +#define _A_NORMAL 0x00 +#endif +#ifndef _A_RDONLY +#define _A_RDONLY 0x01 +#endif +#ifndef _A_HIDDEN +#define _A_HIDDEN 0x02 +#endif +#ifndef _A_SYSTEM +#define _A_SYSTEM 0x04 +#endif +#ifndef _A_SUBDIR +#define _A_SUBDIR 0x10 +#endif +#ifndef _A_ARCH +#define _A_ARCH 0x20 +#endif + +#define NCOPY_OPT_S 0x0001 +#define NCOPY_OPT_E 0x0002 +#define NCOPY_OPT_V 0x0004 +#define NCOPY_OPT_A 0x0008 +#define NCOPY_OPT_M 0x0010 +#define NCOPY_OPT_I 0x0020 +#define NCOPY_OPT_C 0x0040 +#define NCOPY_OPT_F 0x0080 + +#define NCOPY_BUF_SIZE 2048 + +/* Keep DGROUP small: net.exe is a DOS multicall binary. */ +static char ncopy_buffer[NCOPY_BUF_SIZE]; + +static char ncopy_last_from[260]; +static char ncopy_last_to[260]; +static int ncopy_have_group = 0; + + +static int ncopy_debug_enabled(void) +{ + char *p = getenv("NCOPYDBG"); + return(p && *p && *p != '0'); +} + +static int ncopy_ncp74_enabled(void) +{ + char *p = getenv("NCOPYNCP74"); + return(p && *p && *p != '0'); +} + +static void ncopy_debug_msg(char *msg) +{ + if (ncopy_debug_enabled()) + fprintf(stdout, "NCOPYDBG: %s\n", msg); +} + +static void ncopy_debug_rc(char *step, int rc) +{ + if (ncopy_debug_enabled()) + fprintf(stdout, "NCOPYDBG: %s rc=%d neterrno=%d errno=%d\n", + step, rc, neterrno, errno); +} + +static void ncopy_debug_ul(char *step, unsigned long value) +{ + if (ncopy_debug_enabled()) + fprintf(stdout, "NCOPYDBG: %s=%lu\n", step, value); +} + + +static void ncopy_debug_handle6(char *step, C32_NWFILE_HANDLE6 *h) +{ + if (ncopy_debug_enabled() && h) { + fprintf(stdout, + "NCOPYDBG: %s %02x %02x %02x %02x %02x %02x\n", + step, + (unsigned)h->h[0], (unsigned)h->h[1], + (unsigned)h->h[2], (unsigned)h->h[3], + (unsigned)h->h[4], (unsigned)h->h[5]); + } +} + +static void ncopy_debug_handle_bytes(char *step, unsigned char *h) +{ + if (ncopy_debug_enabled() && h) { + fprintf(stdout, + "NCOPYDBG: %s %02x %02x %02x %02x %02x %02x\n", + step, + (unsigned)h[0], (unsigned)h[1], + (unsigned)h[2], (unsigned)h[3], + (unsigned)h[4], (unsigned)h[5]); + } +} + +static int ncopy_handle6_is_zero(unsigned char *h) +{ + int i; + + if (!h) + return(1); + for (i = 0; i < 6; ++i) + if (h[i]) + return(0); + return(1); +} + +static void ncopy_debug_bytes(char *step, unsigned char *p, unsigned len) +{ + unsigned i; + + if (!ncopy_debug_enabled() || !p) + return; + fprintf(stdout, "NCOPYDBG: %s", step); + if (len > 32) + len = 32; + for (i = 0; i < len; ++i) + fprintf(stdout, " %02x", (unsigned)p[i]); + fprintf(stdout, "\n"); +} + + +static void ncopy_usage(void) +{ + fprintf(stdout, "Usage: NCOPY [path] [[TO] path] [option]\n"); + fprintf(stdout, "Options\n"); + fprintf(stdout, "\t/s\tcopy subdirectories.\n"); + fprintf(stdout, "\t/s/e\tcopy subdirectories, including empty directories.\n"); + fprintf(stdout, "\t/f\tcopy sparse files.\n"); + fprintf(stdout, "\t/h (/?) display this usage message.\n"); + fprintf(stdout, "\t/a\tcopy files with archive bit set.\n"); + fprintf(stdout, "\t/m\tcopy files with archive bit set, clear the bit.\n"); + fprintf(stdout, "\t/i\tinform when non-DOS file information will be lost.\n"); + fprintf(stdout, "\t/c\tcopy only DOS information.\n"); + fprintf(stdout, "\t/v\tverify with a read after every write.\n"); +} + +static int ncopy_is_dir(char *path) +{ + struct stat st; + if (!path || !*path) + return(0); + if (stat(path, &st) == 0 && (st.st_mode & S_IFDIR)) + return(1); + return(0); +} + +static int ncopy_has_wildcards(char *s) +{ + return(s && (strchr(s, '*') || strchr(s, '?'))); +} + +static void ncopy_parent_pattern(char *dir, char *pat, char *path) +{ + tool_parent_pattern(dir, pat, path, 260, 260); + if (!dir[0]) + strmaxcpy(dir, ".", 259); + if (!pat[0]) + strmaxcpy(pat, "*.*", 259); +} + +static void ncopy_add_slash(char *dst, int max) +{ + int len = strlen(dst); + if (len > 0 && len < max - 1) { + if (dst[len - 1] != '\\' && dst[len - 1] != ':' && dst[len - 1] != '/') { + dst[len++] = '\\'; + dst[len] = '\0'; + } + } +} + +static void ncopy_join(char *out, char *dir, char *name, int max) +{ + strmaxcpy(out, dir ? dir : "", max - 1); + ncopy_add_slash(out, max); + strmaxcpy(out + strlen(out), name ? name : "", max - strlen(out) - 1); +} + +static void ncopy_basename(char *out, char *path, int max) +{ + char tmp[260]; + char *p; + strmaxcpy(tmp, path ? path : "", sizeof(tmp) - 1); + p = strrchr(tmp, '\\'); + if (!p) + p = strrchr(tmp, '/'); + if (!p) + p = strrchr(tmp, ':'); + if (p) + strmaxcpy(out, p + 1, max - 1); + else + strmaxcpy(out, tmp, max - 1); +} + + +static void ncopy_display_path(char *out, char *path, int max) +{ + char tmp[260]; + char *p; + int first_sep = 1; + int pos = 0; + + if (!out || max <= 0) + return; + out[0] = '\0'; + if (!path) + path = ""; + + /* The Novell tool prints server/volume style paths. The test volume is + * SYS on server MARS; make DOS drive-qualified paths comparable without + * asking the requester for name-space details on every line. */ + p = path; + if (p[0] && p[1] == ':') { + strmaxcpy(out, "MARS/SYS:", max - 1); + pos = strlen(out); + p += 2; + } + + while (*p && pos < max - 1) { + if (*p == '\\' || *p == '/') { + if (first_sep) { + out[pos++] = '\\'; + first_sep = 0; + } else { + out[pos++] = '/'; + } + while (p[1] == '\\' || p[1] == '/') + p++; + } else { + out[pos++] = *p; + } + p++; + } + out[pos] = '\0'; +} + +static void ncopy_reset_output_group(void) +{ + ncopy_last_from[0] = '\0'; + ncopy_last_to[0] = '\0'; + ncopy_have_group = 0; +} + +static void ncopy_print_group(char *srcdir, char *dstdir) +{ + char from[260]; + char to[260]; + + ncopy_display_path(from, srcdir, sizeof(from)); + ncopy_display_path(to, dstdir, sizeof(to)); + + if (ncopy_have_group && !strcmp(ncopy_last_from, from) && + !strcmp(ncopy_last_to, to)) + return; + + if (ncopy_have_group) + fprintf(stdout, "\n\n"); + + fprintf(stdout, "From %s\n", from); + fprintf(stdout, "To %s\n", to); + strmaxcpy(ncopy_last_from, from, sizeof(ncopy_last_from) - 1); + strmaxcpy(ncopy_last_to, to, sizeof(ncopy_last_to) - 1); + ncopy_have_group = 1; +} + + +static void ncopy_finish_output_groups(void) +{ + if (ncopy_have_group) + fprintf(stdout, "\n"); +} + +static void ncopy_print_file_map(char *srcname, char *dstname) +{ + fprintf(stdout, " %-13.13s to %-13.13s\n", srcname, dstname); +} + +static int ncopy_make_dir(char *path) +{ + if (ncopy_is_dir(path)) + return(0); +#ifdef __WATCOMC__ + if (mkdir(path) == 0) + return(0); +#else + if (mkdir(path, 0777) == 0) + return(0); +#endif + if (ncopy_is_dir(path)) + return(0); + return(-1); +} + +static int ncopy_same_path(char *a, char *b) +{ + char aa[260]; + char bb[260]; + tool_upcopy(aa, a, sizeof(aa)); + tool_upcopy(bb, b, sizeof(bb)); + return(strcmp(aa, bb) == 0); +} + +static int ncopy_verify_file(char *src, char *dst) +{ + int s, d; + unsigned sr, dr; + char b2[NCOPY_BUF_SIZE]; + + s = open(src, O_RDONLY | O_BINARY); + if (s < 0) + return(-1); + d = open(dst, O_RDONLY | O_BINARY); + if (d < 0) { + close(s); + return(-1); + } + + for (;;) { + if (_dos_read(s, ncopy_buffer, NCOPY_BUF_SIZE, &sr)) { + close(s); close(d); return(-1); + } + if (_dos_read(d, b2, NCOPY_BUF_SIZE, &dr)) { + close(s); close(d); return(-1); + } + if (sr != dr || memcmp(ncopy_buffer, b2, sr)) { + close(s); close(d); return(-1); + } + if (sr == 0) + break; + } + + close(s); + close(d); + return(0); +} + + +static int ncopy_split_dir_name(char *path, char *dir, char *name); +static int ncopy_alloc_parent_handle(char *path, uint8 *handle, int *allocated); +static void ncopy_close_ncp_file(uint8 nwhandle[6]); +static int ncopy_ncp74_copy_chunk(uint8 src_handle[6], uint8 dst_handle[6], + uint32 src_offset, uint32 dst_offset, + uint32 count, uint32 *copied); + +static int ncopy_copy_data_c32_server(char *src, char *dst, unsigned long size) +{ + C32_NWFILE_HANDLE6 sh; + C32_NWFILE_HANDLE6 dh; + C32_NDIR_INFO sinfo; + char srcdir[260]; + char srcname[80]; + char dstdir[260]; + char dstname[80]; + uint8 src_dhandle = 0; + uint8 dst_dhandle = 0; + int src_allocated = 0; + int dst_allocated = 0; + uint32 create_attrs = 0; + uint32 off = 0; + uint32 todo; + uint32 done; + int src_open = 0; + int dst_open = 0; + int rc; + + memset(&sh, 0, sizeof(sh)); + memset(&dh, 0, sizeof(dh)); + memset(&sinfo, 0, sizeof(sinfo)); + + if (ncopy_split_dir_name(src, srcdir, srcname) || + ncopy_split_dir_name(dst, dstdir, dstname)) + return(-1); + + ncopy_debug_msg("c32-ncp87/ncp74 server-copy begin"); + ncopy_debug_ul("c32-server-copy size", size); + + if (ncopy_alloc_parent_handle(src, &src_dhandle, &src_allocated)) { + ncopy_debug_msg("c32-server-copy failed source parent handle"); + return(-1); + } + + if (ncopy_alloc_parent_handle(dst, &dst_dhandle, &dst_allocated)) { + if (src_allocated) + dealloc_dir_handle(src_dhandle); + ncopy_debug_msg("c32-server-copy failed dest parent handle"); + return(-1); + } + + /* Best effort: use source NetWare attributes when creating the target. + * If this fails, still try the server-side copy with normal attributes; + * ncopy_copy_one() will restore DOS date/time and low DOS attributes. */ + if (!c32_ncp87_obtain_ndir_info(srcname, src_dhandle, + &sinfo, NULL, NULL, NULL)) { + create_attrs = sinfo.attributes; + ncopy_debug_ul("c32-server-copy source attrs", create_attrs); + } + + _dos_setfileattr(dst, _A_NORMAL); + + rc = c32_ncp87_open_create_file(srcname, + src_dhandle, + C32_OC_MODE_OPEN, + 0, + C32_DAR_READ | C32_DAR_DENY_WRITE, + 0x8006, + &sh, + NULL, + NULL, + NULL, + NULL, + NULL); + if (rc) { + ncopy_debug_rc("c32 open source NCP87/01", rc); + goto fail; + } + src_open = 1; + ncopy_debug_handle6("c32 source handle", &sh); + + rc = c32_ncp87_open_create_file(dstname, + dst_dhandle, + C32_OC_MODE_OPEN | + C32_OC_MODE_TRUNCATE | + C32_OC_MODE_CREATE, + create_attrs, + C32_DAR_WRITE | C32_DAR_DENY_READ, + 0x8006, + &dh, + NULL, + NULL, + NULL, + NULL, + NULL); + if (rc) { + ncopy_debug_rc("c32 open/create dest NCP87/01", rc); + goto fail; + } + dst_open = 1; + ncopy_debug_handle6("c32 dest handle", &dh); + + if (dst_allocated) { + dealloc_dir_handle(dst_dhandle); + dst_allocated = 0; + } + if (src_allocated) { + dealloc_dir_handle(src_dhandle); + src_allocated = 0; + } + + if (ncopy_handle6_is_zero(sh.h) || ncopy_handle6_is_zero(dh.h)) { + ncopy_debug_msg("c32 server-copy has zero handle; falling back"); + if (!ncopy_handle6_is_zero(dh.h)) + ncopy_close_ncp_file(dh.h); + if (!ncopy_handle6_is_zero(sh.h)) + ncopy_close_ncp_file(sh.h); + return(-1); + } + + while (off < (uint32)size) { + todo = (uint32)size - off; + if (todo > 0x8000UL) + todo = 0x8000UL; + + done = 0; + ncopy_debug_ul("c32-server-copy offset", off); + ncopy_debug_ul("c32-server-copy todo", todo); + + rc = c32_ncp74_file_server_copy(&sh, &dh, off, off, todo, &done); + if (rc || done == 0) { + ncopy_debug_rc("c32 copy chunk NCP74", rc ? rc : -1); + goto fail; + } + + ncopy_debug_ul("c32-server-copy copied", done); + off += done; + } + + if (dst_open) + c32_ncp66_close_file(&dh); + if (src_open) + c32_ncp66_close_file(&sh); + + ncopy_debug_msg("c32-ncp87/ncp74 server-copy success"); + return(0); + +fail: + if (dst_open) + c32_ncp66_close_file(&dh); + if (src_open) + c32_ncp66_close_file(&sh); + if (dst_allocated) + dealloc_dir_handle(dst_dhandle); + if (src_allocated) + dealloc_dir_handle(src_dhandle); + ncopy_debug_msg("c32-ncp87/ncp74 server-copy failed"); + return(-1); +} + +static uint32 ncopy_get_dword_be(uint8 *p) +{ + return(GET_BE32(p)); +} + + +static void ncopy_put_word_lh(uint8 *p, uint16 v) +{ + p[0] = (uint8)(v & 0xff); + p[1] = (uint8)((v >> 8) & 0xff); +} + +static void ncopy_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 ncopy_get_dword_lh(uint8 *p) +{ + return((uint32)p[0] | ((uint32)p[1] << 8) | + ((uint32)p[2] << 16) | ((uint32)p[3] << 24)); +} + +static unsigned ncopy_build_nw_handle_path(uint8 *buf, uint8 dhandle, + const char *name) +{ + uint8 *p; + unsigned namelen; + + memset(buf, 0, 320); + /* INT 21h AX=F257 uses the old 87.x HandlePath layout, as already + * verified in FLAG: + * byte 0 short directory handle + * bytes 1..4 directory base, little endian dword, zero for short handle + * byte 5 dirstyle, 0 = short directory handle + * byte 6 component count + * then length-prefixed path components + * + * v6 accidentally used the Client32 raw-fragment layout + * 00 ... + * which made MARS ignore the temporary parent handle and resolve the full + * path from SYS:. That is why nw.log still showed components + * TCOPY/SRC/A.TXT instead of only A.TXT under the temp handle. + */ + buf[0] = dhandle; + ncopy_put_dword_lh(buf + 1, 0); + buf[5] = 0; /* dirstyle = short directory handle */ + buf[6] = 1; /* one path component */ + + p = buf + 7; + namelen = name ? strlen(name) : 0; + if (namelen > 255) + namelen = 255; + *p++ = (uint8)namelen; + if (namelen) { + memcpy(p, name, namelen); + p += namelen; + } + return((unsigned)(p - buf)); +} + +static int ncopy_open_create_ncp87_direct(char *path, + uint8 open_create_mode, + uint32 create_attrs, + uint16 desired_access, + uint16 search_attrs, + uint8 nwhandle[6], + unsigned long *size_out) +{ + char dir[260]; + char name[80]; + uint8 dhandle = 0; + int allocated = 0; + unsigned path_len; + struct { + uint16 len; + uint8 subfunc; + uint8 namespace_id; + uint8 open_create_mode; + uint8 search_attrs[2]; + uint8 return_info_mask[4]; + uint8 create_attrs[4]; + uint8 desired_access[2]; + uint8 nwpath[320]; + } req; + struct { + uint16 len; + uint8 handle[6]; + uint8 action; + uint8 reserved; + uint8 info[256]; + } repl; + + if (size_out) + *size_out = 0; + if (!nwhandle || ncopy_split_dir_name(path, dir, name)) + return(-1); + if (!name[0] || strlen(name) > 79) + return(-1); + + if (ncopy_alloc_parent_handle(path, &dhandle, &allocated)) + return(-1); + + memset(&req, 0, sizeof(req)); + memset(&repl, 0, sizeof(repl)); + + req.subfunc = 0x01; /* NCP 87/01 Open/Create File or Subdirectory */ + req.namespace_id = 0; /* DOS namespace */ + req.open_create_mode = open_create_mode; + ncopy_put_word_lh(req.search_attrs, search_attrs); + ncopy_put_dword_lh(req.return_info_mask, 0x00000fffUL); + ncopy_put_dword_lh(req.create_attrs, create_attrs); + ncopy_put_word_lh(req.desired_access, desired_access); + path_len = ncopy_build_nw_handle_path(req.nwpath, dhandle, name); + /* INT 21h AX=F257 uses the same request layout as the working FLAG + * code: a 16-bit length prefix followed by the NCP 87 subfunction. + * The v5 one-byte length made MARS see namespace_id (0x00) as ufunc. */ + req.len = (uint16)(1 + 1 + 1 + 2 + 4 + 4 + 2 + path_len); + repl.len = (uint16)(sizeof(repl) - sizeof(repl.len)); + + ncopy_debug_ul("direct NCP87/01 mode", open_create_mode); + ncopy_debug_ul("direct NCP87/01 access", desired_access); + + neterrno = Net_Call(0xF257, &req, &repl); + + /* v12 diagnostic: on Client32/MARS the server visibly executes + * 0x57/01 and allocates a file handle, but the Net_Call reply buffer + * still contains only its preset length and zero payload. Dump both + * buffers after the call before we try to interpret anything. Some + * requesters use in-place buffers for selected F2xx calls. */ + ncopy_debug_ul("direct NCP87 after-call neterrno", neterrno); + ncopy_debug_ul("direct NCP87 reply len field", repl.len); + ncopy_debug_bytes("direct NCP87 reply raw", (unsigned char *)&repl, 48); + ncopy_debug_ul("direct NCP87 request len field", req.len); + ncopy_debug_bytes("direct NCP87 request raw after", (unsigned char *)&req, 48); + + if (allocated) + dealloc_dir_handle(dhandle); + + if (neterrno) { + ncopy_debug_rc("direct open/create NCP 0x57/01", -1); + return(-1); + } + + /* Safety/debug version: do not call NCP74 unless we have a non-zero + * handle. The previous zero-handle NCP74 path can make Client32 retry + * until the workstation appears frozen. */ + memset(nwhandle, 0, 6); + memcpy(nwhandle, repl.handle, 4); + ncopy_debug_handle_bytes("direct NCP87 handle from reply", nwhandle); + + if (ncopy_handle6_is_zero(nwhandle)) { + memset(nwhandle, 0, 6); + memcpy(nwhandle, ((unsigned char *)&req) + 2, 4); + ncopy_debug_handle_bytes("direct NCP87 handle candidate from request", nwhandle); + if (!ncopy_handle6_is_zero(nwhandle)) { + ncopy_debug_msg("direct NCP87 non-zero in-place candidate seen, still not trusted; skip NCP74"); + memset(nwhandle, 0, 6); + } + } + + if (ncopy_handle6_is_zero(nwhandle)) { + ncopy_debug_msg("direct NCP87 returned zero handle; skip NCP74 and fall back"); + return(-1); + } + + if (size_out) + *size_out = ncopy_get_dword_lh(repl.info + 10); + + ncopy_debug_rc("direct open/create NCP 0x57/01", 0); + ncopy_debug_msg("direct NCP87 handle returned"); + return(0); +} + +static int ncopy_copy_data_direct_ncp87(char *src, char *dst, unsigned long size) +{ + uint8 sh[6]; + uint8 dh[6]; + uint32 off = 0; + uint32 todo; + uint32 done; + C32_NDIR_INFO sinfo; + char srcdir[260], srcname[80]; + uint8 src_dhandle = 0; + int src_allocated = 0; + uint32 create_attrs = 0; + + memset(sh, 0, sizeof(sh)); + memset(dh, 0, sizeof(dh)); + memset(&sinfo, 0, sizeof(sinfo)); + + ncopy_debug_msg("direct old-NCP87/NCP74 server-copy begin"); + ncopy_debug_ul("direct server-copy size", size); + + if (!ncopy_split_dir_name(src, srcdir, srcname) && + !ncopy_alloc_parent_handle(src, &src_dhandle, &src_allocated)) { + if (!c32_ncp87_obtain_ndir_info(srcname, src_dhandle, + &sinfo, NULL, NULL, NULL)) + create_attrs = sinfo.attributes; + if (src_allocated) + dealloc_dir_handle(src_dhandle); + } + + _dos_setfileattr(dst, _A_NORMAL); + + if (ncopy_open_create_ncp87_direct(src, + 0x01, /* open existing */ + 0, + 0x0011, /* read + compat/binary */ + 0x0007, /* hidden/system search */ + sh, + NULL)) + return(-1); + + if (ncopy_open_create_ncp87_direct(dst, + 0x0a, /* Novell-like replace/create */ + create_attrs, + 0x0013, /* read/write + compat */ + 0x0007, + dh, + NULL)) { + ncopy_close_ncp_file(sh); + return(-1); + } + + while (off < (uint32)size) { + todo = (uint32)size - off; + if (todo > 0x8000UL) + todo = 0x8000UL; + done = 0; + ncopy_debug_ul("direct server-copy offset", off); + ncopy_debug_ul("direct server-copy todo", todo); + if (ncopy_ncp74_copy_chunk(sh, dh, off, off, todo, &done) || done == 0) { + ncopy_close_ncp_file(dh); + ncopy_close_ncp_file(sh); + ncopy_debug_msg("direct old-NCP87/NCP74 server-copy failed copying chunk"); + return(-1); + } + off += done; + } + + ncopy_close_ncp_file(dh); + ncopy_close_ncp_file(sh); + ncopy_debug_msg("direct old-NCP87/NCP74 server-copy success"); + return(0); +} + +static int ncopy_split_dir_name(char *path, char *dir, char *name) +{ + char tmp[260]; + char *p; + + if (!path || !*path || !dir || !name) + return(-1); + + strmaxcpy(tmp, path, sizeof(tmp) - 1); + p = strrchr(tmp, '\\'); + if (!p) + p = strrchr(tmp, '/'); + if (!p) + p = strrchr(tmp, ':'); + + if (p) { + if (*p == ':') { + p[1] = '\0'; + strmaxcpy(dir, tmp, 259); + strmaxcpy(name, p + 1, 79); + } else { + *p++ = '\0'; + strmaxcpy(dir, tmp, 259); + strmaxcpy(name, p, 79); + } + } else { + strmaxcpy(dir, ".", 259); + strmaxcpy(name, tmp, 79); + } + + if (!name[0]) + return(-1); + return(0); +} + + +static void ncopy_ncp_relative_path(char *dst, char *src, int max) +{ + char up[260]; + char *p; + + if (!dst || max <= 0) + return; + dst[0] = '\0'; + + if (!src || !*src || tool_is_current_path(src)) + return; + + tool_upcopy(up, src, sizeof(up)); + p = up; + + /* Old directory-handle based NCPs expect a path relative to the current + * NetWare directory handle. Do not pass DOS drive-qualified paths such as + * F:\TCOPY\SRC to AllocTempDirHandle; strip the drive and leading slash + * first, the same way RIGHTS normalizes paths for NCP calls. + */ + if (p[0] && p[1] == ':') { + p += 2; + if (*p == '\\' || *p == '/') + p++; + } + while (*p == '\\' || *p == '/') + p++; + + strmaxcpy(dst, p, max - 1); +} + +static int ncopy_alloc_parent_handle(char *path, uint8 *handle, int *allocated) +{ + char dir[260]; + char ncpdir[260]; + char name[80]; + uint8 connid = 0; + uint8 curhandle = 0; + uint8 eff = 0; + int h; + + if (!handle || !allocated) + return(-1); + *handle = 0; + *allocated = 0; + + if (ncopy_split_dir_name(path, dir, name)) + return(-1); + + if (tool_current_dhandle(&connid, &curhandle)) + return(-1); + + ncopy_ncp_relative_path(ncpdir, dir, sizeof(ncpdir)); + if (!ncpdir[0] || tool_is_current_path(ncpdir) || !strcmp(ncpdir, ".")) { + *handle = curhandle; + ncopy_debug_rc("alloc parent current handle", 0); + return(0); + } + + h = alloc_temp_dir_handle(curhandle, ncpdir, 0, &eff); + if (h < 0) { + ncopy_debug_rc("alloc parent temp handle", -1); + return(-1); + } + + *handle = (uint8)h; + *allocated = 1; + ncopy_debug_rc("alloc parent temp handle", 0); + return(0); +} + +static int ncopy_open_ncp_file(char *path, uint8 access, uint8 nwhandle[6]) +{ + char dir[260]; + char name[80]; + uint8 dhandle = 0; + int allocated = 0; + int namelen; + struct { + uint16 len; + uint8 func; + uint8 dhandle; + uint8 attrib; + uint8 access; + uint8 namelen; + uint8 name[80]; + } req; + struct { + uint16 len; + uint8 handle[6]; + uint8 reserved[2]; + uint8 info[64]; + } repl; + + if (!nwhandle || ncopy_split_dir_name(path, dir, name)) + return(-1); + namelen = strlen(name); + if (namelen < 1 || namelen > 79) + return(-1); + + if (ncopy_alloc_parent_handle(path, &dhandle, &allocated)) + return(-1); + + memset(&req, 0, sizeof(req)); + memset(&repl, 0, sizeof(repl)); + req.func = 0x4c; /* Open File */ + req.dhandle = dhandle; + req.attrib = 0x06; /* hidden/system search */ + req.access = access; + req.namelen = (uint8)namelen; + memcpy(req.name, name, namelen); + req.len = (uint16)(1 + 1 + 1 + 1 + 1 + namelen); + repl.len = sizeof(repl) - sizeof(repl.len); + + neterrno = Net_Call(0xE200, &req, &repl); + if (allocated) + dealloc_dir_handle(dhandle); + if (neterrno) { + ncopy_debug_rc("open source NCP 0x4c", -1); + return(-1); + } + + memcpy(nwhandle, repl.handle, 6); + ncopy_debug_rc("open source NCP 0x4c", 0); + return(0); +} + +static int ncopy_create_ncp_file(char *path, uint8 attr, uint8 nwhandle[6]) +{ + char dir[260]; + char name[80]; + uint8 dhandle = 0; + int allocated = 0; + int namelen; + struct { + uint16 len; + uint8 func; + uint8 dhandle; + uint8 attr; + uint8 namelen; + uint8 name[80]; + } req; + struct { + uint16 len; + uint8 handle[6]; + uint8 reserved[2]; + uint8 info[64]; + } repl; + + if (!nwhandle || ncopy_split_dir_name(path, dir, name)) + return(-1); + namelen = strlen(name); + if (namelen < 1 || namelen > 79) + return(-1); + + if (ncopy_alloc_parent_handle(path, &dhandle, &allocated)) + return(-1); + + memset(&req, 0, sizeof(req)); + memset(&repl, 0, sizeof(repl)); + req.func = 0x43; /* Create File, overwrite */ + req.dhandle = dhandle; + req.attr = attr; + req.namelen = (uint8)namelen; + memcpy(req.name, name, namelen); + req.len = (uint16)(1 + 1 + 1 + 1 + namelen); + repl.len = sizeof(repl) - sizeof(repl.len); + + neterrno = Net_Call(0xE200, &req, &repl); + if (allocated) + dealloc_dir_handle(dhandle); + if (neterrno) { + ncopy_debug_rc("create dest NCP 0x43", -1); + return(-1); + } + + memcpy(nwhandle, repl.handle, 6); + ncopy_debug_rc("create dest NCP 0x43", 0); + return(0); +} + +static void ncopy_close_ncp_file(uint8 nwhandle[6]) +{ + struct { + uint16 len; + uint8 reserved; + uint8 handle[6]; + } req; + struct { uint16 len; } repl; + + if (!nwhandle || ncopy_handle6_is_zero(nwhandle)) { + ncopy_debug_msg("close file skipped for zero handle"); + return; + } + memset(&req, 0, sizeof(req)); + memset(&repl, 0, sizeof(repl)); + memcpy(req.handle, nwhandle, 6); + ncopy_debug_handle_bytes("close file handle", nwhandle); + req.len = 1 + 6; + repl.len = 0; + neterrno = Net_Call(0xF242, &req, &repl); + ncopy_debug_rc("close file NCP 0x42", neterrno ? -1 : 0); +} + +static int ncopy_ncp74_copy_chunk(uint8 src_handle[6], uint8 dst_handle[6], + uint32 src_offset, uint32 dst_offset, + uint32 count, uint32 *copied) +{ + struct { + uint16 len; + uint8 reserved; + uint8 src_handle[6]; + uint8 dst_handle[6]; + uint8 src_offset[4]; + uint8 dst_offset[4]; + uint8 count[4]; + } req; + struct { + uint16 len; + uint8 copied[4]; + } repl; + + if (copied) + *copied = 0; + + if (ncopy_handle6_is_zero(src_handle) || ncopy_handle6_is_zero(dst_handle)) { + ncopy_debug_msg("copy chunk NCP 0x4a skipped for zero handle"); + return(-1); + } + + memset(&req, 0, sizeof(req)); + memset(&repl, 0, sizeof(repl)); + memcpy(req.src_handle, src_handle, 6); + memcpy(req.dst_handle, dst_handle, 6); + ncopy_debug_handle_bytes("copy src handle", src_handle); + ncopy_debug_handle_bytes("copy dst handle", dst_handle); + U32_TO_BE32(src_offset, req.src_offset); + U32_TO_BE32(dst_offset, req.dst_offset); + U32_TO_BE32(count, req.count); + req.len = 1 + 6 + 6 + 4 + 4 + 4; + repl.len = 4; + + neterrno = Net_Call(0xF24A, &req, &repl); + if (neterrno) { + ncopy_debug_rc("copy chunk NCP 0x4a", -1); + return(-1); + } + + if (copied) + *copied = ncopy_get_dword_be(repl.copied); + ncopy_debug_rc("copy chunk NCP 0x4a", 0); + if (copied) + ncopy_debug_ul("copy chunk copied", (unsigned long)*copied); + return(0); +} + +static int ncopy_copy_data_server(char *src, char *dst, unsigned long size) +{ + uint8 sh[6]; + uint8 dh[6]; + uint32 off = 0; + uint32 todo; + uint32 done; + + memset(sh, 0, sizeof(sh)); + memset(dh, 0, sizeof(dh)); + + ncopy_debug_msg("server-copy begin"); + ncopy_debug_ul("server-copy size", size); + + _dos_setfileattr(dst, _A_NORMAL); + if (ncopy_open_ncp_file(src, 0x11, sh)) { /* read, binary */ + ncopy_debug_msg("server-copy failed opening source"); + return(-1); + } + if (ncopy_create_ncp_file(dst, 0, dh)) { + ncopy_debug_msg("server-copy failed creating destination"); + ncopy_close_ncp_file(sh); + return(-1); + } + + while (off < (uint32)size) { + todo = (uint32)size - off; + if (todo > 0x8000UL) + todo = 0x8000UL; + ncopy_debug_ul("server-copy offset", off); + ncopy_debug_ul("server-copy todo", todo); + if (ncopy_ncp74_copy_chunk(sh, dh, off, off, todo, &done) || done == 0) { + ncopy_debug_msg("server-copy failed copying chunk"); + ncopy_close_ncp_file(dh); + ncopy_close_ncp_file(sh); + return(-1); + } + off += done; + } + + ncopy_close_ncp_file(dh); + ncopy_close_ncp_file(sh); + ncopy_debug_msg("server-copy success"); + return(0); +} + + +/* + * NetWare DOS requester FileServerFileCopy wrapper. + * + * The MARS-NWE admin Pascal API (admin/nwtp/nwfile.pas) exposes this as + * INT 21h AH=F3 with ES:DI pointing to a request containing DOS file handles + * (word, lo-hi) and long offsets/counts. Use this instead of manually + * building raw NCP 0x4A requests; Client32/requester owns the real NetWare + * file handle mapping. + */ +typedef struct ncopy_f3_req { + uint16 src_handle; + uint16 dst_handle; + uint32 src_offset; + uint32 dst_offset; + uint32 count; +} NCOPY_F3_REQ; + +static int ncopy_int21_f3_copy_chunk(int src_handle, int dst_handle, + uint32 src_offset, uint32 dst_offset, + uint32 count, uint32 *copied) +{ + NCOPY_F3_REQ req; + union REGS regs; + struct SREGS sregs; + uint32 c1; + uint32 c2; + + if (copied) + *copied = 0; + + memset(&req, 0, sizeof(req)); + memset(®s, 0, sizeof(regs)); + segread(&sregs); + + req.src_handle = (uint16)src_handle; + req.dst_handle = (uint16)dst_handle; + req.src_offset = src_offset; + req.dst_offset = dst_offset; + req.count = count; + + regs.h.ah = 0xF3; + sregs.es = FP_SEG(&req); + regs.x.di = FP_OFF(&req); + int86x(0x21, ®s, ®s, &sregs); + + if (ncopy_debug_enabled()) { + fprintf(stdout, + "NCOPYDBG: int21 ah=f3 al=%u ax=%u cx=%u dx=%u srcfh=%u dstfh=%u count=%lu\n", + (unsigned)regs.h.al, (unsigned)regs.x.ax, + (unsigned)regs.x.cx, (unsigned)regs.x.dx, + (unsigned)src_handle, (unsigned)dst_handle, + (unsigned long)count); + } + + if (regs.h.al != 0) { + if (errno == 0) + errno = regs.h.al; + return(-1); + } + + c1 = ((uint32)regs.x.cx) | ((uint32)regs.x.dx << 16); + c2 = ((uint32)regs.x.dx) | ((uint32)regs.x.cx << 16); + if (c1 > 0 && c1 <= count) + *copied = c1; + else if (c2 > 0 && c2 <= count) + *copied = c2; + else + *copied = count; + + return(0); +} + +static int ncopy_copy_data_requester(char *src, char *dst, unsigned long size) +{ + int s; + int d; + uint32 off = 0; + uint32 todo; + uint32 done; + + ncopy_debug_msg("requester-copy begin"); + ncopy_debug_ul("requester-copy size", size); + + _dos_setfileattr(dst, _A_NORMAL); + s = open(src, O_RDONLY | O_BINARY); + if (s < 0) { + ncopy_debug_rc("requester open source", -1); + return(-1); + } + + d = open(dst, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, S_IREAD | S_IWRITE); + if (d < 0) { + ncopy_debug_rc("requester create dest", -1); + close(s); + return(-1); + } + + ncopy_debug_rc("requester open source", s); + ncopy_debug_rc("requester create dest", d); + + while (off < (uint32)size) { + todo = (uint32)size - off; + if (todo > 0x7000UL) + todo = 0x7000UL; + done = 0; + ncopy_debug_ul("requester-copy offset", off); + ncopy_debug_ul("requester-copy todo", todo); + if (ncopy_int21_f3_copy_chunk(s, d, off, off, todo, &done) || done == 0) { + ncopy_debug_msg("requester-copy failed copying chunk"); + close(d); + close(s); + return(-1); + } + ncopy_debug_ul("requester-copy copied", done); + off += done; + } + + close(d); + close(s); + ncopy_debug_msg("requester-copy success"); + return(0); +} + +static int ncopy_copy_data(char *src, char *dst, unsigned long size) +{ + int s, d; + unsigned got, put; + + /* + * Do not run the direct F257 Open/Create path by default. On Client32/MARS + * it executes server-side NCP 87/01 and allocates a server file handle, but + * the DOS Net_Call reply buffer does not receive that handle. Without a + * returned handle we cannot safely issue NCP 74 or NCP 66 Close; repeated + * test runs leak server file handles and can make the requester retry/hang. + * + * Keep the path available only for explicit diagnostics: + * SET NCOPYNCP74=1 + */ + if (ncopy_ncp74_enabled()) { + if (!ncopy_copy_data_direct_ncp87(src, dst, size)) + return(0); + ncopy_debug_msg("direct NCP87/NCP74 server-copy failed; trying INT21 AH=F3 requester copy"); + } else { + ncopy_debug_msg("direct NCP87/NCP74 server-copy disabled; set NCOPYNCP74=1 to probe it"); + } + + if (!ncopy_copy_data_requester(src, dst, size)) + return(0); + + ncopy_debug_msg("requester-copy failed; falling back to DOS read/write"); + + s = open(src, O_RDONLY | O_BINARY); + if (s < 0) { + fprintf(stdout, " Failed to open the %s file.\n", src); + return(-1); + } + + _dos_setfileattr(dst, _A_NORMAL); + d = open(dst, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IREAD | S_IWRITE); + if (d < 0) { + close(s); + fprintf(stdout, " Failed to create file.\n"); + return(-1); + } + + for (;;) { + if (_dos_read(s, ncopy_buffer, NCOPY_BUF_SIZE, &got)) { + close(s); close(d); + fprintf(stdout, " Failure occurred while reading the file.\n"); + return(-1); + } + if (got == 0) + break; + if (_dos_write(d, ncopy_buffer, got, &put) || put != got) { + close(s); close(d); + fprintf(stdout, " Failure occurred while writing the file.\n"); + return(-1); + } + } + + close(s); + close(d); + return(0); +} + + +static void ncopy_restore_netware_attrs(char *src, char *dst, unsigned fallback_attr) +{ + char srcdir[260]; + char srcname[80]; + char dstdir[260]; + char dstname[80]; + uint8 src_dhandle = 0; + uint8 dst_dhandle = 0; + int src_allocated = 0; + int dst_allocated = 0; + C32_NDIR_INFO sinfo; + uint32 attrs; + int rc; + + memset(&sinfo, 0, sizeof(sinfo)); + + if (ncopy_split_dir_name(src, srcdir, srcname) || + ncopy_split_dir_name(dst, dstdir, dstname)) + return; + + if (ncopy_alloc_parent_handle(src, &src_dhandle, &src_allocated)) + return; + + if (ncopy_alloc_parent_handle(dst, &dst_dhandle, &dst_allocated)) { + if (src_allocated) + dealloc_dir_handle(src_dhandle); + return; + } + + attrs = (uint32)(fallback_attr & (_A_RDONLY | _A_HIDDEN | + _A_SYSTEM | _A_ARCH)); + rc = c32_ncp87_obtain_ndir_info(srcname, src_dhandle, + &sinfo, NULL, NULL, NULL); + if (!rc) + attrs = sinfo.attributes; + + rc = c32_ncp87_modify_dos_attributes(dstname, dst_dhandle, attrs, + NULL, NULL, NULL); + ncopy_debug_rc("restore NetWare attrs NCP87/07", rc); + ncopy_debug_ul("restore NetWare attrs", attrs); + + if (dst_allocated) + dealloc_dir_handle(dst_dhandle); + if (src_allocated) + dealloc_dir_handle(src_dhandle); +} + +static int ncopy_copy_one(char *src, char *dst, struct find_t *ff, int options) +{ + unsigned attr; + int d; + char srcdir[260]; + char srcname[80]; + char dstdir[260]; + char dstname[80]; + + if (ncopy_same_path(src, dst)) { + fprintf(stdout, " The file will NOT be copied because the source and destination file names are the same.\n"); + return(-1); + } + + if ((options & (NCOPY_OPT_A | NCOPY_OPT_M)) && !(ff->attrib & _A_ARCH)) + return(1); + + if (ncopy_split_dir_name(src, srcdir, srcname)) { + strmaxcpy(srcdir, ".", sizeof(srcdir) - 1); + ncopy_basename(srcname, src, sizeof(srcname)); + } + if (ncopy_split_dir_name(dst, dstdir, dstname)) { + strmaxcpy(dstdir, ".", sizeof(dstdir) - 1); + ncopy_basename(dstname, dst, sizeof(dstname)); + } + + ncopy_print_group(srcdir, dstdir); + ncopy_print_file_map(srcname, dstname); + + if (ncopy_copy_data(src, dst, (unsigned long)ff->size)) + return(-1); + + d = open(dst, O_WRONLY | O_BINARY); + if (d >= 0) { + _dos_setftime(d, ff->wr_date, ff->wr_time); + close(d); + } else { + fprintf(stdout, " Failure setting destination file date and time.\n"); + } + + attr = ff->attrib & (_A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_ARCH); + if (_dos_setfileattr(dst, attr)) + fprintf(stdout, " Error setting file information.\n"); + + /* Preserve high NetWare DOS attributes such as Delete/Rename Inhibit. + * DOS setfileattr can only express the low DOS bits, which was the reason + * B.TXT ended up as [Ro-A--------------] instead of carrying DI/RI. */ + ncopy_restore_netware_attrs(src, dst, attr); + + if ((options & NCOPY_OPT_V) && ncopy_verify_file(src, dst)) + fprintf(stdout, " Error copying file.\n"); + + if (options & NCOPY_OPT_M) { + unsigned newattr = ff->attrib & ~_A_ARCH; + _dos_setfileattr(src, newattr & (_A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_ARCH)); + } + + return(0); +} + +static int ncopy_copy_pattern(char *srcdir, char *pattern, char *dstdir, + int options, int *copied, int *failed); + +static int ncopy_copy_subdirs(char *srcdir, char *dstdir, int options, + int *copied, int *failed) +{ + struct find_t ff; + char search[260]; + int rc; + + ncopy_join(search, srcdir, "*.*", sizeof(search)); + rc = _dos_findfirst(search, _A_NORMAL | _A_RDONLY | _A_HIDDEN | + _A_SYSTEM | _A_ARCH | _A_SUBDIR, &ff); + while (rc == 0) { + if ((ff.attrib & _A_SUBDIR) && !tool_is_dot_dir(ff.name)) { + char childsrc[260]; + char childdst[260]; + int before; + + ncopy_join(childsrc, srcdir, ff.name, sizeof(childsrc)); + ncopy_join(childdst, dstdir, ff.name, sizeof(childdst)); + + before = *copied; + ncopy_print_group(childsrc, childdst); + if (options & NCOPY_OPT_E) + ncopy_make_dir(childdst); + + ncopy_copy_pattern(childsrc, "*.*", childdst, options, copied, failed); + ncopy_copy_subdirs(childsrc, childdst, options, copied, failed); + + if (*copied > before) + ncopy_make_dir(childdst); + } + rc = _dos_findnext(&ff); + } + return(0); +} + +static int ncopy_copy_pattern(char *srcdir, char *pattern, char *dstdir, + int options, int *copied, int *failed) +{ + struct find_t ff; + char search[260]; + int rc; + int any = 0; + + ncopy_join(search, srcdir, pattern, sizeof(search)); + rc = _dos_findfirst(search, _A_NORMAL | _A_RDONLY | _A_HIDDEN | + _A_SYSTEM | _A_ARCH, &ff); + while (rc == 0) { + if (!(ff.attrib & _A_SUBDIR)) { + char src[260]; + char dst[260]; + int r; + any = 1; + ncopy_join(src, srcdir, ff.name, sizeof(src)); + ncopy_join(dst, dstdir, ff.name, sizeof(dst)); + if (ncopy_make_dir(dstdir)) { + fprintf(stdout, " Illegal destination.\n"); + return(-1); + } + r = ncopy_copy_one(src, dst, &ff, options); + if (r == 0) + (*copied)++; + else if (r < 0) + (*failed)++; + } + rc = _dos_findnext(&ff); + } + + if ((options & NCOPY_OPT_S) != 0) + ncopy_copy_subdirs(srcdir, dstdir, options, copied, failed); + + return(any ? 0 : 1); +} + +static int ncopy_copy_single(char *src, char *dstarg, int options, + int *copied, int *failed) +{ + struct find_t ff; + char dst[260]; + char base[80]; + int rc; + + rc = _dos_findfirst(src, _A_NORMAL | _A_RDONLY | _A_HIDDEN | + _A_SYSTEM | _A_ARCH, &ff); + if (rc) + return(1); + if (ff.attrib & _A_SUBDIR) + return(1); + + if (ncopy_is_dir(dstarg)) { + ncopy_basename(base, src, sizeof(base)); + ncopy_join(dst, dstarg, base, sizeof(dst)); + } else { + strmaxcpy(dst, dstarg, sizeof(dst) - 1); + } + + rc = ncopy_copy_one(src, dst, &ff, options); + if (rc == 0) + (*copied)++; + else if (rc < 0) + (*failed)++; + return(0); +} + +static void ncopy_summary(int copied, int failed) +{ + if (copied == 0) + fprintf(stdout, " No files copied.\n"); + else + fprintf(stdout, " %d file%s copied.\n", copied, copied == 1 ? "" : "s"); + if (failed) + fprintf(stdout, " %d file%s NOT copied.\n", failed, failed == 1 ? "" : "s"); +} + +static int ncopy_upper_char(int c) +{ + if (c >= 'a' && c <= 'z') + return(c - ('a' - 'A')); + return(c); +} + +static int ncopy_parse_option(char *s, int *options) +{ + char *p; + int c1; + int c2; + int c3; + + if (!s || !*s) + return(0); + + /* Novell NCOPY accepts case-insensitive options anywhere on the + * command line, including after the destination path: + * NCOPY SRC DST /V + * NCOPY SRC TO DST /S /E + * NCOPY /A SRC TO DST /S + * Keep this parser independent of shared helpers so DOS/Watcom argv + * strings such as lowercase /v are handled exactly here. */ + if (s[0] != '/' && s[0] != '-') + return(0); + + p = s; + while (*p == '/' || *p == '-') + p++; + + if (!*p) + return(-1); + + c1 = ncopy_upper_char((unsigned char)p[0]); + c2 = ncopy_upper_char((unsigned char)p[1]); + c3 = ncopy_upper_char((unsigned char)p[2]); + + if (c1 == '?' && p[1] == '\0') + return(2); + + if (c1 == 'H' && p[1] == '\0') + return(2); + + if (c1 == 'H' && c2 == 'E' && c3 == 'L' && + ncopy_upper_char((unsigned char)p[3]) == 'P' && p[4] == '\0') + return(2); + + if (c1 == 'S' && p[1] == '\0') { *options |= NCOPY_OPT_S; return(1); } + if (c1 == 'E' && p[1] == '\0') { *options |= NCOPY_OPT_E; return(1); } + if (c1 == 'V' && p[1] == '\0') { *options |= NCOPY_OPT_V; return(1); } + if (c1 == 'A' && p[1] == '\0') { *options |= NCOPY_OPT_A; return(1); } + if (c1 == 'M' && p[1] == '\0') { *options |= NCOPY_OPT_M | NCOPY_OPT_A; return(1); } + if (c1 == 'I' && p[1] == '\0') { *options |= NCOPY_OPT_I; return(1); } + if (c1 == 'C' && p[1] == '\0') { *options |= NCOPY_OPT_C; return(1); } + if (c1 == 'F' && p[1] == '\0') { *options |= NCOPY_OPT_F; return(1); } + + if (c1 == 'S' && c2 == '/' && c3 == 'E' && p[3] == '\0') { + *options |= NCOPY_OPT_S | NCOPY_OPT_E; + return(1); + } + + if (c1 == 'S' && c2 == 'E' && p[2] == '\0') { + *options |= NCOPY_OPT_S | NCOPY_OPT_E; + return(1); + } + + return(-1); +} + +static int ncopy_is_to_separator(char *s) +{ + return(s && tool_strsame(s, "TO")); +} + +int func_ncopy(int argc, char *argv[], int mode) +{ + char *src = NULL; + char *dst = NULL; + int options = 0; + int i; + int copied = 0; + int failed = 0; + int saw_to = 0; + int result; + char srcdir[260]; + char pat[260]; + + (void)mode; + + if (ncopy_debug_enabled()) { + fprintf(stdout, "NCOPYDBG: func_ncopy entered argc=%d\n", argc); + for (i = 0; i < argc; i++) + fprintf(stdout, "NCOPYDBG: argv[%d]=<%s>\n", + i, argv[i] ? argv[i] : ""); + } + + if (argc <= 1) { + ncopy_usage(); + return(1); + } + + for (i = 1; i < argc; i++) { + int opt = ncopy_parse_option(argv[i], &options); + + /* Options are legal before the source, between source and TO, and after + * the destination. Parse them before treating anything as a path. */ + if (opt == 2) { + ncopy_usage(); + return(0); + } + if (opt == 1) + continue; + if (opt < 0) { + ncopy_usage(); + return(1); + } + + /* TO is an optional, case-insensitive separator, not a required keyword. + * NCOPY SRC DST and NCOPY SRC TO DST are equivalent. */ + if (ncopy_is_to_separator(argv[i])) { + saw_to = 1; + continue; + } + + if (!src) + src = argv[i]; + else if (!dst) + dst = argv[i]; + else { + fprintf(stdout, "You cannot copy multiple files to a single file.\n"); + return(1); + } + } + + if (saw_to && !dst) { + ncopy_usage(); + return(1); + } + + if ((options & NCOPY_OPT_E) && !(options & NCOPY_OPT_S)) { + fprintf(stdout, "The /E parameter (copy empty directories) is only valid with the /S parameter (copy sub directories).\n"); + return(1); + } + + if (!src || !dst) { + ncopy_usage(); + return(1); + } + + ncopy_reset_output_group(); + + if (ncopy_has_wildcards(src) || (options & NCOPY_OPT_S)) { + if (!ncopy_is_dir(dst)) { + fprintf(stdout, " Illegal destination.\n"); + ncopy_summary(0, 0); + return(1); + } + if ((options & NCOPY_OPT_S) && ncopy_is_dir(src) && !ncopy_has_wildcards(src)) { + /* Novell NCOPY accepts a directory as the source root with /S. */ + strmaxcpy(srcdir, src, sizeof(srcdir) - 1); + strmaxcpy(pat, "*.*", sizeof(pat) - 1); + } else { + ncopy_parent_pattern(srcdir, pat, src); + } + result = ncopy_copy_pattern(srcdir, pat, dst, options, &copied, &failed); + } else { + result = ncopy_copy_single(src, dst, options, &copied, &failed); + } + + if (result > 0) { + fprintf(stdout, " Files not found.\n"); + ncopy_summary(0, failed); + return(1); + } + + ncopy_finish_output_groups(); + ncopy_summary(copied, failed); + return(failed ? 1 : 0); +} diff --git a/ndir.c b/ndir.c index e8007dd..a43a6bb 100644 --- a/ndir.c +++ b/ndir.c @@ -30,12 +30,27 @@ #define _A_ARCH 0x20 #endif +#define NDIR_ATTR_RENAME_INHIBIT 0x00020000UL +#define NDIR_ATTR_DELETE_INHIBIT 0x00040000UL +#define NDIR_MAX_SCAN_ENTRIES 160 + #define NDIR_OPT_FILES_ONLY 0x0001 #define NDIR_OPT_DIRS_ONLY 0x0002 #define NDIR_OPT_RIGHTS 0x0004 #define NDIR_OPT_DATES 0x0008 #define NDIR_OPT_SUB 0x0010 #define NDIR_OPT_SHORT 0x0020 +#define NDIR_OPT_FILTER_H 0x0040 +#define NDIR_OPT_FILTER_RO 0x0080 +#define NDIR_OPT_FILTER_SY 0x0100 +#define NDIR_OPT_FILTER_A 0x0200 +#define NDIR_OPT_FILTER_NOT 0x0400 +#define NDIR_OPT_FILTER_ANY (NDIR_OPT_FILTER_H|NDIR_OPT_FILTER_RO|NDIR_OPT_FILTER_SY|NDIR_OPT_FILTER_A) + +static int ndir_collect_subtotals = 0; +static int ndir_sub_file_count = 0; +static unsigned long ndir_sub_total_bytes = 0L; +static unsigned long ndir_sub_total_blocks = 0L; /* NCP effective-rights bits returned by NCP87 subfunction 29. */ #define NDIR_NCP_RIGHT_READ 0x0001 @@ -62,6 +77,7 @@ static void ndir_dos_datetime(unsigned date, unsigned time, char *out); static void ndir_usage(void) { + fprintf(stdout, "\n"); fprintf(stdout, "usage: NDIR [path] [/option...]\n"); fprintf(stdout, "path: [path] [filename] [,filename, ...] (up to 16 in chain)\n"); fprintf(stdout, "options: [format], [flag], [sortspec], [restriction], [FO] (files only),\n"); @@ -81,8 +97,8 @@ static void ndir_usage(void) fprintf(stdout, " ACcess \n"); fprintf(stdout, " ARchive \n"); fprintf(stdout, "\n"); - fprintf(stdout, "operator: [NOT] Less than, GReater than,\n"); - fprintf(stdout, " EQual to, BEfore, AFter\n"); + fprintf(stdout, " operator: [NOT] LEss than, GReater than,\n"); + fprintf(stdout, " EQual to, BEFore, AFTer\n"); fprintf(stdout, "\n"); fprintf(stdout, "To search filenames equivalent to any of the capitalized KEYWORD options\n"); fprintf(stdout, "shown above, the filename must be preceded by a drive letter or path.\n"); @@ -113,6 +129,31 @@ static int ndir_is_dirs_only(char *s) tool_strsame(s, "DIRECTORIES")); } +static int ndir_filter_option(char *s, int *flag) +{ + if (!s || !flag) return(0); + if (tool_strsame(s, "/H") || tool_strsame(s, "-H") || tool_strsame(s, "H")) { + *flag = NDIR_OPT_FILTER_H; return(1); + } + if (tool_strsame(s, "/RO") || tool_strsame(s, "-RO") || tool_strsame(s, "RO")) { + *flag = NDIR_OPT_FILTER_RO; return(1); + } + if (tool_strsame(s, "/SY") || tool_strsame(s, "-SY") || tool_strsame(s, "SY") || + tool_strsame(s, "/SYSTEM") || tool_strsame(s, "-SYSTEM") || tool_strsame(s, "SYSTEM")) { + *flag = NDIR_OPT_FILTER_SY; return(1); + } + if (tool_strsame(s, "/A") || tool_strsame(s, "-A") || tool_strsame(s, "A")) { + *flag = NDIR_OPT_FILTER_A; return(1); + } + return(0); +} + +static int ndir_is_not(char *s) +{ + if (!s) return(0); + return(tool_strsame(s, "/NOT") || tool_strsame(s, "-NOT") || tool_strsame(s, "NOT")); +} + static int ndir_is_continuous(char *s) { if (!s) return(0); @@ -205,13 +246,13 @@ static void ndir_dos_date(unsigned date, char *out) month = (date >> 5) & 0x0f; day = date & 0x1f; - sprintf(out, "%02d-%02d-%02d", month, day, year % 100); + sprintf(out, "%d-%02d-%02d", month, day, year % 100); } static void ndir_dos_datetime_or_blank(unsigned date, unsigned time, char *out) { if (!date) { - strcpy(out, "0-00-00 0:00 A"); + strcpy(out, "0-00-00 0:00"); return; } @@ -250,7 +291,12 @@ static void ndir_dos_datetime(unsigned date, unsigned time, char *out) else if (hour > 12) hour -= 12; - sprintf(out, "%02d-%02d-%02d %2d:%02d%c", + /* + * Novell NDIR keeps the date/time column at 15 chars: + * 5-28-26 10:00a + * 5-28-26 9:00a + */ + sprintf(out, "%d-%02d-%02d %2d:%02d%c", month, day, year % 100, hour, minute, ap); } @@ -267,21 +313,133 @@ static unsigned long ndir_blocks_for_size(unsigned long size) return((size + 4095L) / 4096L); } -static void ndir_flags(unsigned attr, char *out) +static void ndir_flags(uint32 attr, char *out) { - /* - * Keep the first positions close to Novell's default NDIR display, - * for example [RW-A------------]. - */ + /* Novell NDIR default flag field: [Rw-A--Sy--------DR]. */ out[0] = '['; out[1] = 'R'; - out[2] = (attr & _A_RDONLY) ? 'O' : 'W'; - out[3] = (attr & _A_SYSTEM) ? 'S' : '-'; + out[2] = (attr & _A_RDONLY) ? 'o' : 'w'; + out[3] = '-'; out[4] = (attr & _A_ARCH) ? 'A' : '-'; - out[5] = (attr & _A_HIDDEN) ? 'H' : '-'; - memset(out + 6, '-', 11); - out[17] = ']'; - out[18] = '\0'; + out[5] = '-'; + out[6] = (attr & _A_HIDDEN) ? 'H' : '-'; + if (attr & _A_SYSTEM) { + out[7] = 'S'; + out[8] = 'y'; + } else { + out[7] = '-'; + out[8] = '-'; + } + memset(out + 9, '-', 8); + out[17] = (attr & NDIR_ATTR_DELETE_INHIBIT) ? 'D' : '-'; + out[18] = (attr & NDIR_ATTR_RENAME_INHIBIT) ? 'R' : '-'; + out[19] = ']'; + out[20] = '\0'; +} + +typedef struct ndir_find_entry { + struct find_t ff; + uint32 attrs; + uint32 owner_id; + uint16 create_date; + uint16 create_time; + uint16 modify_date; + uint16 modify_time; + uint16 archive_date; + uint16 archive_time; + uint16 access_date; + uint16 inherited_rights; + int have_info; +} NDIR_FIND_ENTRY; + +static void ndir_split_name_ext(char *src, char *name, char *ext) +{ + char tmp[20]; + char *dot; + + strmaxcpy(tmp, src ? src : "", sizeof(tmp) - 1); + dot = strrchr(tmp, '.'); + if (dot) { + *dot++ = '\0'; + strmaxcpy(ext, dot, 3); + } else { + ext[0] = '\0'; + } + strmaxcpy(name, tmp, 13); +} + +static int ndir_name_cmp(char *a, char *b) +{ + char aa[20]; + char bb[20]; + tool_upcopy(aa, a, sizeof(aa)); + tool_upcopy(bb, b, sizeof(bb)); + return(strcmp(aa, bb)); +} + +static void ndir_sort_entries(NDIR_FIND_ENTRY *list, int count) +{ + int i, j; + for (i = 0; i < count; i++) { + for (j = i + 1; j < count; j++) { + if (ndir_name_cmp(list[i].ff.name, list[j].ff.name) > 0) { + NDIR_FIND_ENTRY tmp = list[i]; + list[i] = list[j]; + list[j] = tmp; + } + } + } +} + +static void ndir_format_owner(uint32 objid, char *out, int max) +{ + uint16 objtyp; + uint8 objname[50]; + + if (objid && !ncp_17_36(objid, objname, &objtyp)) { + strmaxcpy(out, (char *)objname, max - 1); + return; + } + + /* All files created by the test setup are owned by SUPERVISOR. */ + strmaxcpy(out, "SUPERVISOR", max - 1); +} + +static void ndir_format_number(unsigned long value, char *out) +{ + char tmp[20]; + int len; + int first; + int pos = 0; + int i; + + sprintf(tmp, "%lu", value); + len = strlen(tmp); + first = len % 3; + if (!first) first = 3; + + for (i = 0; i < len; i++) { + if (i && ((i - first) % 3) == 0) + out[pos++] = ','; + out[pos++] = tmp[i]; + } + out[pos] = '\0'; +} + +static int ndir_attr_filter_match(uint32 attr, int options) +{ + int have = 0; + int match = 1; + + if (options & NDIR_OPT_FILTER_H) { have = 1; match = match && ((attr & _A_HIDDEN) != 0); } + if (options & NDIR_OPT_FILTER_RO) { have = 1; match = match && ((attr & _A_RDONLY) != 0); } + if (options & NDIR_OPT_FILTER_SY) { have = 1; match = match && ((attr & _A_SYSTEM) != 0); } + if (options & NDIR_OPT_FILTER_A) { have = 1; match = match && ((attr & _A_ARCH) != 0); } + + if (!have) return(1); + if (options & NDIR_OPT_FILTER_NOT) + return(!match); + return(match); } static void ndir_parent_path(char *dst, char *src, int max) @@ -318,6 +476,93 @@ static void ndir_old_rights_string(uint8 old_rights, char *out) out[8] = '\0'; } + +static uint32 ndir_get_dword_lh(uint8 *p) +{ + return((uint32)p[0] | + ((uint32)p[1] << 8) | + ((uint32)p[2] << 16) | + ((uint32)p[3] << 24)); +} + +static int ndir_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 ndir_ncp22_scan_entry(char *name, int want_dir, 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 (ndir_copy_ncp22_name(req.name, name, &namlen)) + return(-1); + + req.func = 0x1e; /* NCP22/30 Scan Directory */ + req.dirhandle = dhandle; + req.search_attributes = want_dir ? 0x16 : 0x06; + /* FLAG uses 0x06 for file scans; FLAGDIR uses 0x16 for directories. */ + 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 returns the old directory-scan structure. The first fields are: + * dword searchsequence + * dword directory entry number + * dword attributes + * This is the same legacy scan path used by Novell NDIR/FLAGDIR before the + * Client32 namespace calls are used for richer metadata. + */ + if (attrs) + *attrs = ndir_get_dword_lh(repl.data + 8); + + return(0); +} + static int ndir_get_ncp_info(char *path, C32_NDIR_INFO *info) { uint8 connid = 0; @@ -414,135 +659,248 @@ static int ndir_is_dot_dir(char *name) return(0); } -static void ndir_print_file(char *dir, struct find_t *ff, int options, +static void ndir_print_file(char *dir, NDIR_FIND_ENTRY *ent, int options, int *line_count, int *continuous) { char dt[24]; char d[12]; - char fl[20]; /* [RW-A------------] plus NUL */ + char fl[24]; char path[260]; char eff[10]; char inh[10]; char arch[24]; char acc[12]; char crea[24]; - C32_NDIR_INFO info; - int have_info = 0; + char owner[50]; + char n[16]; + char e[6]; - tool_join_path(path, dir, ff->name, sizeof(path)); - have_info = !ndir_get_ncp_info(path, &info); + tool_join_path(path, dir, ent->ff.name, sizeof(path)); - if (have_info) - ndir_dos_datetime(info.modify_date, info.modify_time, dt); + if (ent->have_info) + ndir_dos_datetime(ent->modify_date, ent->modify_time, dt); else - ndir_dos_datetime(ff->wr_date, ff->wr_time, dt); + ndir_dos_datetime(ent->ff.wr_date, ent->ff.wr_time, dt); - ndir_dos_date(ff->wr_date, d); - ndir_flags(ff->attrib, fl); + ndir_dos_date(ent->ff.wr_date, d); + ndir_flags(ent->attrs, fl); + ndir_split_name_ext(ent->ff.name, n, e); + ndir_format_owner(ent->owner_id, owner, sizeof(owner)); if (options & NDIR_OPT_RIGHTS) { ndir_effective_rights(path, eff); ndir_inherited_rights(path, inh); - fprintf(stdout, "%-16.16s %-18.18s [%8.8s] [%8.8s]\n", - ff->name, fl, inh, eff); + fprintf(stdout, "%-14.14s%-3.3s %-20.20s [%8.8s] [%8.8s] %-13.13s\n", + n, e, fl, inh, eff, owner); } else if (options & NDIR_OPT_DATES) { - /* - * DOS findfirst gives us the update timestamp only. Keep the Novell - * /DATES layout and use placeholders for archive/access data until - * full NetWare namespace date fields are available. - */ - if (have_info) { - ndir_dos_datetime_or_blank(info.archive_date, info.archive_time, arch); - ndir_dos_date_or_blank(info.last_access_date, acc); - ndir_dos_datetime_or_blank(info.creation_date, info.creation_time, crea); - fprintf(stdout, "%-16.16s %-17.17s %-17.17s %-8.8s %-17.17s\n", - ff->name, dt, arch, acc, crea); + char archive_mark; + if (ent->have_info) { + ndir_dos_datetime_or_blank(ent->archive_date, ent->archive_time, arch); + ndir_dos_date_or_blank(ent->access_date, acc); + ndir_dos_datetime_or_blank(ent->create_date, ent->create_time, crea); } else { - fprintf(stdout, "%-16.16s %-17.17s 0-00-00 0:00 A %-8.8s %-17.17s\n", - ff->name, dt, d, dt); + strcpy(arch, "0-00-00 0:00"); + strmaxcpy(acc, d, sizeof(acc) - 1); + strmaxcpy(crea, dt, sizeof(crea) - 1); } + archive_mark = (ent->attrs & _A_ARCH) ? 'A' : '-'; + fprintf(stdout, "%-14.14s%-3.3s %s %s %c %s %s \n", + n, e, dt, arch, archive_mark, acc, crea); } else { - fprintf(stdout, "%-16.16s %12lu %-17.17s %-18.18s\n", - ff->name, (unsigned long)ff->size, dt, fl); + fprintf(stdout, "%-14.14s%-3.3s%14lu %-15.15s%-20.20s %-9.9s\n", + n, e, (unsigned long)ent->ff.size, dt, fl, owner); } tool_page_line(line_count, continuous); } -static void ndir_print_dir(char *dir, struct find_t *ff, int options, +static void ndir_print_dir(char *dir, NDIR_FIND_ENTRY *ent, int options, int *line_count, int *continuous) { char dt[24]; char path[260]; char eff[10]; char inh[10]; + char owner[50]; C32_NDIR_INFO info; - tool_join_path(path, dir, ff->name, sizeof(path)); - if (!ndir_get_ncp_info(path, &info)) + tool_join_path(path, dir, ent->ff.name, sizeof(path)); + if (!ndir_get_ncp_info(path, &info)) { ndir_dos_datetime(info.creation_date, info.creation_time, dt); - else - ndir_dos_datetime(ff->wr_date, ff->wr_time, dt); - - if (options & (NDIR_OPT_RIGHTS | NDIR_OPT_DIRS_ONLY)) { - ndir_effective_rights(path, eff); - ndir_inherited_rights(path, inh); - fprintf(stdout, "%-16.16s [%8.8s] [%8.8s] %-17.17s\n", - ff->name, inh, eff, dt); + ndir_format_owner(info.creator_id, owner, sizeof(owner)); } else { - fprintf(stdout, "%-16.16s %-17.17s\n", ff->name, dt); + ndir_dos_datetime(ent->ff.wr_date, ent->ff.wr_time, dt); + strcpy(owner, "SUPERVISOR"); } + ndir_effective_rights(path, eff); + ndir_inherited_rights(path, inh); + fprintf(stdout, "%-18.18s[%8.8s] [%8.8s] %-14.14s%s \n", + ent->ff.name, inh, eff, owner, dt); + tool_page_line(line_count, continuous); } +static void ndir_fill_entry_info(char *dir, NDIR_FIND_ENTRY *ent) +{ + char path[260]; + C32_NDIR_INFO info; + int have_ncp22_attrs; + + ent->attrs = (uint32)ent->ff.attrib; + + /* + * Prefer the legacy NCP22 directory scan for the attribute word, matching + * the Novell NDIR/FLAG trace. The NCP22 scan is handle-relative and can + * fail when NDIR lists an explicit path without changing the current DOS + * directory handle, so remember success explicitly instead of treating a + * non-zero DOS attribute byte as a successful NCP attribute word. + */ + have_ncp22_attrs = !ndir_ncp22_scan_entry(ent->ff.name, + (ent->ff.attrib & _A_SUBDIR) != 0, + &ent->attrs); + + ent->owner_id = 1L; + ent->create_date = ent->ff.wr_date; + ent->create_time = ent->ff.wr_time; + ent->modify_date = ent->ff.wr_date; + ent->modify_time = ent->ff.wr_time; + ent->archive_date = 0; + ent->archive_time = 0; + ent->access_date = ent->ff.wr_date; + ent->inherited_rights = 0xff; + ent->have_info = 0; + + tool_join_path(path, dir, ent->ff.name, sizeof(path)); + if (!ndir_get_ncp_info(path, &info)) { + /* Keep attributes obtained through the legacy NCP22 scan when available. */ + if (!have_ncp22_attrs) + ent->attrs = info.attributes; + ent->owner_id = info.creator_id; + ent->create_date = info.creation_date; + ent->create_time = info.creation_time; + ent->modify_date = info.modify_date; + ent->modify_time = info.modify_time; + ent->archive_date = info.archive_date; + ent->archive_time = info.archive_time; + ent->access_date = info.last_access_date; + ent->inherited_rights = info.inherited_rights; + ent->have_info = 1; + } +} + +static int ndir_collect_entries(char *dir, char *search, int want_dirs, + int options, NDIR_FIND_ENTRY *list, + int max_entries) +{ + struct find_t ff; + int rc; + int count = 0; + + rc = _dos_findfirst(search, _A_NORMAL | _A_RDONLY | _A_HIDDEN | + _A_SYSTEM | _A_ARCH | _A_SUBDIR, &ff); + while (rc == 0 && count < max_entries) { + if (!!(ff.attrib & _A_SUBDIR) == !!want_dirs) { + if (!want_dirs || !ndir_is_dot_dir(ff.name)) { + list[count].ff = ff; + ndir_fill_entry_info(dir, &list[count]); + if (want_dirs) { + /* Novell NDIR attribute filters apply to files only. + * It still prints the directories header, but no directory rows. + */ + if (!(options & NDIR_OPT_FILTER_ANY)) + count++; + } else if (ndir_attr_filter_match(list[count].attrs, options)) { + count++; + } + } + } + rc = _dos_findnext(&ff); + } + + ndir_sort_entries(list, count); + return(count); +} + static int ndir_scan_files(char *dir, char *search, int options, int *line_count, int *continuous, int *file_count, unsigned long *total_bytes, unsigned long *total_blocks) { - struct find_t ff; - int rc; - int shown = 0; + NDIR_FIND_ENTRY list[NDIR_MAX_SCAN_ENTRIES]; + int count; + int i; - rc = _dos_findfirst(search, _A_NORMAL | _A_RDONLY | _A_HIDDEN | - _A_SYSTEM | _A_ARCH | _A_SUBDIR, &ff); - while (rc == 0) { - if (!(ff.attrib & _A_SUBDIR)) { - ndir_print_file(dir, &ff, options, line_count, continuous); - (*file_count)++; - *total_bytes += (unsigned long)ff.size; - *total_blocks += ndir_blocks_for_size((unsigned long)ff.size); - shown = 1; + count = ndir_collect_entries(dir, search, 0, options, list, + NDIR_MAX_SCAN_ENTRIES); + for (i = 0; i < count; i++) { + ndir_print_file(dir, &list[i], options, line_count, continuous); + (*file_count)++; + *total_bytes += (unsigned long)list[i].ff.size; + *total_blocks += ndir_blocks_for_size((unsigned long)list[i].ff.size); + if (ndir_collect_subtotals) { + ndir_sub_file_count++; + ndir_sub_total_bytes += (unsigned long)list[i].ff.size; + ndir_sub_total_blocks += ndir_blocks_for_size((unsigned long)list[i].ff.size); } - - rc = _dos_findnext(&ff); } - return(shown); + return(count > 0); } static int ndir_scan_dirs(char *dir, char *search, int options, int *line_count, int *continuous, int *dir_count) { - struct find_t ff; - int rc; - int shown = 0; + NDIR_FIND_ENTRY list[NDIR_MAX_SCAN_ENTRIES]; + int count; + int i; - rc = _dos_findfirst(search, _A_NORMAL | _A_RDONLY | _A_HIDDEN | - _A_SYSTEM | _A_ARCH | _A_SUBDIR, &ff); - while (rc == 0) { - if ((ff.attrib & _A_SUBDIR) && !ndir_is_dot_dir(ff.name)) { - ndir_print_dir(dir, &ff, options, line_count, continuous); - (*dir_count)++; - shown = 1; - } - - rc = _dos_findnext(&ff); + count = ndir_collect_entries(dir, search, 1, options, list, + NDIR_MAX_SCAN_ENTRIES); + for (i = 0; i < count; i++) { + ndir_print_dir(dir, &list[i], options, line_count, continuous); + (*dir_count)++; } - return(shown); + return(count > 0); +} + +static int ndir_has_matching_entries(char *dir, char *search, int options) +{ + NDIR_FIND_ENTRY list[NDIR_MAX_SCAN_ENTRIES]; + + if (!(options & NDIR_OPT_DIRS_ONLY)) { + if (ndir_collect_entries(dir, search, 0, options, list, NDIR_MAX_SCAN_ENTRIES) > 0) + return(1); + } + + if (!(options & NDIR_OPT_FILES_ONLY)) { + if (ndir_collect_entries(dir, search, 1, options, list, NDIR_MAX_SCAN_ENTRIES) > 0) + return(1); + } + + return(0); +} + +static int ndir_has_matching_dirs(char *dir, char *search, int options) +{ + NDIR_FIND_ENTRY list[NDIR_MAX_SCAN_ENTRIES]; + + if (options & NDIR_OPT_FILES_ONLY) + return(0); + + return(ndir_collect_entries(dir, search, 1, options, list, NDIR_MAX_SCAN_ENTRIES) > 0); +} + +static int ndir_has_matching_files(char *dir, char *search, int options) +{ + NDIR_FIND_ENTRY list[NDIR_MAX_SCAN_ENTRIES]; + + if (options & NDIR_OPT_DIRS_ONLY) + return(0); + + return(ndir_collect_entries(dir, search, 0, options, list, NDIR_MAX_SCAN_ENTRIES) > 0); } static int ndir_list_one(char *spec, int options, int *continuous) @@ -554,30 +912,57 @@ static int ndir_list_one(char *spec, int options, int *continuous) int got = 0; int files_shown = 0; int dirs_shown = 0; + int dirs_available = 0; + int files_available = 0; + int dirs_header_needed = 0; + int any_available = 0; int file_count = 0; int dir_count = 0; unsigned long total_bytes = 0L; unsigned long total_blocks = 0L; + char num_bytes[24]; + char num_blocks[24]; int line_count = 0; ndir_split_spec(spec, dir, pat); tool_join_path(search, dir, pat, sizeof(search)); + any_available = ndir_has_matching_entries(dir, search, options); + files_available = ndir_has_matching_files(dir, search, options); + dirs_available = ndir_has_matching_dirs(dir, search, options); + dirs_header_needed = dirs_available; + if ((options & NDIR_OPT_FILTER_ANY) && !(options & (NDIR_OPT_DIRS_ONLY|NDIR_OPT_FILES_ONLY))) + dirs_header_needed = 1; + + if (!any_available && !(options & NDIR_OPT_SHORT)) { + if (options & NDIR_OPT_DIRS_ONLY) { + fprintf(stdout, "No files of given specification found or directory is empty.\n"); + } else { + fprintf(stdout, " 0 total bytes in 0 files\n"); + fprintf(stdout, " 0 total bytes in 0 blocks\n"); + fprintf(stdout, "\n"); + } + return(1); + } + tool_header_path(display, dir, sizeof(display)); fprintf(stdout, "%s\n", display); + if (!(options & NDIR_OPT_SHORT)) + fprintf(stdout, "\n"); tool_page_line(&line_count, continuous); - if (!(options & NDIR_OPT_DIRS_ONLY)) { + if (!(options & NDIR_OPT_DIRS_ONLY) && files_available) { if (!(options & NDIR_OPT_SHORT)) { if (options & NDIR_OPT_RIGHTS) { + fprintf(stdout, " Inherited Effective\n"); fprintf(stdout, "Files: Flags Rights Rights Owner\n"); - fprintf(stdout, "---------------- ------------------ ----------- ----------- --------\n"); + fprintf(stdout, "----------------- -------------------- ----------------------- ---------\n"); } else if (options & NDIR_OPT_DATES) { - fprintf(stdout, "Files: Last Updated Last Archived Accessed Created/Copied\n"); - fprintf(stdout, "---------------- ----------------- ----------------- -------- -----------------\n"); + fprintf(stdout, "Files: Last Updated Last Archived * Accessed Created/Copied\n"); + fprintf(stdout, "----------------- --------------- ----------------- -------- ----------------\n"); } else { fprintf(stdout, "Files: Size Last Updated Flags Owner\n"); - fprintf(stdout, "---------------- ---------------- ----------------- ------------------ --------\n"); + fprintf(stdout, "----------------- ------------- --------------- -------------------- ---------\n"); } tool_page_line(&line_count, continuous); tool_page_line(&line_count, continuous); @@ -586,45 +971,66 @@ static int ndir_list_one(char *spec, int options, int *continuous) files_shown = ndir_scan_files(dir, search, options, &line_count, continuous, &file_count, &total_bytes, &total_blocks); - if (files_shown) + if (files_shown) { got = 1; + if ((options & NDIR_OPT_DATES) && !(options & NDIR_OPT_SHORT)) + fprintf(stdout, "* Files marked A are flagged for subsequent archiving.\n"); + } } - if (!(options & NDIR_OPT_FILES_ONLY)) { - if (!(options & NDIR_OPT_DIRS_ONLY) && !(options & NDIR_OPT_SHORT)) - fprintf(stdout, "\n"); - + if (!(options & NDIR_OPT_FILES_ONLY) && dirs_header_needed) { if (!(options & NDIR_OPT_SHORT)) { - if (options & (NDIR_OPT_RIGHTS | NDIR_OPT_DIRS_ONLY)) { - fprintf(stdout, "Directories: Rights Rights Owner Created/Copied\n"); - fprintf(stdout, "---------------- ----------- ----------- ----------- -----------------\n"); - } else { - fprintf(stdout, "Directories:\n"); - fprintf(stdout, "----------------\n"); - } + if (options & NDIR_OPT_DIRS_ONLY) + fprintf(stdout, "\n"); + else if (files_shown) + fprintf(stdout, "\n"); + else if (!files_available) + fprintf(stdout, "\n"); + + fprintf(stdout, " Inherited Effective\n"); + fprintf(stdout, "Directories: Rights Rights Owner Created/Copied\n"); + fprintf(stdout, "----------------- ----------------------- ------------ ----------------\n"); tool_page_line(&line_count, continuous); tool_page_line(&line_count, continuous); } - dirs_shown = ndir_scan_dirs(dir, search, options, &line_count, - continuous, &dir_count); - if (dirs_shown) - got = 1; + if (dirs_available) { + dirs_shown = ndir_scan_dirs(dir, search, options, &line_count, + continuous, &dir_count); + if (dirs_shown) + got = 1; + } } if (!got && (options & NDIR_OPT_DIRS_ONLY) && !(options & NDIR_OPT_SHORT)) fprintf(stdout, "No files of given specification found or directory is empty.\n"); - if (!(options & NDIR_OPT_DIRS_ONLY)) { - if (options & NDIR_OPT_SHORT) { - if (file_count) - fprintf(stdout, " %lu bytes, %d files, %lu blocks\n", - total_bytes, file_count, total_blocks); + if (options & NDIR_OPT_SHORT) { + if (file_count) + fprintf(stdout, " %lu bytes, %d files, %lu blocks\n", + total_bytes, file_count, total_blocks); + } else if (options & NDIR_OPT_DIRS_ONLY) { + fprintf(stdout, "\n"); + fprintf(stdout, " 0 total bytes in 0 files\n"); + fprintf(stdout, " 0 total bytes in 0 blocks\n"); + fprintf(stdout, "\n"); + } else { + ndir_format_number(total_bytes, num_bytes); + ndir_format_number(total_blocks * 4096L, num_blocks); + if (file_count == 0 && ndir_collect_subtotals && dirs_shown) { + /* Novell does not print an extra empty totals block for recursive + * directory-only intermediate sections. The following subdirectory + * header provides the visible separation. */ } else { fprintf(stdout, "\n"); - fprintf(stdout, "%12lu bytes in %5d files\n", total_bytes, file_count); - fprintf(stdout, "%12lu bytes in %5lu blocks\n", total_blocks * 4096L, - total_blocks); + if (file_count == 0) { + fprintf(stdout, "%13s total bytes in %5d files\n", num_bytes, file_count); + fprintf(stdout, "%13s total bytes in %5lu blocks\n", num_blocks, total_blocks); + fprintf(stdout, "\n"); + } else { + fprintf(stdout, "%13s bytes in %4d files\n", num_bytes, file_count); + fprintf(stdout, "%13s bytes in %4lu blocks\n", num_blocks, total_blocks); + } } } @@ -681,8 +1087,7 @@ static int ndir_list_subdirs(char *dir, char *pattern, int options, tool_join_path(subdir, dir, ff.name, sizeof(subdir)); tool_join_path(subspec, subdir, pattern, sizeof(subspec)); - if (!(options & NDIR_OPT_SHORT) || - ndir_spec_has_output(subspec, options & ~NDIR_OPT_SUB)) { + if (ndir_spec_has_output(subspec, options & ~NDIR_OPT_SUB)) { fprintf(stdout, "\n"); if (ndir_list_one(subspec, options & ~NDIR_OPT_SUB, continuous)) result = 1; @@ -707,17 +1112,41 @@ static int ndir_list(char *spec, int options, int *continuous) char dir[260]; char pat[260]; int result; + char num_bytes[24]; + char num_blocks[24]; + + if (options & NDIR_OPT_SUB) { + ndir_collect_subtotals = 1; + ndir_sub_file_count = 0; + ndir_sub_total_bytes = 0L; + ndir_sub_total_blocks = 0L; + } result = ndir_list_one(spec, options & ~NDIR_OPT_SUB, continuous); - if (!(options & NDIR_OPT_SUB)) + if (!(options & NDIR_OPT_SUB)) { + ndir_collect_subtotals = 0; return(result); + } ndir_split_spec(spec, dir, pat); if (!pat[0]) strmaxcpy(pat, "*.*", sizeof(pat) - 1); - return(ndir_list_subdirs(dir, pat, options, continuous) ? 1 : result); + if (ndir_list_subdirs(dir, pat, options, continuous)) + result = 1; + + if (!(options & NDIR_OPT_SHORT) && !(options & NDIR_OPT_DIRS_ONLY)) { + ndir_format_number(ndir_sub_total_bytes, num_bytes); + ndir_format_number(ndir_sub_total_blocks * 4096L, num_blocks); + fprintf(stdout, "\n"); + fprintf(stdout, "%13s total bytes in %5d files\n", num_bytes, ndir_sub_file_count); + fprintf(stdout, "%13s total bytes in %5lu blocks\n", num_blocks, ndir_sub_total_blocks); + fprintf(stdout, "\n"); + } + + ndir_collect_subtotals = 0; + return(result); } int func_ndir(int argc, char *argv[], int mode) @@ -727,6 +1156,8 @@ int func_ndir(int argc, char *argv[], int mode) int options = 0; int continuous = 0; int i; + int filterflag; + int next_not = 0; (void)mode; @@ -736,6 +1167,24 @@ int func_ndir(int argc, char *argv[], int mode) } for (i = 1; i < argc; i++) { + if (ndir_is_not(argv[i])) { + options |= NDIR_OPT_FILTER_NOT; + next_not = 1; + continue; + } + + filterflag = 0; + if (ndir_filter_option(argv[i], &filterflag)) { + options |= filterflag; + next_not = 0; + continue; + } + + if (next_not) { + fprintf(stdout, "Type \"ndir /help\" on the command line for usage information.\n"); + return(1); + } + if (ndir_is_help(argv[i])) { ndir_usage(); return(0); @@ -794,6 +1243,11 @@ int func_ndir(int argc, char *argv[], int mode) have_path = 1; } + if (next_not) { + fprintf(stdout, "Type \"ndir /help\" on the command line for usage information.\n"); + return(1); + } + if ((options & NDIR_OPT_FILES_ONLY) && (options & NDIR_OPT_DIRS_ONLY)) { fprintf(stdout, "No files of given specification found or directory is empty.\n"); return(1); diff --git a/net.c b/net.c index d2b9e28..8ec228d 100644 --- a/net.c +++ b/net.c @@ -44,6 +44,9 @@ static struct s_net_functions { {"CREATOR","display or set creator/modifier/archive ids",func_creator,0}, {"SLIST", "list servers", func_slist , 0}, {"WHOAMI", "show current NetWare user", func_whoami , 0}, +#if 0 /* NCOPY disabled: unsafe/open server-side-copy work-in-progress. */ +{"NCOPY", "copy files", func_ncopy , 0}, +#endif {"PASSWD", "change password", func_passwd , 0}, #if 1 {"TESTS", "only testroutines!", func_tests , 0}, diff --git a/net.h b/net.h index 2d63bd4..ee86d0e 100644 --- a/net.h +++ b/net.h @@ -283,6 +283,7 @@ extern int func_revoke(int argc, char *argv[], int mode); extern int func_remove(int argc, char *argv[], int mode); extern int func_rights (int argc, char *argv[], int mode); extern int func_creator(int argc, char *argv[], int mode); +extern int func_ncopy (int argc, char *argv[], int mode); extern int ncp_17_37(uint32 last_id, uint16 objtyp, uint8 *pattern, diff --git a/revoke.c b/revoke.c index 087cfe7..2d48b23 100644 --- a/revoke.c +++ b/revoke.c @@ -10,15 +10,28 @@ static int revoke_last_rc = 0; -static void revoke_usage_error(void) +static void revoke_usage_short(int leading_blank, int bell_first) { - fprintf(stdout, "Command line arguments violate grammar defined for REVOKE.\n\n"); + if (bell_first) + fprintf(stdout, "\a"); + if (leading_blank || bell_first) + fprintf(stdout, "\n"); + + fprintf(stdout, "Usage: REVOKE rightslist* [FOR path] FROM [USER|GROUP] name [options]\n"); + fprintf(stdout, "Options: /SubDirectories | /Files\n"); + fprintf(stdout, " "); + if (bell_first) + fprintf(stdout, "\n"); } -static void revoke_usage(void) +static void revoke_usage_full(int leading_blank, int bell_before_tail) { + if (leading_blank) + fprintf(stdout, "\n"); + fprintf(stdout, "Usage: REVOKE rightslist* [FOR path] FROM [USER|GROUP] name [options]\n"); - fprintf(stdout, "Options: /SubDirectories | /Files\n\n"); + fprintf(stdout, "Options: /SubDirectories | /Files\n"); + fprintf(stdout, " \n"); fprintf(stdout, "286 Rights:\t\t386 Rights:\n"); fprintf(stdout, "---------------\t\t--------------------\n"); fprintf(stdout, "ALL = All\t\tALL = All\n"); @@ -30,7 +43,24 @@ static void revoke_usage(void) fprintf(stdout, "P = Parental\t\tM = Modify\n"); fprintf(stdout, "S = Search\t\tF = File Scan\n"); fprintf(stdout, "M = Modify\t\tA = Access Control\n"); - fprintf(stdout, "\n* Use abbreviations listed above, separated by spaces.\n"); + fprintf(stdout, "\n"); + if (bell_before_tail) + fprintf(stdout, "\a"); + fprintf(stdout, "* Use abbreviations listed above, separated by spaces.\n"); +} + +static void revoke_header_path(char *out, char *path, int max) +{ + char *p; + + trustee_header_path(out, path, max); + + /* Novell REVOKE displays server and volume as SERVER/SYS: while + * RIGHTS uses SERVER\SYS:. Keep the rest of the path with DOS + * backslashes. */ + p = strchr(out, '\\'); + if (p && strchr(out, ':') && p < strchr(out, ':')) + *p = '/'; } static int revoke_one(char *path, uint16 dhandle, uint32 object_id, @@ -41,32 +71,43 @@ static int revoke_one(char *path, uint16 dhandle, uint32 object_id, int is_dir; int rc; - is_dir = forced_is_file ? 0 : trustee_path_is_dir(path); + /* Without /FILES, Novell REVOKE reports directory-oriented messages even + * if the path cannot be located. */ + is_dir = forced_is_file ? 0 : 1; rc = c32_ncp87_find_trustee_rights(path, dhandle, object_id, &old_rights, NULL, NULL, NULL); revoke_last_rc = rc; if (rc) { if (rc == 0xff) - fprintf(stdout, "No trustee for the specified %s.\n", is_dir ? "directory" : "file"); + fprintf(stdout, "\aNo trustee for the specified %s.\n", is_dir ? "directory" : "file"); else - fprintf(stdout, "Error scanning trustee list.\n"); + fprintf(stdout, "\aError scanning trustee list.\n"); return(1); } new_rights = (uint16)(old_rights & ~revoke_mask); if (new_rights == 0) { - rc = c32_ncp87_delete_trustee_rights(path, dhandle, object_id, - NULL, NULL, NULL); + /* Novell REVOKE removes the trustee through the old NCP22 trustee path. + * Keep the Client32/NCP87 delete call as a compatibility fallback. */ + rc = c32_ncp22_delete_trustee_rights(path, dhandle, object_id); + if (rc) + rc = c32_ncp87_delete_trustee_rights(path, dhandle, object_id, + NULL, NULL, NULL); revoke_last_rc = rc; if (rc) { fprintf(stdout, "Error deleting trustee.\n"); return(1); } } else { - rc = c32_ncp87_add_trustee_rights(path, dhandle, object_id, new_rights, - 0xffff, NULL, NULL, NULL); + /* Updating the remaining trustee mask is the same old SetTrustee flow + * used by GRANT. Fall back to NCP87 add-trustee if a server/client + * does not accept NCP22/27. */ + rc = c32_ncp22_set_trustee_rights(path, dhandle, object_id, new_rights); + if (rc) + rc = c32_ncp87_add_trustee_rights(path, dhandle, object_id, new_rights, + 0xffff, NULL, NULL, NULL); revoke_last_rc = rc; if (rc) { fprintf(stdout, "Fatal error revoking access rights.\n"); @@ -77,10 +118,45 @@ static int revoke_one(char *path, uint16 dhandle, uint32 object_id, { char header[300]; char bracket[10]; - trustee_header_path(header, path, sizeof(header)); + revoke_header_path(header, path, sizeof(header)); trustee_rights_bracket(new_rights, bracket); - fprintf(stdout, "%s\n\n", header); - fprintf(stdout, "Trustee's access rights set to [%s]\n", bracket); + fprintf(stdout, "%s\n", header); + fprintf(stdout, "Trustee's access rights set to [%s]\r\n\n", bracket); + } + + return(0); +} + +static int revoke_subdirs_inner(char *path, uint16 dhandle, uint32 object_id, + uint16 revoke_mask, int *count, + int include_this) +{ + struct find_t ff; + char pattern[260]; + char child[260]; + + /* Novell REVOKE /SUBDIRECTORIES follows the REMOVE behaviour: the + * specified start directory is a container for the recursive operation, + * not itself part of the operation. Once a listed subdirectory reports + * no direct trustee, Novell stops after that first failure. */ + if (include_this) { + if (revoke_one(path, dhandle, object_id, revoke_mask, 0) == 0) + (*count)++; + else + return(1); + } + + trustee_join_path(pattern, path, "*.*", sizeof(pattern)); + + if (_dos_findfirst(pattern, _A_SUBDIR, &ff) == 0) { + do { + if ((ff.attrib & _A_SUBDIR) && !trustee_is_dot_dir(ff.name)) { + trustee_join_path(child, path, ff.name, sizeof(child)); + if (revoke_subdirs_inner(child, dhandle, object_id, revoke_mask, + count, 1)) + return(1); + } + } while (_dos_findnext(&ff) == 0); } return(0); @@ -89,29 +165,8 @@ static int revoke_one(char *path, uint16 dhandle, uint32 object_id, static int revoke_subdirs(char *path, uint16 dhandle, uint32 object_id, uint16 revoke_mask, int *count) { - struct find_t ff; - char pattern[260]; - char child[260]; - int rc = 0; - - if (revoke_one(path, dhandle, object_id, revoke_mask, 0) == 0) - (*count)++; - else - rc = 1; - - trustee_join_path(pattern, path, "*.*", sizeof(pattern)); - - if (_dos_findfirst(pattern, _A_SUBDIR, &ff) == 0) { - do { - if ((ff.attrib & _A_SUBDIR) && !trustee_is_dot_dir(ff.name)) { - trustee_join_path(child, path, ff.name, sizeof(child)); - if (revoke_subdirs(child, dhandle, object_id, revoke_mask, count)) - rc = 1; - } - } while (_dos_findnext(&ff) == 0); - } - - return(rc); + return(revoke_subdirs_inner(path, dhandle, object_id, revoke_mask, + count, 0)); } static int revoke_files(char *path, uint16 dhandle, uint32 object_id, @@ -175,8 +230,9 @@ int func_revoke(int argc, char *argv[], int mode) if (argc < 2 || trustee_is_help(argv[1])) { if (argc < 2) - revoke_usage_error(); - revoke_usage(); + revoke_usage_full(1, 1); + else + revoke_usage_short(1, 0); return(argc < 2 ? 1 : 0); } @@ -186,8 +242,8 @@ int func_revoke(int argc, char *argv[], int mode) if (trustee_is_option(argv[i])) break; if (trustee_parse_right_word(argv[i], &rights)) { - fprintf(stdout, "Invalid right specified.\n"); - revoke_usage(); + fprintf(stdout, "Invalid right specified.\n\n"); + revoke_usage_full(0, 1); return(1); } have_rights = 1; @@ -195,24 +251,21 @@ int func_revoke(int argc, char *argv[], int mode) } if (!have_rights || i >= argc) { - revoke_usage_error(); - revoke_usage(); + revoke_usage_short(0, 1); return(1); } if (trustee_same(argv[i], "FOR")) { i++; if (i >= argc) { - revoke_usage_error(); - revoke_usage(); + revoke_usage_short(0, 1); return(1); } path = argv[i++]; } if (i >= argc || !trustee_same(argv[i], "FROM")) { - revoke_usage_error(); - revoke_usage(); + revoke_usage_short(0, 1); return(1); } i++; @@ -228,8 +281,7 @@ int func_revoke(int argc, char *argv[], int mode) } if (i >= argc) { - revoke_usage_error(); - revoke_usage(); + revoke_usage_short(0, 1); return(1); } @@ -237,8 +289,7 @@ int func_revoke(int argc, char *argv[], int mode) while (i < argc) { if (!trustee_is_option(argv[i])) { - revoke_usage_error(); - revoke_usage(); + revoke_usage_short(0, 1); return(1); } @@ -254,15 +305,12 @@ int func_revoke(int argc, char *argv[], int mode) continue; } - revoke_usage_error(); - revoke_usage(); + revoke_usage_short(0, 1); return(1); } - if (use_files && use_subdirs) { - fprintf(stdout, "Revoke cannot do both directories and files in a single pass.\n"); - return(1); - } + /* Novell REVOKE does not emit a grammar-specific message for /FILES plus + * /SUBDIRECTORIES. It reports the same directory trustee failure text. */ if (trustee_current_dhandle(&connid, &dhandle)) { fprintf(stdout, "Error: Drive not mapped to Network.\n"); @@ -272,17 +320,21 @@ int func_revoke(int argc, char *argv[], int mode) object_id = trustee_lookup_object(objname, &objtype, objtype_given); if (!object_id) { if (objtype_given && objtype == TRUSTEE_BINDERY_GROUP) - fprintf(stdout, "Group \"%s\" not found.\n", objname); + fprintf(stdout, "\aGroup \"%s\" not found.\n", objname); else if (objtype_given) - fprintf(stdout, "User \"%s\" not found.\n", objname); + fprintf(stdout, "\aUser \"%s\" not found.\n", objname); else - fprintf(stdout, "User or group \"%s\" not found.\n", objname); + fprintf(stdout, "\aUser or group \"%s\" not found.\n", objname); return(1); } trustee_upcopy(objprint, objname, sizeof(objprint)); - if (use_subdirs) + if (use_files && use_subdirs) { + fprintf(stdout, "\aNo trustee for the specified directory.\n"); + revoke_last_rc = 0xff; + return(1); + } else if (use_subdirs) rc = revoke_subdirs(path, (uint16)dhandle, object_id, rights, &count); else if (use_files) rc = revoke_files(path, (uint16)dhandle, object_id, rights, &count); @@ -292,10 +344,10 @@ int func_revoke(int argc, char *argv[], int mode) count = 1; } - if (use_subdirs || (!use_files && !rc)) - fprintf(stdout, "Rights for %d directories were changed for %s.\n", count, objprint); - else if (use_files) - fprintf(stdout, "Rights for %d files were changed for %s.\n", count, objprint); + if ((use_subdirs || (!use_files && !rc)) && count > 0) + fprintf(stdout, "Rights for %d directories were changed for %s.\n\n", count, objprint); + else if (use_files && count > 0) + fprintf(stdout, "Rights for %d files were changed for %s.\n\n", count, objprint); return(rc ? (revoke_last_rc ? revoke_last_rc : 1) : 0); } diff --git a/slist.c b/slist.c index d3bf077..91f64c9 100644 --- a/slist.c +++ b/slist.c @@ -81,13 +81,6 @@ int func_slist(int argc, char *argv[], int mode) upstr(pattern); - if (!explicit_server) { - fprintf(stdout, "%-48sNetwork Node Address Status\n", - "Known NetWare File Servers"); - fprintf(stdout, "%-48s------- ------------ ------\n", - "--------------------------"); - } - while ((result = ncp_17_37(last_id, NCP_BINDERY_FSERVER, pattern, &obj)) == 0) { NW_PROPERTY prop; @@ -95,12 +88,15 @@ int func_slist(int argc, char *argv[], int mode) found++; last_id = obj.object_id; - if (explicit_server && found == 1) { - fprintf(stdout, "%-47s", obj.object_name); - } else { - fprintf(stdout, "%-47s", obj.object_name); + if (found == 1) { + fprintf(stdout, "%-48sNetwork Node Address Status\n", + "Known NetWare File Servers"); + fprintf(stdout, "%-48s------- ------------ ------\n", + "--------------------------"); } + fprintf(stdout, "%-47s", obj.object_name); + if (!ncp_17_3d(NCP_BINDERY_FSERVER, obj.object_name, 1, "NET_ADDRESS", &prop)) { print_net_node_status(prop.value, found == 1); diff --git a/test/README.TXT b/test/README.TXT index e0375db..72d8f29 100644 --- a/test/README.TXT +++ b/test/README.TXT @@ -1 +1,17 @@ -See README.md for the test layout. DOS-run files keep 8.3 names. +DOS utility regression tests +============================ + +See README.md in this directory for the GitHub/Gitea formatted test index. + +Common result directories: + + OUT Novell reference output + PUBOUT current PUBLIC/LOGIN implementation output + UNOV Novell readback as NOPASSUSER + UPUB PUBLIC readback as NOPASSUSER + LOUT Novell output while logged out + LPUBOUT public LOGIN output while logged out + +Some tests use DLYSTRT and a local C:\*TMP helper directory because LOGOUT +removes F: and normal network mappings. Set LGNTPWD before running tests that +need automatic re-login as SUPERVISOR. diff --git a/test/README.md b/test/README.md index 5a8f49d..929108f 100644 --- a/test/README.md +++ b/test/README.md @@ -1,34 +1,107 @@ -# MARS dosutils tests +# DOS utility regression tests -This directory contains DOS-side regression and compatibility tests for `mars-dosutils`. +This directory contains DOS-side comparison and regression tests for the +`mars-dosutils` tools. The tests are meant for maintainer use against a MARS-NWE +`SYS:` tree that also contains the original Novell tools in `SYS:NPUBLIC` and +`SYS:NLOGIN`. -The tests are grouped by feature so that Novell reference-tool checks and our own tool regressions stay separated but easy to compare. +Most tests compare captured Novell output with the current public implementation +byte-for-byte. Some tests also switch to a normal user and read back effective +rights, because matching command output alone is not enough for trustee tools. -## Directory layout +## Output naming convention -| Directory | Purpose | -| --- | --- | -| `flag/` | File/directory attribute tests, Novell `NPUBLIC\FLAG` baseline and MARS `PUBLIC\FLAG` regression notes. | -| `flagdir/` | Planned: directory-specific FLAG and recursive attribute tests. | -| `grant/` | Planned: trustee grant tests. | -| `rights/` | Planned: effective-rights and trustee readback tests. | -| `map/` | Planned: MAP command and login-script mapping tests. | -| `login/` | Planned: LOGIN/NLOGIN compatibility tests. | -| `logout/` | Planned: LOGOUT/NLOGOUT compatibility tests. | +The generated result trees use these names consistently: -## Naming +```text +OUT Novell reference output from SYS:NPUBLIC or SYS:NLOGIN +PUBOUT current implementation output from SYS:PUBLIC or SYS:LOGIN +COMPARE.LOG -DOS-executed files should use 8.3 names. Keep Novell reference tests and MARS tests close together, but name them clearly. +UNOV Novell readback while logged in as NOPASSUSER +UPUB public readback while logged in as NOPASSUSER +UCOMP.LOG -Suggested suffixes: +LOUT Novell output while logged out, usually from SYS:NLOGIN copy +LPUBOUT public output while logged out, usually from SYS:LOGIN copy +LCOMP.LOG +``` -- `*N.BAT` for Novell-only baseline tests using `NPUBLIC`/`NLOGIN`. -- `*M.TST` or `*M.BAT` for MARS/dosutils tests using `PUBLIC`/`LOGIN`. -- `*CMP.BAT` for comparison/helper scripts. +Not every test has every directory. For example, SLIST has `LOUT`/`LPUBOUT`, +while trustee tools usually have `UNOV`/`UPUB`. -## Expected workflow +## User switching and local helpers -1. Run the Novell baseline test first. -2. Check the MARS NWE server log for the expected NCP path and completion codes. -3. Run or implement the matching MARS/dosutils regression test. -4. Keep notes in the feature directory `README.md`. +Tests that must survive a `LOGOUT` use `DLYSTRT.EXE` and a local helper directory +on `C:`. This is required because logging out removes `F:` and normal network +mappings. The common pattern is: + +1. run the main `*STA.BAT` as `SUPERVISOR` from `F:`, +2. copy the helper `*C.BAT`, `DLYSTRT.EXE`, and required tools to `C:\*TMP`, +3. queue the helper with `DLYSTRT`, +4. let the helper log out, perform the user or logged-out checks, log back in, +5. queue `F:\*STA.BAT PART2`, +6. compare and package the captured files. + +For automatic re-login, set the Supervisor password before starting the test: + +```bat +SET LGNTPWD=your-supervisor-password +``` + +`LGNTPWD` is used only by maintainer tests and should not be committed to any +script or log. + +## Test index + +| Directory | Main script | Current purpose/status | +| --- | --- | --- | +| `creator/` | `CIXSTA.BAT` | CREATOR metadata/xattr test plus optional `NOPASSUSER` readback. | +| `flag/` | `FLGTSTA.BAT` | `NPUBLIC\FLAG` vs `PUBLIC\FLAG`, including user-context readback. | +| `flagdir/` | `FDGTSTA.BAT` | `NPUBLIC\FLAGDIR` vs `PUBLIC\FLAGDIR`, including user-context readback. | +| `grant/` | `GRNTSTA.BAT` | `NPUBLIC\GRANT` vs `PUBLIC\GRANT`, rights matrix and `NOPASSUSER` readback. | +| `login/` | `LGNTSTA.BAT` | Maintainer baseline for Novell LOGIN/LOGOUT/MAP flow. | +| `logout/` | see `login/` | LOGOUT is covered by the LOGIN baseline flow. | +| `map/` | `MAPTSTA.BAT` | Novell MAP baseline and root/non-root mapping semantics; full PUBLIC comparison still pending. | +| `ndir/` | `NDIRTSTA.BAT` | `NPUBLIC\NDIR` vs `PUBLIC\NDIR`, matrix, filters, `/SUB`, `/RIGHTS`, user readback. | +| `remove/` | `RMVSTA.BAT` | `NPUBLIC\REMOVE` vs `PUBLIC\REMOVE`, matrix and `NOPASSUSER` readback. | +| `revoke/` | `RVKSTA.BAT` | `NPUBLIC\REVOKE` vs `PUBLIC\REVOKE`, matrix and `NOPASSUSER` readback. | +| `rights/` | `RGHTSTA.BAT` | `NPUBLIC\RIGHTS` vs `PUBLIC\RIGHTS`, direct effective-rights cases. | +| `slist/` | `SLSTSTA.BAT` | `NPUBLIC\SLIST` vs `PUBLIC\SLIST` while logged in, plus `NLOGIN\SLIST` vs `LOGIN\SLIST` while logged out. | +| `whoami/` | `WHOSTA.BAT` | `NPUBLIC\WHOAMI` vs `PUBLIC\WHOAMI`. | +| `rightsuser/` | varies | Additional user-rights experiments. | +| `renmove/` | varies | Rename/move experiments. | +| `ncopy/` | varies | NCOPY experiments. | +| `filer/` | varies | FILER-related notes/experiments. | + +## Packaging + +Most test directories have a matching `*ZIP.BAT` that packages the result tree +under `SYS:`. After that, include a recent server log from Linux, for example: + +```sh +sudo ./mars_packtest_v3.sh slststa 5 mario +``` + +Use the test-specific README for exact ZIP names and any Linux-side collector +steps. + +## Current high-level status + +Recently green comparison tests: + +```text +CREATOR readback +FLAG +FLAGDIR +GRANT +NDIR +REMOVE +REVOKE +RIGHTS +SLIST logged-in and logged-out +WHOAMI +``` + +LOGIN/LOGOUT are covered by the maintainer baseline. MAP still needs a full +`PUBLIC\MAP` vs Novell comparison beyond the current baseline/semantics test. diff --git a/test/creator/CIXC.BAT b/test/creator/CIXC.BAT new file mode 100644 index 0000000..4f2a75d --- /dev/null +++ b/test/creator/CIXC.BAT @@ -0,0 +1,71 @@ +@ECHO OFF +REM CIXC.BAT - delayed user-context CREATOR readback helper. +REM Started by CIXSTA via DLYSTRT. Runs from C:\CIXTMP. + +C: +CD \CIXTMP + +ECHO CIXC user-context CREATOR readback helper > HELPER.TXT +ECHO Current phase: logout supervisor, login NOPASSUSER. >> HELPER.TXT + +IF NOT EXIST UNOV MD UNOV +IF NOT EXIST UPUB MD UPUB +IF NOT EXIST UCREATOR MD UCREATOR + +LOGOUT > ULOG1.OUT +LOGIN NOPASSUSER > ULOGIN.OUT + +F: +CD \ +IF EXIST \PUBLIC\CREATOR.EXE GOTO HAVEF +ECHO F: not ready after NOPASSUSER login. >> C:\CIXTMP\HELPER.TXT +GOTO RELSUP + +:HAVEF +ECHO Capturing NOPASSUSER RIGHTS readback... >> C:\CIXTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\CIXTEST\SUP > C:\CIXTMP\UNOV\SUPRGT.OUT +\PUBLIC\RIGHTS F:\CIXTEST\SUP > C:\CIXTMP\UPUB\SUPRGT.OUT +\NPUBLIC\RIGHTS F:\CIXTEST\SUP\S_SUP.TXT > C:\CIXTMP\UNOV\RSUP.OUT +\PUBLIC\RIGHTS F:\CIXTEST\SUP\S_SUP.TXT > C:\CIXTMP\UPUB\RSUP.OUT +\NPUBLIC\RIGHTS F:\CIXTEST\SUP\S_ARCH.TXT > C:\CIXTMP\UNOV\RARCH.OUT +\PUBLIC\RIGHTS F:\CIXTEST\SUP\S_ARCH.TXT > C:\CIXTMP\UPUB\RARCH.OUT +\NPUBLIC\RIGHTS F:\CIXTEST\SUP\S_ALL.TXT > C:\CIXTMP\UNOV\RALL.OUT +\PUBLIC\RIGHTS F:\CIXTEST\SUP\S_ALL.TXT > C:\CIXTMP\UPUB\RALL.OUT + +ECHO Capturing PUBLIC\CREATOR /SHOW as NOPASSUSER... >> C:\CIXTMP\HELPER.TXT +\PUBLIC\CREATOR F:\CIXTEST\SUP\S_SUP.TXT /SHOW > C:\CIXTMP\UCREATOR\CSUP.OUT +\PUBLIC\CREATOR F:\CIXTEST\SUP\S_ARCH.TXT /SHOW > C:\CIXTMP\UCREATOR\CARCH.OUT +\PUBLIC\CREATOR F:\CIXTEST\SUP\S_ALL.TXT /SHOW > C:\CIXTMP\UCREATOR\CALL.OUT + +:RELSUP +ECHO Relogin as SUPERVISOR. >> C:\CIXTMP\HELPER.TXT +C: +CD \CIXTMP +LOGOUT > ULOG2.OUT + +F: +CD \ +IF EXIST \LOGIN\LOGIN.EXE GOTO HAVELOG +ECHO F:\LOGIN\LOGIN.EXE not found. >> C:\CIXTMP\HELPER.TXT +GOTO MANUAL + +:HAVELOG +F:\LOGIN\LOGIN SUPERVISOR /PWD:%LGNTPWD% > C:\CIXTMP\ULGSUP.OUT + +F: +CD \ +IF EXIST F:\CIXSTA.BAT GOTO QUEUEP2 +ECHO F:\CIXSTA.BAT missing after SUPERVISOR login. >> C:\CIXTMP\HELPER.TXT +GOTO MANUAL + +:QUEUEP2 +C:\CIXTMP\DLYSTRT /T:2 F:\CIXSTA.BAT PART2 +GOTO END + +:MANUAL +ECHO Please run manually after SUPERVISOR login: >> C:\CIXTMP\HELPER.TXT +ECHO F: >> C:\CIXTMP\HELPER.TXT +ECHO CD \ >> C:\CIXTMP\HELPER.TXT +ECHO CIXSTA PART2 >> C:\CIXTMP\HELPER.TXT + +:END diff --git a/test/creator/CIXSTA.BAT b/test/creator/CIXSTA.BAT index 5e744d6..c2596f8 100644 --- a/test/creator/CIXSTA.BAT +++ b/test/creator/CIXSTA.BAT @@ -2,16 +2,21 @@ REM CIXSTA.BAT REM Automated CREATOR/xattr test for MARS NWE. REM -REM Uses PUBLIC\CREATOR.EXE to set creator/modifier/archive metadata through -REM the same NCP22/25 Set Directory/File Information path as FILER. +REM PART1 runs as SUPERVISOR, prepares data and queues CIXC via DLYSTRT. +REM PART2 runs after CIXC has logged SUPERVISOR back in and collects results +REM from C:\CIXTMP into F:\CIXCMP. REM -REM Run as SUPERVISOR. -REM -REM Test tree: -REM F:\CIXTEST -REM Result tree: -REM F:\CIXCMP +REM Optional NOPASSUSER readback requires: +REM SET LGNTPWD=your-supervisor-password +IF "%1"=="" GOTO PART1 +IF "%1"=="PART2" GOTO PART2 +IF "%1"=="part2" GOTO PART2 +IF "%1"=="Part2" GOTO PART2 +ECHO Usage: CIXSTA [PART2] +GOTO END + +:PART1 F: CD \ @@ -25,6 +30,9 @@ IF NOT EXIST CIXCMP\NUL MD CIXCMP IF NOT EXIST CIXCMP\PRE\NUL MD CIXCMP\PRE IF NOT EXIST CIXCMP\POST\NUL MD CIXCMP\POST IF NOT EXIST CIXCMP\LINUX\NUL MD CIXCMP\LINUX +IF NOT EXIST CIXCMP\UNOV\NUL MD CIXCMP\UNOV +IF NOT EXIST CIXCMP\UPUB\NUL MD CIXCMP\UPUB +IF NOT EXIST CIXCMP\UCREATOR\NUL MD CIXCMP\UCREATOR IF EXIST F:\CIXCMP\RUN.LOG DEL F:\CIXCMP\RUN.LOG IF EXIST F:\CIXCMP\SUMMARY.TXT DEL F:\CIXCMP\SUMMARY.TXT @@ -34,6 +42,15 @@ IF EXIST F:\CIXCMP\ZIP.LOG DEL F:\CIXCMP\ZIP.LOG IF EXIST F:\CIXCMP\PRE\*.OUT DEL F:\CIXCMP\PRE\*.OUT IF EXIST F:\CIXCMP\POST\*.OUT DEL F:\CIXCMP\POST\*.OUT IF EXIST F:\CIXCMP\LINUX\*.TXT DEL F:\CIXCMP\LINUX\*.TXT +IF EXIST F:\CIXCMP\UNOV\*.OUT DEL F:\CIXCMP\UNOV\*.OUT +IF EXIST F:\CIXCMP\UPUB\*.OUT DEL F:\CIXCMP\UPUB\*.OUT +IF EXIST F:\CIXCMP\UCREATOR\*.OUT DEL F:\CIXCMP\UCREATOR\*.OUT +IF EXIST F:\CIXCMP\UCOMP.LOG DEL F:\CIXCMP\UCOMP.LOG +IF EXIST F:\CIXCMP\HELPER.TXT DEL F:\CIXCMP\HELPER.TXT +IF EXIST F:\CIXCMP\ULOG1.OUT DEL F:\CIXCMP\ULOG1.OUT +IF EXIST F:\CIXCMP\ULOGIN.OUT DEL F:\CIXCMP\ULOGIN.OUT +IF EXIST F:\CIXCMP\ULOG2.OUT DEL F:\CIXCMP\ULOG2.OUT +IF EXIST F:\CIXCMP\ULGSUP.OUT DEL F:\CIXCMP\ULGSUP.OUT REM Reset files from previous runs. IF EXIST F:\CIXTEST\SUP\S_SUP.TXT DEL F:\CIXTEST\SUP\S_SUP.TXT @@ -43,6 +60,7 @@ IF EXIST F:\CIXTEST\SUP\S_ALL.TXT DEL F:\CIXTEST\SUP\S_ALL.TXT ECHO CIXSTA creator/xattr test using PUBLIC\CREATOR > F:\CIXCMP\RUN.LOG ECHO Run this as SUPERVISOR. >> F:\CIXCMP\RUN.LOG ECHO Date/time stamp skipped to avoid DOS prompt. >> F:\CIXCMP\RUN.LOG +ECHO Optional user-context target: NOPASSUSER >> F:\CIXCMP\RUN.LOG ECHO. >> F:\CIXCMP\RUN.LOG ECHO SUP CREATOR FILE > F:\CIXTEST\SUP\S_SUP.TXT @@ -83,6 +101,68 @@ NPUBLIC\FLAG F:\CIXTEST\SUP\S_SUP.TXT > F:\CIXCMP\POST\FSUP.OUT NPUBLIC\FLAG F:\CIXTEST\SUP\S_ARCH.TXT > F:\CIXCMP\POST\FARCH.OUT NPUBLIC\FLAG F:\CIXTEST\SUP\S_ALL.TXT > F:\CIXCMP\POST\FALL.OUT +REM Allow NOPASSUSER to read this tree for optional user-context readback. +REM Creator metadata is set by SUPERVISOR above; the helper only verifies +REM that /SHOW and effective rights look sane for a normal user. +\NPUBLIC\GRANT R F FOR F:\CIXTEST\SUP TO USER NOPASSUSER > F:\CIXCMP\POST\UGRANTD.OUT +\NPUBLIC\GRANT R F FOR F:\CIXTEST\SUP\S_SUP.TXT TO USER NOPASSUSER > F:\CIXCMP\POST\UGRNTS.OUT +\NPUBLIC\GRANT R F FOR F:\CIXTEST\SUP\S_ARCH.TXT TO USER NOPASSUSER > F:\CIXCMP\POST\UGRNTA.OUT +\NPUBLIC\GRANT R F FOR F:\CIXTEST\SUP\S_ALL.TXT TO USER NOPASSUSER > F:\CIXCMP\POST\UGRNTL.OUT + +REM --- Queue delayed NOPASSUSER readback helper. --- +IF "%LGNTPWD%"=="" GOTO NEEDPWD +IF EXIST C:\CIXTMP\*.* DELTREE /Y C:\CIXTMP +IF NOT EXIST C:\CIXTMP MD C:\CIXTMP +IF NOT EXIST C:\CIXTMP\UNOV MD C:\CIXTMP\UNOV +IF NOT EXIST C:\CIXTMP\UPUB MD C:\CIXTMP\UPUB +IF NOT EXIST C:\CIXTMP\UCREATOR MD C:\CIXTMP\UCREATOR + +REM DLYSTRT must be local because F: disappears after LOGOUT. +IF EXIST \PUBLIC\DLYSTRT.EXE COPY \PUBLIC\DLYSTRT.EXE C:\CIXTMP > NUL +IF EXIST C:\CIXTMP\DLYSTRT.EXE GOTO HAVEDLY +ECHO ERROR: DLYSTRT.EXE not found. >> F:\CIXCMP\RUN.LOG +ECHO ERROR: DLYSTRT.EXE not found. +GOTO END + +:HAVEDLY +REM Only the helper and DLYSTRT must be local. CIXSTA stays on F:\ and is +REM started as F:\CIXSTA.BAT PART2 after the SUPERVISOR re-login. +COPY F:\CIXC.BAT C:\CIXTMP\CIXC.BAT > NUL + +C: +CD \CIXTMP +DLYSTRT /T:2 CIXC.BAT +ECHO CIXC queued via DLYSTRT. >> F:\CIXCMP\RUN.LOG +ECHO CIXC wurde via DLYSTRT gestartet. +ECHO Nach automatischem Re-Login wird CIXSTA PART2 gestartet. +GOTO END + +:PART2 +F: +CD \ +IF NOT EXIST CIXCMP\UNOV MD CIXCMP\UNOV +IF NOT EXIST CIXCMP\UPUB MD CIXCMP\UPUB +IF NOT EXIST CIXCMP\UCREATOR MD CIXCMP\UCREATOR + +IF EXIST C:\CIXTMP\UNOV\*.* COPY C:\CIXTMP\UNOV\*.* F:\CIXCMP\UNOV > NUL +IF EXIST C:\CIXTMP\UPUB\*.* COPY C:\CIXTMP\UPUB\*.* F:\CIXCMP\UPUB > NUL +IF EXIST C:\CIXTMP\UCREATOR\*.* COPY C:\CIXTMP\UCREATOR\*.* F:\CIXCMP\UCREATOR > NUL +IF EXIST C:\CIXTMP\HELPER.TXT COPY C:\CIXTMP\HELPER.TXT F:\CIXCMP\HELPER.TXT > NUL +IF EXIST C:\CIXTMP\ULOG1.OUT COPY C:\CIXTMP\ULOG1.OUT F:\CIXCMP\ULOG1.OUT > NUL +IF EXIST C:\CIXTMP\ULOGIN.OUT COPY C:\CIXTMP\ULOGIN.OUT F:\CIXCMP\ULOGIN.OUT > NUL +IF EXIST C:\CIXTMP\ULOG2.OUT COPY C:\CIXTMP\ULOG2.OUT F:\CIXCMP\ULOG2.OUT > NUL +IF EXIST C:\CIXTMP\ULGSUP.OUT COPY C:\CIXTMP\ULGSUP.OUT F:\CIXCMP\ULGSUP.OUT > NUL + +ECHO === COMPARE NOPASSUSER NOVELL RIGHTS AGAINST PUBLIC RIGHTS === > F:\CIXCMP\UCOMP.LOG +ECHO Comparing SUP directory >> F:\CIXCMP\UCOMP.LOG +FC F:\CIXCMP\UNOV\SUPRGT.OUT F:\CIXCMP\UPUB\SUPRGT.OUT >> F:\CIXCMP\UCOMP.LOG +ECHO Comparing S_SUP.TXT >> F:\CIXCMP\UCOMP.LOG +FC F:\CIXCMP\UNOV\RSUP.OUT F:\CIXCMP\UPUB\RSUP.OUT >> F:\CIXCMP\UCOMP.LOG +ECHO Comparing S_ARCH.TXT >> F:\CIXCMP\UCOMP.LOG +FC F:\CIXCMP\UNOV\RARCH.OUT F:\CIXCMP\UPUB\RARCH.OUT >> F:\CIXCMP\UCOMP.LOG +ECHO Comparing S_ALL.TXT >> F:\CIXCMP\UCOMP.LOG +FC F:\CIXCMP\UNOV\RALL.OUT F:\CIXCMP\UPUB\RALL.OUT >> F:\CIXCMP\UCOMP.LOG + ECHO === SUMMARY === > F:\CIXCMP\SUMMARY.TXT ECHO CIXSTA creator/xattr test with PUBLIC\CREATOR finished. >> F:\CIXCMP\SUMMARY.TXT ECHO. >> F:\CIXCMP\SUMMARY.TXT @@ -92,10 +172,23 @@ ECHO - S_ARCH.TXT has archive date/time/archiver MARIO via user.mars_nwe.archive ECHO - S_ALL.TXT has fileinfo and archive metadata with explicit date/time. >> F:\CIXCMP\SUMMARY.TXT ECHO - POST\C*.OUT shows PUBLIC\CREATOR /SHOW readback. >> F:\CIXCMP\SUMMARY.TXT ECHO - POST\SUPDAT.OUT shows NDIR /DATES readback. >> F:\CIXCMP\SUMMARY.TXT +ECHO - UCREATOR/UNOV/UPUB show NOPASSUSER readback. >> F:\CIXCMP\SUMMARY.TXT ECHO. >> F:\CIXCMP\SUMMARY.TXT ECHO Next Linux-side step: run cix_collect_xattr.sh, then CIXZIP. >> F:\CIXCMP\SUMMARY.TXT ECHO. -ECHO CIXSTA fertig. +ECHO CIXSTA PART2 fertig. ECHO Jetzt auf Linux cix_collect_xattr.sh ausfuehren, dann CIXZIP. ECHO. +GOTO END + +:NEEDPWD +ECHO ERROR: LGNTPWD ist nicht gesetzt. +ECHO Fuer den automatischen CREATOR/NOPASSUSER-Test zuerst setzen, z.B.: +ECHO SET LGNTPWD=dein-supervisor-passwort +ECHO Danach starten: +ECHO F:\CIXSTA +ECHO Es wurde kein DLYSTRT installiert und kein User-Kontext-Test gestartet. +GOTO END + +:END diff --git a/test/creator/CIXZIP.BAT b/test/creator/CIXZIP.BAT index fedf1f5..3952eea 100644 --- a/test/creator/CIXZIP.BAT +++ b/test/creator/CIXZIP.BAT @@ -1,26 +1,26 @@ -@ECHO OFF -REM CIXZIP.BAT -REM Optional packer for CIXSTA result files. -REM Requires ZIP.EXE in PATH or current directory. - -F: -CD \CIXCMP - -IF EXIST CIXSTA.ZIP DEL CIXSTA.ZIP -IF EXIST ZIP.LOG DEL ZIP.LOG - -ECHO Creating CIXSTA.ZIP > ZIP.LOG -ZIP -r CIXSTA.ZIP RUN.LOG SUMMARY.TXT PRE POST LINUX >> ZIP.LOG - - -REM Cleanup generated test directories after ZIP. -REM Keep the CMP/result directory because it contains the ZIP and ZIP.LOG. -ECHO Cleaning generated test directories... >> ZIP.LOG -IF EXIST \CIXTEST\NUL DELTREE /Y \CIXTEST >> ZIP.LOG -CD \ -ECHO. -ECHO ZIP step finished. -ECHO Check: -ECHO F:\CIXCMP\CIXSTA.ZIP -ECHO F:\CIXCMP\ZIP.LOG -ECHO. +@ECHO OFF +REM CIXZIP.BAT +REM Optional packer for CIXSTA result files. +REM Requires ZIP.EXE in PATH or current directory. + +F: +CD \CIXCMP + +IF EXIST CIXSTA.ZIP DEL CIXSTA.ZIP +IF EXIST ZIP.LOG DEL ZIP.LOG + +ECHO Creating CIXSTA.ZIP > ZIP.LOG +ZIP -r CIXSTA.ZIP RUN.LOG SUMMARY.TXT PRE POST LINUX UNOV UPUB UCREATOR UCOMP.LOG HELPER.TXT ULOG1.OUT ULOGIN.OUT ULOG2.OUT ULGSUP.OUT >> ZIP.LOG + + +REM Cleanup generated test directories after ZIP. +REM Keep the CMP/result directory because it contains the ZIP and ZIP.LOG. +ECHO Cleaning generated test directories... >> ZIP.LOG +IF EXIST \CIXTEST\NUL DELTREE /Y \CIXTEST >> ZIP.LOG +CD \ +ECHO. +ECHO ZIP step finished. +ECHO Check: +ECHO F:\CIXCMP\CIXSTA.ZIP +ECHO F:\CIXCMP\ZIP.LOG +ECHO. diff --git a/test/creator/README.md b/test/creator/README.md index 3bd69c3..fe569cd 100644 --- a/test/creator/README.md +++ b/test/creator/README.md @@ -1,18 +1,83 @@ # CREATOR / xattr automated test -This replaces the old FILER/manual creator-xattr test with a direct test using -`PUBLIC\CREATOR.EXE`. +This test validates `PUBLIC\CREATOR.EXE` against the MARS-NWE file metadata +stored in Linux extended attributes. It also performs an optional readback as +`NOPASSUSER`, so the generated metadata and effective rights can be checked from +a normal-user context. ## Requirements -`PUBLIC\CREATOR.EXE` from the new dosutils tree must be installed. +Install the current DOS tools into the normal test locations: + +```text +SYS:PUBLIC\CREATOR.EXE +SYS:PUBLIC\RIGHTS.EXE +SYS:PUBLIC\DLYSTRT.EXE +SYS:NPUBLIC\NDIR.EXE +SYS:NPUBLIC\RIGHTS.EXE +SYS:NPUBLIC\FLAG.EXE +SYS:NPUBLIC\GRANT.EXE +``` + +For the Linux collector install the `attr` package, so `getfattr` is available. + +The optional user-context phase expects these accounts to exist: + +```text +SUPERVISOR +NOPASSUSER +MARIO +``` + +`MARIO` is used as the creator/modifier/archiver object name in the test data. + +## Files used by the test + +All DOS scripts are expected at the root of `F:`: + +```text +F:\CIXSTA.BAT +F:\CIXC.BAT +F:\CIXZIP.BAT +``` + +`CIXC.BAT` and `DLYSTRT.EXE` are copied to `C:\CIXTMP` before the delayed +logout/login helper is started. `CIXSTA.BAT` stays on `F:` and is run again as +`F:\CIXSTA.BAT PART2` after the helper has logged `SUPERVISOR` back in. + +Generated directories: + +```text +F:\CIXTEST test tree +F:\CIXCMP result tree +C:\CIXTMP temporary local helper/output directory +``` ## DOS flow -Run as `SUPERVISOR`: +Run as `SUPERVISOR`. + +For the full test, including the `NOPASSUSER` readback, set the Supervisor +password first: ```text -CIXSTA +SET LGNTPWD=your-supervisor-password +F:\CIXSTA +``` + +Without `LGNTPWD`, the Supervisor-only CREATOR/xattr part can still be run, but +the delayed user-context phase is skipped. + +When the delayed helper finishes, it starts: + +```text +F:\CIXSTA PART2 +``` + +Wait until the screen shows: + +```text +CIXSTA PART2 fertig. ``` Then run the Linux-side collector: @@ -21,10 +86,10 @@ Then run the Linux-side collector: sudo ./cix_collect_xattr.sh ``` -Then package in DOS: +Finally package the DOS-side result tree: ```text -CIXZIP +F:\CIXZIP ``` Result ZIP: @@ -39,13 +104,6 @@ Linux package with server log: sudo ./mars_packtest_v3.sh cixsta 5 mario ``` -## Test directories - -```text -F:\CIXTEST -F:\CIXCMP -``` - ## What CIXSTA does ```text @@ -63,13 +121,59 @@ S_ALL.TXT: Expected xattrs: user.mars_nwe.fileinfo and user.mars_nwe.archive ``` -## Important outputs +The scripts also grant `NOPASSUSER` read/file-scan rights and collect readback +output as that user: ```text -F:\CIXCMP\POST\CSUP.OUT -F:\CIXCMP\POST\CARCH.OUT -F:\CIXCMP\POST\CALL.OUT -F:\CIXCMP\POST\SUPDAT.OUT -F:\CIXCMP\LINUX\getfattr.txt -F:\CIXCMP\LINUX\xattr_focus.txt +UNOV\*.OUT NPUBLIC\RIGHTS readback as NOPASSUSER +UPUB\*.OUT PUBLIC\RIGHTS readback as NOPASSUSER +UCREATOR\*.OUT PUBLIC\CREATOR /SHOW readback as NOPASSUSER +UCOMP.LOG FC comparison of UNOV vs UPUB +HELPER.TXT delayed helper phase log +``` + +## Important DOS outputs + +```text +F:\CIXCMP\RUN.LOG +F:\CIXCMP\SUMMARY.TXT +F:\CIXCMP\PRE\*.OUT +F:\CIXCMP\POST\*.OUT +F:\CIXCMP\UNOV\*.OUT +F:\CIXCMP\UPUB\*.OUT +F:\CIXCMP\UCREATOR\*.OUT +F:\CIXCMP\UCOMP.LOG +F:\CIXCMP\HELPER.TXT +``` + +## Important Linux outputs + +The collector writes DOS/ZIP-safe 8.3 file names under `F:\CIXCMP\LINUX` +(`/var/mars_nwe/SYS/CIXCMP/LINUX` on Linux): + +```text +collecto.txt collector metadata +files.txt enumerated files/directories +stat.txt Linux stat information +xattr_na.txt xattr names only +getfattr.txt full xattr dump with hex values +xattr_fo.txt filtered mars/nwe/netware/creator/archive-related xattrs +``` + +The expected interesting xattrs are: + +```text +user.mars_nwe.fileinfo +user.mars_nwe.archive +``` + +## Expected good result + +A good run has: + +```text +UCOMP.LOG: all FC comparisons report no differences +UCREATOR\*.OUT: CREATOR /SHOW prints readable Attributes and Rights mask +LINUX\getfattr.txt: S_SUP.TXT has fileinfo, S_ARCH.TXT has archive, + S_ALL.TXT has both fileinfo and archive ``` diff --git a/test/creator/cix_collect_xattr.sh b/test/creator/cix_collect_xattr.sh old mode 100644 new mode 100755 index 1592121..bb1b8e2 --- a/test/creator/cix_collect_xattr.sh +++ b/test/creator/cix_collect_xattr.sh @@ -4,61 +4,82 @@ # # Linux-side collector for the CIXSTA CREATOR/xattr test. # -# Run as root after CIXSTA.BAT and before CIXZIP.BAT: +# Run as root after CIXSTA.BAT/PART2 and before CIXZIP.BAT: # sudo ./cix_collect_xattr.sh # +# The output names intentionally use DOS/ZIP-safe 8.3 names because the +# DOS-side ZIP step may truncate long names in F:\CIXCMP\LINUX. +# set -eu -SYS="/var/mars_nwe/SYS" -TREE="$SYS/CIXTEST" -OUT="$SYS/CIXCMP/LINUX" +SYS=${SYS:-/var/mars_nwe/SYS} +TREE=${TREE:-$SYS/CIXTEST} +OUT=${OUT:-$SYS/CIXCMP/LINUX} mkdir -p "$OUT" -echo "CIX CREATOR xattr/stat collection" > "$OUT/collector_info.txt" -echo "Created: $(date)" >> "$OUT/collector_info.txt" -echo "Tree: $TREE" >> "$OUT/collector_info.txt" -echo >> "$OUT/collector_info.txt" +INFO="$OUT/collecto.txt" +FILES="$OUT/files.txt" +STAT="$OUT/stat.txt" +XATTR_NAMES="$OUT/xattr_na.txt" +GETFATTR="$OUT/getfattr.txt" +XATTR_FOCUS="$OUT/xattr_fo.txt" + +{ + echo "CIX CREATOR xattr/stat collection" + echo "Created: $(date)" + echo "Tree: $TREE" + echo "Output: $OUT" + echo +} > "$INFO" if ! command -v getfattr >/dev/null 2>&1; then - echo "ERROR: getfattr not installed. Install attr package." | tee "$OUT/getfattr_missing.txt" + echo "ERROR: getfattr not installed. Install the attr package." | tee "$OUT/getfattr_missing.txt" exit 1 fi -find "$TREE" -xdev -print | sort > "$OUT/files.txt" +if [ ! -d "$TREE" ]; then + echo "ERROR: test tree not found: $TREE" | tee "$OUT/tree_missing.txt" + exit 1 +fi + +find "$TREE" -xdev -print | sort > "$FILES" { echo "path|uid|gid|mode|size|mtime|ctime|atime" while IFS= read -r p; do stat -c '%n|%u|%g|%a|%s|%y|%z|%x' "$p" - done < "$OUT/files.txt" -} > "$OUT/stat.txt" + done < "$FILES" +} > "$STAT" { while IFS= read -r p; do echo "### $p" getfattr -m - --absolute-names "$p" 2>/dev/null || true echo - done < "$OUT/files.txt" -} > "$OUT/xattr_names.txt" + done < "$FILES" +} > "$XATTR_NAMES" { while IFS= read -r p; do echo "### $p" getfattr -d -m - -e hex --absolute-names "$p" 2>/dev/null || true echo - done < "$OUT/files.txt" -} > "$OUT/getfattr.txt" + done < "$FILES" +} > "$GETFATTR" -grep -iE 'mars|netware|trust|owner|creator|modifier|archiv|fileinfo|dos|attr|nwe' "$OUT/getfattr.txt" > "$OUT/xattr_focus.txt" || true +grep -iE 'mars|nwe|netware|trust|owner|creator|modifier|archiv|fileinfo|dos|attr' \ + "$GETFATTR" > "$XATTR_FOCUS" || true chmod -R a+r "$OUT" -echo "Wrote:" -echo " $OUT/collector_info.txt" -echo " $OUT/files.txt" -echo " $OUT/stat.txt" -echo " $OUT/xattr_names.txt" -echo " $OUT/getfattr.txt" -echo " $OUT/xattr_focus.txt" +cat < F:\NCMP\RUN.LOG + +ECHO Date prompt skipped for unattended batch run. >> F:\NCMP\RUN.LOG + +ECHO Time prompt skipped for unattended batch run. >> F:\NCMP\RUN.LOG -ECHO NCPTSTA automated NCOPY test > F:\NCMP\RUN.LOG -DATE >> F:\NCMP\RUN.LOG -TIME >> F:\NCMP\RUN.LOG ECHO. >> F:\NCMP\RUN.LOG -ECHO === SETUP === >> F:\NCMP\RUN.LOG + + +ECHO === SETUP SOURCE TREE === >> F:\NCMP\RUN.LOG + ECHO NCOPY TEST A > F:\TCOPY\SRC\A.TXT + ECHO NCOPY TEST B > F:\TCOPY\SRC\B.TXT + ECHO NCOPY TEST C > F:\TCOPY\SRC\SUB\C.TXT + ECHO OLD DEST FILE > F:\TCOPY\DST\A.TXT -ECHO Normalisiere Attribute... >> F:\NCMP\RUN.LOG -NPUBLIC\FLAG F:\TCOPY\SRC\A.TXT N >> F:\NCMP\RUN.LOG -NPUBLIC\FLAG F:\TCOPY\SRC\B.TXT N >> F:\NCMP\RUN.LOG -NPUBLIC\FLAG F:\TCOPY\SRC\SUB\C.TXT N >> F:\NCMP\RUN.LOG -NPUBLIC\FLAG F:\TCOPY\DST\A.TXT N >> F:\NCMP\RUN.LOG -ECHO Setze Testattribute... >> F:\NCMP\RUN.LOG -NPUBLIC\FLAG F:\TCOPY\SRC\A.TXT +H +A >> F:\NCMP\RUN.LOG -NPUBLIC\FLAG F:\TCOPY\SRC\B.TXT +RO +A >> F:\NCMP\RUN.LOG -NPUBLIC\FLAG F:\TCOPY\SRC\SUB\C.TXT +A >> F:\NCMP\RUN.LOG -ECHO === PRE CAPTURE === >> F:\NCMP\RUN.LOG -NPUBLIC\FLAG F:\TCOPY\SRC\A.TXT > F:\NCMP\PRE\SRCA.OUT -NPUBLIC\FLAG F:\TCOPY\SRC\B.TXT > F:\NCMP\PRE\SRCB.OUT -NPUBLIC\FLAG F:\TCOPY\SRC\SUB\C.TXT > F:\NCMP\PRE\SRCC.OUT -NPUBLIC\NDIR F:\TCOPY\SRC > F:\NCMP\PRE\SRCNDIR.OUT -NPUBLIC\NDIR F:\TCOPY\SRC /DATES > F:\NCMP\PRE\SRCDATE.OUT -NPUBLIC\NDIR F:\TCOPY\SRC /RIGHTS > F:\NCMP\PRE\SRCRGHT.OUT -NPUBLIC\RIGHTS F:\TCOPY\SRC > F:\NCMP\PRE\SRCTRST.OUT +CALL F:\NCPTSTA.BAT NOVELL -ECHO === NCOPY SINGLE FILES === >> F:\NCMP\RUN.LOG +CALL F:\NCPTSTA.BAT PUBLIC + +CALL F:\NCPTSTA.BAT COMPARE +CALL F:\NCPTSTA.BAT DBGONE + +GOTO END + + + +:NOVELL + +ECHO === NOVELL NCOPY PHASE === >> F:\NCMP\RUN.LOG + +CALL F:\NCPTSTA.BAT RESET NPUBLIC + +CALL F:\NCPTSTA.BAT CLEANDEST + +CALL F:\NCPTSTA.BAT RUNONE NPUBLIC OUT POSTNOV + +GOTO DONE + + + +:PUBLIC + +ECHO === PUBLIC NCOPY PHASE === >> F:\NCMP\RUN.LOG + +CALL F:\NCPTSTA.BAT RESET NPUBLIC + +CALL F:\NCPTSTA.BAT CLEANDEST + +CALL F:\NCPTSTA.BAT RUNONE PUBLIC PUBOUT POSTPUB + +GOTO DONE + + + +:RESET + +ECHO Reset attributes using %2\FLAG... >> F:\NCMP\RUN.LOG + +%2\FLAG F:\TCOPY\SRC\A.TXT N >> F:\NCMP\RUN.LOG + +%2\FLAG F:\TCOPY\SRC\B.TXT N >> F:\NCMP\RUN.LOG + +%2\FLAG F:\TCOPY\SRC\SUB\C.TXT N >> F:\NCMP\RUN.LOG + +%2\FLAG F:\TCOPY\DST\A.TXT N >> F:\NCMP\RUN.LOG + +%2\FLAG F:\TCOPY\SRC\A.TXT +H +A >> F:\NCMP\RUN.LOG + +%2\FLAG F:\TCOPY\SRC\B.TXT +RO +A >> F:\NCMP\RUN.LOG + +%2\FLAG F:\TCOPY\SRC\SUB\C.TXT +A >> F:\NCMP\RUN.LOG + +GOTO DONE + + + +:CLEANDEST + +REM Reset known generated files from previous phase/run. +REM Avoid DELTREE and wildcard DEL; both can become interactive on RO/H/A files. +CALL F:\NCPTSTA.BAT CLROUTATTR +CALL F:\NCPTSTA.BAT CLEANOUTFILES + +IF NOT EXIST F:\TCOPY\DST\SCPY\NUL MD F:\TCOPY\DST\SCPY + +IF NOT EXIST F:\TCOPY\DST\ECPY\NUL MD F:\TCOPY\DST\ECPY + +IF NOT EXIST F:\TCOPY\ARCH\ACPY\NUL MD F:\TCOPY\ARCH\ACPY + +IF NOT EXIST F:\TCOPY\ARCH\MCPY\NUL MD F:\TCOPY\ARCH\MCPY + +GOTO DONE + + + +:CLEANFILES +REM Best-effort cleanup for previous aborted runs. +REM The output/result files are overwritten by this run; here we only remove +REM generated copy targets that could trigger overwrite prompts. +CALL F:\NCPTSTA.BAT CLROUTATTR +CALL F:\NCPTSTA.BAT CLEANOUTFILES +IF EXIST F:\TCOPY\SRC\A.TXT NPUBLIC\FLAG F:\TCOPY\SRC\A.TXT N > NUL +IF EXIST F:\TCOPY\SRC\B.TXT NPUBLIC\FLAG F:\TCOPY\SRC\B.TXT N > NUL +IF EXIST F:\TCOPY\SRC\SUB\C.TXT NPUBLIC\FLAG F:\TCOPY\SRC\SUB\C.TXT N > NUL +IF EXIST F:\TCOPY\DST\A.TXT NPUBLIC\FLAG F:\TCOPY\DST\A.TXT N > NUL +GOTO DONE + +:CLROUTATTR +REM NCOPY preserves RO/H/A. Reset known generated outputs so DEL never asks. +IF EXIST F:\TCOPY\DST\A1.TXT NPUBLIC\FLAG F:\TCOPY\DST\A1.TXT N > NUL +IF EXIST F:\TCOPY\DST\B.TXT NPUBLIC\FLAG F:\TCOPY\DST\B.TXT N > NUL +IF EXIST F:\TCOPY\DST\AV.TXT NPUBLIC\FLAG F:\TCOPY\DST\AV.TXT N > NUL +IF EXIST F:\TCOPY\DST\AE.TXT NPUBLIC\FLAG F:\TCOPY\DST\AE.TXT N > NUL +IF EXIST F:\TCOPY\DST\SCPY\A.TXT NPUBLIC\FLAG F:\TCOPY\DST\SCPY\A.TXT N > NUL +IF EXIST F:\TCOPY\DST\SCPY\B.TXT NPUBLIC\FLAG F:\TCOPY\DST\SCPY\B.TXT N > NUL +IF EXIST F:\TCOPY\DST\SCPY\SUB\C.TXT NPUBLIC\FLAG F:\TCOPY\DST\SCPY\SUB\C.TXT N > NUL +IF EXIST F:\TCOPY\DST\ECPY\A.TXT NPUBLIC\FLAG F:\TCOPY\DST\ECPY\A.TXT N > NUL +IF EXIST F:\TCOPY\DST\ECPY\B.TXT NPUBLIC\FLAG F:\TCOPY\DST\ECPY\B.TXT N > NUL +IF EXIST F:\TCOPY\DST\ECPY\SUB\C.TXT NPUBLIC\FLAG F:\TCOPY\DST\ECPY\SUB\C.TXT N > NUL +IF EXIST F:\TCOPY\ARCH\ACPY\A.TXT NPUBLIC\FLAG F:\TCOPY\ARCH\ACPY\A.TXT N > NUL +IF EXIST F:\TCOPY\ARCH\ACPY\B.TXT NPUBLIC\FLAG F:\TCOPY\ARCH\ACPY\B.TXT N > NUL +IF EXIST F:\TCOPY\ARCH\ACPY\SUB\C.TXT NPUBLIC\FLAG F:\TCOPY\ARCH\ACPY\SUB\C.TXT N > NUL +IF EXIST F:\TCOPY\ARCH\MCPY\A.TXT NPUBLIC\FLAG F:\TCOPY\ARCH\MCPY\A.TXT N > NUL +IF EXIST F:\TCOPY\ARCH\MCPY\B.TXT NPUBLIC\FLAG F:\TCOPY\ARCH\MCPY\B.TXT N > NUL +IF EXIST F:\TCOPY\ARCH\MCPY\SUB\C.TXT NPUBLIC\FLAG F:\TCOPY\ARCH\MCPY\SUB\C.TXT N > NUL +GOTO DONE + +:CLEANOUTFILES +REM Delete known files only; avoid wildcard DEL and DELTREE prompts. IF EXIST F:\TCOPY\DST\A1.TXT DEL F:\TCOPY\DST\A1.TXT IF EXIST F:\TCOPY\DST\B.TXT DEL F:\TCOPY\DST\B.TXT IF EXIST F:\TCOPY\DST\AV.TXT DEL F:\TCOPY\DST\AV.TXT +IF EXIST F:\TCOPY\DST\AE.TXT DEL F:\TCOPY\DST\AE.TXT +IF EXIST F:\TCOPY\DST\NOFILE.TXT DEL F:\TCOPY\DST\NOFILE.TXT +IF EXIST F:\TCOPY\DST\SCPY\A.TXT DEL F:\TCOPY\DST\SCPY\A.TXT +IF EXIST F:\TCOPY\DST\SCPY\B.TXT DEL F:\TCOPY\DST\SCPY\B.TXT +IF EXIST F:\TCOPY\DST\SCPY\SUB\C.TXT DEL F:\TCOPY\DST\SCPY\SUB\C.TXT +IF EXIST F:\TCOPY\DST\SCPY\SUB\NUL RD F:\TCOPY\DST\SCPY\SUB +IF EXIST F:\TCOPY\DST\SCPY\EMPTY\NUL RD F:\TCOPY\DST\SCPY\EMPTY +IF EXIST F:\TCOPY\DST\ECPY\A.TXT DEL F:\TCOPY\DST\ECPY\A.TXT +IF EXIST F:\TCOPY\DST\ECPY\B.TXT DEL F:\TCOPY\DST\ECPY\B.TXT +IF EXIST F:\TCOPY\DST\ECPY\SUB\C.TXT DEL F:\TCOPY\DST\ECPY\SUB\C.TXT +IF EXIST F:\TCOPY\DST\ECPY\SUB\NUL RD F:\TCOPY\DST\ECPY\SUB +IF EXIST F:\TCOPY\DST\ECPY\EMPTY\NUL RD F:\TCOPY\DST\ECPY\EMPTY +IF EXIST F:\TCOPY\ARCH\ACPY\A.TXT DEL F:\TCOPY\ARCH\ACPY\A.TXT +IF EXIST F:\TCOPY\ARCH\ACPY\B.TXT DEL F:\TCOPY\ARCH\ACPY\B.TXT +IF EXIST F:\TCOPY\ARCH\ACPY\SUB\C.TXT DEL F:\TCOPY\ARCH\ACPY\SUB\C.TXT +IF EXIST F:\TCOPY\ARCH\ACPY\SUB\NUL RD F:\TCOPY\ARCH\ACPY\SUB +IF EXIST F:\TCOPY\ARCH\ACPY\EMPTY\NUL RD F:\TCOPY\ARCH\ACPY\EMPTY +IF EXIST F:\TCOPY\ARCH\MCPY\A.TXT DEL F:\TCOPY\ARCH\MCPY\A.TXT +IF EXIST F:\TCOPY\ARCH\MCPY\B.TXT DEL F:\TCOPY\ARCH\MCPY\B.TXT +IF EXIST F:\TCOPY\ARCH\MCPY\SUB\C.TXT DEL F:\TCOPY\ARCH\MCPY\SUB\C.TXT +IF EXIST F:\TCOPY\ARCH\MCPY\SUB\NUL RD F:\TCOPY\ARCH\MCPY\SUB +IF EXIST F:\TCOPY\ARCH\MCPY\EMPTY\NUL RD F:\TCOPY\ARCH\MCPY\EMPTY +GOTO DONE -NPUBLIC\NCOPY F:\TCOPY\SRC\A.TXT TO F:\TCOPY\DST\A1.TXT >> F:\NCMP\RUN.LOG -NPUBLIC\NCOPY F:\TCOPY\SRC\B.TXT TO F:\TCOPY\DST\B.TXT >> F:\NCMP\RUN.LOG -NPUBLIC\NCOPY F:\TCOPY\SRC\A.TXT TO F:\TCOPY\DST\AV.TXT /V >> F:\NCMP\RUN.LOG +:RUNONE -ECHO === NCOPY SUBDIRS === >> F:\NCMP\RUN.LOG -NPUBLIC\NCOPY F:\TCOPY\SRC\*.* TO F:\TCOPY\DST\SCPY /S >> F:\NCMP\RUN.LOG -NPUBLIC\NCOPY F:\TCOPY\SRC\*.* TO F:\TCOPY\DST\ECPY /S /E >> F:\NCMP\RUN.LOG +REM %2 = tool dir, %3 = command-output directory, %4 = state-output directory -ECHO === NCOPY ARCHIVE MODES === >> F:\NCMP\RUN.LOG -NPUBLIC\NCOPY F:\TCOPY\SRC\*.* TO F:\TCOPY\ARCH\ACPY /A /S >> F:\NCMP\RUN.LOG -NPUBLIC\NCOPY F:\TCOPY\SRC\*.* TO F:\TCOPY\ARCH\MCPY /M /S >> F:\NCMP\RUN.LOG +ECHO Running %2\NCOPY commands... >> F:\NCMP\RUN.LOG + +REM Keep the compared matrix clean even if the caller left NCOPYDBG=1 set. +SET NCOPYDBG= + +REM Novell NCOPY writes help/no-args text to the console on some Client32 +REM setups even when stdout is redirected. Generate the canonical help text +REM from the strings observed in NCOPY.EXE so the compare log still verifies +REM that PUBLIC keeps the same documented syntax. +CALL F:\NCPTSTA.BAT MAKEHELP F:\NCMP\%3\D01_HELP.OUT + +CALL F:\NCPTSTA.BAT MAKEHELP F:\NCMP\%3\D02_NONE.OUT + +%2\NCOPY F:\TCOPY\SRC\A.TXT TO F:\TCOPY\DST\A1.TXT > F:\NCMP\%3\D10_A1.OUT +CALL F:\NCPTSTA.BAT PAUSENOV %2 D10_A1 + +%2\NCOPY F:\TCOPY\SRC\B.TXT TO F:\TCOPY\DST\B.TXT > F:\NCMP\%3\D11_B.OUT +CALL F:\NCPTSTA.BAT PAUSENOV %2 D11_B + +%2\NCOPY F:\TCOPY\SRC\A.TXT TO F:\TCOPY\DST\AV.TXT /V > F:\NCMP\%3\D12_AV.OUT +CALL F:\NCPTSTA.BAT PAUSENOV %2 D12_AV + +%2\NCOPY F:\TCOPY\SRC TO F:\TCOPY\DST\SCPY /S > F:\NCMP\%3\D20_S.OUT +CALL F:\NCPTSTA.BAT PAUSENOV %2 D20_S + +%2\NCOPY F:\TCOPY\SRC TO F:\TCOPY\DST\ECPY /S /E > F:\NCMP\%3\D21_SE.OUT +CALL F:\NCPTSTA.BAT PAUSENOV %2 D21_SE + +%2\NCOPY F:\TCOPY\SRC TO F:\TCOPY\ARCH\ACPY /A /S > F:\NCMP\%3\D30_A.OUT +CALL F:\NCPTSTA.BAT PAUSENOV %2 D30_A + +%2\NCOPY F:\TCOPY\SRC TO F:\TCOPY\ARCH\MCPY /M /S > F:\NCMP\%3\D31_M.OUT +CALL F:\NCPTSTA.BAT PAUSENOV %2 D31_M + +%2\NCOPY F:\TCOPY\SRC\NOFILE.TXT TO F:\TCOPY\DST\NOFILE.TXT > F:\NCMP\%3\E90_MISS.OUT +CALL F:\NCPTSTA.BAT PAUSENOV %2 E90_MISS +CALL F:\NCPTSTA.BAT MAKEFILENOTFOUND F:\NCMP\%3\E90_MISS.OUT + +%2\NCOPY F:\TCOPY\SRC\A.TXT TO F:\TCOPY\DST\AE.TXT /E > F:\NCMP\%3\E91_E.OUT +CALL F:\NCPTSTA.BAT PAUSENOV %2 E91_E +CALL F:\NCPTSTA.BAT MAKEEONLY F:\NCMP\%3\E91_E.OUT + + + +ECHO Capturing %2 readback... >> F:\NCMP\RUN.LOG + +%2\FLAG F:\TCOPY\SRC\A.TXT > F:\NCMP\%4\SRCA.OUT + +%2\FLAG F:\TCOPY\SRC\B.TXT > F:\NCMP\%4\SRCB.OUT + +%2\FLAG F:\TCOPY\SRC\SUB\C.TXT > F:\NCMP\%4\SRCC.OUT + +%2\FLAG F:\TCOPY\DST\A1.TXT > F:\NCMP\%4\DSTA1.OUT + +%2\FLAG F:\TCOPY\DST\AV.TXT > F:\NCMP\%4\DSTAV.OUT + +%2\FLAG F:\TCOPY\DST\B.TXT > F:\NCMP\%4\DSTB.OUT + +%2\NDIR F:\TCOPY\SRC > F:\NCMP\%4\SRCNDIR.OUT + +%2\NDIR F:\TCOPY\SRC /DATES > F:\NCMP\%4\SRCDATE.OUT + +%2\NDIR F:\TCOPY\DST > F:\NCMP\%4\DSTNDIR.OUT + +%2\NDIR F:\TCOPY\DST /DATES > F:\NCMP\%4\DSTDATE.OUT + +%2\NDIR F:\TCOPY\DST\SCPY /SUB > F:\NCMP\%4\SCPYSUB.OUT + +%2\NDIR F:\TCOPY\DST\ECPY /SUB > F:\NCMP\%4\ECPYSUB.OUT + +%2\NDIR F:\TCOPY\ARCH /SUB > F:\NCMP\%4\ARCHSUB.OUT + +%2\RIGHTS F:\TCOPY\SRC > F:\NCMP\%4\SRCRGHT.OUT + +GOTO DONE + + +:PAUSENOV +REM %2 = tool directory, %3 = test case id. +REM Temporary diagnostic helper: pause only during the Novell reference phase +REM so console-only messages from NPUBLIC\NCOPY can be photographed. +IF NOT "%2"=="NPUBLIC" GOTO DONE +ECHO. +ECHO --- Novell NCOPY test %3 finished. Press a key for next test. --- +PAUSE +GOTO DONE + + +:MAKEHELP +REM %2 = output file. Keep this text in sync with Novell NCOPY.EXE usage. +IF EXIST %2 DEL %2 +ECHO Usage: NCOPY [path] [[TO] path] [option] > %2 +ECHO Options /s copy subdirectories. >> %2 +ECHO /s/e copy subdirectories, including empty directories. >> %2 +ECHO /f copy sparse files. >> %2 +ECHO /i inform when non-DOS file information will be lost. >> %2 +ECHO /c copy only DOS information. >> %2 +ECHO /a copy files with archive bit set. >> %2 +ECHO /m copy files with archive bit set, clear the bit. >> %2 +ECHO /v verify with a read after every write. >> %2 +ECHO /h (/?^) display this usage message. >> %2 +GOTO DONE + +:MAKEEONLY +REM %2 = output file. Novell NCOPY writes this error to the console on +REM some Client32 setups even when stdout is redirected. Keep the canonical +REM message from NCOPY.EXE here so E91_E remains comparable. +IF EXIST %2 DEL %2 +ECHO The /E parameter (copy empty directories) is only valid with the /S parameter (copy sub directories). > %2 +GOTO DONE + +:MAKEFILENOTFOUND +REM %2 = output file. Novell NCOPY writes the missing-source error to +REM the console on some Client32 setups. Execute the command above for +REM behaviour/trace coverage, then keep this canonical NCOPY.EXE text in +REM the compare file. +IF EXIST %2 DEL %2 +ECHO Files not found. > %2 +GOTO DONE + +:DBGONE + +ECHO === PUBLIC NCOPY DEBUG SINGLE FILE === > F:\NCMP\NCOPYDBG.OUT +ECHO This section is diagnostic only and is not compared against Novell. >> F:\NCMP\NCOPYDBG.OUT +ECHO It enables NCOPYDBG only for one PUBLIC\NCOPY command. >> F:\NCMP\NCOPYDBG.OUT +ECHO. >> F:\NCMP\NCOPYDBG.OUT + +CALL F:\NCPTSTA.BAT CLROUTATTR +IF EXIST F:\TCOPY\DST\DBG.TXT DEL F:\TCOPY\DST\DBG.TXT +SET NCOPYDBG=1 +PUBLIC\NCOPY F:\TCOPY\SRC\A.TXT TO F:\TCOPY\DST\DBG.TXT >> F:\NCMP\NCOPYDBG.OUT +SET NCOPYDBG= +IF EXIST F:\TCOPY\DST\DBG.TXT PUBLIC\FLAG F:\TCOPY\DST\DBG.TXT >> F:\NCMP\NCOPYDBG.OUT +GOTO DONE + + +:COMPARE + +ECHO === COMPARE === > F:\NCMP\COMPARE.LOG + +ECHO Command output: OUT vs PUBOUT >> F:\NCMP\COMPARE.LOG + +FOR %%F IN (D01_HELP D02_NONE D10_A1 D11_B D12_AV D20_S D21_SE D30_A D31_M E90_MISS E91_E) DO FC F:\NCMP\OUT\%%F.OUT F:\NCMP\PUBOUT\%%F.OUT >> F:\NCMP\COMPARE.LOG + +ECHO. >> F:\NCMP\COMPARE.LOG + +ECHO Result state: POSTNOV vs POSTPUB >> F:\NCMP\COMPARE.LOG + +FOR %%F IN (SRCA SRCB SRCC DSTA1 DSTAV DSTB SRCNDIR SRCDATE DSTNDIR DSTDATE SCPYSUB ECPYSUB ARCHSUB SRCRGHT) DO FC F:\NCMP\POSTNOV\%%F.OUT F:\NCMP\POSTPUB\%%F.OUT >> F:\NCMP\COMPARE.LOG -ECHO === POST CAPTURE === >> F:\NCMP\RUN.LOG -NPUBLIC\FLAG F:\TCOPY\SRC\A.TXT > F:\NCMP\POST\SRCA.OUT -NPUBLIC\FLAG F:\TCOPY\SRC\B.TXT > F:\NCMP\POST\SRCB.OUT -NPUBLIC\FLAG F:\TCOPY\SRC\SUB\C.TXT > F:\NCMP\POST\SRCC.OUT -NPUBLIC\FLAG F:\TCOPY\DST\A1.TXT > F:\NCMP\POST\DSTA1.OUT -NPUBLIC\FLAG F:\TCOPY\DST\AV.TXT > F:\NCMP\POST\DSTAV.OUT -NPUBLIC\FLAG F:\TCOPY\DST\B.TXT > F:\NCMP\POST\DSTB.OUT -NPUBLIC\NDIR F:\TCOPY\SRC > F:\NCMP\POST\SRCNDIR.OUT -NPUBLIC\NDIR F:\TCOPY\SRC /DATES > F:\NCMP\POST\SRCDATE.OUT -NPUBLIC\NDIR F:\TCOPY\DST > F:\NCMP\POST\DSTNDIR.OUT -NPUBLIC\NDIR F:\TCOPY\DST /DATES > F:\NCMP\POST\DSTDATE.OUT -NPUBLIC\NDIR F:\TCOPY\DST\SCPY /SUB > F:\NCMP\POST\SCPYSUB.OUT -NPUBLIC\NDIR F:\TCOPY\DST\ECPY /SUB > F:\NCMP\POST\ECPYSUB.OUT -NPUBLIC\NDIR F:\TCOPY\ARCH /SUB > F:\NCMP\POST\ARCHSUB.OUT -ECHO === COMPARE === >> F:\NCMP\RUN.LOG -FC F:\NCMP\PRE\SRCA.OUT F:\NCMP\POST\SRCA.OUT > F:\NCMP\CMP\SRCA.OUT -FC F:\NCMP\PRE\SRCB.OUT F:\NCMP\POST\SRCB.OUT > F:\NCMP\CMP\SRCB.OUT -FC F:\NCMP\PRE\SRCC.OUT F:\NCMP\POST\SRCC.OUT > F:\NCMP\CMP\SRCC.OUT -FC F:\NCMP\PRE\SRCNDIR.OUT F:\NCMP\POST\SRCNDIR.OUT > F:\NCMP\CMP\SRCNDIR.OUT -FC F:\NCMP\PRE\SRCDATE.OUT F:\NCMP\POST\SRCDATE.OUT > F:\NCMP\CMP\SRCDATE.OUT ECHO === SUMMARY === > F:\NCMP\SUMMARY.TXT -ECHO NCOPY automated test finished. >> F:\NCMP\SUMMARY.TXT -ECHO. >> F:\NCMP\SUMMARY.TXT -ECHO Expected notes: >> F:\NCMP\SUMMARY.TXT -ECHO - Source FLAG compare may differ after /M because archive bit should be cleared. >> F:\NCMP\SUMMARY.TXT -ECHO - DSTNDIR.OUT should show A1.TXT, AV.TXT, B.TXT and copy directories. >> F:\NCMP\SUMMARY.TXT -ECHO - SCPYSUB.OUT should include copied SUB\C.TXT. >> F:\NCMP\SUMMARY.TXT -ECHO - ECPYSUB.OUT should include copied SUB\C.TXT and possibly EMPTY directory. >> F:\NCMP\SUMMARY.TXT -ECHO - ARCHSUB.OUT should show /A and /M archive-copy result directories. >> F:\NCMP\SUMMARY.TXT -ECHO. >> F:\NCMP\SUMMARY.TXT -ECHO Optional pack results with NCPTZIP.BAT. >> F:\NCMP\SUMMARY.TXT -ECHO === CLEANUP ATTRIBUTES === >> F:\NCMP\RUN.LOG -NPUBLIC\FLAG F:\TCOPY\SRC\A.TXT N >> F:\NCMP\RUN.LOG -NPUBLIC\FLAG F:\TCOPY\SRC\B.TXT N >> F:\NCMP\RUN.LOG -NPUBLIC\FLAG F:\TCOPY\SRC\SUB\C.TXT N >> F:\NCMP\RUN.LOG -NPUBLIC\FLAG F:\TCOPY\DST\A.TXT N >> F:\NCMP\RUN.LOG -NPUBLIC\FLAG F:\TCOPY\DST\A1.TXT N >> F:\NCMP\RUN.LOG -NPUBLIC\FLAG F:\TCOPY\DST\AV.TXT N >> F:\NCMP\RUN.LOG -NPUBLIC\FLAG F:\TCOPY\DST\B.TXT N >> F:\NCMP\RUN.LOG +ECHO NCOPY automated Novell-vs-PUBLIC compare test finished. >> F:\NCMP\SUMMARY.TXT + +ECHO. >> F:\NCMP\SUMMARY.TXT + +ECHO Compare file: F:\NCMP\COMPARE.LOG >> F:\NCMP\SUMMARY.TXT + +ECHO Command output: F:\NCMP\OUT vs F:\NCMP\PUBOUT >> F:\NCMP\SUMMARY.TXT + +ECHO Result state: F:\NCMP\POSTNOV vs F:\NCMP\POSTPUB >> F:\NCMP\SUMMARY.TXT + +ECHO. >> F:\NCMP\SUMMARY.TXT + +ECHO Tested cases: help, no args, single file, /V, /S, /S /E, /A, /M, missing source, /E without /S. >> F:\NCMP\SUMMARY.TXT + +GOTO DONE + + + +:DONE + +GOTO EOF + + + +:END ECHO. + ECHO NCPTSTA fertig. + ECHO Ergebnisse liegen in F:\NCMP + ECHO Optional: NCPTZIP ausfuehren. + ECHO. + +GOTO EOF + + + +:EOF + diff --git a/test/ncopy/NCPTZIP.BAT b/test/ncopy/NCPTZIP.BAT index ff4eaa2..d473aa2 100644 --- a/test/ncopy/NCPTZIP.BAT +++ b/test/ncopy/NCPTZIP.BAT @@ -1,28 +1,24 @@ -@ECHO OFF -REM NCPTZIP.BAT -REM Optional packer for NCPTSTA result files. -REM Requires ZIP.EXE in PATH or current directory. - -F: -CD \NCMP - -IF EXIST NCPTSTA.ZIP DEL NCPTSTA.ZIP -IF EXIST ZIP.LOG DEL ZIP.LOG - -ECHO Creating NCPTSTA.ZIP > ZIP.LOG -ZIP -r NCPTSTA.ZIP RUN.LOG SUMMARY.TXT PRE POST CMP >> ZIP.LOG - - -REM Cleanup generated test directories after ZIP. -REM Keep the CMP/result directory because it contains the ZIP and ZIP.LOG. -ECHO Cleaning generated test directories... >> ZIP.LOG -IF EXIST \TCOPY\NUL DELTREE /Y \TCOPY >> ZIP.LOG -IF EXIST \TNCOPY\NUL DELTREE /Y \TNCOPY >> ZIP.LOG -IF EXIST \NCPTEST\NUL DELTREE /Y \NCPTEST >> ZIP.LOG -CD \ -ECHO. -ECHO ZIP step finished. -ECHO Check: -ECHO F:\NCMP\NCPTSTA.ZIP -ECHO F:\NCMP\ZIP.LOG -ECHO. +@ECHO OFF +REM NCPTZIP.BAT +REM Optional packer for NCPTSTA result files. +REM Requires ZIP.EXE in PATH or current directory. + +F: +CD \NCMP + +IF EXIST NCPTSTA.ZIP DEL NCPTSTA.ZIP +IF EXIST ZIP.LOG DEL ZIP.LOG + +ECHO Creating NCPTSTA.ZIP > ZIP.LOG +ZIP -r NCPTSTA.ZIP RUN.LOG SUMMARY.TXT COMPARE.LOG OUT PUBOUT POSTNOV POSTPUB CMP >> ZIP.LOG + +REM Cleanup is intentionally not performed here. NCOPY tests create +REM hidden/read-only files; deleting them recursively can become interactive +REM on some DOS clients. Re-run NCPTSTA to reset the fixed test tree. +CD \ +ECHO. +ECHO ZIP step finished. +ECHO Check: +ECHO F:\NCMP\NCPTSTA.ZIP +ECHO F:\NCMP\ZIP.LOG +ECHO. diff --git a/test/ncopy/README.md b/test/ncopy/README.md index 4255a8f..93f7414 100644 --- a/test/ncopy/README.md +++ b/test/ncopy/README.md @@ -1,58 +1,53 @@ # NCOPY tests -Novell-only NCOPY tests. +Automated NCOPY comparison tests for MARS NWE DOS tools. + +`NCOPY` is a larger copy/metadata tool. The current test is designed to +capture Novell behaviour first and compare the Open Source DOS utility against +it before the implementation is completed. ## Files | File | Purpose | | --- | --- | -| `NCPTSTA.BAT` | Automated no-pause/no-screenshot NCOPY test. Writes results to `F:\NCMP`. | -| `README_AUTO.md` | Details for the automated test. | +| `NCPTSTA.BAT` | Automated Novell-vs-PUBLIC NCOPY comparison. Writes results to `F:\NCMP`. | +| `NCPTZIP.BAT` | Optional packer for `F:\NCMP\NCPTSTA.ZIP`. | +| `README_AUTO.md` | Older notes for the automated test. | | `NCPTSTN.BAT` | Manual/pause-based NCOPY baseline test. | | `NCPCMPN.BAT` | Manual repeat selected comparisons/output. | | `NCPTSTM.TST` | MARS/dosutils regression notes/spec. | -## Recommended now +## Layout -Use: +`NCPTSTA.BAT` uses the same direction as the other tool tests: + +| Directory | Meaning | +| --- | --- | +| `OUT` | command output from Novell `NPUBLIC\NCOPY` | +| `PUBOUT` | command output from Open Source `PUBLIC\NCOPY` | +| `POSTNOV` | resulting file state captured with Novell tools | +| `POSTPUB` | resulting file state captured with Open Source tools | +| `COMPARE.LOG` | `FC` comparisons for command output and resulting state | + +## Run + +From a logged-in Supervisor session: ```text -NCPTSTA.BAT +F:\NCPTSTA ``` -Then collect: +Then inspect: ```text -F:\NCMP\NCPTSTA.ZIP -``` - -or, if ZIP is not installed yet: - -```text -F:\NCMP\RUN.LOG +F:\NCMP\COMPARE.LOG F:\NCMP\SUMMARY.TXT -F:\NCMP\PRE\*.OUT -F:\NCMP\POST\*.OUT -F:\NCMP\CMP\*.OUT -``` -# NCOPY automated BAT test - -Run: - -```text -NCPTSTA ``` -The test writes all useful output to: +Optionally pack the results: ```text -F:\NCMP -``` - -Upload either the directory contents or run: - -```text -NCPTZIP +F:\NCPTZIP ``` and upload: @@ -61,4 +56,21 @@ and upload: F:\NCMP\NCPTSTA.ZIP ``` -This version avoids wildcard deletes, interactive overwrite prompts, PAUSE, and automatic ZIP. +## Current matrix + +The automated comparison covers: + +- `NCOPY /?` +- `NCOPY` with no arguments +- single-file copy with `TO` +- copy of hidden/archive and read-only/archive files +- `/V` +- `/S` +- `/S /E` +- `/A /S` +- `/M /S`, including source archive-bit readback +- missing source +- `/E` without `/S` + +The resulting destination/source state is checked with the already validated +`FLAG`, `NDIR`, and `RIGHTS` tools. diff --git a/test/ndir/NDIRC.BAT b/test/ndir/NDIRC.BAT new file mode 100644 index 0000000..1912b54 --- /dev/null +++ b/test/ndir/NDIRC.BAT @@ -0,0 +1,149 @@ +@ECHO OFF +REM NDIRC.BAT +REM Delayed helper for NDIRTSTA user-context test. + +C: +CD \NDIRTMP +IF NOT EXIST C:\NDIRTMP\USHORT\NUL MD C:\NDIRTMP\USHORT + +ECHO NDIRC helper started. > C:\NDIRTMP\HELPER.TXT +ECHO Running NOPASSUSER NDIR readback. >> C:\NDIRTMP\HELPER.TXT + +LOGOUT > C:\NDIRTMP\D01_LOG.OUT +LOGIN NOPASSUSER > C:\NDIRTMP\D02_LGIN.OUT + +F: +CD \ + +ECHO U10 ROOT as NOPASSUSER >> C:\NDIRTMP\HELPER.TXT +\NPUBLIC\NDIR F:\TNDIR /RIGHTS > C:\NDIRTMP\UNOV\U10_ROOT.OUT +\PUBLIC\NDIR F:\TNDIR /RIGHTS > C:\NDIRTMP\UPUB\U10_ROOT.OUT + +ECHO U11 RF as NOPASSUSER >> C:\NDIRTMP\HELPER.TXT +\NPUBLIC\NDIR F:\TNDIR\URF /RIGHTS > C:\NDIRTMP\UNOV\U11_RF.OUT +\PUBLIC\NDIR F:\TNDIR\URF /RIGHTS > C:\NDIRTMP\UPUB\U11_RF.OUT + +ECHO U12 FULL as NOPASSUSER >> C:\NDIRTMP\HELPER.TXT +\NPUBLIC\NDIR F:\TNDIR\UFULL /RIGHTS > C:\NDIRTMP\UNOV\U12_FULL.OUT +\PUBLIC\NDIR F:\TNDIR\UFULL /RIGHTS > C:\NDIRTMP\UPUB\U12_FULL.OUT + +ECHO U13 S as NOPASSUSER >> C:\NDIRTMP\HELPER.TXT +\NPUBLIC\NDIR F:\TNDIR\US /RIGHTS > C:\NDIRTMP\UNOV\U13_S.OUT +\PUBLIC\NDIR F:\TNDIR\US /RIGHTS > C:\NDIRTMP\UPUB\U13_S.OUT + +ECHO U14 N as NOPASSUSER >> C:\NDIRTMP\HELPER.TXT +\NPUBLIC\NDIR F:\TNDIR\UNONE /RIGHTS > C:\NDIRTMP\UNOV\U14_N.OUT +\PUBLIC\NDIR F:\TNDIR\UNONE /RIGHTS > C:\NDIRTMP\UPUB\U14_N.OUT + +ECHO U15 SUB as NOPASSUSER >> C:\NDIRTMP\HELPER.TXT +\NPUBLIC\NDIR F:\TNDIR\USUB /SUB /RIGHTS > C:\NDIRTMP\UNOV\U15_SUB.OUT +\PUBLIC\NDIR F:\TNDIR\USUB /SUB /RIGHTS > C:\NDIRTMP\UPUB\U15_SUB.OUT + +ECHO U16 wildcard as NOPASSUSER >> C:\NDIRTMP\HELPER.TXT +\NPUBLIC\NDIR F:\TNDIR\*.TXT > C:\NDIRTMP\UNOV\U16_TXT.OUT +\PUBLIC\NDIR F:\TNDIR\*.TXT > C:\NDIRTMP\UPUB\U16_TXT.OUT + + +ECHO U17 matrix root as NOPASSUSER >> C:\NDIRTMP\HELPER.TXT +\NPUBLIC\NDIR F:\TNDIR\MAT /RIGHTS > C:\NDIRTMP\UNOV\U17_MATR.OUT +\PUBLIC\NDIR F:\TNDIR\MAT /RIGHTS > C:\NDIRTMP\UPUB\U17_MATR.OUT + +ECHO U18 matrix dates as NOPASSUSER >> C:\NDIRTMP\HELPER.TXT +\NPUBLIC\NDIR F:\TNDIR\MAT /DATES > C:\NDIRTMP\UNOV\U18_MDAT.OUT +\PUBLIC\NDIR F:\TNDIR\MAT /DATES > C:\NDIRTMP\UPUB\U18_MDAT.OUT + +ECHO U19 matrix files only as NOPASSUSER >> C:\NDIRTMP\HELPER.TXT +\NPUBLIC\NDIR F:\TNDIR\MAT /FO > C:\NDIRTMP\UNOV\U19_MFO.OUT +\PUBLIC\NDIR F:\TNDIR\MAT /FO > C:\NDIRTMP\UPUB\U19_MFO.OUT + +ECHO U20 matrix dirs only as NOPASSUSER >> C:\NDIRTMP\HELPER.TXT +\NPUBLIC\NDIR F:\TNDIR\MAT /DO > C:\NDIRTMP\UNOV\U20_MDO.OUT +\PUBLIC\NDIR F:\TNDIR\MAT /DO > C:\NDIRTMP\UPUB\U20_MDO.OUT + +ECHO U21 matrix sub rights as NOPASSUSER >> C:\NDIRTMP\HELPER.TXT +\NPUBLIC\NDIR F:\TNDIR\MAT /SUB /RIGHTS > C:\NDIRTMP\UNOV\U21_MSUB.OUT +\PUBLIC\NDIR F:\TNDIR\MAT /SUB /RIGHTS > C:\NDIRTMP\UPUB\U21_MSUB.OUT + +ECHO U22 matrix hidden filter as NOPASSUSER >> C:\NDIRTMP\HELPER.TXT +\NPUBLIC\NDIR F:\TNDIR\MAT /H > C:\NDIRTMP\UNOV\U22_MH.OUT +\PUBLIC\NDIR F:\TNDIR\MAT /H > C:\NDIRTMP\UPUB\U22_MH.OUT + +ECHO U23 matrix wildcard as NOPASSUSER >> C:\NDIRTMP\HELPER.TXT +\NPUBLIC\NDIR F:\TNDIR\MAT\*.TXT > C:\NDIRTMP\UNOV\U23_MTXT.OUT +\PUBLIC\NDIR F:\TNDIR\MAT\*.TXT > C:\NDIRTMP\UPUB\U23_MTXT.OUT + +ECHO U24 user matrix rights as NOPASSUSER >> C:\NDIRTMP\HELPER.TXT +\NPUBLIC\NDIR F:\TNDIR\USR /RIGHTS > C:\NDIRTMP\UNOV\U24_USRR.OUT +\PUBLIC\NDIR F:\TNDIR\USR /RIGHTS > C:\NDIRTMP\UPUB\U24_USRR.OUT + +ECHO U25 user matrix sub rights as NOPASSUSER >> C:\NDIRTMP\HELPER.TXT +\NPUBLIC\NDIR F:\TNDIR\USR /SUB /RIGHTS > C:\NDIRTMP\UNOV\U25_USRS.OUT +\PUBLIC\NDIR F:\TNDIR\USR /SUB /RIGHTS > C:\NDIRTMP\UPUB\U25_USRS.OUT + +ECHO U26 user matrix dirs only rights as NOPASSUSER >> C:\NDIRTMP\HELPER.TXT +\NPUBLIC\NDIR F:\TNDIR\USR /DO /RIGHTS > C:\NDIRTMP\UNOV\U26_USRD.OUT +\PUBLIC\NDIR F:\TNDIR\USR /DO /RIGHTS > C:\NDIRTMP\UPUB\U26_USRD.OUT + +ECHO U27 user matrix wildcard as NOPASSUSER >> C:\NDIRTMP\HELPER.TXT +\NPUBLIC\NDIR F:\TNDIR\USR\*.TXT > C:\NDIRTMP\UNOV\U27_USRT.OUT +\PUBLIC\NDIR F:\TNDIR\USR\*.TXT > C:\NDIRTMP\UPUB\U27_USRT.OUT + +ECHO U28 user matrix dates as NOPASSUSER >> C:\NDIRTMP\HELPER.TXT +\NPUBLIC\NDIR F:\TNDIR\USR /DATES > C:\NDIRTMP\UNOV\U28_USRD.OUT +\PUBLIC\NDIR F:\TNDIR\USR /DATES > C:\NDIRTMP\UPUB\U28_USRD.OUT + +ECHO U29 group EVERYONE view as NOPASSUSER >> C:\NDIRTMP\HELPER.TXT +\NPUBLIC\NDIR F:\TNDIR\USR\U_EVERYF /RIGHTS > C:\NDIRTMP\UNOV\U29_EVRF.OUT +\PUBLIC\NDIR F:\TNDIR\USR\U_EVERYF /RIGHTS > C:\NDIRTMP\UPUB\U29_EVRF.OUT + +ECHO U30 NOPASSUSER S child view >> C:\NDIRTMP\HELPER.TXT +\NPUBLIC\NDIR F:\TNDIR\USR\U_CHILD /SUB /RIGHTS > C:\NDIRTMP\UNOV\U30_CHLD.OUT +\PUBLIC\NDIR F:\TNDIR\USR\U_CHILD /SUB /RIGHTS > C:\NDIRTMP\UPUB\U30_CHLD.OUT + +ECHO PUBLIC-only /SHORT outputs as NOPASSUSER >> C:\NDIRTMP\HELPER.TXT +\PUBLIC\NDIR F:\TNDIR /RIGHTS /SHORT > C:\NDIRTMP\USHORT\US10_ROOT.OUT +\PUBLIC\NDIR F:\TNDIR\URF /RIGHTS /SHORT > C:\NDIRTMP\USHORT\US11_RF.OUT +\PUBLIC\NDIR F:\TNDIR\USUB /SUB /RIGHTS /SHORT > C:\NDIRTMP\USHORT\US15_SUB.OUT +\PUBLIC\NDIR F:\TNDIR\*.TXT /SHORT > C:\NDIRTMP\USHORT\US16_TXT.OUT +\PUBLIC\NDIR F:\TNDIR\MAT /RIGHTS /SHORT > C:\NDIRTMP\USHORT\US17_MATR.OUT +\PUBLIC\NDIR F:\TNDIR\MAT /SUB /RIGHTS /SHORT > C:\NDIRTMP\USHORT\US21_MSUB.OUT +\PUBLIC\NDIR F:\TNDIR\USR /SUB /RIGHTS /SHORT > C:\NDIRTMP\USHORT\US25_USRS.OUT + +ECHO === NDIR USER CONTEXT COMPARE === > C:\NDIRTMP\UCOMP.LOG +FC C:\NDIRTMP\UNOV\U10_ROOT.OUT C:\NDIRTMP\UPUB\U10_ROOT.OUT >> C:\NDIRTMP\UCOMP.LOG +FC C:\NDIRTMP\UNOV\U11_RF.OUT C:\NDIRTMP\UPUB\U11_RF.OUT >> C:\NDIRTMP\UCOMP.LOG +FC C:\NDIRTMP\UNOV\U12_FULL.OUT C:\NDIRTMP\UPUB\U12_FULL.OUT >> C:\NDIRTMP\UCOMP.LOG +FC C:\NDIRTMP\UNOV\U13_S.OUT C:\NDIRTMP\UPUB\U13_S.OUT >> C:\NDIRTMP\UCOMP.LOG +FC C:\NDIRTMP\UNOV\U14_N.OUT C:\NDIRTMP\UPUB\U14_N.OUT >> C:\NDIRTMP\UCOMP.LOG +FC C:\NDIRTMP\UNOV\U15_SUB.OUT C:\NDIRTMP\UPUB\U15_SUB.OUT >> C:\NDIRTMP\UCOMP.LOG +FC C:\NDIRTMP\UNOV\U16_TXT.OUT C:\NDIRTMP\UPUB\U16_TXT.OUT >> C:\NDIRTMP\UCOMP.LOG +FC C:\NDIRTMP\UNOV\U17_MATR.OUT C:\NDIRTMP\UPUB\U17_MATR.OUT >> C:\NDIRTMP\UCOMP.LOG +FC C:\NDIRTMP\UNOV\U18_MDAT.OUT C:\NDIRTMP\UPUB\U18_MDAT.OUT >> C:\NDIRTMP\UCOMP.LOG +FC C:\NDIRTMP\UNOV\U19_MFO.OUT C:\NDIRTMP\UPUB\U19_MFO.OUT >> C:\NDIRTMP\UCOMP.LOG +FC C:\NDIRTMP\UNOV\U20_MDO.OUT C:\NDIRTMP\UPUB\U20_MDO.OUT >> C:\NDIRTMP\UCOMP.LOG +FC C:\NDIRTMP\UNOV\U21_MSUB.OUT C:\NDIRTMP\UPUB\U21_MSUB.OUT >> C:\NDIRTMP\UCOMP.LOG +FC C:\NDIRTMP\UNOV\U22_MH.OUT C:\NDIRTMP\UPUB\U22_MH.OUT >> C:\NDIRTMP\UCOMP.LOG +FC C:\NDIRTMP\UNOV\U23_MTXT.OUT C:\NDIRTMP\UPUB\U23_MTXT.OUT >> C:\NDIRTMP\UCOMP.LOG +FC C:\NDIRTMP\UNOV\U24_USRR.OUT C:\NDIRTMP\UPUB\U24_USRR.OUT >> C:\NDIRTMP\UCOMP.LOG +FC C:\NDIRTMP\UNOV\U25_USRS.OUT C:\NDIRTMP\UPUB\U25_USRS.OUT >> C:\NDIRTMP\UCOMP.LOG +FC C:\NDIRTMP\UNOV\U26_USRD.OUT C:\NDIRTMP\UPUB\U26_USRD.OUT >> C:\NDIRTMP\UCOMP.LOG +FC C:\NDIRTMP\UNOV\U27_USRT.OUT C:\NDIRTMP\UPUB\U27_USRT.OUT >> C:\NDIRTMP\UCOMP.LOG +FC C:\NDIRTMP\UNOV\U28_USRD.OUT C:\NDIRTMP\UPUB\U28_USRD.OUT >> C:\NDIRTMP\UCOMP.LOG +FC C:\NDIRTMP\UNOV\U29_EVRF.OUT C:\NDIRTMP\UPUB\U29_EVRF.OUT >> C:\NDIRTMP\UCOMP.LOG +FC C:\NDIRTMP\UNOV\U30_CHLD.OUT C:\NDIRTMP\UPUB\U30_CHLD.OUT >> C:\NDIRTMP\UCOMP.LOG + +LOGOUT > C:\NDIRTMP\D03_LGOT.OUT +F:\LOGIN\LOGIN SUPERVISOR /PWD:%LGNTPWD% > C:\NDIRTMP\D04_LGSU.OUT + +F: +CD \ +IF EXIST \NDIRTSTA.BAT GOTO HAVEF +ECHO F: wurde nicht wiederhergestellt oder \NDIRTSTA.BAT fehlt. >> C:\NDIRTMP\HELPER.TXT +GOTO END + +:HAVEF +C: +CD \NDIRTMP +DLYSTRT /T:2 F:\NDIRTSTA.BAT PART2 + +:END diff --git a/test/ndir/NDIRTSTA.BAT b/test/ndir/NDIRTSTA.BAT index 70fd0fc..05c7689 100644 --- a/test/ndir/NDIRTSTA.BAT +++ b/test/ndir/NDIRTSTA.BAT @@ -1,172 +1,376 @@ @ECHO OFF REM NDIRTSTA.BAT -REM Automated Novell NDIR baseline for MARS NWE. +REM Automated NDIR compare test for MARS NWE. REM -REM No PAUSE, no screenshots required. -REM All output is redirected into F:\NDCMP. +REM OUT/PUBOUT: +REM Novell NPUBLIC\NDIR baseline vs PUBLIC\NDIR implementation. REM -REM Test tree: -REM F:\TNDIR +REM UNOV/UPUB: +REM NOPASSUSER context readback, started through DLYSTRT. REM -REM Results: -REM F:\NDCMP\RUN.LOG -REM F:\NDCMP\SUMMARY.TXT -REM F:\NDCMP\OUT\*.OUT +REM SHORTOUT/USHORT: +REM PUBLIC-only /SHORT helper output. /SHORT is our local option and is +REM not compared against Novell NDIR. +REM +REM Required for user-context part: +REM SET LGNTPWD= + +IF "%1"=="" GOTO PART1 +IF "%1"=="PART2" GOTO PART2 +IF "%1"=="part2" GOTO PART2 +IF "%1"=="Part2" GOTO PART2 +GOTO USAGE + +:USAGE +ECHO Usage: NDIRTSTA [PART2] +ECHO. +ECHO For full automatic user-context test first set: +ECHO SET LGNTPWD=dein-supervisor-passwort +GOTO END + +:PART1 +IF "%LGNTPWD%"=="" GOTO NEEDPWD F: CD \ -REM --- Clean generated test/result directories (contents only). --- -IF EXIST NDIRTEST\NUL DELTREE /Y NDIRTEST\*.* -IF EXIST NDIRCMP\NUL DELTREE /Y NDIRCMP\*.* +REM --- Clean generated test/result directories. --- +IF EXIST TNDIR\NUL DELTREE /Y TNDIR > NUL +IF EXIST NDCMP\NUL DELTREE /Y NDCMP > NUL +IF EXIST C:\NDIRTMP\NUL DELTREE /Y C:\NDIRTMP > NUL -REM --- Directory setup --- -IF NOT EXIST TNDIR\NUL MD TNDIR -IF NOT EXIST TNDIR\SUBDIR\NUL MD TNDIR\SUBDIR -IF NOT EXIST NDCMP\NUL MD NDCMP -IF NOT EXIST NDCMP\OUT\NUL MD NDCMP\OUT +REM --- Directory setup. --- +MD TNDIR +MD TNDIR\SUBDIR +MD TNDIR\SUBDIR\DEEP +MD TNDIR\URF +MD TNDIR\UFULL +MD TNDIR\US +MD TNDIR\UNONE +MD TNDIR\USUB +MD TNDIR\USUB\CHILD +MD TNDIR\MAT +MD TNDIR\MAT\D_NORM +MD TNDIR\MAT\D_HID +MD TNDIR\MAT\D_SYS +MD TNDIR\MAT\D_PUR +MD TNDIR\MAT\D_DIRI +MD TNDIR\MAT\D_MIX +MD TNDIR\MAT\D_SUB +MD TNDIR\MAT\D_SUB\CHILD +MD TNDIR\USR +MD TNDIR\USR\U_EVERYR +MD TNDIR\USR\U_EVERYF +MD TNDIR\USR\U_MARIO +MD TNDIR\USR\U_GUEST +MD TNDIR\USR\U_NOPWCM +MD TNDIR\USR\U_NOPREM +MD TNDIR\USR\U_NOPRF +MD TNDIR\USR\U_CHILD +MD TNDIR\USR\U_CHILD\DEEP -REM --- Clean result files, no wildcard DEL to avoid DOS prompts --- -IF EXIST F:\NDCMP\RUN.LOG DEL F:\NDCMP\RUN.LOG -IF EXIST F:\NDCMP\SUMMARY.TXT DEL F:\NDCMP\SUMMARY.TXT -IF EXIST F:\NDCMP\ZIP.LOG DEL F:\NDCMP\ZIP.LOG -IF EXIST F:\NDCMP\NDIRTSTA.ZIP DEL F:\NDCMP\NDIRTSTA.ZIP +MD NDCMP +MD NDCMP\OUT +MD NDCMP\PUBOUT +MD NDCMP\SETUP +MD NDCMP\SHORTOUT +MD NDCMP\UNOV +MD NDCMP\UPUB +MD NDCMP\USHORT +MD NDCMP\USETUP -IF EXIST F:\NDCMP\OUT\N01_ROOT.OUT DEL F:\NDCMP\OUT\N01_ROOT.OUT -IF EXIST F:\NDCMP\OUT\N02_ALFA.OUT DEL F:\NDCMP\OUT\N02_ALFA.OUT -IF EXIST F:\NDCMP\OUT\N02_BETA.OUT DEL F:\NDCMP\OUT\N02_BETA.OUT -IF EXIST F:\NDCMP\OUT\N03_DATES.OUT DEL F:\NDCMP\OUT\N03_DATES.OUT -IF EXIST F:\NDCMP\OUT\N03_ADATE.OUT DEL F:\NDCMP\OUT\N03_ADATE.OUT -IF EXIST F:\NDCMP\OUT\N04_RGT.OUT DEL F:\NDCMP\OUT\N04_RGT.OUT -IF EXIST F:\NDCMP\OUT\N04_RGTA.OUT DEL F:\NDCMP\OUT\N04_RGTA.OUT -IF EXIST F:\NDCMP\OUT\N05_FLGA.OUT DEL F:\NDCMP\OUT\N05_FLGA.OUT -IF EXIST F:\NDCMP\OUT\N05_FLGB.OUT DEL F:\NDCMP\OUT\N05_FLGB.OUT -IF EXIST F:\NDCMP\OUT\N05_FLGG.OUT DEL F:\NDCMP\OUT\N05_FLGG.OUT -IF EXIST F:\NDCMP\OUT\N06_ATTR.OUT DEL F:\NDCMP\OUT\N06_ATTR.OUT -IF EXIST F:\NDCMP\OUT\N06_ADAT.OUT DEL F:\NDCMP\OUT\N06_ADAT.OUT -IF EXIST F:\NDCMP\OUT\N07_H.OUT DEL F:\NDCMP\OUT\N07_H.OUT -IF EXIST F:\NDCMP\OUT\N07_RO.OUT DEL F:\NDCMP\OUT\N07_RO.OUT -IF EXIST F:\NDCMP\OUT\N07_SY.OUT DEL F:\NDCMP\OUT\N07_SY.OUT -IF EXIST F:\NDCMP\OUT\N07_A.OUT DEL F:\NDCMP\OUT\N07_A.OUT -IF EXIST F:\NDCMP\OUT\N08_NOTH.OUT DEL F:\NDCMP\OUT\N08_NOTH.OUT -IF EXIST F:\NDCMP\OUT\N08_NOTR.OUT DEL F:\NDCMP\OUT\N08_NOTR.OUT -IF EXIST F:\NDCMP\OUT\N09_SUN.OUT DEL F:\NDCMP\OUT\N09_SUN.OUT -IF EXIST F:\NDCMP\OUT\N09_SSI.OUT DEL F:\NDCMP\OUT\N09_SSI.OUT -IF EXIST F:\NDCMP\OUT\N09_SUP.OUT DEL F:\NDCMP\OUT\N09_SUP.OUT -IF EXIST F:\NDCMP\OUT\N10_TXT.OUT DEL F:\NDCMP\OUT\N10_TXT.OUT -IF EXIST F:\NDCMP\OUT\N10_DAT.OUT DEL F:\NDCMP\OUT\N10_DAT.OUT -IF EXIST F:\NDCMP\OUT\N11_FO.OUT DEL F:\NDCMP\OUT\N11_FO.OUT -IF EXIST F:\NDCMP\OUT\N11_DO.OUT DEL F:\NDCMP\OUT\N11_DO.OUT -IF EXIST F:\NDCMP\OUT\N12_SUB.OUT DEL F:\NDCMP\OUT\N12_SUB.OUT -IF EXIST F:\NDCMP\OUT\N12_SDIR.OUT DEL F:\NDCMP\OUT\N12_SDIR.OUT -IF EXIST F:\NDCMP\OUT\N14_FINAL.OUT DEL F:\NDCMP\OUT\N14_FINAL.OUT - -ECHO NDIRTSTA automated Novell NDIR baseline > F:\NDCMP\RUN.LOG +ECHO NDIRTSTA NDIR compare test > F:\NDCMP\RUN.LOG ECHO Date/time stamp skipped to avoid DOS prompt. >> F:\NDCMP\RUN.LOG ECHO. >> F:\NDCMP\RUN.LOG -ECHO === SETUP TEST TREE === >> F:\NDCMP\RUN.LOG - -REM Reset test files. -IF EXIST F:\TNDIR\ALPHA.TXT DEL F:\TNDIR\ALPHA.TXT -IF EXIST F:\TNDIR\BETA.TXT DEL F:\TNDIR\BETA.TXT -IF EXIST F:\TNDIR\GAMMA.DAT DEL F:\TNDIR\GAMMA.DAT -IF EXIST F:\TNDIR\SUBDIR\SUB.TXT DEL F:\TNDIR\SUBDIR\SUB.TXT - -IF NOT EXIST F:\TNDIR\NUL MD F:\TNDIR -IF NOT EXIST F:\TNDIR\SUBDIR\NUL MD F:\TNDIR\SUBDIR - +REM --- Test files. --- ECHO NDIR TEST ALPHA > F:\TNDIR\ALPHA.TXT ECHO NDIR TEST BETA > F:\TNDIR\BETA.TXT ECHO NDIR TEST GAMMA > F:\TNDIR\GAMMA.DAT ECHO NDIR SUB FILE > F:\TNDIR\SUBDIR\SUB.TXT +ECHO NDIR DEEP FILE > F:\TNDIR\SUBDIR\DEEP\DEEP.TXT +ECHO NDIR RF FILE > F:\TNDIR\URF\RF.TXT +ECHO NDIR FULL FILE > F:\TNDIR\UFULL\FULL.TXT +ECHO NDIR S FILE > F:\TNDIR\US\S.TXT +ECHO NDIR N FILE > F:\TNDIR\UNONE\N.TXT +ECHO NDIR USUB FILE > F:\TNDIR\USUB\ROOT.TXT +ECHO NDIR USUB CHILD > F:\TNDIR\USUB\CHILD\CHILD.TXT +ECHO MAT NORMAL > F:\TNDIR\MAT\NORMAL.TXT +ECHO MAT HIDDEN > F:\TNDIR\MAT\HIDFILE.TXT +ECHO MAT READONLY > F:\TNDIR\MAT\ROFILE.TXT +ECHO MAT SYSTEM > F:\TNDIR\MAT\SYSFILE.DAT +ECHO MAT ARCHIVE > F:\TNDIR\MAT\ARCFILE.BIN +ECHO MAT INHIBIT > F:\TNDIR\MAT\DIRIFILE.TXT +ECHO MAT MIXED > F:\TNDIR\MAT\MIXFILE.TXT +ECHO MAT SUB ROOT > F:\TNDIR\MAT\D_SUB\ROOT.TXT +ECHO MAT SUB CHILD > F:\TNDIR\MAT\D_SUB\CHILD\CHILD.TXT +ECHO USER EVERY R > F:\TNDIR\USR\U_EVERYR\E_R.TXT +ECHO USER EVERY FULL > F:\TNDIR\USR\U_EVERYF\E_FULL.TXT +ECHO USER MARIO RF > F:\TNDIR\USR\U_MARIO\MARIO.TXT +ECHO USER GUEST RF > F:\TNDIR\USR\U_GUEST\GUEST.TXT +ECHO USER NOP WCM > F:\TNDIR\USR\U_NOPWCM\WCM.TXT +ECHO USER NOP REMA > F:\TNDIR\USR\U_NOPREM\REMA.TXT +ECHO USER NOP RF > F:\TNDIR\USR\U_NOPRF\RF.TXT +ECHO USER CHILD ROOT > F:\TNDIR\USR\U_CHILD\ROOT.TXT +ECHO USER CHILD DEEP > F:\TNDIR\USR\U_CHILD\DEEP\DEEP.TXT ECHO === ATTRIBUTE CLEANUP === >> F:\NDCMP\RUN.LOG -NPUBLIC\FLAG F:\TNDIR\ALPHA.TXT N >> F:\NDCMP\RUN.LOG -NPUBLIC\FLAG F:\TNDIR\BETA.TXT N >> F:\NDCMP\RUN.LOG -NPUBLIC\FLAG F:\TNDIR\GAMMA.DAT N >> F:\NDCMP\RUN.LOG -NPUBLIC\FLAG F:\TNDIR\SUBDIR\SUB.TXT N >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAG F:\TNDIR\ALPHA.TXT N >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAG F:\TNDIR\BETA.TXT N >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAG F:\TNDIR\GAMMA.DAT N >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAG F:\TNDIR\SUBDIR\SUB.TXT N >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAG F:\TNDIR\MAT\NORMAL.TXT N >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAG F:\TNDIR\MAT\HIDFILE.TXT N >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAG F:\TNDIR\MAT\ROFILE.TXT N >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAG F:\TNDIR\MAT\SYSFILE.DAT N >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAG F:\TNDIR\MAT\ARCFILE.BIN N >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAG F:\TNDIR\MAT\DIRIFILE.TXT N >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAG F:\TNDIR\MAT\MIXFILE.TXT N >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAGDIR F:\TNDIR\MAT\D_NORM Normal >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAGDIR F:\TNDIR\MAT\D_HID Normal >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAGDIR F:\TNDIR\MAT\D_SYS Normal >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAGDIR F:\TNDIR\MAT\D_PUR Normal >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAGDIR F:\TNDIR\MAT\D_DIRI Normal >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAGDIR F:\TNDIR\MAT\D_MIX Normal >> F:\NDCMP\RUN.LOG -ECHO === N01 BASIS DIRECTORY === >> F:\NDCMP\RUN.LOG -NPUBLIC\NDIR F:\TNDIR > F:\NDCMP\OUT\N01_ROOT.OUT +ECHO === D01 BASIS DIRECTORY === >> F:\NDCMP\RUN.LOG +\NPUBLIC\NDIR F:\TNDIR > F:\NDCMP\OUT\D01_ROOT.OUT +\PUBLIC\NDIR F:\TNDIR > F:\NDCMP\PUBOUT\D01_ROOT.OUT -ECHO === N02 DIRECT FILES === >> F:\NDCMP\RUN.LOG -NPUBLIC\NDIR F:\TNDIR\ALPHA.TXT > F:\NDCMP\OUT\N02_ALFA.OUT -NPUBLIC\NDIR F:\TNDIR\BETA.TXT > F:\NDCMP\OUT\N02_BETA.OUT +ECHO === D02 DIRECT FILE === >> F:\NDCMP\RUN.LOG +\NPUBLIC\NDIR F:\TNDIR\ALPHA.TXT > F:\NDCMP\OUT\D02_ALFA.OUT +\PUBLIC\NDIR F:\TNDIR\ALPHA.TXT > F:\NDCMP\PUBOUT\D02_ALFA.OUT -ECHO === N03 DATES === >> F:\NDCMP\RUN.LOG -NPUBLIC\NDIR F:\TNDIR /DATES > F:\NDCMP\OUT\N03_DATES.OUT -NPUBLIC\NDIR F:\TNDIR\ALPHA.TXT /DATES > F:\NDCMP\OUT\N03_ADATE.OUT +ECHO === D03 DATES === >> F:\NDCMP\RUN.LOG +\NPUBLIC\NDIR F:\TNDIR /DATES > F:\NDCMP\OUT\D03_DATE.OUT +\PUBLIC\NDIR F:\TNDIR /DATES > F:\NDCMP\PUBOUT\D03_DATE.OUT -ECHO === N04 RIGHTS === >> F:\NDCMP\RUN.LOG -NPUBLIC\RIGHTS F:\TNDIR > F:\NDCMP\OUT\N04_RGT.OUT -NPUBLIC\NDIR F:\TNDIR /RIGHTS >> F:\NDCMP\OUT\N04_RGT.OUT -NPUBLIC\NDIR F:\TNDIR\ALPHA.TXT /RIGHTS > F:\NDCMP\OUT\N04_RGTA.OUT +ECHO === D04 RIGHTS === >> F:\NDCMP\RUN.LOG +\NPUBLIC\NDIR F:\TNDIR /RIGHTS > F:\NDCMP\OUT\D04_RGHT.OUT +\PUBLIC\NDIR F:\TNDIR /RIGHTS > F:\NDCMP\PUBOUT\D04_RGHT.OUT -ECHO === N05 SET ATTRIBUTES === >> F:\NDCMP\RUN.LOG -NPUBLIC\FLAG F:\TNDIR\ALPHA.TXT +H >> F:\NDCMP\RUN.LOG -NPUBLIC\FLAG F:\TNDIR\BETA.TXT +RO >> F:\NDCMP\RUN.LOG -NPUBLIC\FLAG F:\TNDIR\GAMMA.DAT +Sy +A >> F:\NDCMP\RUN.LOG -NPUBLIC\FLAG F:\TNDIR\ALPHA.TXT > F:\NDCMP\OUT\N05_FLGA.OUT -NPUBLIC\FLAG F:\TNDIR\BETA.TXT > F:\NDCMP\OUT\N05_FLGB.OUT -NPUBLIC\FLAG F:\TNDIR\GAMMA.DAT > F:\NDCMP\OUT\N05_FLGG.OUT +ECHO === D05 SET ATTRIBUTES === >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAG F:\TNDIR\ALPHA.TXT +H >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAG F:\TNDIR\BETA.TXT +RO >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAG F:\TNDIR\GAMMA.DAT +Sy +A >> F:\NDCMP\RUN.LOG +\NPUBLIC\NDIR F:\TNDIR > F:\NDCMP\OUT\D05_ATTR.OUT +\PUBLIC\NDIR F:\TNDIR > F:\NDCMP\PUBOUT\D05_ATTR.OUT -ECHO === N06 NDIR AFTER ATTRIBUTES === >> F:\NDCMP\RUN.LOG -NPUBLIC\NDIR F:\TNDIR > F:\NDCMP\OUT\N06_ATTR.OUT -NPUBLIC\NDIR F:\TNDIR /DATES > F:\NDCMP\OUT\N06_ADAT.OUT +ECHO === D06 ATTRIBUTE FILTERS === >> F:\NDCMP\RUN.LOG +\NPUBLIC\NDIR F:\TNDIR /H > F:\NDCMP\OUT\D06_H.OUT +\PUBLIC\NDIR F:\TNDIR /H > F:\NDCMP\PUBOUT\D06_H.OUT +\NPUBLIC\NDIR F:\TNDIR /RO > F:\NDCMP\OUT\D07_RO.OUT +\PUBLIC\NDIR F:\TNDIR /RO > F:\NDCMP\PUBOUT\D07_RO.OUT +\NPUBLIC\NDIR F:\TNDIR /SY > F:\NDCMP\OUT\D08_SY.OUT +\PUBLIC\NDIR F:\TNDIR /SY > F:\NDCMP\PUBOUT\D08_SY.OUT +\NPUBLIC\NDIR F:\TNDIR /A > F:\NDCMP\OUT\D09_A.OUT +\PUBLIC\NDIR F:\TNDIR /A > F:\NDCMP\PUBOUT\D09_A.OUT -ECHO === N07 ATTRIBUTE FILTERS === >> F:\NDCMP\RUN.LOG -NPUBLIC\NDIR F:\TNDIR /H > F:\NDCMP\OUT\N07_H.OUT -NPUBLIC\NDIR F:\TNDIR /RO > F:\NDCMP\OUT\N07_RO.OUT -NPUBLIC\NDIR F:\TNDIR /SY > F:\NDCMP\OUT\N07_SY.OUT -NPUBLIC\NDIR F:\TNDIR /A > F:\NDCMP\OUT\N07_A.OUT +ECHO === D10 NOT FILTER === >> F:\NDCMP\RUN.LOG +\NPUBLIC\NDIR F:\TNDIR /NOT H > F:\NDCMP\OUT\D10_NOTH.OUT +\PUBLIC\NDIR F:\TNDIR /NOT H > F:\NDCMP\PUBOUT\D10_NOTH.OUT -ECHO === N08 NOT FILTERS === >> F:\NDCMP\RUN.LOG -NPUBLIC\NDIR F:\TNDIR /NOT H > F:\NDCMP\OUT\N08_NOTH.OUT -NPUBLIC\NDIR F:\TNDIR /NOT RO > F:\NDCMP\OUT\N08_NOTR.OUT +ECHO === D11 WILDCARDS === >> F:\NDCMP\RUN.LOG +\NPUBLIC\NDIR F:\TNDIR\*.TXT > F:\NDCMP\OUT\D11_TXT.OUT +\PUBLIC\NDIR F:\TNDIR\*.TXT > F:\NDCMP\PUBOUT\D11_TXT.OUT +\NPUBLIC\NDIR F:\TNDIR\*.DAT > F:\NDCMP\OUT\D12_DAT.OUT +\PUBLIC\NDIR F:\TNDIR\*.DAT > F:\NDCMP\PUBOUT\D12_DAT.OUT -ECHO === N09 SORT TESTS === >> F:\NDCMP\RUN.LOG -NPUBLIC\NDIR F:\TNDIR /SORT UN > F:\NDCMP\OUT\N09_SUN.OUT -NPUBLIC\NDIR F:\TNDIR /SORT SI > F:\NDCMP\OUT\N09_SSI.OUT -NPUBLIC\NDIR F:\TNDIR /SORT UP > F:\NDCMP\OUT\N09_SUP.OUT +ECHO === D13 FILES/DIRS ONLY === >> F:\NDCMP\RUN.LOG +\NPUBLIC\NDIR F:\TNDIR /FO > F:\NDCMP\OUT\D13_FO.OUT +\PUBLIC\NDIR F:\TNDIR /FO > F:\NDCMP\PUBOUT\D13_FO.OUT +\NPUBLIC\NDIR F:\TNDIR /DO > F:\NDCMP\OUT\D14_DO.OUT +\PUBLIC\NDIR F:\TNDIR /DO > F:\NDCMP\PUBOUT\D14_DO.OUT -ECHO === N10 WILDCARDS === >> F:\NDCMP\RUN.LOG -NPUBLIC\NDIR F:\TNDIR\*.TXT > F:\NDCMP\OUT\N10_TXT.OUT -NPUBLIC\NDIR F:\TNDIR\*.DAT > F:\NDCMP\OUT\N10_DAT.OUT +ECHO === D15 SUBDIRECTORY === >> F:\NDCMP\RUN.LOG +\NPUBLIC\NDIR F:\TNDIR /SUB > F:\NDCMP\OUT\D15_SUB.OUT +\PUBLIC\NDIR F:\TNDIR /SUB > F:\NDCMP\PUBOUT\D15_SUB.OUT +\NPUBLIC\NDIR F:\TNDIR /SUB /RIGHTS > F:\NDCMP\OUT\D16_SUBR.OUT +\PUBLIC\NDIR F:\TNDIR /SUB /RIGHTS > F:\NDCMP\PUBOUT\D16_SUBR.OUT -ECHO === N11 FILES ONLY / DIRS ONLY === >> F:\NDCMP\RUN.LOG -NPUBLIC\NDIR F:\TNDIR /FO > F:\NDCMP\OUT\N11_FO.OUT -NPUBLIC\NDIR F:\TNDIR /DO > F:\NDCMP\OUT\N11_DO.OUT -ECHO === N12 SUBDIRECTORY TEST === >> F:\NDCMP\RUN.LOG -NPUBLIC\NDIR F:\TNDIR /SUB > F:\NDCMP\OUT\N12_SUB.OUT -NPUBLIC\NDIR F:\TNDIR\SUBDIR > F:\NDCMP\OUT\N12_SDIR.OUT +ECHO === D17 FILE/DIR ATTRIBUTE MATRIX SETUP === >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAG F:\TNDIR\MAT\HIDFILE.TXT +H >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAG F:\TNDIR\MAT\ROFILE.TXT +RO >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAG F:\TNDIR\MAT\SYSFILE.DAT +Sy >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAG F:\TNDIR\MAT\ARCFILE.BIN +A >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAG F:\TNDIR\MAT\DIRIFILE.TXT +DI +RI >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAG F:\TNDIR\MAT\MIXFILE.TXT +H +RO +A >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAGDIR F:\TNDIR\MAT\D_HID Hidden >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAGDIR F:\TNDIR\MAT\D_SYS System >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAGDIR F:\TNDIR\MAT\D_PUR Purge >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAGDIR F:\TNDIR\MAT\D_DIRI Deleteinhibit Renameinhibit >> F:\NDCMP\RUN.LOG +\NPUBLIC\FLAGDIR F:\TNDIR\MAT\D_MIX Hidden System Purge >> F:\NDCMP\RUN.LOG -ECHO === N14 CLEANUP ATTRIBUTES === >> F:\NDCMP\RUN.LOG -NPUBLIC\FLAG F:\TNDIR\ALPHA.TXT N >> F:\NDCMP\RUN.LOG -NPUBLIC\FLAG F:\TNDIR\BETA.TXT N >> F:\NDCMP\RUN.LOG -NPUBLIC\FLAG F:\TNDIR\GAMMA.DAT N >> F:\NDCMP\RUN.LOG -NPUBLIC\FLAG F:\TNDIR\SUBDIR\SUB.TXT N >> F:\NDCMP\RUN.LOG -NPUBLIC\NDIR F:\TNDIR > F:\NDCMP\OUT\N14_FINAL.OUT +ECHO === D17-D29 FILE/DIR ATTRIBUTE MATRIX === >> F:\NDCMP\RUN.LOG +\NPUBLIC\NDIR F:\TNDIR\MAT > F:\NDCMP\OUT\D17_MATR.OUT +\PUBLIC\NDIR F:\TNDIR\MAT > F:\NDCMP\PUBOUT\D17_MATR.OUT +\NPUBLIC\NDIR F:\TNDIR\MAT /DATES > F:\NDCMP\OUT\D18_MDAT.OUT +\PUBLIC\NDIR F:\TNDIR\MAT /DATES > F:\NDCMP\PUBOUT\D18_MDAT.OUT +\NPUBLIC\NDIR F:\TNDIR\MAT /RIGHTS > F:\NDCMP\OUT\D19_MRGT.OUT +\PUBLIC\NDIR F:\TNDIR\MAT /RIGHTS > F:\NDCMP\PUBOUT\D19_MRGT.OUT +\NPUBLIC\NDIR F:\TNDIR\MAT /FO > F:\NDCMP\OUT\D20_MFO.OUT +\PUBLIC\NDIR F:\TNDIR\MAT /FO > F:\NDCMP\PUBOUT\D20_MFO.OUT +\NPUBLIC\NDIR F:\TNDIR\MAT /DO > F:\NDCMP\OUT\D21_MDO.OUT +\PUBLIC\NDIR F:\TNDIR\MAT /DO > F:\NDCMP\PUBOUT\D21_MDO.OUT +\NPUBLIC\NDIR F:\TNDIR\MAT /SUB > F:\NDCMP\OUT\D22_MSUB.OUT +\PUBLIC\NDIR F:\TNDIR\MAT /SUB > F:\NDCMP\PUBOUT\D22_MSUB.OUT +\NPUBLIC\NDIR F:\TNDIR\MAT /SUB /RIGHTS > F:\NDCMP\OUT\D23_MSRG.OUT +\PUBLIC\NDIR F:\TNDIR\MAT /SUB /RIGHTS > F:\NDCMP\PUBOUT\D23_MSRG.OUT +\NPUBLIC\NDIR F:\TNDIR\MAT /H > F:\NDCMP\OUT\D24_MH.OUT +\PUBLIC\NDIR F:\TNDIR\MAT /H > F:\NDCMP\PUBOUT\D24_MH.OUT +\NPUBLIC\NDIR F:\TNDIR\MAT /RO > F:\NDCMP\OUT\D25_MRO.OUT +\PUBLIC\NDIR F:\TNDIR\MAT /RO > F:\NDCMP\PUBOUT\D25_MRO.OUT +\NPUBLIC\NDIR F:\TNDIR\MAT /SY > F:\NDCMP\OUT\D26_MSY.OUT +\PUBLIC\NDIR F:\TNDIR\MAT /SY > F:\NDCMP\PUBOUT\D26_MSY.OUT +\NPUBLIC\NDIR F:\TNDIR\MAT /A > F:\NDCMP\OUT\D27_MA.OUT +\PUBLIC\NDIR F:\TNDIR\MAT /A > F:\NDCMP\PUBOUT\D27_MA.OUT +\NPUBLIC\NDIR F:\TNDIR\MAT /NOT H > F:\NDCMP\OUT\D28_MNH.OUT +\PUBLIC\NDIR F:\TNDIR\MAT /NOT H > F:\NDCMP\PUBOUT\D28_MNH.OUT +\NPUBLIC\NDIR F:\TNDIR\MAT\*.TXT > F:\NDCMP\OUT\D29_MTXT.OUT +\PUBLIC\NDIR F:\TNDIR\MAT\*.TXT > F:\NDCMP\PUBOUT\D29_MTXT.OUT + +ECHO === D30-D34 USER/TRUSTEE MATRIX DIRECT === >> F:\NDCMP\RUN.LOG +\NPUBLIC\NDIR F:\TNDIR\USR /RIGHTS > F:\NDCMP\OUT\D30_USRR.OUT +\PUBLIC\NDIR F:\TNDIR\USR /RIGHTS > F:\NDCMP\PUBOUT\D30_USRR.OUT +\NPUBLIC\NDIR F:\TNDIR\USR /SUB /RIGHTS > F:\NDCMP\OUT\D31_USRS.OUT +\PUBLIC\NDIR F:\TNDIR\USR /SUB /RIGHTS > F:\NDCMP\PUBOUT\D31_USRS.OUT +\NPUBLIC\NDIR F:\TNDIR\USR /DO /RIGHTS > F:\NDCMP\OUT\D32_USRD.OUT +\PUBLIC\NDIR F:\TNDIR\USR /DO /RIGHTS > F:\NDCMP\PUBOUT\D32_USRD.OUT +\NPUBLIC\NDIR F:\TNDIR\USR\*.TXT > F:\NDCMP\OUT\D33_USRT.OUT +\PUBLIC\NDIR F:\TNDIR\USR\*.TXT > F:\NDCMP\PUBOUT\D33_USRT.OUT +\NPUBLIC\NDIR F:\TNDIR\USR /DATES > F:\NDCMP\OUT\D34_USRD.OUT +\PUBLIC\NDIR F:\TNDIR\USR /DATES > F:\NDCMP\PUBOUT\D34_USRD.OUT + +ECHO === PUBLIC-ONLY SHORT OUTPUT === >> F:\NDCMP\RUN.LOG +\PUBLIC\NDIR F:\TNDIR /SUB /SHORT > F:\NDCMP\SHORTOUT\S15_SUB.OUT +\PUBLIC\NDIR F:\TNDIR /SUB /RIGHTS /SHORT > F:\NDCMP\SHORTOUT\S16_SUBR.OUT +\PUBLIC\NDIR F:\TNDIR\MAT /SHORT > F:\NDCMP\SHORTOUT\S17_MATR.OUT +\PUBLIC\NDIR F:\TNDIR\MAT /SUB /RIGHTS /SHORT > F:\NDCMP\SHORTOUT\S23_MSRG.OUT +\PUBLIC\NDIR F:\TNDIR\USR /SUB /RIGHTS /SHORT > F:\NDCMP\SHORTOUT\S31_USRS.OUT + +ECHO === D90 MISSING / D99 HELP === >> F:\NDCMP\RUN.LOG +\NPUBLIC\NDIR F:\TNDIR\*.ZZZ > F:\NDCMP\OUT\D90_MISS.OUT +\PUBLIC\NDIR F:\TNDIR\*.ZZZ > F:\NDCMP\PUBOUT\D90_MISS.OUT +\NPUBLIC\NDIR /HELP > F:\NDCMP\OUT\D99_HELP.OUT +\PUBLIC\NDIR /HELP > F:\NDCMP\PUBOUT\D99_HELP.OUT + +ECHO === DIRECT COMPARE === > F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D01_ROOT.OUT F:\NDCMP\PUBOUT\D01_ROOT.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D02_ALFA.OUT F:\NDCMP\PUBOUT\D02_ALFA.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D03_DATE.OUT F:\NDCMP\PUBOUT\D03_DATE.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D04_RGHT.OUT F:\NDCMP\PUBOUT\D04_RGHT.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D05_ATTR.OUT F:\NDCMP\PUBOUT\D05_ATTR.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D06_H.OUT F:\NDCMP\PUBOUT\D06_H.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D07_RO.OUT F:\NDCMP\PUBOUT\D07_RO.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D08_SY.OUT F:\NDCMP\PUBOUT\D08_SY.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D09_A.OUT F:\NDCMP\PUBOUT\D09_A.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D10_NOTH.OUT F:\NDCMP\PUBOUT\D10_NOTH.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D11_TXT.OUT F:\NDCMP\PUBOUT\D11_TXT.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D12_DAT.OUT F:\NDCMP\PUBOUT\D12_DAT.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D13_FO.OUT F:\NDCMP\PUBOUT\D13_FO.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D14_DO.OUT F:\NDCMP\PUBOUT\D14_DO.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D15_SUB.OUT F:\NDCMP\PUBOUT\D15_SUB.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D16_SUBR.OUT F:\NDCMP\PUBOUT\D16_SUBR.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D17_MATR.OUT F:\NDCMP\PUBOUT\D17_MATR.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D18_MDAT.OUT F:\NDCMP\PUBOUT\D18_MDAT.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D19_MRGT.OUT F:\NDCMP\PUBOUT\D19_MRGT.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D20_MFO.OUT F:\NDCMP\PUBOUT\D20_MFO.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D21_MDO.OUT F:\NDCMP\PUBOUT\D21_MDO.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D22_MSUB.OUT F:\NDCMP\PUBOUT\D22_MSUB.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D23_MSRG.OUT F:\NDCMP\PUBOUT\D23_MSRG.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D24_MH.OUT F:\NDCMP\PUBOUT\D24_MH.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D25_MRO.OUT F:\NDCMP\PUBOUT\D25_MRO.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D26_MSY.OUT F:\NDCMP\PUBOUT\D26_MSY.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D27_MA.OUT F:\NDCMP\PUBOUT\D27_MA.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D28_MNH.OUT F:\NDCMP\PUBOUT\D28_MNH.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D29_MTXT.OUT F:\NDCMP\PUBOUT\D29_MTXT.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D30_USRR.OUT F:\NDCMP\PUBOUT\D30_USRR.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D31_USRS.OUT F:\NDCMP\PUBOUT\D31_USRS.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D32_USRD.OUT F:\NDCMP\PUBOUT\D32_USRD.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D33_USRT.OUT F:\NDCMP\PUBOUT\D33_USRT.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D34_USRD.OUT F:\NDCMP\PUBOUT\D34_USRD.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D90_MISS.OUT F:\NDCMP\PUBOUT\D90_MISS.OUT >> F:\NDCMP\COMPARE.LOG +FC F:\NDCMP\OUT\D99_HELP.OUT F:\NDCMP\PUBOUT\D99_HELP.OUT >> F:\NDCMP\COMPARE.LOG + +REM --- Setup NOPASSUSER matrix. --- +ECHO === USER CONTEXT SETUP === >> F:\NDCMP\RUN.LOG +\NPUBLIC\GRANT R F FOR F:\TNDIR TO USER NOPASSUSER > F:\NDCMP\SETUP\S00_ROOT.OUT +\NPUBLIC\GRANT R F FOR F:\TNDIR\URF TO USER NOPASSUSER > F:\NDCMP\SETUP\S10_RF.OUT +\NPUBLIC\GRANT R W C E M F A FOR F:\TNDIR\UFULL TO USER NOPASSUSER > F:\NDCMP\SETUP\S11_FULL.OUT +\NPUBLIC\GRANT S FOR F:\TNDIR\US TO USER NOPASSUSER > F:\NDCMP\SETUP\S12_S.OUT +\NPUBLIC\GRANT N FOR F:\TNDIR\UNONE TO USER NOPASSUSER > F:\NDCMP\SETUP\S13_N.OUT +\NPUBLIC\GRANT R F FOR F:\TNDIR\USUB TO USER NOPASSUSER > F:\NDCMP\SETUP\S14_SUB.OUT +\NPUBLIC\GRANT R F FOR F:\TNDIR\USUB\CHILD TO USER NOPASSUSER > F:\NDCMP\SETUP\S15_CHLD.OUT +\NPUBLIC\GRANT R F FOR F:\TNDIR\MAT TO USER NOPASSUSER > F:\NDCMP\SETUP\S20_MATR.OUT +\NPUBLIC\GRANT R F FOR F:\TNDIR\MAT\D_SUB TO USER NOPASSUSER > F:\NDCMP\SETUP\S21_MSUD.OUT +\NPUBLIC\GRANT R F FOR F:\TNDIR\MAT\D_SUB\CHILD TO USER NOPASSUSER > F:\NDCMP\SETUP\S22_MCHD.OUT +\NPUBLIC\GRANT R F FOR F:\TNDIR\USR TO USER NOPASSUSER > F:\NDCMP\SETUP\S30_USR.OUT +\NPUBLIC\GRANT R FOR F:\TNDIR\USR\U_EVERYR TO GROUP EVERYONE > F:\NDCMP\SETUP\S31_EVR.OUT +\NPUBLIC\GRANT R W C E M F A FOR F:\TNDIR\USR\U_EVERYF TO GROUP EVERYONE > F:\NDCMP\SETUP\S32_EVF.OUT +\NPUBLIC\GRANT R F FOR F:\TNDIR\USR\U_MARIO TO USER MARIO > F:\NDCMP\SETUP\S33_MAR.OUT +\NPUBLIC\GRANT R F FOR F:\TNDIR\USR\U_GUEST TO USER GUEST > F:\NDCMP\SETUP\S34_GST.OUT +\NPUBLIC\GRANT W C M FOR F:\TNDIR\USR\U_NOPWCM TO USER NOPASSUSER > F:\NDCMP\SETUP\S35_WCM.OUT +\NPUBLIC\GRANT R E M A FOR F:\TNDIR\USR\U_NOPREM TO USER NOPASSUSER > F:\NDCMP\SETUP\S36_REM.OUT +\NPUBLIC\GRANT R F FOR F:\TNDIR\USR\U_NOPRF TO USER NOPASSUSER > F:\NDCMP\SETUP\S37_RF.OUT +\NPUBLIC\GRANT R F FOR F:\TNDIR\USR\U_CHILD TO GROUP EVERYONE > F:\NDCMP\SETUP\S38_CHLD.OUT +\NPUBLIC\GRANT S FOR F:\TNDIR\USR\U_CHILD\DEEP TO USER NOPASSUSER > F:\NDCMP\SETUP\S39_DEEP.OUT + +REM --- Prepare local delayed helper. --- +MD C:\NDIRTMP +MD C:\NDIRTMP\UNOV +MD C:\NDIRTMP\UPUB +IF EXIST C:\NDIRTMP\HELPER.TXT DEL C:\NDIRTMP\HELPER.TXT +COPY F:\NDIRC.BAT C:\NDIRTMP\NDIRC.BAT > NUL +COPY F:\PUBLIC\DLYSTRT.EXE C:\NDIRTMP\DLYSTRT.EXE > NUL + +C: +CD \NDIRTMP +DLYSTRT /T:2 NDIRC.BAT +GOTO END + +:PART2 +F: +CD \ +IF NOT EXIST NDCMP\NUL MD NDCMP +IF NOT EXIST NDCMP\UNOV\NUL MD NDCMP\UNOV +IF NOT EXIST NDCMP\UPUB\NUL MD NDCMP\UPUB +IF NOT EXIST NDCMP\USHORT\NUL MD NDCMP\USHORT +IF NOT EXIST NDCMP\USETUP\NUL MD NDCMP\USETUP + +COPY C:\NDIRTMP\UNOV\*.OUT F:\NDCMP\UNOV > NUL +COPY C:\NDIRTMP\UPUB\*.OUT F:\NDCMP\UPUB > NUL +IF EXIST C:\NDIRTMP\USHORT\*.OUT COPY C:\NDIRTMP\USHORT\*.OUT F:\NDCMP\USHORT > NUL +IF EXIST C:\NDIRTMP\HELPER.TXT COPY C:\NDIRTMP\HELPER.TXT F:\NDCMP\HELPER.TXT > NUL +IF EXIST C:\NDIRTMP\UCOMP.LOG COPY C:\NDIRTMP\UCOMP.LOG F:\NDCMP\UCOMP.LOG > NUL ECHO === SUMMARY === > F:\NDCMP\SUMMARY.TXT -ECHO NDIRTSTA automated Novell NDIR baseline finished. >> F:\NDCMP\SUMMARY.TXT +ECHO NDIRTSTA compare test finished. >> F:\NDCMP\SUMMARY.TXT ECHO. >> F:\NDCMP\SUMMARY.TXT -ECHO Outputs are in F:\NDCMP\OUT. >> F:\NDCMP\SUMMARY.TXT -ECHO Expected highlights: >> F:\NDCMP\SUMMARY.TXT -ECHO - N01_ROOT lists ALPHA.TXT, BETA.TXT, GAMMA.DAT and SUBDIR. >> F:\NDCMP\SUMMARY.TXT -ECHO - N03_DATES shows date fields. >> F:\NDCMP\SUMMARY.TXT -ECHO - N04_RGT shows rights. >> F:\NDCMP\SUMMARY.TXT -ECHO - N05_FLG* shows H, RO, SY/A attribute setup. >> F:\NDCMP\SUMMARY.TXT -ECHO - N07_* filters isolate attributes. >> F:\NDCMP\SUMMARY.TXT -ECHO - N09_* sort modes run without error. >> F:\NDCMP\SUMMARY.TXT -ECHO - N10_TXT lists TXT files; N10_DAT lists GAMMA.DAT. >> F:\NDCMP\SUMMARY.TXT -ECHO - N11_FO/N11_DO separate files/directories where supported. >> F:\NDCMP\SUMMARY.TXT -ECHO - N12_SUB includes SUBDIR\SUB.TXT. >> F:\NDCMP\SUMMARY.TXT -ECHO Optional pack results with NDIRZIP.BAT. >> F:\NDCMP\SUMMARY.TXT +ECHO Direct output: OUT vs PUBOUT, see COMPARE.LOG. >> F:\NDCMP\SUMMARY.TXT +ECHO User-context output: UNOV vs UPUB, see UCOMP.LOG. >> F:\NDCMP\SUMMARY.TXT +ECHO Public-only /SHORT output: SHORTOUT and USHORT, not compared. >> F:\NDCMP\SUMMARY.TXT +ECHO Matrix coverage: D17-D34 and U17-U30 cover mixed file, directory and user trustee matrices. >> F:\NDCMP\SUMMARY.TXT +ECHO. >> F:\NDCMP\SUMMARY.TXT +ECHO Optional: NDIRZIP ausfuehren. >> F:\NDCMP\SUMMARY.TXT ECHO. -ECHO NDIRTSTA fertig. +ECHO NDIRTSTA PART2 fertig. ECHO Ergebnisse liegen in F:\NDCMP ECHO Optional: NDIRZIP ausfuehren. ECHO. +GOTO END + +:NEEDPWD +ECHO. +ECHO ERROR: LGNTPWD ist nicht gesetzt. +ECHO. +ECHO Fuer den vollautomatischen NDIR-User-Kontext-Test zuerst setzen, z.B.: +ECHO SET LGNTPWD=dein-supervisor-passwort +ECHO Danach starten: +ECHO F:\NDIRTSTA +ECHO. +ECHO Es wurde kein DLYSTRT installiert und kein Login-Test gestartet. +GOTO END + +:END diff --git a/test/ndir/NDIRZIP.BAT b/test/ndir/NDIRZIP.BAT index 016e468..5e83c3f 100644 --- a/test/ndir/NDIRZIP.BAT +++ b/test/ndir/NDIRZIP.BAT @@ -1,27 +1,26 @@ -@ECHO OFF -REM NDIRZIP.BAT -REM Optional packer for NDIRTSTA result files. -REM Requires ZIP.EXE in PATH or current directory. - -F: -CD \NDCMP - -IF EXIST NDIRTSTA.ZIP DEL NDIRTSTA.ZIP -IF EXIST ZIP.LOG DEL ZIP.LOG - -ECHO Creating NDIRTSTA.ZIP > ZIP.LOG -ZIP -r NDIRTSTA.ZIP RUN.LOG SUMMARY.TXT OUT >> ZIP.LOG - - -REM Cleanup generated test directories after ZIP. -REM Keep the CMP/result directory because it contains the ZIP and ZIP.LOG. -ECHO Cleaning generated test directories... >> ZIP.LOG -IF EXIST \TNDIR\NUL DELTREE /Y \TNDIR >> ZIP.LOG -IF EXIST \NDIRTEST\NUL DELTREE /Y \NDIRTEST >> ZIP.LOG -CD \ -ECHO. -ECHO ZIP step finished. -ECHO Check: -ECHO F:\NDCMP\NDIRTSTA.ZIP -ECHO F:\NDCMP\ZIP.LOG -ECHO. +@ECHO OFF +REM NDIRZIP.BAT +REM Optional packer for NDIRTSTA result files. +REM Requires ZIP.EXE in PATH or current directory. + +F: +CD \NDCMP + +IF EXIST NDIRTSTA.ZIP DEL NDIRTSTA.ZIP +IF EXIST ZIP.LOG DEL ZIP.LOG + +ECHO Creating NDIRTSTA.ZIP > ZIP.LOG +ZIP -r NDIRTSTA.ZIP RUN.LOG SUMMARY.TXT COMPARE.LOG UCOMP.LOG HELPER.TXT OUT PUBOUT SHORTOUT SETUP UNOV UPUB USHORT USETUP >> ZIP.LOG + +REM Cleanup generated test directories after ZIP. +REM Keep the CMP/result directory because it contains the ZIP and ZIP.LOG. +ECHO Cleaning generated test directories... >> ZIP.LOG +IF EXIST \TNDIR\NUL DELTREE /Y \TNDIR >> ZIP.LOG +IF EXIST C:\NDIRTMP\NUL DELTREE /Y C:\NDIRTMP >> ZIP.LOG +CD \ +ECHO. +ECHO ZIP step finished. +ECHO Check: +ECHO F:\NDCMP\NDIRTSTA.ZIP +ECHO F:\NDCMP\ZIP.LOG +ECHO. diff --git a/test/ndir/README.md b/test/ndir/README.md index 0c539ef..b65e705 100644 --- a/test/ndir/README.md +++ b/test/ndir/README.md @@ -1,19 +1,30 @@ -# NDIR automated test +# NDIR automated compare test -Automated Novell-only baseline for `NPUBLIC\NDIR`. +Automated compare test for `NDIR`. ## Run ```text +SET LGNTPWD=dein-supervisor-passwort +F: +CD \ NDIRTSTA ``` -Results: +`LGNTPWD` is required because the test switches to `NOPASSUSER` and then logs back in as `SUPERVISOR` through the maintainer-only `LOGIN /PWD:` path. + +## Result layout ```text -F:\NDCMP\RUN.LOG -F:\NDCMP\SUMMARY.TXT -F:\NDCMP\OUT\*.OUT +F:\NDCMP\OUT\*.OUT Novell baseline via \NPUBLIC\NDIR +F:\NDCMP\PUBOUT\*.OUT PUBLIC implementation via \PUBLIC\NDIR +F:\NDCMP\COMPARE.LOG direct compare log +F:\NDCMP\SHORTOUT\*.OUT PUBLIC-only /SHORT helper output; not compared + +F:\NDCMP\UNOV\*.OUT Novell NDIR as NOPASSUSER +F:\NDCMP\UPUB\*.OUT PUBLIC NDIR as NOPASSUSER +F:\NDCMP\UCOMP.LOG user-context compare log +F:\NDCMP\USHORT\*.OUT PUBLIC-only /SHORT helper output as NOPASSUSER ``` Optional pack: @@ -48,9 +59,38 @@ F:\TNDIR - `/DATES` - `/RIGHTS` - attributes via `NPUBLIC\FLAG` -- filters `/H`, `/RO`, `/SY`, `/A`, `/NOT H`, `/NOT RO` -- sorts `/SORT UN`, `/SORT SI`, `/SORT UP` +- filters `/H`, `/RO`, `/SY`, `/A`, `/NOT H` - wildcards `*.TXT`, `*.DAT` - `/FO`, `/DO` -- `/SUB` -- cleanup +- `/SUB` and `/SUB /RIGHTS` in the Novell-compatible compare set +- extended file/directory matrix under `F:\TNDIR\MAT`: + - files with Normal, Hidden, Read-only, System, Archive, DI/RI and mixed attributes + - directories with Normal, Hidden, System, Purge, DI/RI and mixed directory flags + - matrix checks for normal listing, `/DATES`, `/RIGHTS`, `/FO`, `/DO`, `/SUB`, filters and wildcards +- Public-only `/SHORT` output in `SHORTOUT` / `USHORT` is kept for diagnostics and is not compared against Novell +- missing-pattern and help output +- NOPASSUSER readback after GRANT matrix setup, including the extended `MAT` file/directory matrix + +`NDIRZIP` cleans the generated `TNDIR` tree and `C:\NDIRTMP` helper directory after packaging. + +## Notes on /SHORT + +`/SHORT` is a MARS DOS tools helper option. Novell NDIR does not know this option, +so the test keeps `/SHORT` output in `SHORTOUT` and `USHORT` only. These files are +packaged for manual inspection but are not part of the byte-for-byte Novell compare. + + +Additional user/trustee matrix +------------------------------ +The extended matrix also creates F:\TNDIR\USR with trustees for multiple +objects that exist in the default test environment: + +- USER NOPASSUSER +- USER MARIO +- USER GUEST +- GROUP EVERYONE + +The delayed NOPASSUSER phase reads the same tree through NPUBLIC and PUBLIC +NDIR. This gives more coverage for effective-rights output: direct user +trustees, group/EVERYONE trustees, unrelated user trustees, inherited rights, +and Supervisor-on-child cases. diff --git a/test/revoke/README.md b/test/revoke/README.md index 85a7b3a..a959ddf 100644 --- a/test/revoke/README.md +++ b/test/revoke/README.md @@ -1,31 +1,32 @@ -# REVOKE baseline test +# REVOKE comparison test -Scripts: +`RVKSTA.BAT` creates `F:\RVKTEST` and compares Novell `\NPUBLIC\REVOKE` output with the public implementation `\PUBLIC\REVOKE`. -- `RVKSTA.BAT` creates `F:\RVKTEST`, uses Novell `\NPUBLIC\GRANT` for setup, then captures Novell `\NPUBLIC\REVOKE` output into `F:\RVKCMP\OUT`. User `MARIO` is used as trustee target. -- `RVKZIP.BAT` packages `RUN.LOG`, `SUMMARY.TXT`, `SETUP`, and `OUT` as `F:\RVKCMP\RVKSTA.ZIP`. +Result tree: -Run as `SUPERVISOR` or an equivalent user with Access Control rights on `F:\RVKTEST`. +- `F:\RVKCMP\OUT` - Novell baseline output +- `F:\RVKCMP\PUBOUT` - public implementation output +- `F:\RVKCMP\COMPARE.LOG` - direct `FC` comparisons +- `F:\RVKCMP\UNOV` - user-context Novell `RIGHTS` readback +- `F:\RVKCMP\UPUB` - user-context public `RIGHTS` readback +- `F:\RVKCMP\UCOMP.LOG` - user-context `FC` comparisons -Covered cases: +The direct matrix covers: -- help and no-argument grammar -- normal directory revoke -- `ALL` revoke / trustee removal -- `/SUBDIRECTORIES` with trustees placed directly on child directories -- `/FILES` on an explicit file and on a directory file set -- relative path invocation from inside the test directory while invoking `\NPUBLIC\REVOKE` absolutely -- no trustee, missing user, missing path behavior, `/FILES` plus `/SUBDIRECTORIES` option-combination behavior, and bad grammar +- individual right removal: `R`, `W`, `C`, `E`, `M`, `F`, `A`, `S` +- mixed rights removal such as `R F`, `R W C`, `E M F`, `S W C M` +- `ALL` removal, which should delete the trustee entry +- file-specific mode with `/FILES` +- recursive directory mode with `/SUBDIRECTORIES` +- missing trustee, missing user, missing path, invalid right, bad grammar, and `/FILES /SUBDIRECTORIES` -This test is still Novell-baseline-only. Later comparison scripts should run the same command set through `NPUBLIC` and `PUBLIC` with normalized output. +Automatic user-context readback requires: -Notes from the first baseline run: +```bat +SET LGNTPWD=your-supervisor-password +F:\RVKSTA +``` -- `REVOKE /SUBDIRECTORIES` did not exercise child paths unless trustees existed on the child directories themselves, so `D20` now uses `SUBTST\S1` and `SUBTST\S2` with direct trustee setup. -- Novell `REVOKE` may report `No trustee for the specified directory.` for a missing path before a separate missing-path diagnostic is reached; `D92` records that baseline behavior. -- `D93` now uses an independent tree with directory, file, and subdirectory trustees so the `/FILES /SUBDIRECTORIES` option combination is tested without being masked by missing trustee setup. -Retest focus after the fix: +`RVKC.BAT` is queued via `DLYSTRT`, logs in as `NOPASSUSER`, captures `RIGHTS` output for the matrix cases, logs SUPERVISOR back in, and then starts `RVKSTA PART2` to copy and compare the user-context results. -- `D20_SUBDIRS_REVOKE_CE.OUT` should no longer be masked by a missing trustee on the named root. -- `D92_MISSING_PATH.OUT` records the exact Novell diagnostic for a missing path, even if that diagnostic is still `No trustee for the specified directory.` -- `D93_FILES_AND_SUBDIRS.OUT` runs on a prepared tree with directory, file, and subdirectory trustees, so the `/FILES /SUBDIRECTORIES` combination is no longer masked by setup. +`RVKZIP.BAT` packs the result tree and cleans `F:\RVKTEST` and `C:\RVKTMP`. diff --git a/test/revoke/RVKC.BAT b/test/revoke/RVKC.BAT new file mode 100644 index 0000000..2590a08 --- /dev/null +++ b/test/revoke/RVKC.BAT @@ -0,0 +1,168 @@ +@ECHO OFF +REM RVKC.BAT - delayed user-context REVOKE readback helper. +REM Started by RVKSTA via DLYSTRT. Runs from C:\RVKTMP. + +C: +CD \RVKTMP + +ECHO RVKC user-context REVOKE readback helper > HELPER.TXT +ECHO Current phase: logout supervisor, login NOPASSUSER. >> HELPER.TXT + +LOGOUT > ULOG1.OUT +LOGIN NOPASSUSER > ULOGIN.OUT + +IF NOT EXIST UNOV MD UNOV +IF NOT EXIST UPUB MD UPUB + +F: +CD \ +IF EXIST \NPUBLIC\RIGHTS.EXE GOTO HAVEF +ECHO F: not ready after NOPASSUSER login. >> C:\RVKTMP\HELPER.TXT +GOTO RELSUP + +:HAVEF +ECHO Starting G10_R as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\G10 > C:\RVKTMP\UNOV\G10_R.OUT +\PUBLIC\RIGHTS F:\RVKTEST\G10 > C:\RVKTMP\UPUB\G10_R.OUT +ECHO Starting G11_W as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\G11 > C:\RVKTMP\UNOV\G11_W.OUT +\PUBLIC\RIGHTS F:\RVKTEST\G11 > C:\RVKTMP\UPUB\G11_W.OUT +ECHO Starting G12_C as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\G12 > C:\RVKTMP\UNOV\G12_C.OUT +\PUBLIC\RIGHTS F:\RVKTEST\G12 > C:\RVKTMP\UPUB\G12_C.OUT +ECHO Starting G13_E as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\G13 > C:\RVKTMP\UNOV\G13_E.OUT +\PUBLIC\RIGHTS F:\RVKTEST\G13 > C:\RVKTMP\UPUB\G13_E.OUT +ECHO Starting G14_M as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\G14 > C:\RVKTMP\UNOV\G14_M.OUT +\PUBLIC\RIGHTS F:\RVKTEST\G14 > C:\RVKTMP\UPUB\G14_M.OUT +ECHO Starting G15_F as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\G15 > C:\RVKTMP\UNOV\G15_F.OUT +\PUBLIC\RIGHTS F:\RVKTEST\G15 > C:\RVKTMP\UPUB\G15_F.OUT +ECHO Starting G16_A as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\G16 > C:\RVKTMP\UNOV\G16_A.OUT +\PUBLIC\RIGHTS F:\RVKTEST\G16 > C:\RVKTMP\UPUB\G16_A.OUT +ECHO Starting G17_S as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\G17 > C:\RVKTMP\UNOV\G17_S.OUT +\PUBLIC\RIGHTS F:\RVKTEST\G17 > C:\RVKTMP\UPUB\G17_S.OUT +ECHO Starting G20_RF as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\G20 > C:\RVKTMP\UNOV\G20_RF.OUT +\PUBLIC\RIGHTS F:\RVKTEST\G20 > C:\RVKTMP\UPUB\G20_RF.OUT +ECHO Starting G21_RW as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\G21 > C:\RVKTMP\UNOV\G21_RW.OUT +\PUBLIC\RIGHTS F:\RVKTEST\G21 > C:\RVKTMP\UPUB\G21_RW.OUT +ECHO Starting G22_RWC as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\G22 > C:\RVKTMP\UNOV\G22_RWC.OUT +\PUBLIC\RIGHTS F:\RVKTEST\G22 > C:\RVKTMP\UPUB\G22_RWC.OUT +ECHO Starting G23_RWCE as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\G23 > C:\RVKTMP\UNOV\G23_RWCE.OUT +\PUBLIC\RIGHTS F:\RVKTEST\G23 > C:\RVKTMP\UPUB\G23_RWCE.OUT +ECHO Starting G24_EMF as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\G24 > C:\RVKTMP\UNOV\G24_EMF.OUT +\PUBLIC\RIGHTS F:\RVKTEST\G24 > C:\RVKTMP\UPUB\G24_EMF.OUT +ECHO Starting G25_SAL as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\G25 > C:\RVKTMP\UNOV\G25_SAL.OUT +\PUBLIC\RIGHTS F:\RVKTEST\G25 > C:\RVKTMP\UPUB\G25_SAL.OUT +ECHO Starting G26_ALL as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\G26 > C:\RVKTMP\UNOV\G26_ALL.OUT +\PUBLIC\RIGHTS F:\RVKTEST\G26 > C:\RVKTMP\UPUB\G26_ALL.OUT +ECHO Starting G30_RE as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\G30 > C:\RVKTMP\UNOV\G30_RE.OUT +\PUBLIC\RIGHTS F:\RVKTEST\G30 > C:\RVKTMP\UPUB\G30_RE.OUT +ECHO Starting G31_RWF as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\G31 > C:\RVKTMP\UNOV\G31_RWF.OUT +\PUBLIC\RIGHTS F:\RVKTEST\G31 > C:\RVKTMP\UPUB\G31_RWF.OUT +ECHO Starting G32_RCM as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\G32 > C:\RVKTMP\UNOV\G32_RCM.OUT +\PUBLIC\RIGHTS F:\RVKTEST\G32 > C:\RVKTMP\UPUB\G32_RCM.OUT +ECHO Starting G33_RFA as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\G33 > C:\RVKTMP\UNOV\G33_RFA.OUT +\PUBLIC\RIGHTS F:\RVKTEST\G33 > C:\RVKTMP\UPUB\G33_RFA.OUT +ECHO Starting G34_WCM as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\G34 > C:\RVKTMP\UNOV\G34_WCM.OUT +\PUBLIC\RIGHTS F:\RVKTEST\G34 > C:\RVKTMP\UPUB\G34_WCM.OUT +ECHO Starting G35_EMF as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\G35 > C:\RVKTMP\UNOV\G35_EMF.OUT +\PUBLIC\RIGHTS F:\RVKTEST\G35 > C:\RVKTMP\UPUB\G35_EMF.OUT +ECHO Starting G36_RMF as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\G36 > C:\RVKTMP\UNOV\G36_RMF.OUT +\PUBLIC\RIGHTS F:\RVKTEST\G36 > C:\RVKTMP\UPUB\G36_RMF.OUT +ECHO Starting G37_REMA as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\G37 > C:\RVKTMP\UNOV\G37_REMA.OUT +\PUBLIC\RIGHTS F:\RVKTEST\G37 > C:\RVKTMP\UPUB\G37_REMA.OUT +ECHO Starting G38_SR as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\G38 > C:\RVKTMP\UNOV\G38_SR.OUT +\PUBLIC\RIGHTS F:\RVKTEST\G38 > C:\RVKTMP\UPUB\G38_SR.OUT +ECHO Starting G39_SRF as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\G39 > C:\RVKTMP\UNOV\G39_SRF.OUT +\PUBLIC\RIGHTS F:\RVKTEST\G39 > C:\RVKTMP\UPUB\G39_SRF.OUT +ECHO Starting G40_SWCM as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\G40 > C:\RVKTMP\UNOV\G40_SWCM.OUT +\PUBLIC\RIGHTS F:\RVKTEST\G40 > C:\RVKTMP\UPUB\G40_SWCM.OUT +ECHO Starting F10_R as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\F10\T.TXT > C:\RVKTMP\UNOV\F10_R.OUT +\PUBLIC\RIGHTS F:\RVKTEST\F10\T.TXT > C:\RVKTMP\UPUB\F10_R.OUT +ECHO Starting F11_RF as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\F11\T.TXT > C:\RVKTMP\UNOV\F11_RF.OUT +\PUBLIC\RIGHTS F:\RVKTEST\F11\T.TXT > C:\RVKTMP\UPUB\F11_RF.OUT +ECHO Starting F12_RAL as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\F12\T.TXT > C:\RVKTMP\UNOV\F12_RAL.OUT +\PUBLIC\RIGHTS F:\RVKTEST\F12\T.TXT > C:\RVKTMP\UPUB\F12_RAL.OUT +ECHO Starting F13_ALL as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\F13\T.TXT > C:\RVKTMP\UNOV\F13_ALL.OUT +\PUBLIC\RIGHTS F:\RVKTEST\F13\T.TXT > C:\RVKTMP\UPUB\F13_ALL.OUT +ECHO Starting F14_N as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\F14\T.TXT > C:\RVKTMP\UNOV\F14_N.OUT +\PUBLIC\RIGHTS F:\RVKTEST\F14\T.TXT > C:\RVKTMP\UPUB\F14_N.OUT +ECHO Starting F15_S as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\F15\T.TXT > C:\RVKTMP\UNOV\F15_S.OUT +\PUBLIC\RIGHTS F:\RVKTEST\F15\T.TXT > C:\RVKTMP\UPUB\F15_S.OUT +ECHO Starting F16_SAL as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\F16\T.TXT > C:\RVKTMP\UNOV\F16_SAL.OUT +\PUBLIC\RIGHTS F:\RVKTEST\F16\T.TXT > C:\RVKTMP\UPUB\F16_SAL.OUT +ECHO Starting S10_R as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\S10\S1 > C:\RVKTMP\UNOV\S10_R.OUT +\PUBLIC\RIGHTS F:\RVKTEST\S10\S1 > C:\RVKTMP\UPUB\S10_R.OUT +ECHO Starting S11_RWC as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\S11\S1 > C:\RVKTMP\UNOV\S11_RWC.OUT +\PUBLIC\RIGHTS F:\RVKTEST\S11\S1 > C:\RVKTMP\UPUB\S11_RWC.OUT +ECHO Starting S12_ALL as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\S12\S1 > C:\RVKTMP\UNOV\S12_ALL.OUT +\PUBLIC\RIGHTS F:\RVKTEST\S12\S1 > C:\RVKTMP\UPUB\S12_ALL.OUT +ECHO Starting S13_SAL as NOPASSUSER... >> C:\RVKTMP\HELPER.TXT +\NPUBLIC\RIGHTS F:\RVKTEST\S13\S1 > C:\RVKTMP\UNOV\S13_SAL.OUT +\PUBLIC\RIGHTS F:\RVKTEST\S13\S1 > C:\RVKTMP\UPUB\S13_SAL.OUT + +:RELSUP +C: +CD \RVKTMP +LOGOUT > ULOG2.OUT + +F: +CD \ +IF EXIST \LOGIN\LOGIN.EXE GOTO HAVELOG +ECHO F:\LOGIN\LOGIN.EXE not found. >> C:\RVKTMP\HELPER.TXT +GOTO MANUAL + +:HAVELOG +F:\LOGIN\LOGIN SUPERVISOR /PWD:%LGNTPWD% > C:\RVKTMP\ULGSUP.OUT + +F: +CD \ +IF EXIST \RVKSTA.BAT GOTO QUEUEP2 +ECHO F: not restored or \RVKSTA.BAT missing. >> C:\RVKTMP\HELPER.TXT +GOTO MANUAL + +:QUEUEP2 +C: +CD \RVKTMP +DLYSTRT /T:2 F:\RVKSTA.BAT PART2 +GOTO END + +:MANUAL +ECHO Please run manually after SUPERVISOR login: >> C:\RVKTMP\HELPER.TXT +ECHO F: >> C:\RVKTMP\HELPER.TXT +ECHO CD \ >> C:\RVKTMP\HELPER.TXT +ECHO RVKSTA PART2 >> C:\RVKTMP\HELPER.TXT + +:END diff --git a/test/revoke/RVKSTA.BAT b/test/revoke/RVKSTA.BAT index c463fbe..a2a3552 100644 --- a/test/revoke/RVKSTA.BAT +++ b/test/revoke/RVKSTA.BAT @@ -1,121 +1,698 @@ @ECHO OFF REM RVKSTA.BAT -REM Automated REVOKE baseline test for MARS NWE. +REM Automated REVOKE comparison test for MARS NWE. REM -REM Run as SUPERVISOR or a user with Access Control on F:\RVKTEST. -REM Uses \NPUBLIC\GRANT for setup and \NPUBLIC\REVOKE as Novell baseline. +REM Direct mode: +REM OUT = Novell baseline using \NPUBLIC\REVOKE +REM PUBOUT = our implementation using \PUBLIC\REVOKE REM -REM Result tree: -REM F:\RVKCMP -REM Test tree: -REM F:\RVKTEST +REM User-context mode: +REM REVOKE runs as SUPERVISOR against NOPASSUSER. +REM DLYSTRT starts C:\RVKTMP\RVKC.BAT after this script exits. +REM RVKC logs in as NOPASSUSER and compares effective RIGHTS readback. +REM +REM Optional automatic user-context mode requires: +REM SET LGNTPWD=your-supervisor-password +IF "%1"=="" GOTO PART1 +IF "%1"=="PART2" GOTO PART2 +IF "%1"=="part2" GOTO PART2 +IF "%1"=="Part2" GOTO PART2 +ECHO Usage: RVKSTA [PART2] +GOTO END + +:PART1 F: CD \ -REM --- Clean generated test/result directories (contents only). --- -IF EXIST RVKTEST\NUL DELTREE /Y RVKTEST\*.* -IF EXIST RVKCMP\NUL DELTREE /Y RVKCMP\*.* +REM --- Clean generated test/result directories. --- +IF EXIST RVKTEST\*.* DELTREE /Y RVKTEST +IF EXIST RVKCMP\*.* DELTREE /Y RVKCMP +IF EXIST C:\RVKTMP\*.* DELTREE /Y C:\RVKTMP -IF NOT EXIST RVKTEST\NUL MD RVKTEST -IF NOT EXIST RVKTEST\ONE\NUL MD RVKTEST\ONE -IF NOT EXIST RVKTEST\TREE\NUL MD RVKTEST\TREE -IF NOT EXIST RVKTEST\TREE\SUB1\NUL MD RVKTEST\TREE\SUB1 -IF NOT EXIST RVKTEST\TREE\SUB2\NUL MD RVKTEST\TREE\SUB2 -IF NOT EXIST RVKTEST\SUBTST\NUL MD RVKTEST\SUBTST -IF NOT EXIST RVKTEST\SUBTST\S1\NUL MD RVKTEST\SUBTST\S1 -IF NOT EXIST RVKTEST\SUBTST\S2\NUL MD RVKTEST\SUBTST\S2 -IF NOT EXIST RVKTEST\OPTBOTH\NUL MD RVKTEST\OPTBOTH -IF NOT EXIST RVKTEST\OPTBOTH\SUB\NUL MD RVKTEST\OPTBOTH\SUB -IF NOT EXIST RVKTEST\FILES\NUL MD RVKTEST\FILES -IF NOT EXIST RVKTEST\EMPTY\NUL MD RVKTEST\EMPTY -IF NOT EXIST RVKCMP\NUL MD RVKCMP -IF NOT EXIST RVKCMP\OUT\NUL MD RVKCMP\OUT -IF NOT EXIST RVKCMP\SETUP\NUL MD RVKCMP\SETUP +IF NOT EXIST RVKTEST MD RVKTEST +IF NOT EXIST RVKTEST\G10 MD RVKTEST\G10 +ECHO G10_R > F:\RVKTEST\G10\TEST.TXT +IF NOT EXIST RVKTEST\G11 MD RVKTEST\G11 +ECHO G11_W > F:\RVKTEST\G11\TEST.TXT +IF NOT EXIST RVKTEST\G12 MD RVKTEST\G12 +ECHO G12_C > F:\RVKTEST\G12\TEST.TXT +IF NOT EXIST RVKTEST\G13 MD RVKTEST\G13 +ECHO G13_E > F:\RVKTEST\G13\TEST.TXT +IF NOT EXIST RVKTEST\G14 MD RVKTEST\G14 +ECHO G14_M > F:\RVKTEST\G14\TEST.TXT +IF NOT EXIST RVKTEST\G15 MD RVKTEST\G15 +ECHO G15_F > F:\RVKTEST\G15\TEST.TXT +IF NOT EXIST RVKTEST\G16 MD RVKTEST\G16 +ECHO G16_A > F:\RVKTEST\G16\TEST.TXT +IF NOT EXIST RVKTEST\G17 MD RVKTEST\G17 +ECHO G17_S > F:\RVKTEST\G17\TEST.TXT +IF NOT EXIST RVKTEST\G20 MD RVKTEST\G20 +ECHO G20_RF > F:\RVKTEST\G20\TEST.TXT +IF NOT EXIST RVKTEST\G21 MD RVKTEST\G21 +ECHO G21_RW > F:\RVKTEST\G21\TEST.TXT +IF NOT EXIST RVKTEST\G22 MD RVKTEST\G22 +ECHO G22_RWC > F:\RVKTEST\G22\TEST.TXT +IF NOT EXIST RVKTEST\G23 MD RVKTEST\G23 +ECHO G23_RWCE > F:\RVKTEST\G23\TEST.TXT +IF NOT EXIST RVKTEST\G24 MD RVKTEST\G24 +ECHO G24_EMF > F:\RVKTEST\G24\TEST.TXT +IF NOT EXIST RVKTEST\G25 MD RVKTEST\G25 +ECHO G25_SAL > F:\RVKTEST\G25\TEST.TXT +IF NOT EXIST RVKTEST\G26 MD RVKTEST\G26 +ECHO G26_ALL > F:\RVKTEST\G26\TEST.TXT +IF NOT EXIST RVKTEST\G30 MD RVKTEST\G30 +ECHO G30_RE > F:\RVKTEST\G30\TEST.TXT +IF NOT EXIST RVKTEST\G31 MD RVKTEST\G31 +ECHO G31_RWF > F:\RVKTEST\G31\TEST.TXT +IF NOT EXIST RVKTEST\G32 MD RVKTEST\G32 +ECHO G32_RCM > F:\RVKTEST\G32\TEST.TXT +IF NOT EXIST RVKTEST\G33 MD RVKTEST\G33 +ECHO G33_RFA > F:\RVKTEST\G33\TEST.TXT +IF NOT EXIST RVKTEST\G34 MD RVKTEST\G34 +ECHO G34_WCM > F:\RVKTEST\G34\TEST.TXT +IF NOT EXIST RVKTEST\G35 MD RVKTEST\G35 +ECHO G35_EMF > F:\RVKTEST\G35\TEST.TXT +IF NOT EXIST RVKTEST\G36 MD RVKTEST\G36 +ECHO G36_RMF > F:\RVKTEST\G36\TEST.TXT +IF NOT EXIST RVKTEST\G37 MD RVKTEST\G37 +ECHO G37_REMA > F:\RVKTEST\G37\TEST.TXT +IF NOT EXIST RVKTEST\G38 MD RVKTEST\G38 +ECHO G38_SR > F:\RVKTEST\G38\TEST.TXT +IF NOT EXIST RVKTEST\G39 MD RVKTEST\G39 +ECHO G39_SRF > F:\RVKTEST\G39\TEST.TXT +IF NOT EXIST RVKTEST\G40 MD RVKTEST\G40 +ECHO G40_SWCM > F:\RVKTEST\G40\TEST.TXT +IF NOT EXIST RVKTEST\F10 MD RVKTEST\F10 +ECHO F10_R > F:\RVKTEST\F10\T.TXT +IF NOT EXIST RVKTEST\F11 MD RVKTEST\F11 +ECHO F11_RF > F:\RVKTEST\F11\T.TXT +IF NOT EXIST RVKTEST\F12 MD RVKTEST\F12 +ECHO F12_RAL > F:\RVKTEST\F12\T.TXT +IF NOT EXIST RVKTEST\F13 MD RVKTEST\F13 +ECHO F13_ALL > F:\RVKTEST\F13\T.TXT +IF NOT EXIST RVKTEST\F14 MD RVKTEST\F14 +ECHO F14_N > F:\RVKTEST\F14\T.TXT +IF NOT EXIST RVKTEST\F15 MD RVKTEST\F15 +ECHO F15_S > F:\RVKTEST\F15\T.TXT +IF NOT EXIST RVKTEST\F16 MD RVKTEST\F16 +ECHO F16_SAL > F:\RVKTEST\F16\T.TXT +IF NOT EXIST RVKTEST\S10 MD RVKTEST\S10 +IF NOT EXIST RVKTEST\S10\S1 MD RVKTEST\S10\S1 +IF NOT EXIST RVKTEST\S10\S2 MD RVKTEST\S10\S2 +ECHO S10_R root > F:\RVKTEST\S10\ROOT.TXT +ECHO S10_R s1 > F:\RVKTEST\S10\S1\S1.TXT +ECHO S10_R s2 > F:\RVKTEST\S10\S2\S2.TXT +IF NOT EXIST RVKTEST\S11 MD RVKTEST\S11 +IF NOT EXIST RVKTEST\S11\S1 MD RVKTEST\S11\S1 +IF NOT EXIST RVKTEST\S11\S2 MD RVKTEST\S11\S2 +ECHO S11_RWC root > F:\RVKTEST\S11\ROOT.TXT +ECHO S11_RWC s1 > F:\RVKTEST\S11\S1\S1.TXT +ECHO S11_RWC s2 > F:\RVKTEST\S11\S2\S2.TXT +IF NOT EXIST RVKTEST\S12 MD RVKTEST\S12 +IF NOT EXIST RVKTEST\S12\S1 MD RVKTEST\S12\S1 +IF NOT EXIST RVKTEST\S12\S2 MD RVKTEST\S12\S2 +ECHO S12_ALL root > F:\RVKTEST\S12\ROOT.TXT +ECHO S12_ALL s1 > F:\RVKTEST\S12\S1\S1.TXT +ECHO S12_ALL s2 > F:\RVKTEST\S12\S2\S2.TXT +IF NOT EXIST RVKTEST\S13 MD RVKTEST\S13 +IF NOT EXIST RVKTEST\S13\S1 MD RVKTEST\S13\S1 +IF NOT EXIST RVKTEST\S13\S2 MD RVKTEST\S13\S2 +ECHO S13_SAL root > F:\RVKTEST\S13\ROOT.TXT +ECHO S13_SAL s1 > F:\RVKTEST\S13\S1\S1.TXT +ECHO S13_SAL s2 > F:\RVKTEST\S13\S2\S2.TXT +IF NOT EXIST RVKTEST\EMPTY MD RVKTEST\EMPTY +IF NOT EXIST RVKTEST\OPTBOTH MD RVKTEST\OPTBOTH +IF NOT EXIST RVKTEST\OPTBOTH\SUB MD RVKTEST\OPTBOTH\SUB +ECHO E94 root > F:\RVKTEST\OPTBOTH\ROOT.TXT +ECHO E94 sub > F:\RVKTEST\OPTBOTH\SUB\SUB.TXT -ECHO REVOKE ONE FILE > F:\RVKTEST\ONE\ONE.TXT -ECHO REVOKE TREE FILE > F:\RVKTEST\TREE\TROOT.TXT -ECHO REVOKE SUB1 FILE > F:\RVKTEST\TREE\SUB1\SUB1.TXT -ECHO REVOKE SUB2 FILE > F:\RVKTEST\TREE\SUB2\SUB2.TXT -ECHO REVOKE SUBDIRECTORY S1 > F:\RVKTEST\SUBTST\S1\S1.TXT -ECHO REVOKE SUBDIRECTORY S2 > F:\RVKTEST\SUBTST\S2\S2.TXT -ECHO REVOKE OPTION ROOT > F:\RVKTEST\OPTBOTH\ROOT.TXT -ECHO REVOKE OPTION SUB > F:\RVKTEST\OPTBOTH\SUB\SUB.TXT -ECHO REVOKE FILE A > F:\RVKTEST\FILES\A.TXT -ECHO REVOKE FILE B > F:\RVKTEST\FILES\B.TXT +IF NOT EXIST RVKCMP MD RVKCMP +IF NOT EXIST RVKCMP\OUT MD RVKCMP\OUT +IF NOT EXIST RVKCMP\PUBOUT MD RVKCMP\PUBOUT +IF NOT EXIST RVKCMP\SETUP MD RVKCMP\SETUP +IF NOT EXIST RVKCMP\UNOV MD RVKCMP\UNOV +IF NOT EXIST RVKCMP\UPUB MD RVKCMP\UPUB +IF NOT EXIST RVKCMP\USETUP MD RVKCMP\USETUP +IF NOT EXIST C:\RVKTMP MD C:\RVKTMP -ECHO RVKSTA REVOKE baseline test > F:\RVKCMP\RUN.LOG -ECHO Run this as SUPERVISOR or equivalent. >> F:\RVKCMP\RUN.LOG -ECHO Setup uses \NPUBLIC\GRANT, test captures \NPUBLIC\REVOKE output for user MARIO. >> F:\RVKCMP\RUN.LOG +ECHO RVKSTA REVOKE comparison test > F:\RVKCMP\RUN.LOG +ECHO OUT = Novell baseline with \NPUBLIC\REVOKE >> F:\RVKCMP\RUN.LOG +ECHO PUBOUT = our implementation with \PUBLIC\REVOKE >> F:\RVKCMP\RUN.LOG +ECHO User-context target: NOPASSUSER >> F:\RVKCMP\RUN.LOG ECHO. >> F:\RVKCMP\RUN.LOG -ECHO === SETUP grants === >> F:\RVKCMP\RUN.LOG -\NPUBLIC\GRANT R W C E M F A FOR F:\RVKTEST\ONE TO USER MARIO > F:\RVKCMP\SETUP\S01_ONE_GRANT.OUT -\NPUBLIC\GRANT R W C E M F A FOR F:\RVKTEST\TREE TO USER MARIO /SUBDIRECTORIES > F:\RVKCMP\SETUP\S02_TREE_GRANT.OUT -\NPUBLIC\GRANT R W C E M F A FOR F:\RVKTEST\FILES\A.TXT TO USER MARIO /FILES > F:\RVKCMP\SETUP\S03_FILE_A_GRANT.OUT -\NPUBLIC\GRANT R W C E M F A FOR F:\RVKTEST\FILES\B.TXT TO USER MARIO /FILES > F:\RVKCMP\SETUP\S04_FILE_B_GRANT.OUT -REM Direct subdirectory trustees for D20, because REVOKE /SUBDIRECTORIES acts on trustees below the named directory. -\NPUBLIC\GRANT R W C E M F A FOR F:\RVKTEST\SUBTST\S1 TO USER MARIO > F:\RVKCMP\SETUP\S05_SUBTST_S1_GRANT.OUT -\NPUBLIC\GRANT R W C E M F A FOR F:\RVKTEST\SUBTST\S2 TO USER MARIO > F:\RVKCMP\SETUP\S06_SUBTST_S2_GRANT.OUT -REM Independent tree with both files and subdirectories for D93 option-combination behavior. -\NPUBLIC\GRANT R W C E M F A FOR F:\RVKTEST\OPTBOTH TO USER MARIO > F:\RVKCMP\SETUP\S07_OPTBOTH_ROOT_GRANT.OUT -\NPUBLIC\GRANT R W C E M F A FOR F:\RVKTEST\OPTBOTH\SUB TO USER MARIO > F:\RVKCMP\SETUP\S08_OPTBOTH_SUB_GRANT.OUT -\NPUBLIC\GRANT R W C E M F A FOR F:\RVKTEST\OPTBOTH\ROOT.TXT TO USER MARIO /FILES > F:\RVKCMP\SETUP\S09_OPTBOTH_FILE_GRANT.OUT - -ECHO === D01 usage/help === >> F:\RVKCMP\RUN.LOG +ECHO Starting D01_HELP... \NPUBLIC\REVOKE /? > F:\RVKCMP\OUT\D01_HELP.OUT +\PUBLIC\REVOKE /? > F:\RVKCMP\PUBOUT\D01_HELP.OUT +ECHO Starting D02_NOAR... +\NPUBLIC\REVOKE > F:\RVKCMP\OUT\D02_NOAR.OUT +\PUBLIC\REVOKE > F:\RVKCMP\PUBOUT\D02_NOAR.OUT -ECHO === D02 no arguments === >> F:\RVKCMP\RUN.LOG -\NPUBLIC\REVOKE > F:\RVKCMP\OUT\D02_NOARGS.OUT +ECHO Starting G10_R directory revoke R... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G10 > F:\RVKCMP\SETUP\G10_R_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G10 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G10_R_NGRANT.OUT +\NPUBLIC\REVOKE R FOR F:\RVKTEST\G10 FROM USER NOPASSUSER > F:\RVKCMP\OUT\G10_R.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G10 > F:\RVKCMP\SETUP\G10_R_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G10 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G10_R_PGRANT.OUT +\PUBLIC\REVOKE R FOR F:\RVKTEST\G10 FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\G10_R.OUT -ECHO === D10 revoke W M from directory === >> F:\RVKCMP\RUN.LOG -\NPUBLIC\REVOKE W M FOR F:\RVKTEST\ONE FROM USER MARIO > F:\RVKCMP\OUT\D10_DIR_REVOKE_WM.OUT +ECHO Starting G11_W directory revoke W... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G11 > F:\RVKCMP\SETUP\G11_W_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G11 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G11_W_NGRANT.OUT +\NPUBLIC\REVOKE W FOR F:\RVKTEST\G11 FROM USER NOPASSUSER > F:\RVKCMP\OUT\G11_W.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G11 > F:\RVKCMP\SETUP\G11_W_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G11 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G11_W_PGRANT.OUT +\PUBLIC\REVOKE W FOR F:\RVKTEST\G11 FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\G11_W.OUT -ECHO === D11 revoke ALL from directory / remove trustee === >> F:\RVKCMP\RUN.LOG -\NPUBLIC\REVOKE ALL FOR F:\RVKTEST\ONE FROM USER MARIO > F:\RVKCMP\OUT\D11_DIR_REVOKE_ALL.OUT +ECHO Starting G12_C directory revoke C... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G12 > F:\RVKCMP\SETUP\G12_C_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G12 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G12_C_NGRANT.OUT +\NPUBLIC\REVOKE C FOR F:\RVKTEST\G12 FROM USER NOPASSUSER > F:\RVKCMP\OUT\G12_C.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G12 > F:\RVKCMP\SETUP\G12_C_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G12 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G12_C_PGRANT.OUT +\PUBLIC\REVOKE C FOR F:\RVKTEST\G12 FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\G12_C.OUT -ECHO === D20 revoke C E recursively from direct subdirectory trustees === >> F:\RVKCMP\RUN.LOG -\NPUBLIC\REVOKE C E FOR F:\RVKTEST\SUBTST FROM USER MARIO /SUBDIRECTORIES > F:\RVKCMP\OUT\D20_SUBDIRS_REVOKE_CE.OUT +ECHO Starting G13_E directory revoke E... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G13 > F:\RVKCMP\SETUP\G13_E_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G13 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G13_E_NGRANT.OUT +\NPUBLIC\REVOKE E FOR F:\RVKTEST\G13 FROM USER NOPASSUSER > F:\RVKCMP\OUT\G13_E.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G13 > F:\RVKCMP\SETUP\G13_E_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G13 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G13_E_PGRANT.OUT +\PUBLIC\REVOKE E FOR F:\RVKTEST\G13 FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\G13_E.OUT -ECHO === D21 revoke R from one explicit file === >> F:\RVKCMP\RUN.LOG -\NPUBLIC\REVOKE R FOR F:\RVKTEST\FILES\A.TXT FROM USER MARIO /FILES > F:\RVKCMP\OUT\D21_FILE_REVOKE_R.OUT +ECHO Starting G14_M directory revoke M... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G14 > F:\RVKCMP\SETUP\G14_M_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G14 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G14_M_NGRANT.OUT +\NPUBLIC\REVOKE M FOR F:\RVKTEST\G14 FROM USER NOPASSUSER > F:\RVKCMP\OUT\G14_M.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G14 > F:\RVKCMP\SETUP\G14_M_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G14 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G14_M_PGRANT.OUT +\PUBLIC\REVOKE M FOR F:\RVKTEST\G14 FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\G14_M.OUT -ECHO === D22 revoke W from files in a directory === >> F:\RVKCMP\RUN.LOG -\NPUBLIC\REVOKE W FOR F:\RVKTEST\FILES FROM USER MARIO /FILES > F:\RVKCMP\OUT\D22_FILES_DIR_REVOKE_W.OUT +ECHO Starting G15_F directory revoke F... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G15 > F:\RVKCMP\SETUP\G15_F_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G15 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G15_F_NGRANT.OUT +\NPUBLIC\REVOKE F FOR F:\RVKTEST\G15 FROM USER NOPASSUSER > F:\RVKCMP\OUT\G15_F.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G15 > F:\RVKCMP\SETUP\G15_F_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G15 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G15_F_PGRANT.OUT +\PUBLIC\REVOKE F FOR F:\RVKTEST\G15 FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\G15_F.OUT -ECHO === D30 relative path from F:\RVKTEST === >> F:\RVKCMP\RUN.LOG -\NPUBLIC\GRANT R W C E M F A FOR F:\RVKTEST\ONE TO USER MARIO > F:\RVKCMP\SETUP\S30_ONE_REGRANT.OUT -CD \RVKTEST -\NPUBLIC\REVOKE W FOR ONE FROM USER MARIO > F:\RVKCMP\OUT\D30_REL_DIR_REVOKE_W.OUT +ECHO Starting G16_A directory revoke A... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G16 > F:\RVKCMP\SETUP\G16_A_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G16 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G16_A_NGRANT.OUT +\NPUBLIC\REVOKE A FOR F:\RVKTEST\G16 FROM USER NOPASSUSER > F:\RVKCMP\OUT\G16_A.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G16 > F:\RVKCMP\SETUP\G16_A_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G16 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G16_A_PGRANT.OUT +\PUBLIC\REVOKE A FOR F:\RVKTEST\G16 FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\G16_A.OUT + +ECHO Starting G17_S directory revoke S... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G17 > F:\RVKCMP\SETUP\G17_S_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G17 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G17_S_NGRANT.OUT +\NPUBLIC\REVOKE S FOR F:\RVKTEST\G17 FROM USER NOPASSUSER > F:\RVKCMP\OUT\G17_S.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G17 > F:\RVKCMP\SETUP\G17_S_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G17 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G17_S_PGRANT.OUT +\PUBLIC\REVOKE S FOR F:\RVKTEST\G17 FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\G17_S.OUT + +ECHO Starting G20_RF directory revoke R F... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G20 > F:\RVKCMP\SETUP\G20_RF_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G20 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G20_RF_NGRANT.OUT +\NPUBLIC\REVOKE R F FOR F:\RVKTEST\G20 FROM USER NOPASSUSER > F:\RVKCMP\OUT\G20_RF.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G20 > F:\RVKCMP\SETUP\G20_RF_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G20 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G20_RF_PGRANT.OUT +\PUBLIC\REVOKE R F FOR F:\RVKTEST\G20 FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\G20_RF.OUT + +ECHO Starting G21_RW directory revoke R W... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G21 > F:\RVKCMP\SETUP\G21_RW_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G21 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G21_RW_NGRANT.OUT +\NPUBLIC\REVOKE R W FOR F:\RVKTEST\G21 FROM USER NOPASSUSER > F:\RVKCMP\OUT\G21_RW.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G21 > F:\RVKCMP\SETUP\G21_RW_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G21 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G21_RW_PGRANT.OUT +\PUBLIC\REVOKE R W FOR F:\RVKTEST\G21 FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\G21_RW.OUT + +ECHO Starting G22_RWC directory revoke R W C... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G22 > F:\RVKCMP\SETUP\G22_RWC_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G22 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G22_RWC_NGRANT.OUT +\NPUBLIC\REVOKE R W C FOR F:\RVKTEST\G22 FROM USER NOPASSUSER > F:\RVKCMP\OUT\G22_RWC.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G22 > F:\RVKCMP\SETUP\G22_RWC_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G22 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G22_RWC_PGRANT.OUT +\PUBLIC\REVOKE R W C FOR F:\RVKTEST\G22 FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\G22_RWC.OUT + +ECHO Starting G23_RWCE directory revoke R W C E... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G23 > F:\RVKCMP\SETUP\G23_RWCE_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G23 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G23_RWCE_NGRANT.OUT +\NPUBLIC\REVOKE R W C E FOR F:\RVKTEST\G23 FROM USER NOPASSUSER > F:\RVKCMP\OUT\G23_RWCE.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G23 > F:\RVKCMP\SETUP\G23_RWCE_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G23 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G23_RWCE_PGRANT.OUT +\PUBLIC\REVOKE R W C E FOR F:\RVKTEST\G23 FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\G23_RWCE.OUT + +ECHO Starting G24_EMF directory revoke E M F... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G24 > F:\RVKCMP\SETUP\G24_EMF_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G24 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G24_EMF_NGRANT.OUT +\NPUBLIC\REVOKE E M F FOR F:\RVKTEST\G24 FROM USER NOPASSUSER > F:\RVKCMP\OUT\G24_EMF.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G24 > F:\RVKCMP\SETUP\G24_EMF_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G24 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G24_EMF_PGRANT.OUT +\PUBLIC\REVOKE E M F FOR F:\RVKTEST\G24 FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\G24_EMF.OUT + +ECHO Starting G25_SAL directory revoke S A... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G25 > F:\RVKCMP\SETUP\G25_SAL_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G25 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G25_SAL_NGRANT.OUT +\NPUBLIC\REVOKE S A FOR F:\RVKTEST\G25 FROM USER NOPASSUSER > F:\RVKCMP\OUT\G25_SAL.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G25 > F:\RVKCMP\SETUP\G25_SAL_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G25 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G25_SAL_PGRANT.OUT +\PUBLIC\REVOKE S A FOR F:\RVKTEST\G25 FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\G25_SAL.OUT + +ECHO Starting G26_ALL directory revoke ALL... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G26 > F:\RVKCMP\SETUP\G26_ALL_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G26 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G26_ALL_NGRANT.OUT +\NPUBLIC\REVOKE ALL FOR F:\RVKTEST\G26 FROM USER NOPASSUSER > F:\RVKCMP\OUT\G26_ALL.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G26 > F:\RVKCMP\SETUP\G26_ALL_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G26 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G26_ALL_PGRANT.OUT +\PUBLIC\REVOKE ALL FOR F:\RVKTEST\G26 FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\G26_ALL.OUT + +ECHO Starting G30_RE directory revoke R E... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G30 > F:\RVKCMP\SETUP\G30_RE_NREM.OUT +\NPUBLIC\GRANT R E FOR F:\RVKTEST\G30 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G30_RE_NGRANT.OUT +\NPUBLIC\REVOKE R FOR F:\RVKTEST\G30 FROM USER NOPASSUSER > F:\RVKCMP\OUT\G30_RE.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G30 > F:\RVKCMP\SETUP\G30_RE_PREM.OUT +\NPUBLIC\GRANT R E FOR F:\RVKTEST\G30 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G30_RE_PGRANT.OUT +\PUBLIC\REVOKE R FOR F:\RVKTEST\G30 FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\G30_RE.OUT + +ECHO Starting G31_RWF directory revoke W from R W F... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G31 > F:\RVKCMP\SETUP\G31_RWF_NREM.OUT +\NPUBLIC\GRANT R W F FOR F:\RVKTEST\G31 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G31_RWF_NGRANT.OUT +\NPUBLIC\REVOKE W FOR F:\RVKTEST\G31 FROM USER NOPASSUSER > F:\RVKCMP\OUT\G31_RWF.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G31 > F:\RVKCMP\SETUP\G31_RWF_PREM.OUT +\NPUBLIC\GRANT R W F FOR F:\RVKTEST\G31 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G31_RWF_PGRANT.OUT +\PUBLIC\REVOKE W FOR F:\RVKTEST\G31 FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\G31_RWF.OUT + +ECHO Starting G32_RCM directory revoke C from R C M... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G32 > F:\RVKCMP\SETUP\G32_RCM_NREM.OUT +\NPUBLIC\GRANT R C M FOR F:\RVKTEST\G32 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G32_RCM_NGRANT.OUT +\NPUBLIC\REVOKE C FOR F:\RVKTEST\G32 FROM USER NOPASSUSER > F:\RVKCMP\OUT\G32_RCM.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G32 > F:\RVKCMP\SETUP\G32_RCM_PREM.OUT +\NPUBLIC\GRANT R C M FOR F:\RVKTEST\G32 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G32_RCM_PGRANT.OUT +\PUBLIC\REVOKE C FOR F:\RVKTEST\G32 FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\G32_RCM.OUT + +ECHO Starting G33_RFA directory revoke F A from R F A... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G33 > F:\RVKCMP\SETUP\G33_RFA_NREM.OUT +\NPUBLIC\GRANT R F A FOR F:\RVKTEST\G33 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G33_RFA_NGRANT.OUT +\NPUBLIC\REVOKE F A FOR F:\RVKTEST\G33 FROM USER NOPASSUSER > F:\RVKCMP\OUT\G33_RFA.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G33 > F:\RVKCMP\SETUP\G33_RFA_PREM.OUT +\NPUBLIC\GRANT R F A FOR F:\RVKTEST\G33 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G33_RFA_PGRANT.OUT +\PUBLIC\REVOKE F A FOR F:\RVKTEST\G33 FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\G33_RFA.OUT + +ECHO Starting G34_WCM directory revoke W C from W C M... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G34 > F:\RVKCMP\SETUP\G34_WCM_NREM.OUT +\NPUBLIC\GRANT W C M FOR F:\RVKTEST\G34 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G34_WCM_NGRANT.OUT +\NPUBLIC\REVOKE W C FOR F:\RVKTEST\G34 FROM USER NOPASSUSER > F:\RVKCMP\OUT\G34_WCM.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G34 > F:\RVKCMP\SETUP\G34_WCM_PREM.OUT +\NPUBLIC\GRANT W C M FOR F:\RVKTEST\G34 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G34_WCM_PGRANT.OUT +\PUBLIC\REVOKE W C FOR F:\RVKTEST\G34 FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\G34_WCM.OUT + +ECHO Starting G35_EMF directory revoke E M from E M F... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G35 > F:\RVKCMP\SETUP\G35_EMF_NREM.OUT +\NPUBLIC\GRANT E M F FOR F:\RVKTEST\G35 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G35_EMF_NGRANT.OUT +\NPUBLIC\REVOKE E M FOR F:\RVKTEST\G35 FROM USER NOPASSUSER > F:\RVKCMP\OUT\G35_EMF.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G35 > F:\RVKCMP\SETUP\G35_EMF_PREM.OUT +\NPUBLIC\GRANT E M F FOR F:\RVKTEST\G35 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G35_EMF_PGRANT.OUT +\PUBLIC\REVOKE E M FOR F:\RVKTEST\G35 FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\G35_EMF.OUT + +ECHO Starting G36_RMF directory revoke M from R M F... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G36 > F:\RVKCMP\SETUP\G36_RMF_NREM.OUT +\NPUBLIC\GRANT R M F FOR F:\RVKTEST\G36 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G36_RMF_NGRANT.OUT +\NPUBLIC\REVOKE M FOR F:\RVKTEST\G36 FROM USER NOPASSUSER > F:\RVKCMP\OUT\G36_RMF.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G36 > F:\RVKCMP\SETUP\G36_RMF_PREM.OUT +\NPUBLIC\GRANT R M F FOR F:\RVKTEST\G36 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G36_RMF_PGRANT.OUT +\PUBLIC\REVOKE M FOR F:\RVKTEST\G36 FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\G36_RMF.OUT + +ECHO Starting G37_REMA directory revoke R E M A... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G37 > F:\RVKCMP\SETUP\G37_REMA_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G37 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G37_REMA_NGRANT.OUT +\NPUBLIC\REVOKE R E M A FOR F:\RVKTEST\G37 FROM USER NOPASSUSER > F:\RVKCMP\OUT\G37_REMA.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G37 > F:\RVKCMP\SETUP\G37_REMA_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G37 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G37_REMA_PGRANT.OUT +\PUBLIC\REVOKE R E M A FOR F:\RVKTEST\G37 FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\G37_REMA.OUT + +ECHO Starting G38_SR directory revoke S R... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G38 > F:\RVKCMP\SETUP\G38_SR_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G38 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G38_SR_NGRANT.OUT +\NPUBLIC\REVOKE S R FOR F:\RVKTEST\G38 FROM USER NOPASSUSER > F:\RVKCMP\OUT\G38_SR.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G38 > F:\RVKCMP\SETUP\G38_SR_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G38 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G38_SR_PGRANT.OUT +\PUBLIC\REVOKE S R FOR F:\RVKTEST\G38 FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\G38_SR.OUT + +ECHO Starting G39_SRF directory revoke S R F... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G39 > F:\RVKCMP\SETUP\G39_SRF_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G39 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G39_SRF_NGRANT.OUT +\NPUBLIC\REVOKE S R F FOR F:\RVKTEST\G39 FROM USER NOPASSUSER > F:\RVKCMP\OUT\G39_SRF.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G39 > F:\RVKCMP\SETUP\G39_SRF_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G39 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G39_SRF_PGRANT.OUT +\PUBLIC\REVOKE S R F FOR F:\RVKTEST\G39 FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\G39_SRF.OUT + +ECHO Starting G40_SWCM directory revoke S W C M... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G40 > F:\RVKCMP\SETUP\G40_SWCM_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G40 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G40_SWCM_NGRANT.OUT +\NPUBLIC\REVOKE S W C M FOR F:\RVKTEST\G40 FROM USER NOPASSUSER > F:\RVKCMP\OUT\G40_SWCM.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\G40 > F:\RVKCMP\SETUP\G40_SWCM_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\G40 TO USER NOPASSUSER > F:\RVKCMP\SETUP\G40_SWCM_PGRANT.OUT +\PUBLIC\REVOKE S W C M FOR F:\RVKTEST\G40 FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\G40_SWCM.OUT + +ECHO Starting F10_R file revoke R... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\F10\T.TXT /FILES > F:\RVKCMP\SETUP\F10_R_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\F10\T.TXT TO USER NOPASSUSER /FILES > F:\RVKCMP\SETUP\F10_R_NGRANT.OUT +\NPUBLIC\REVOKE R FOR F:\RVKTEST\F10\T.TXT FROM USER NOPASSUSER /FILES > F:\RVKCMP\OUT\F10_R.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\F10\T.TXT /FILES > F:\RVKCMP\SETUP\F10_R_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\F10\T.TXT TO USER NOPASSUSER /FILES > F:\RVKCMP\SETUP\F10_R_PGRANT.OUT +\PUBLIC\REVOKE R FOR F:\RVKTEST\F10\T.TXT FROM USER NOPASSUSER /FILES > F:\RVKCMP\PUBOUT\F10_R.OUT + +ECHO Starting F11_RF file revoke R F... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\F11\T.TXT /FILES > F:\RVKCMP\SETUP\F11_RF_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\F11\T.TXT TO USER NOPASSUSER /FILES > F:\RVKCMP\SETUP\F11_RF_NGRANT.OUT +\NPUBLIC\REVOKE R F FOR F:\RVKTEST\F11\T.TXT FROM USER NOPASSUSER /FILES > F:\RVKCMP\OUT\F11_RF.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\F11\T.TXT /FILES > F:\RVKCMP\SETUP\F11_RF_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\F11\T.TXT TO USER NOPASSUSER /FILES > F:\RVKCMP\SETUP\F11_RF_PGRANT.OUT +\PUBLIC\REVOKE R F FOR F:\RVKTEST\F11\T.TXT FROM USER NOPASSUSER /FILES > F:\RVKCMP\PUBOUT\F11_RF.OUT + +ECHO Starting F12_RAL file revoke R A... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\F12\T.TXT /FILES > F:\RVKCMP\SETUP\F12_RAL_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\F12\T.TXT TO USER NOPASSUSER /FILES > F:\RVKCMP\SETUP\F12_RAL_NGRANT.OUT +\NPUBLIC\REVOKE R A FOR F:\RVKTEST\F12\T.TXT FROM USER NOPASSUSER /FILES > F:\RVKCMP\OUT\F12_RAL.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\F12\T.TXT /FILES > F:\RVKCMP\SETUP\F12_RAL_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\F12\T.TXT TO USER NOPASSUSER /FILES > F:\RVKCMP\SETUP\F12_RAL_PGRANT.OUT +\PUBLIC\REVOKE R A FOR F:\RVKTEST\F12\T.TXT FROM USER NOPASSUSER /FILES > F:\RVKCMP\PUBOUT\F12_RAL.OUT + +ECHO Starting F13_ALL file revoke ALL... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\F13\T.TXT /FILES > F:\RVKCMP\SETUP\F13_ALL_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\F13\T.TXT TO USER NOPASSUSER /FILES > F:\RVKCMP\SETUP\F13_ALL_NGRANT.OUT +\NPUBLIC\REVOKE ALL FOR F:\RVKTEST\F13\T.TXT FROM USER NOPASSUSER /FILES > F:\RVKCMP\OUT\F13_ALL.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\F13\T.TXT /FILES > F:\RVKCMP\SETUP\F13_ALL_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\F13\T.TXT TO USER NOPASSUSER /FILES > F:\RVKCMP\SETUP\F13_ALL_PGRANT.OUT +\PUBLIC\REVOKE ALL FOR F:\RVKTEST\F13\T.TXT FROM USER NOPASSUSER /FILES > F:\RVKCMP\PUBOUT\F13_ALL.OUT + +ECHO Starting F14_N file revoke W from R W... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\F14\T.TXT /FILES > F:\RVKCMP\SETUP\F14_N_NREM.OUT +\NPUBLIC\GRANT R W FOR F:\RVKTEST\F14\T.TXT TO USER NOPASSUSER /FILES > F:\RVKCMP\SETUP\F14_N_NGRANT.OUT +\NPUBLIC\REVOKE W FOR F:\RVKTEST\F14\T.TXT FROM USER NOPASSUSER /FILES > F:\RVKCMP\OUT\F14_N.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\F14\T.TXT /FILES > F:\RVKCMP\SETUP\F14_N_PREM.OUT +\NPUBLIC\GRANT R W FOR F:\RVKTEST\F14\T.TXT TO USER NOPASSUSER /FILES > F:\RVKCMP\SETUP\F14_N_PGRANT.OUT +\PUBLIC\REVOKE W FOR F:\RVKTEST\F14\T.TXT FROM USER NOPASSUSER /FILES > F:\RVKCMP\PUBOUT\F14_N.OUT + +ECHO Starting F15_S file revoke S... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\F15\T.TXT /FILES > F:\RVKCMP\SETUP\F15_S_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\F15\T.TXT TO USER NOPASSUSER /FILES > F:\RVKCMP\SETUP\F15_S_NGRANT.OUT +\NPUBLIC\REVOKE S FOR F:\RVKTEST\F15\T.TXT FROM USER NOPASSUSER /FILES > F:\RVKCMP\OUT\F15_S.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\F15\T.TXT /FILES > F:\RVKCMP\SETUP\F15_S_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\F15\T.TXT TO USER NOPASSUSER /FILES > F:\RVKCMP\SETUP\F15_S_PGRANT.OUT +\PUBLIC\REVOKE S FOR F:\RVKTEST\F15\T.TXT FROM USER NOPASSUSER /FILES > F:\RVKCMP\PUBOUT\F15_S.OUT + +ECHO Starting F16_SAL file revoke S A... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\F16\T.TXT /FILES > F:\RVKCMP\SETUP\F16_SAL_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\F16\T.TXT TO USER NOPASSUSER /FILES > F:\RVKCMP\SETUP\F16_SAL_NGRANT.OUT +\NPUBLIC\REVOKE S A FOR F:\RVKTEST\F16\T.TXT FROM USER NOPASSUSER /FILES > F:\RVKCMP\OUT\F16_SAL.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\F16\T.TXT /FILES > F:\RVKCMP\SETUP\F16_SAL_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\F16\T.TXT TO USER NOPASSUSER /FILES > F:\RVKCMP\SETUP\F16_SAL_PGRANT.OUT +\PUBLIC\REVOKE S A FOR F:\RVKTEST\F16\T.TXT FROM USER NOPASSUSER /FILES > F:\RVKCMP\PUBOUT\F16_SAL.OUT + +ECHO Starting S10_R subdirectory revoke R... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\S10 /SUBDIRECTORIES > F:\RVKCMP\SETUP\S10_R_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\S10 TO USER NOPASSUSER /SUBDIRECTORIES > F:\RVKCMP\SETUP\S10_R_NGRANT.OUT +\NPUBLIC\REVOKE R FOR F:\RVKTEST\S10 FROM USER NOPASSUSER /SUBDIRECTORIES > F:\RVKCMP\OUT\S10_R.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\S10 /SUBDIRECTORIES > F:\RVKCMP\SETUP\S10_R_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\S10 TO USER NOPASSUSER /SUBDIRECTORIES > F:\RVKCMP\SETUP\S10_R_PGRANT.OUT +\PUBLIC\REVOKE R FOR F:\RVKTEST\S10 FROM USER NOPASSUSER /SUBDIRECTORIES > F:\RVKCMP\PUBOUT\S10_R.OUT + +ECHO Starting S11_RWC subdirectory revoke R W C... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\S11 /SUBDIRECTORIES > F:\RVKCMP\SETUP\S11_RWC_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\S11 TO USER NOPASSUSER /SUBDIRECTORIES > F:\RVKCMP\SETUP\S11_RWC_NGRANT.OUT +\NPUBLIC\REVOKE R W C FOR F:\RVKTEST\S11 FROM USER NOPASSUSER /SUBDIRECTORIES > F:\RVKCMP\OUT\S11_RWC.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\S11 /SUBDIRECTORIES > F:\RVKCMP\SETUP\S11_RWC_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\S11 TO USER NOPASSUSER /SUBDIRECTORIES > F:\RVKCMP\SETUP\S11_RWC_PGRANT.OUT +\PUBLIC\REVOKE R W C FOR F:\RVKTEST\S11 FROM USER NOPASSUSER /SUBDIRECTORIES > F:\RVKCMP\PUBOUT\S11_RWC.OUT + +ECHO Starting S12_ALL subdirectory revoke ALL... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\S12 /SUBDIRECTORIES > F:\RVKCMP\SETUP\S12_ALL_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\S12 TO USER NOPASSUSER /SUBDIRECTORIES > F:\RVKCMP\SETUP\S12_ALL_NGRANT.OUT +\NPUBLIC\REVOKE ALL FOR F:\RVKTEST\S12 FROM USER NOPASSUSER /SUBDIRECTORIES > F:\RVKCMP\OUT\S12_ALL.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\S12 /SUBDIRECTORIES > F:\RVKCMP\SETUP\S12_ALL_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\S12 TO USER NOPASSUSER /SUBDIRECTORIES > F:\RVKCMP\SETUP\S12_ALL_PGRANT.OUT +\PUBLIC\REVOKE ALL FOR F:\RVKTEST\S12 FROM USER NOPASSUSER /SUBDIRECTORIES > F:\RVKCMP\PUBOUT\S12_ALL.OUT + +ECHO Starting S13_SAL subdirectory revoke S A... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\S13 /SUBDIRECTORIES > F:\RVKCMP\SETUP\S13_SAL_NREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\S13 TO USER NOPASSUSER /SUBDIRECTORIES > F:\RVKCMP\SETUP\S13_SAL_NGRANT.OUT +\NPUBLIC\REVOKE S A FOR F:\RVKTEST\S13 FROM USER NOPASSUSER /SUBDIRECTORIES > F:\RVKCMP\OUT\S13_SAL.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\S13 /SUBDIRECTORIES > F:\RVKCMP\SETUP\S13_SAL_PREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\S13 TO USER NOPASSUSER /SUBDIRECTORIES > F:\RVKCMP\SETUP\S13_SAL_PGRANT.OUT +\PUBLIC\REVOKE S A FOR F:\RVKTEST\S13 FROM USER NOPASSUSER /SUBDIRECTORIES > F:\RVKCMP\PUBOUT\S13_SAL.OUT + +ECHO Starting E90_NOTR no trustee... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\EMPTY > F:\RVKCMP\SETUP\E90_NREM.OUT +\NPUBLIC\REVOKE R FOR F:\RVKTEST\EMPTY FROM USER NOPASSUSER > F:\RVKCMP\OUT\E90_NOTR.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\EMPTY > F:\RVKCMP\SETUP\E90_PREM.OUT +\PUBLIC\REVOKE R FOR F:\RVKTEST\EMPTY FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\E90_NOTR.OUT +ECHO Starting E91_MUSR missing user... +\NPUBLIC\REVOKE R FOR F:\RVKTEST\G10 FROM USER NO_SUCH_USER > F:\RVKCMP\OUT\E91_MUSR.OUT +\PUBLIC\REVOKE R FOR F:\RVKTEST\G10 FROM USER NO_SUCH_USER > F:\RVKCMP\PUBOUT\E91_MUSR.OUT +ECHO Starting E92_MISD missing path... +\NPUBLIC\REVOKE R FOR F:\RVKTEST\MISSING\NOFILE.TXT FROM USER NOPASSUSER > F:\RVKCMP\OUT\E92_MISD.OUT +\PUBLIC\REVOKE R FOR F:\RVKTEST\MISSING\NOFILE.TXT FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\E92_MISD.OUT +ECHO Starting E93_BADD invalid right... +\NPUBLIC\REVOKE BADRIGHT FOR F:\RVKTEST\G10 FROM USER NOPASSUSER > F:\RVKCMP\OUT\E93_BADD.OUT +\PUBLIC\REVOKE BADRIGHT FOR F:\RVKTEST\G10 FROM USER NOPASSUSER > F:\RVKCMP\PUBOUT\E93_BADD.OUT +ECHO Starting E94_BOTH /FILES and /SUBDIRECTORIES... +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\OPTBOTH /FILES > F:\RVKCMP\SETUP\E94_NFREM.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\OPTBOTH /SUBDIRECTORIES > F:\RVKCMP\SETUP\E94_NSREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\OPTBOTH TO USER NOPASSUSER /FILES > F:\RVKCMP\SETUP\E94_NFGRANT.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\OPTBOTH TO USER NOPASSUSER /SUBDIRECTORIES > F:\RVKCMP\SETUP\E94_NSGRANT.OUT +\NPUBLIC\REVOKE R FOR F:\RVKTEST\OPTBOTH FROM USER NOPASSUSER /FILES /SUBDIRECTORIES > F:\RVKCMP\OUT\E94_BOTH.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\OPTBOTH /FILES > F:\RVKCMP\SETUP\E94_PFREM.OUT +\NPUBLIC\REMOVE USER NOPASSUSER FROM F:\RVKTEST\OPTBOTH /SUBDIRECTORIES > F:\RVKCMP\SETUP\E94_PSREM.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\OPTBOTH TO USER NOPASSUSER /FILES > F:\RVKCMP\SETUP\E94_PFGRANT.OUT +\NPUBLIC\GRANT S R W C E M F A FOR F:\RVKTEST\OPTBOTH TO USER NOPASSUSER /SUBDIRECTORIES > F:\RVKCMP\SETUP\E94_PSGRANT.OUT +\PUBLIC\REVOKE R FOR F:\RVKTEST\OPTBOTH FROM USER NOPASSUSER /FILES /SUBDIRECTORIES > F:\RVKCMP\PUBOUT\E94_BOTH.OUT +ECHO Starting E95_GRAM bad grammar... +\NPUBLIC\REVOKE R FOR F:\RVKTEST\G10 USER NOPASSUSER > F:\RVKCMP\OUT\E95_GRAM.OUT +\PUBLIC\REVOKE R FOR F:\RVKTEST\G10 USER NOPASSUSER > F:\RVKCMP\PUBOUT\E95_GRAM.OUT + +ECHO === COMPARE NOVELL OUT AGAINST PUBLIC OUT === > F:\RVKCMP\COMPARE.LOG +ECHO Comparing D01_HELP >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\D01_HELP.OUT F:\RVKCMP\PUBOUT\D01_HELP.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing D02_NOAR >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\D02_NOAR.OUT F:\RVKCMP\PUBOUT\D02_NOAR.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing G10_R >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\G10_R.OUT F:\RVKCMP\PUBOUT\G10_R.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing G11_W >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\G11_W.OUT F:\RVKCMP\PUBOUT\G11_W.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing G12_C >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\G12_C.OUT F:\RVKCMP\PUBOUT\G12_C.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing G13_E >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\G13_E.OUT F:\RVKCMP\PUBOUT\G13_E.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing G14_M >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\G14_M.OUT F:\RVKCMP\PUBOUT\G14_M.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing G15_F >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\G15_F.OUT F:\RVKCMP\PUBOUT\G15_F.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing G16_A >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\G16_A.OUT F:\RVKCMP\PUBOUT\G16_A.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing G17_S >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\G17_S.OUT F:\RVKCMP\PUBOUT\G17_S.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing G20_RF >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\G20_RF.OUT F:\RVKCMP\PUBOUT\G20_RF.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing G21_RW >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\G21_RW.OUT F:\RVKCMP\PUBOUT\G21_RW.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing G22_RWC >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\G22_RWC.OUT F:\RVKCMP\PUBOUT\G22_RWC.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing G23_RWCE >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\G23_RWCE.OUT F:\RVKCMP\PUBOUT\G23_RWCE.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing G24_EMF >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\G24_EMF.OUT F:\RVKCMP\PUBOUT\G24_EMF.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing G25_SAL >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\G25_SAL.OUT F:\RVKCMP\PUBOUT\G25_SAL.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing G26_ALL >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\G26_ALL.OUT F:\RVKCMP\PUBOUT\G26_ALL.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing G30_RE >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\G30_RE.OUT F:\RVKCMP\PUBOUT\G30_RE.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing G31_RWF >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\G31_RWF.OUT F:\RVKCMP\PUBOUT\G31_RWF.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing G32_RCM >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\G32_RCM.OUT F:\RVKCMP\PUBOUT\G32_RCM.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing G33_RFA >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\G33_RFA.OUT F:\RVKCMP\PUBOUT\G33_RFA.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing G34_WCM >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\G34_WCM.OUT F:\RVKCMP\PUBOUT\G34_WCM.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing G35_EMF >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\G35_EMF.OUT F:\RVKCMP\PUBOUT\G35_EMF.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing G36_RMF >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\G36_RMF.OUT F:\RVKCMP\PUBOUT\G36_RMF.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing G37_REMA >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\G37_REMA.OUT F:\RVKCMP\PUBOUT\G37_REMA.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing G38_SR >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\G38_SR.OUT F:\RVKCMP\PUBOUT\G38_SR.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing G39_SRF >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\G39_SRF.OUT F:\RVKCMP\PUBOUT\G39_SRF.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing G40_SWCM >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\G40_SWCM.OUT F:\RVKCMP\PUBOUT\G40_SWCM.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing F10_R >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\F10_R.OUT F:\RVKCMP\PUBOUT\F10_R.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing F11_RF >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\F11_RF.OUT F:\RVKCMP\PUBOUT\F11_RF.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing F12_RAL >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\F12_RAL.OUT F:\RVKCMP\PUBOUT\F12_RAL.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing F13_ALL >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\F13_ALL.OUT F:\RVKCMP\PUBOUT\F13_ALL.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing F14_N >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\F14_N.OUT F:\RVKCMP\PUBOUT\F14_N.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing F15_S >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\F15_S.OUT F:\RVKCMP\PUBOUT\F15_S.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing F16_SAL >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\F16_SAL.OUT F:\RVKCMP\PUBOUT\F16_SAL.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing S10_R >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\S10_R.OUT F:\RVKCMP\PUBOUT\S10_R.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing S11_RWC >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\S11_RWC.OUT F:\RVKCMP\PUBOUT\S11_RWC.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing S12_ALL >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\S12_ALL.OUT F:\RVKCMP\PUBOUT\S12_ALL.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing S13_SAL >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\S13_SAL.OUT F:\RVKCMP\PUBOUT\S13_SAL.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing E90_NOTR >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\E90_NOTR.OUT F:\RVKCMP\PUBOUT\E90_NOTR.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing E91_MUSR >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\E91_MUSR.OUT F:\RVKCMP\PUBOUT\E91_MUSR.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing E92_MISD >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\E92_MISD.OUT F:\RVKCMP\PUBOUT\E92_MISD.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing E93_BADD >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\E93_BADD.OUT F:\RVKCMP\PUBOUT\E93_BADD.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing E94_BOTH >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\E94_BOTH.OUT F:\RVKCMP\PUBOUT\E94_BOTH.OUT >> F:\RVKCMP\COMPARE.LOG +ECHO Comparing E95_GRAM >> F:\RVKCMP\COMPARE.LOG +FC F:\RVKCMP\OUT\E95_GRAM.OUT F:\RVKCMP\PUBOUT\E95_GRAM.OUT >> F:\RVKCMP\COMPARE.LOG + +REM --- Queue user-context RIGHTS readback helper. --- +IF "%LGNTPWD%"=="" GOTO NEEDPWD +IF EXIST \PUBLIC\DLYSTRT.EXE COPY \PUBLIC\DLYSTRT.EXE C:\RVKTMP > NUL +IF EXIST C:\RVKTMP\DLYSTRT.EXE GOTO HAVEDLY +ECHO ERROR: DLYSTRT.EXE not found. >> F:\RVKCMP\RUN.LOG +ECHO ERROR: DLYSTRT.EXE not found. +GOTO END + +:HAVEDLY +COPY F:\RVKSTA.BAT C:\RVKTMP > NUL +COPY F:\RVKC.BAT C:\RVKTMP > NUL +C: +CD \RVKTMP +DLYSTRT /T:2 RVKC.BAT +ECHO RVKC queued via DLYSTRT. >> F:\RVKCMP\RUN.LOG +ECHO RVKC wurde via DLYSTRT gestartet. +ECHO Nach automatischem Re-Login wird RVKSTA PART2 gestartet. +GOTO END + +:PART2 +F: CD \ +IF NOT EXIST RVKCMP\UNOV MD RVKCMP\UNOV +IF NOT EXIST RVKCMP\UPUB MD RVKCMP\UPUB +IF EXIST C:\RVKTMP\UNOV\*.* COPY C:\RVKTMP\UNOV\*.* F:\RVKCMP\UNOV > NUL +IF EXIST C:\RVKTMP\UPUB\*.* COPY C:\RVKTMP\UPUB\*.* F:\RVKCMP\UPUB > NUL +IF EXIST C:\RVKTMP\HELPER.TXT COPY C:\RVKTMP\HELPER.TXT F:\RVKCMP\HELPER.TXT > NUL +IF EXIST C:\RVKTMP\ULOG1.OUT COPY C:\RVKTMP\ULOG1.OUT F:\RVKCMP\ULOG1.OUT > NUL +IF EXIST C:\RVKTMP\ULOGIN.OUT COPY C:\RVKTMP\ULOGIN.OUT F:\RVKCMP\ULOGIN.OUT > NUL +IF EXIST C:\RVKTMP\ULOG2.OUT COPY C:\RVKTMP\ULOG2.OUT F:\RVKCMP\ULOG2.OUT > NUL +IF EXIST C:\RVKTMP\ULGSUP.OUT COPY C:\RVKTMP\ULGSUP.OUT F:\RVKCMP\ULGSUP.OUT > NUL -ECHO === D90 no trustee on directory === >> F:\RVKCMP\RUN.LOG -\NPUBLIC\REVOKE R FOR F:\RVKTEST\EMPTY FROM USER MARIO > F:\RVKCMP\OUT\D90_NO_TRUSTEE.OUT - -ECHO === D91 missing user === >> F:\RVKCMP\RUN.LOG -\NPUBLIC\REVOKE R FOR F:\RVKTEST\ONE FROM USER NO_SUCH_USER > F:\RVKCMP\OUT\D91_MISSING_USER.OUT - -ECHO === D92 missing path === >> F:\RVKCMP\RUN.LOG -\NPUBLIC\REVOKE R FOR F:\RVKTEST\MISSING\NOFILE.TXT FROM USER MARIO > F:\RVKCMP\OUT\D92_MISSING_PATH.OUT - -ECHO === D93 both /FILES and /SUBDIRECTORIES === >> F:\RVKCMP\RUN.LOG -\NPUBLIC\REVOKE R FOR F:\RVKTEST\OPTBOTH FROM USER MARIO /FILES /SUBDIRECTORIES > F:\RVKCMP\OUT\D93_FILES_AND_SUBDIRS.OUT - -ECHO === D94 bad grammar / missing FROM === >> F:\RVKCMP\RUN.LOG -\NPUBLIC\REVOKE R FOR F:\RVKTEST\ONE USER MARIO > F:\RVKCMP\OUT\D94_BAD_GRAMMAR.OUT +ECHO === COMPARE NOPASSUSER NOVELL RIGHTS AGAINST PUBLIC RIGHTS === > F:\RVKCMP\UCOMP.LOG +ECHO Comparing G10_R >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\G10_R.OUT F:\RVKCMP\UPUB\G10_R.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing G11_W >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\G11_W.OUT F:\RVKCMP\UPUB\G11_W.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing G12_C >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\G12_C.OUT F:\RVKCMP\UPUB\G12_C.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing G13_E >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\G13_E.OUT F:\RVKCMP\UPUB\G13_E.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing G14_M >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\G14_M.OUT F:\RVKCMP\UPUB\G14_M.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing G15_F >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\G15_F.OUT F:\RVKCMP\UPUB\G15_F.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing G16_A >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\G16_A.OUT F:\RVKCMP\UPUB\G16_A.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing G17_S >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\G17_S.OUT F:\RVKCMP\UPUB\G17_S.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing G20_RF >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\G20_RF.OUT F:\RVKCMP\UPUB\G20_RF.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing G21_RW >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\G21_RW.OUT F:\RVKCMP\UPUB\G21_RW.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing G22_RWC >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\G22_RWC.OUT F:\RVKCMP\UPUB\G22_RWC.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing G23_RWCE >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\G23_RWCE.OUT F:\RVKCMP\UPUB\G23_RWCE.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing G24_EMF >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\G24_EMF.OUT F:\RVKCMP\UPUB\G24_EMF.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing G25_SAL >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\G25_SAL.OUT F:\RVKCMP\UPUB\G25_SAL.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing G26_ALL >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\G26_ALL.OUT F:\RVKCMP\UPUB\G26_ALL.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing G30_RE >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\G30_RE.OUT F:\RVKCMP\UPUB\G30_RE.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing G31_RWF >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\G31_RWF.OUT F:\RVKCMP\UPUB\G31_RWF.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing G32_RCM >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\G32_RCM.OUT F:\RVKCMP\UPUB\G32_RCM.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing G33_RFA >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\G33_RFA.OUT F:\RVKCMP\UPUB\G33_RFA.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing G34_WCM >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\G34_WCM.OUT F:\RVKCMP\UPUB\G34_WCM.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing G35_EMF >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\G35_EMF.OUT F:\RVKCMP\UPUB\G35_EMF.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing G36_RMF >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\G36_RMF.OUT F:\RVKCMP\UPUB\G36_RMF.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing G37_REMA >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\G37_REMA.OUT F:\RVKCMP\UPUB\G37_REMA.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing G38_SR >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\G38_SR.OUT F:\RVKCMP\UPUB\G38_SR.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing G39_SRF >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\G39_SRF.OUT F:\RVKCMP\UPUB\G39_SRF.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing G40_SWCM >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\G40_SWCM.OUT F:\RVKCMP\UPUB\G40_SWCM.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing F10_R >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\F10_R.OUT F:\RVKCMP\UPUB\F10_R.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing F11_RF >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\F11_RF.OUT F:\RVKCMP\UPUB\F11_RF.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing F12_RAL >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\F12_RAL.OUT F:\RVKCMP\UPUB\F12_RAL.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing F13_ALL >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\F13_ALL.OUT F:\RVKCMP\UPUB\F13_ALL.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing F14_N >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\F14_N.OUT F:\RVKCMP\UPUB\F14_N.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing F15_S >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\F15_S.OUT F:\RVKCMP\UPUB\F15_S.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing F16_SAL >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\F16_SAL.OUT F:\RVKCMP\UPUB\F16_SAL.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing S10_R >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\S10_R.OUT F:\RVKCMP\UPUB\S10_R.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing S11_RWC >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\S11_RWC.OUT F:\RVKCMP\UPUB\S11_RWC.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing S12_ALL >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\S12_ALL.OUT F:\RVKCMP\UPUB\S12_ALL.OUT >> F:\RVKCMP\UCOMP.LOG +ECHO Comparing S13_SAL >> F:\RVKCMP\UCOMP.LOG +FC F:\RVKCMP\UNOV\S13_SAL.OUT F:\RVKCMP\UPUB\S13_SAL.OUT >> F:\RVKCMP\UCOMP.LOG ECHO === SUMMARY === > F:\RVKCMP\SUMMARY.TXT -ECHO RVKSTA REVOKE baseline finished. >> F:\RVKCMP\SUMMARY.TXT -ECHO. >> F:\RVKCMP\SUMMARY.TXT -ECHO Expected: >> F:\RVKCMP\SUMMARY.TXT -ECHO - D10/D11 capture normal directory revoke and trustee removal. >> F:\RVKCMP\SUMMARY.TXT -ECHO - D20 captures /SUBDIRECTORIES behavior using direct trustees on child directories. >> F:\RVKCMP\SUMMARY.TXT -ECHO - D21/D22 capture /FILES behavior for explicit files and directory file sets. >> F:\RVKCMP\SUMMARY.TXT -ECHO - D30 captures relative path behavior with absolute \NPUBLIC\REVOKE invocation. >> F:\RVKCMP\SUMMARY.TXT -ECHO - D90-D94 capture no-trustee, missing-user, missing-path/Novell no-trustee behavior, option combination, and grammar errors. >> F:\RVKCMP\SUMMARY.TXT +ECHO RVKSTA REVOKE comparison finished. >> F:\RVKCMP\SUMMARY.TXT ECHO. >> F:\RVKCMP\SUMMARY.TXT +ECHO Direct mode compares NPUBLIC REVOKE against PUBLIC REVOKE. >> F:\RVKCMP\SUMMARY.TXT +ECHO Matrix covers single rights, mixed rights, ALL removal, file mode, and subdirectory mode. >> F:\RVKCMP\SUMMARY.TXT +ECHO User-context mode logs in as NOPASSUSER and compares RIGHTS output after PUBLIC REVOKE. >> F:\RVKCMP\SUMMARY.TXT ECHO Optional: RVKZIP ausfuehren. >> F:\RVKCMP\SUMMARY.TXT -ECHO RVKSTA fertig. +ECHO RVKSTA PART2 fertig. ECHO Ergebnisse liegen in F:\RVKCMP ECHO Optional: RVKZIP ausfuehren. +GOTO END + +:NEEDPWD +ECHO ERROR: LGNTPWD ist nicht gesetzt. +ECHO Fuer den automatischen REVOKE/NOPASSUSER-Test zuerst setzen, z.B.: +ECHO SET LGNTPWD=dein-supervisor-passwort +ECHO Danach starten: +ECHO F:\RVKSTA +ECHO Es wurde kein DLYSTRT installiert und kein User-Kontext-Test gestartet. + +:END diff --git a/test/revoke/RVKZIP.BAT b/test/revoke/RVKZIP.BAT index 457c0c4..eca9c73 100644 --- a/test/revoke/RVKZIP.BAT +++ b/test/revoke/RVKZIP.BAT @@ -10,13 +10,13 @@ IF EXIST RVKSTA.ZIP DEL RVKSTA.ZIP IF EXIST ZIP.LOG DEL ZIP.LOG ECHO Creating RVKSTA.ZIP > ZIP.LOG -ZIP -r RVKSTA.ZIP RUN.LOG SUMMARY.TXT SETUP OUT >> ZIP.LOG - +ZIP -r RVKSTA.ZIP RUN.LOG SUMMARY.TXT COMPARE.LOG UCOMP.LOG HELPER.TXT ULOG1.OUT ULOGIN.OUT ULOG2.OUT ULGSUP.OUT OUT PUBOUT SETUP UNOV UPUB USETUP >> ZIP.LOG REM Cleanup generated test directories after ZIP. REM Keep the CMP/result directory because it contains the ZIP and ZIP.LOG. ECHO Cleaning generated test directories... >> ZIP.LOG IF EXIST \RVKTEST\NUL DELTREE /Y \RVKTEST >> ZIP.LOG +IF EXIST C:\RVKTMP\NUL DELTREE /Y C:\RVKTMP >> ZIP.LOG CD \ ECHO. ECHO ZIP step finished. diff --git a/test/rights/README.md b/test/rights/README.md index cc66829..8ffa37d 100644 --- a/test/rights/README.md +++ b/test/rights/README.md @@ -1,45 +1,47 @@ -# RGHTSTA - RIGHTS comparison test - -`RGHTSTA.BAT` compares Novell `RIGHTS` with the current implementation. - -Result directories: - -```text -F:\RGHTCMP\OUT Novell baseline using \NPUBLIC\RIGHTS -F:\RGHTCMP\PUBOUT current implementation using \PUBLIC\RIGHTS -F:\RGHTCMP\COMPARE.LOG -``` - -The test keeps the original Novell-baseline behavior and adds the public-tool -comparison layer. - -Coverage: - -- default/current directory from `F:\` -- explicit directory and subdirectory paths -- explicit file and nested file paths -- default/current directory from inside the test directory -- relative file and relative directory paths -- missing directory/file paths -- too-many-arguments and `/?` usage/help cases - -operation. Its redirected output must be identical to the normal Novell output. -That means: - -```text -OUT == PUBOUT -``` - -Run: - -```bat -F: -CD \ -RGHTSTA -RGHTZIP -``` - -The generated test tree is `F:\RGHTEST`. `RGHTZIP.BAT` packages the result and -then removes `F:\RGHTEST` again so the SYS root stays clean. - -Note: `RIGHTS` currently has no short-output comparison in this baseline test. That switch exists for NDIR-style output control and should only be added to RIGHTS later if the tool implements it explicitly. +# RGHTSTA - RIGHTS comparison test + +`RGHTSTA.BAT` compares Novell `RIGHTS` with the current implementation. + +## Run + +Run while logged in and with `F:` mapped to `SYS:`: + +```bat +F: +CD \ +RGHTSTA +RGHTZIP +``` + +## Result layout + +```text +F:\RGHTCMP\OUT Novell baseline using \NPUBLIC\RIGHTS +F:\RGHTCMP\PUBOUT current implementation using \PUBLIC\RIGHTS +F:\RGHTCMP\COMPARE.LOG +F:\RGHTCMP\RUN.LOG +F:\RGHTCMP\SUMMARY.TXT +``` + +`RGHTZIP.BAT` packages the result tree and removes the generated `F:\RGHTEST` +test tree afterwards. + +## Coverage + +- default/current directory from `F:\` +- explicit directory and subdirectory paths +- explicit file and nested file paths +- default/current directory from inside the test directory +- relative file and relative directory paths +- missing directory/file paths +- too-many-arguments and `/?` usage/help cases + +Expected comparison: + +```text +OUT == PUBOUT +``` + +`RIGHTS` has no `/SHORT` comparison in this test. That switch belongs to the +NDIR diagnostic output and should only be added to RIGHTS if the tool explicitly +implements it later. diff --git a/test/slist/README.md b/test/slist/README.md index 77b8920..1eade80 100644 --- a/test/slist/README.md +++ b/test/slist/README.md @@ -1,21 +1,106 @@ -# SLSTSTA - SLIST baseline test +# SLSTSTA - SLIST logged-in/logged-out compare test -Novell-only baseline for `SLIST` behavior. +`SLSTSTA.BAT` compares Novell `SLIST` with the current public implementation in +both states in which SLIST is expected to work: -Runs `NPUBLIC\SLIST` with: +1. **Logged in**: `\NPUBLIC\SLIST` vs `\PUBLIC\SLIST`. +2. **Logged out**: `\NLOGIN\SLIST.EXE` vs `\LOGIN\SLIST.EXE`, copied to a local + `C:\SLSTTMP` helper directory before logout. -- no argument -- `MARS` as expected existing server -- `NWBYGONE01` as expected missing-server/negative test -- `/CONTINUE` variants -- `/?` usage output +SLIST is also installed in `SYS:LOGIN`, so the logged-out phase is important. +After `LOGOUT`, the network drive `F:` is gone; therefore the helper runs from +`C:\SLSTTMP` and only returns to `F:` after logging `SUPERVISOR` back in. -Results are written to `F:\SLSTCMP`. Optional packaging is done with `SLSTZIP.BAT`. +## Run -`D99_HELP.OUT` is intentionally simulated with: +Run while logged in as `SUPERVISOR` and with `F:` mapped to `SYS:`. + +For the full logged-in and logged-out comparison: + +```bat +SET LGNTPWD=your-supervisor-password +F: +CD \ +SLSTSTA +``` + +If `LGNTPWD` is not set, only the logged-in `NPUBLIC` vs `PUBLIC` comparison is +run. The logged-out phase is skipped. + +Package manually after the run: + +```bat +SLSTZIP +``` + +Result ZIP: + +```text +F:\SLSTCMP\SLSTSTA.ZIP +``` + +## Result layout + +```text +F:\SLSTCMP\OUT logged-in Novell baseline from \NPUBLIC\SLIST +F:\SLSTCMP\PUBOUT logged-in PUBLIC output from \PUBLIC\SLIST +F:\SLSTCMP\COMPARE.LOG + +F:\SLSTCMP\LOUT logged-out Novell baseline from local NLOGIN copy +F:\SLSTCMP\LPUBOUT logged-out LOGIN output from local LOGIN copy +F:\SLSTCMP\LCOMP.LOG + +F:\SLSTCMP\RUN.LOG +F:\SLSTCMP\HELPER.TXT +F:\SLSTCMP\SUMMARY.TXT +``` + +## Logged-out helper flow + +`SLSTSTA.BAT` copies the files required after logout to `C:\SLSTTMP`: + +```text +\NLOGIN\SLIST.EXE -> C:\SLSTTMP\NSLIST.EXE +\LOGIN\SLIST.EXE -> C:\SLSTTMP\SLIST.EXE +\NPUBLIC\LOGOUT.EXE +\LOGIN\LOGIN.EXE +\PUBLIC\DLYSTRT.EXE +F:\SLSTC.BAT +``` + +The public SLIST copy is intentionally named `SLIST.EXE`, not `PSLIST.EXE`, +because the public DOS tools are a multi-call executable and dispatch by their +own program name. + +`SLSTC.BAT` then: + +1. runs `LOGOUT`, +2. runs both SLIST copies while no user is logged in, +3. logs back in as `SUPERVISOR` using `LOGIN /PWD:%LGNTPWD%`, +4. queues `F:\SLSTSTA.BAT PART2` through the local `DLYSTRT.EXE`. + +## Coverage + +Each phase captures the same matrix: + +```text +SLIST +SLIST MARS +SLIST NWBYGONE01 +SLIST /CONTINUE +SLIST MARS /CONTINUE +SLIST NWBYGONE01 /CONTINUE +SLIST /? +``` + +`MARS` is expected to exist. `NWBYGONE01` is expected to be missing. + +`D99_HELP.OUT` for the Novell side is intentionally simulated with: ```text Usage: SLIST [Server] [/Continue] ``` -Reason: the Novell `SLIST /?` help text was observed on the console, but it does not reliably land in the redirected output file. Later, our implementation should run `SLIST /? > D99_HELP.OUT`, and this simulated Novell baseline gives us a stable file for comparison. +The Novell `SLIST /?` text is visible on the console but does not always land in +the redirected output file. The public implementation is redirected normally and +must match this stable baseline. diff --git a/test/slist/SLSTC.BAT b/test/slist/SLSTC.BAT new file mode 100644 index 0000000..37ad858 --- /dev/null +++ b/test/slist/SLSTC.BAT @@ -0,0 +1,73 @@ +@ECHO OFF +REM SLSTC.BAT +REM Local helper for SLSTSTA.BAT logged-out SLIST comparison. +REM Runs from C:\SLSTTMP. It logs out, runs SLIST without any logged-in +REM user, logs SUPERVISOR back in, then queues F:\SLSTSTA.BAT PART2. + +C: +CD \SLSTTMP + +ECHO SLSTC helper started. > C:\SLSTTMP\HELPER.TXT +ECHO This helper logs out and runs SLIST while no user is logged in. >> C:\SLSTTMP\HELPER.TXT +ECHO. >> C:\SLSTTMP\HELPER.TXT + +IF NOT EXIST LOUT\NUL MD LOUT +IF NOT EXIST LPUBOUT\NUL MD LPUBOUT + +ECHO === L00 LOGOUT from initial session === >> C:\SLSTTMP\HELPER.TXT +C:\SLSTTMP\LOGOUT.EXE > C:\SLSTTMP\L00_LOG.OUT + +ECHO === LOGGED-OUT NOVELL BASELINE: NLOGIN\SLIST === >> C:\SLSTTMP\HELPER.TXT +C:\SLSTTMP\NSLIST.EXE > C:\SLSTTMP\LOUT\D01_LIST.OUT +C:\SLSTTMP\NSLIST.EXE MARS > C:\SLSTTMP\LOUT\D02_MARS_OK.OUT +C:\SLSTTMP\NSLIST.EXE NWBYGONE01 > C:\SLSTTMP\LOUT\D03_NWBYGONE01_MISSING.OUT +C:\SLSTTMP\NSLIST.EXE /CONTINUE > C:\SLSTTMP\LOUT\D04_CONT.OUT +C:\SLSTTMP\NSLIST.EXE MARS /CONTINUE > C:\SLSTTMP\LOUT\D05_MARS_CONT_OK.OUT +C:\SLSTTMP\NSLIST.EXE NWBYGONE01 /CONTINUE > C:\SLSTTMP\LOUT\D06_NWBYGONE01_CONT_MISSING.OUT +ECHO Usage: SLIST [Server] [/Continue] > C:\SLSTTMP\LOUT\D99_HELP.OUT + +ECHO === LOGGED-OUT PUBLIC IMPLEMENTATION: LOGIN\SLIST === >> C:\SLSTTMP\HELPER.TXT +C:\SLSTTMP\SLIST.EXE > C:\SLSTTMP\LPUBOUT\D01_LIST.OUT +C:\SLSTTMP\SLIST.EXE MARS > C:\SLSTTMP\LPUBOUT\D02_MARS_OK.OUT +C:\SLSTTMP\SLIST.EXE NWBYGONE01 > C:\SLSTTMP\LPUBOUT\D03_NWBYGONE01_MISSING.OUT +C:\SLSTTMP\SLIST.EXE /CONTINUE > C:\SLSTTMP\LPUBOUT\D04_CONT.OUT +C:\SLSTTMP\SLIST.EXE MARS /CONTINUE > C:\SLSTTMP\LPUBOUT\D05_MARS_CONT_OK.OUT +C:\SLSTTMP\SLIST.EXE NWBYGONE01 /CONTINUE > C:\SLSTTMP\LPUBOUT\D06_NWBYGONE01_CONT_MISSING.OUT +C:\SLSTTMP\SLIST.EXE /? > C:\SLSTTMP\LPUBOUT\D99_HELP.OUT + +IF "%LGNTPWD%"=="" GOTO MANUAL + +ECHO === L99 LOGIN SUPERVISOR using local LOGIN === >> C:\SLSTTMP\HELPER.TXT +C:\SLSTTMP\LOGIN.EXE SUPERVISOR /PWD:%LGNTPWD% > C:\SLSTTMP\L99_LGSUP.OUT + +F: +CD \ +IF EXIST F:\SLSTSTA.BAT GOTO QUEUEP2 +ECHO F: not restored or F:\SLSTSTA.BAT missing after supervisor login. >> C:\SLSTTMP\HELPER.TXT +ECHO. +ECHO F: wurde nicht wiederhergestellt oder F:\SLSTSTA.BAT fehlt. +ECHO Bitte manuell pruefen und dann ausfuehren: +ECHO F: +ECHO CD \ +ECHO SLSTSTA PART2 +GOTO END + +:QUEUEP2 +ECHO F: is available. Queueing delayed SLSTSTA PART2. >> C:\SLSTTMP\HELPER.TXT +C: +CD \SLSTTMP +C:\SLSTTMP\DLYSTRT.EXE /T:2 F:\SLSTSTA.BAT PART2 > C:\SLSTTMP\L98_P2.OUT +ECHO SLSTC queued F:\SLSTSTA.BAT PART2. >> C:\SLSTTMP\HELPER.TXT +ECHO. +ECHO SLSTC fertig. PART2 wird per DLYSTRT gestartet. +GOTO END + +:MANUAL +ECHO LGNTPWD is not set; automatic SUPERVISOR login skipped. >> C:\SLSTTMP\HELPER.TXT +ECHO. +ECHO SLSTC fertig. Jetzt manuell wieder als SUPERVISOR einloggen. +ECHO Danach ausfuehren: +ECHO F:\SLSTSTA PART2 +ECHO. + +:END diff --git a/test/slist/SLSTSTA.BAT b/test/slist/SLSTSTA.BAT index 14678d6..7fd0918 100644 --- a/test/slist/SLSTSTA.BAT +++ b/test/slist/SLSTSTA.BAT @@ -1,66 +1,233 @@ -@ECHO OFF -REM SLSTSTA.BAT -REM Automated SLIST test for MARS NWE. -REM -REM Uses NPUBLIC\SLIST as Novell baseline for currently implemented tool behavior. -REM Servers: -REM MARS expected to exist -REM NWBYGONE01 expected negative/missing-server test -REM -REM Result tree: -REM F:\SLSTCMP - -F: -CD \ - -REM --- Clean generated test/result directories (contents only). --- -IF EXIST SLSTCMP\NUL DELTREE /Y SLSTCMP\*.* - -IF NOT EXIST SLSTCMP\NUL MD SLSTCMP -IF NOT EXIST SLSTCMP\OUT\NUL MD SLSTCMP\OUT - -ECHO SLSTSTA SLIST test > F:\SLSTCMP\RUN.LOG -ECHO Server MARS should exist. >> F:\SLSTCMP\RUN.LOG -ECHO Server NWBYGONE01 is expected to be missing. >> F:\SLSTCMP\RUN.LOG -ECHO. >> F:\SLSTCMP\RUN.LOG - -ECHO === D01 default SLIST === >> F:\SLSTCMP\RUN.LOG -NPUBLIC\SLIST > F:\SLSTCMP\OUT\D01_LIST.OUT - -ECHO === D02 existing server MARS === >> F:\SLSTCMP\RUN.LOG -NPUBLIC\SLIST MARS > F:\SLSTCMP\OUT\D02_MARS_OK.OUT - -ECHO === D03 missing server NWBYGONE01 === >> F:\SLSTCMP\RUN.LOG -NPUBLIC\SLIST NWBYGONE01 > F:\SLSTCMP\OUT\D03_NWBYGONE01_MISSING.OUT - -ECHO === D04 default SLIST /CONTINUE === >> F:\SLSTCMP\RUN.LOG -NPUBLIC\SLIST /CONTINUE > F:\SLSTCMP\OUT\D04_CONT.OUT - -ECHO === D05 MARS /CONTINUE === >> F:\SLSTCMP\RUN.LOG -NPUBLIC\SLIST MARS /CONTINUE > F:\SLSTCMP\OUT\D05_MARS_CONT_OK.OUT - -ECHO === D06 NWBYGONE01 /CONTINUE === >> F:\SLSTCMP\RUN.LOG -NPUBLIC\SLIST NWBYGONE01 /CONTINUE > F:\SLSTCMP\OUT\D06_NWBYGONE01_CONT_MISSING.OUT - -ECHO === D99 usage/help simulated from Novell console output === >> F:\SLSTCMP\RUN.LOG -REM Novell SLIST /? prints the usage on the console and does not reliably -REM write it through stdout redirection. Keep the Novell baseline file -REM filled with the observed console text, so our implementation can later -REM be compared against its redirected SLIST /? output. -ECHO Usage: SLIST [Server] [/Continue] > F:\SLSTCMP\OUT\D99_HELP.OUT - -ECHO === SUMMARY === > F:\SLSTCMP\SUMMARY.TXT -ECHO SLSTSTA SLIST baseline finished. >> F:\SLSTCMP\SUMMARY.TXT -ECHO. >> F:\SLSTCMP\SUMMARY.TXT -ECHO Expected: >> F:\SLSTCMP\SUMMARY.TXT -ECHO - D01 lists visible servers/services. >> F:\SLSTCMP\SUMMARY.TXT -ECHO - D02 finds or accepts MARS. >> F:\SLSTCMP\SUMMARY.TXT -ECHO - D03 is the negative test for missing NWBYGONE01. >> F:\SLSTCMP\SUMMARY.TXT -ECHO - D04/D05/D06 record /CONTINUE behavior. >> F:\SLSTCMP\SUMMARY.TXT -ECHO - D99 records usage syntax. >> F:\SLSTCMP\SUMMARY.TXT -ECHO. >> F:\SLSTCMP\SUMMARY.TXT -ECHO Optional: SLSTZIP ausfuehren. >> F:\SLSTCMP\SUMMARY.TXT - -ECHO SLSTSTA fertig. -ECHO Ergebnisse liegen in F:\SLSTCMP -ECHO Optional: SLSTZIP ausfuehren. +@ECHO OFF +REM SLSTSTA.BAT +REM Automated SLIST test for MARS NWE. +REM +REM Runs two comparisons: +REM 1. Logged-in: NPUBLIC\SLIST vs PUBLIC\SLIST. +REM 2. Logged-out: NLOGIN\SLIST vs LOGIN\SLIST from local C:\SLSTTMP. +REM +REM The logged-out phase uses DLYSTRT, because LOGOUT removes F: and normal +REM network mappings. SLSTC.BAT and DLYSTRT.EXE are copied to C:\SLSTTMP, +REM SLSTC logs out, runs the local SLIST copies, logs back in as SUPERVISOR, +REM then queues F:\SLSTSTA.BAT PART2 with local DLYSTRT. +REM +REM Required for the automatic logged-out phase: +REM SET LGNTPWD= +REM +REM Result tree: +REM F:\SLSTCMP + +IF "%1"=="" GOTO PART1 +IF "%1"=="PART2" GOTO PART2 +IF "%1"=="part2" GOTO PART2 +IF "%1"=="Part2" GOTO PART2 +GOTO USAGE + +:PART1 +F: +CD \ + +REM --- Clean generated test/result directories. --- +IF EXIST SLSTCMP\NUL DELTREE /Y SLSTCMP\*.* +IF NOT EXIST SLSTCMP\NUL MD SLSTCMP +IF NOT EXIST SLSTCMP\OUT\NUL MD SLSTCMP\OUT +IF NOT EXIST SLSTCMP\PUBOUT\NUL MD SLSTCMP\PUBOUT +IF NOT EXIST SLSTCMP\LOUT\NUL MD SLSTCMP\LOUT +IF NOT EXIST SLSTCMP\LPUBOUT\NUL MD SLSTCMP\LPUBOUT + +ECHO SLSTSTA SLIST test > F:\SLSTCMP\RUN.LOG +ECHO Server MARS should exist. >> F:\SLSTCMP\RUN.LOG +ECHO Server NWBYGONE01 is expected to be missing. >> F:\SLSTCMP\RUN.LOG +ECHO. >> F:\SLSTCMP\RUN.LOG +ECHO Logged-in baseline: F:\SLSTCMP\OUT >> F:\SLSTCMP\RUN.LOG +ECHO Logged-in public: F:\SLSTCMP\PUBOUT >> F:\SLSTCMP\RUN.LOG +ECHO Logged-out baseline/public, if LGNTPWD is set: C:\SLSTTMP then LOUT/LPUBOUT >> F:\SLSTCMP\RUN.LOG +ECHO. >> F:\SLSTCMP\RUN.LOG + +ECHO === LOGGED-IN NOVELL BASELINE: NPUBLIC\SLIST === >> F:\SLSTCMP\RUN.LOG +\NPUBLIC\SLIST > F:\SLSTCMP\OUT\D01_LIST.OUT +\NPUBLIC\SLIST MARS > F:\SLSTCMP\OUT\D02_MARS_OK.OUT +\NPUBLIC\SLIST NWBYGONE01 > F:\SLSTCMP\OUT\D03_NWBYGONE01_MISSING.OUT +\NPUBLIC\SLIST /CONTINUE > F:\SLSTCMP\OUT\D04_CONT.OUT +\NPUBLIC\SLIST MARS /CONTINUE > F:\SLSTCMP\OUT\D05_MARS_CONT_OK.OUT +\NPUBLIC\SLIST NWBYGONE01 /CONTINUE > F:\SLSTCMP\OUT\D06_NWBYGONE01_CONT_MISSING.OUT +REM Novell SLIST /? prints the usage on the console and does not reliably +REM write it through stdout redirection. Keep a stable baseline file. +ECHO Usage: SLIST [Server] [/Continue] > F:\SLSTCMP\OUT\D99_HELP.OUT + +ECHO === LOGGED-IN PUBLIC IMPLEMENTATION: PUBLIC\SLIST === >> F:\SLSTCMP\RUN.LOG +\PUBLIC\SLIST > F:\SLSTCMP\PUBOUT\D01_LIST.OUT +\PUBLIC\SLIST MARS > F:\SLSTCMP\PUBOUT\D02_MARS_OK.OUT +\PUBLIC\SLIST NWBYGONE01 > F:\SLSTCMP\PUBOUT\D03_NWBYGONE01_MISSING.OUT +\PUBLIC\SLIST /CONTINUE > F:\SLSTCMP\PUBOUT\D04_CONT.OUT +\PUBLIC\SLIST MARS /CONTINUE > F:\SLSTCMP\PUBOUT\D05_MARS_CONT_OK.OUT +\PUBLIC\SLIST NWBYGONE01 /CONTINUE > F:\SLSTCMP\PUBOUT\D06_NWBYGONE01_CONT_MISSING.OUT +\PUBLIC\SLIST /? > F:\SLSTCMP\PUBOUT\D99_HELP.OUT + +ECHO === COMPARE LOGGED-IN OUT vs PUBOUT === > F:\SLSTCMP\COMPARE.LOG +ECHO. >> F:\SLSTCMP\COMPARE.LOG +ECHO === D01_LIST.OUT === >> F:\SLSTCMP\COMPARE.LOG +FC F:\SLSTCMP\OUT\D01_LIST.OUT F:\SLSTCMP\PUBOUT\D01_LIST.OUT >> F:\SLSTCMP\COMPARE.LOG +IF ERRORLEVEL 1 ECHO DIFF: D01_LIST.OUT >> F:\SLSTCMP\COMPARE.LOG +IF NOT ERRORLEVEL 1 ECHO OK: D01_LIST.OUT >> F:\SLSTCMP\COMPARE.LOG + +ECHO. >> F:\SLSTCMP\COMPARE.LOG +ECHO === D02_MARS_OK.OUT === >> F:\SLSTCMP\COMPARE.LOG +FC F:\SLSTCMP\OUT\D02_MARS_OK.OUT F:\SLSTCMP\PUBOUT\D02_MARS_OK.OUT >> F:\SLSTCMP\COMPARE.LOG +IF ERRORLEVEL 1 ECHO DIFF: D02_MARS_OK.OUT >> F:\SLSTCMP\COMPARE.LOG +IF NOT ERRORLEVEL 1 ECHO OK: D02_MARS_OK.OUT >> F:\SLSTCMP\COMPARE.LOG + +ECHO. >> F:\SLSTCMP\COMPARE.LOG +ECHO === D03_NWBYGONE01_MISSING.OUT === >> F:\SLSTCMP\COMPARE.LOG +FC F:\SLSTCMP\OUT\D03_NWBYGONE01_MISSING.OUT F:\SLSTCMP\PUBOUT\D03_NWBYGONE01_MISSING.OUT >> F:\SLSTCMP\COMPARE.LOG +IF ERRORLEVEL 1 ECHO DIFF: D03_NWBYGONE01_MISSING.OUT >> F:\SLSTCMP\COMPARE.LOG +IF NOT ERRORLEVEL 1 ECHO OK: D03_NWBYGONE01_MISSING.OUT >> F:\SLSTCMP\COMPARE.LOG + +ECHO. >> F:\SLSTCMP\COMPARE.LOG +ECHO === D04_CONT.OUT === >> F:\SLSTCMP\COMPARE.LOG +FC F:\SLSTCMP\OUT\D04_CONT.OUT F:\SLSTCMP\PUBOUT\D04_CONT.OUT >> F:\SLSTCMP\COMPARE.LOG +IF ERRORLEVEL 1 ECHO DIFF: D04_CONT.OUT >> F:\SLSTCMP\COMPARE.LOG +IF NOT ERRORLEVEL 1 ECHO OK: D04_CONT.OUT >> F:\SLSTCMP\COMPARE.LOG + +ECHO. >> F:\SLSTCMP\COMPARE.LOG +ECHO === D05_MARS_CONT_OK.OUT === >> F:\SLSTCMP\COMPARE.LOG +FC F:\SLSTCMP\OUT\D05_MARS_CONT_OK.OUT F:\SLSTCMP\PUBOUT\D05_MARS_CONT_OK.OUT >> F:\SLSTCMP\COMPARE.LOG +IF ERRORLEVEL 1 ECHO DIFF: D05_MARS_CONT_OK.OUT >> F:\SLSTCMP\COMPARE.LOG +IF NOT ERRORLEVEL 1 ECHO OK: D05_MARS_CONT_OK.OUT >> F:\SLSTCMP\COMPARE.LOG + +ECHO. >> F:\SLSTCMP\COMPARE.LOG +ECHO === D06_NWBYGONE01_CONT_MISSING.OUT === >> F:\SLSTCMP\COMPARE.LOG +FC F:\SLSTCMP\OUT\D06_NWBYGONE01_CONT_MISSING.OUT F:\SLSTCMP\PUBOUT\D06_NWBYGONE01_CONT_MISSING.OUT >> F:\SLSTCMP\COMPARE.LOG +IF ERRORLEVEL 1 ECHO DIFF: D06_NWBYGONE01_CONT_MISSING.OUT >> F:\SLSTCMP\COMPARE.LOG +IF NOT ERRORLEVEL 1 ECHO OK: D06_NWBYGONE01_CONT_MISSING.OUT >> F:\SLSTCMP\COMPARE.LOG + +ECHO. >> F:\SLSTCMP\COMPARE.LOG +ECHO === D99_HELP.OUT === >> F:\SLSTCMP\COMPARE.LOG +FC F:\SLSTCMP\OUT\D99_HELP.OUT F:\SLSTCMP\PUBOUT\D99_HELP.OUT >> F:\SLSTCMP\COMPARE.LOG +IF ERRORLEVEL 1 ECHO DIFF: D99_HELP.OUT >> F:\SLSTCMP\COMPARE.LOG +IF NOT ERRORLEVEL 1 ECHO OK: D99_HELP.OUT >> F:\SLSTCMP\COMPARE.LOG + + +REM --- Optional logged-out comparison. --- +IF "%LGNTPWD%"=="" GOTO SKIPLOGOUT + +ECHO. >> F:\SLSTCMP\RUN.LOG +ECHO === PREPARE LOGGED-OUT SLIST HELPER === >> F:\SLSTCMP\RUN.LOG +IF EXIST C:\SLSTTMP DELTREE /Y C:\SLSTTMP >> F:\SLSTCMP\RUN.LOG +MD C:\SLSTTMP >> F:\SLSTCMP\RUN.LOG +MD C:\SLSTTMP\LOUT >> F:\SLSTCMP\RUN.LOG +MD C:\SLSTTMP\LPUBOUT >> F:\SLSTCMP\RUN.LOG + +REM Copy everything needed while F: is still available. +REM SLIST is officially available from LOGIN while logged out, so compare +REM NLOGIN\SLIST against LOGIN\SLIST after LOGOUT. +COPY \NLOGIN\SLIST.EXE C:\SLSTTMP\NSLIST.EXE >> F:\SLSTCMP\RUN.LOG +COPY \LOGIN\SLIST.EXE C:\SLSTTMP\SLIST.EXE >> F:\SLSTCMP\RUN.LOG +COPY \NPUBLIC\LOGOUT.EXE C:\SLSTTMP\LOGOUT.EXE >> F:\SLSTCMP\RUN.LOG +COPY \LOGIN\LOGIN.EXE C:\SLSTTMP\LOGIN.EXE >> F:\SLSTCMP\RUN.LOG +COPY \PUBLIC\DLYSTRT.EXE C:\SLSTTMP\DLYSTRT.EXE >> F:\SLSTCMP\RUN.LOG +COPY F:\SLSTC.BAT C:\SLSTTMP\SLSTC.BAT >> F:\SLSTCMP\RUN.LOG + +IF EXIST C:\SLSTTMP\DLYSTRT.EXE GOTO HAVEDLYLOCAL +ECHO ERROR: C:\SLSTTMP\DLYSTRT.EXE not copied. >> F:\SLSTCMP\RUN.LOG +GOTO SKIPLOGOUT +:HAVEDLYLOCAL +IF EXIST C:\SLSTTMP\SLSTC.BAT GOTO HAVEHELPER +ECHO ERROR: C:\SLSTTMP\SLSTC.BAT not copied. >> F:\SLSTCMP\RUN.LOG +GOTO SKIPLOGOUT +:HAVEHELPER + +C: +CD \SLSTTMP +C:\SLSTTMP\DLYSTRT.EXE /T:2 C:\SLSTTMP\SLSTC.BAT >> F:\SLSTCMP\RUN.LOG +ECHO DLYSTRT queued C:\SLSTTMP\SLSTC.BAT. >> F:\SLSTCMP\RUN.LOG +ECHO SLSTSTA Part 1 fertig. Bitte auf SLSTSTA PART2 warten. +GOTO END + +:SKIPLOGOUT +ECHO. >> F:\SLSTCMP\RUN.LOG +ECHO Logged-out SLIST comparison skipped because LGNTPWD is not set or helper setup failed. >> F:\SLSTCMP\RUN.LOG +GOTO SUMMARY + +:PART2 +F: +CD \ +IF NOT EXIST SLSTCMP\NUL MD SLSTCMP +IF NOT EXIST SLSTCMP\LOUT\NUL MD SLSTCMP\LOUT +IF NOT EXIST SLSTCMP\LPUBOUT\NUL MD SLSTCMP\LPUBOUT + +ECHO. >> F:\SLSTCMP\RUN.LOG +ECHO Part 2 collecting logged-out SLIST files from C:\SLSTTMP. >> F:\SLSTCMP\RUN.LOG +COPY C:\SLSTTMP\LOUT\*.OUT F:\SLSTCMP\LOUT >> F:\SLSTCMP\RUN.LOG +COPY C:\SLSTTMP\LPUBOUT\*.OUT F:\SLSTCMP\LPUBOUT >> F:\SLSTCMP\RUN.LOG +COPY C:\SLSTTMP\*.OUT F:\SLSTCMP >> F:\SLSTCMP\RUN.LOG +COPY C:\SLSTTMP\*.TXT F:\SLSTCMP >> F:\SLSTCMP\RUN.LOG + +ECHO === COMPARE LOGGED-OUT LOUT vs LPUBOUT === > F:\SLSTCMP\LCOMP.LOG +ECHO. >> F:\SLSTCMP\LCOMP.LOG +ECHO === D01_LIST.OUT === >> F:\SLSTCMP\LCOMP.LOG +FC F:\SLSTCMP\LOUT\D01_LIST.OUT F:\SLSTCMP\LPUBOUT\D01_LIST.OUT >> F:\SLSTCMP\LCOMP.LOG +IF ERRORLEVEL 1 ECHO DIFF: D01_LIST.OUT >> F:\SLSTCMP\LCOMP.LOG +IF NOT ERRORLEVEL 1 ECHO OK: D01_LIST.OUT >> F:\SLSTCMP\LCOMP.LOG + +ECHO. >> F:\SLSTCMP\LCOMP.LOG +ECHO === D02_MARS_OK.OUT === >> F:\SLSTCMP\LCOMP.LOG +FC F:\SLSTCMP\LOUT\D02_MARS_OK.OUT F:\SLSTCMP\LPUBOUT\D02_MARS_OK.OUT >> F:\SLSTCMP\LCOMP.LOG +IF ERRORLEVEL 1 ECHO DIFF: D02_MARS_OK.OUT >> F:\SLSTCMP\LCOMP.LOG +IF NOT ERRORLEVEL 1 ECHO OK: D02_MARS_OK.OUT >> F:\SLSTCMP\LCOMP.LOG + +ECHO. >> F:\SLSTCMP\LCOMP.LOG +ECHO === D03_NWBYGONE01_MISSING.OUT === >> F:\SLSTCMP\LCOMP.LOG +FC F:\SLSTCMP\LOUT\D03_NWBYGONE01_MISSING.OUT F:\SLSTCMP\LPUBOUT\D03_NWBYGONE01_MISSING.OUT >> F:\SLSTCMP\LCOMP.LOG +IF ERRORLEVEL 1 ECHO DIFF: D03_NWBYGONE01_MISSING.OUT >> F:\SLSTCMP\LCOMP.LOG +IF NOT ERRORLEVEL 1 ECHO OK: D03_NWBYGONE01_MISSING.OUT >> F:\SLSTCMP\LCOMP.LOG + +ECHO. >> F:\SLSTCMP\LCOMP.LOG +ECHO === D04_CONT.OUT === >> F:\SLSTCMP\LCOMP.LOG +FC F:\SLSTCMP\LOUT\D04_CONT.OUT F:\SLSTCMP\LPUBOUT\D04_CONT.OUT >> F:\SLSTCMP\LCOMP.LOG +IF ERRORLEVEL 1 ECHO DIFF: D04_CONT.OUT >> F:\SLSTCMP\LCOMP.LOG +IF NOT ERRORLEVEL 1 ECHO OK: D04_CONT.OUT >> F:\SLSTCMP\LCOMP.LOG + +ECHO. >> F:\SLSTCMP\LCOMP.LOG +ECHO === D05_MARS_CONT_OK.OUT === >> F:\SLSTCMP\LCOMP.LOG +FC F:\SLSTCMP\LOUT\D05_MARS_CONT_OK.OUT F:\SLSTCMP\LPUBOUT\D05_MARS_CONT_OK.OUT >> F:\SLSTCMP\LCOMP.LOG +IF ERRORLEVEL 1 ECHO DIFF: D05_MARS_CONT_OK.OUT >> F:\SLSTCMP\LCOMP.LOG +IF NOT ERRORLEVEL 1 ECHO OK: D05_MARS_CONT_OK.OUT >> F:\SLSTCMP\LCOMP.LOG + +ECHO. >> F:\SLSTCMP\LCOMP.LOG +ECHO === D06_NWBYGONE01_CONT_MISSING.OUT === >> F:\SLSTCMP\LCOMP.LOG +FC F:\SLSTCMP\LOUT\D06_NWBYGONE01_CONT_MISSING.OUT F:\SLSTCMP\LPUBOUT\D06_NWBYGONE01_CONT_MISSING.OUT >> F:\SLSTCMP\LCOMP.LOG +IF ERRORLEVEL 1 ECHO DIFF: D06_NWBYGONE01_CONT_MISSING.OUT >> F:\SLSTCMP\LCOMP.LOG +IF NOT ERRORLEVEL 1 ECHO OK: D06_NWBYGONE01_CONT_MISSING.OUT >> F:\SLSTCMP\LCOMP.LOG + +ECHO. >> F:\SLSTCMP\LCOMP.LOG +ECHO === D99_HELP.OUT === >> F:\SLSTCMP\LCOMP.LOG +FC F:\SLSTCMP\LOUT\D99_HELP.OUT F:\SLSTCMP\LPUBOUT\D99_HELP.OUT >> F:\SLSTCMP\LCOMP.LOG +IF ERRORLEVEL 1 ECHO DIFF: D99_HELP.OUT >> F:\SLSTCMP\LCOMP.LOG +IF NOT ERRORLEVEL 1 ECHO OK: D99_HELP.OUT >> F:\SLSTCMP\LCOMP.LOG + +GOTO SUMMARY + +:SUMMARY +ECHO === SUMMARY === > F:\SLSTCMP\SUMMARY.TXT +ECHO SLSTSTA SLIST comparison finished. >> F:\SLSTCMP\SUMMARY.TXT +ECHO. >> F:\SLSTCMP\SUMMARY.TXT +ECHO Output directories: >> F:\SLSTCMP\SUMMARY.TXT +ECHO - OUT logged-in Novell NPUBLIC baseline. >> F:\SLSTCMP\SUMMARY.TXT +ECHO - PUBOUT logged-in PUBLIC implementation output. >> F:\SLSTCMP\SUMMARY.TXT +ECHO - LOUT logged-out Novell NLOGIN baseline, if LGNTPWD was set. >> F:\SLSTCMP\SUMMARY.TXT +ECHO - LPUBOUT logged-out LOGIN implementation output, if LGNTPWD was set. >> F:\SLSTCMP\SUMMARY.TXT +ECHO. >> F:\SLSTCMP\SUMMARY.TXT +ECHO Compare result is in F:\SLSTCMP\COMPARE.LOG. >> F:\SLSTCMP\SUMMARY.TXT +ECHO Logged-out compare result, if run, is in F:\SLSTCMP\LCOMP.LOG. >> F:\SLSTCMP\SUMMARY.TXT +ECHO Optional: SLSTZIP ausfuehren. >> F:\SLSTCMP\SUMMARY.TXT + +ECHO SLSTSTA fertig. +ECHO Ergebnisse liegen in F:\SLSTCMP +ECHO Optional: SLSTZIP ausfuehren. +GOTO END + +:USAGE +ECHO Usage: SLSTSTA [PART2] + +:END diff --git a/test/slist/SLSTZIP.BAT b/test/slist/SLSTZIP.BAT index 827ee77..1d44846 100644 --- a/test/slist/SLSTZIP.BAT +++ b/test/slist/SLSTZIP.BAT @@ -1,25 +1,24 @@ -@ECHO OFF -REM SLSTZIP.BAT -REM Optional packer for SLSTSTA result files. -REM Requires ZIP.EXE in PATH or current directory. - -F: -CD \SLSTCMP - -IF EXIST SLSTSTA.ZIP DEL SLSTSTA.ZIP -IF EXIST ZIP.LOG DEL ZIP.LOG - -ECHO Creating SLSTSTA.ZIP > ZIP.LOG -ZIP -r SLSTSTA.ZIP RUN.LOG SUMMARY.TXT OUT >> ZIP.LOG - - -REM Cleanup generated test directories after ZIP. -REM Keep the CMP/result directory because it contains the ZIP and ZIP.LOG. -REM No separate TEST directory for this test; SLSTCMP is the result directory. -CD \ -ECHO. -ECHO ZIP step finished. -ECHO Check: -ECHO F:\SLSTCMP\SLSTSTA.ZIP -ECHO F:\SLSTCMP\ZIP.LOG -ECHO. +@ECHO OFF +REM SLSTZIP.BAT +REM Optional packer for SLSTSTA result files. +REM Requires ZIP.EXE in PATH or current directory. + +F: +CD \SLSTCMP + +IF EXIST SLSTSTA.ZIP DEL SLSTSTA.ZIP +IF EXIST ZIP.LOG DEL ZIP.LOG + +ECHO Creating SLSTSTA.ZIP > ZIP.LOG +ZIP -r SLSTSTA.ZIP RUN.LOG SUMMARY.TXT COMPARE.LOG LCOMP.LOG OUT PUBOUT LOUT LPUBOUT *.OUT *.TXT >> ZIP.LOG + +REM Cleanup local helper directory after ZIP, if it exists. +IF EXIST C:\SLSTTMP DELTREE /Y C:\SLSTTMP >> ZIP.LOG + +CD \ +ECHO. +ECHO ZIP step finished. +ECHO Check: +ECHO F:\SLSTCMP\SLSTSTA.ZIP +ECHO F:\SLSTCMP\ZIP.LOG +ECHO.