dosutils: use NCP87 DOS info fields in NDIR
Add a Client32 NCP87 helper for obtaining DOS namespace file and subdirectory information and use it in NDIR. The new helper reads the classic NCP87 subfunction 6 RIM_ALL DOS info block, including timestamps, inherited rights, directory identifiers and size metadata. Use the NCP87 inherited rights mask for the inherited-rights column while keeping the existing Client32 effective-rights path for the effective rights column. Also use the NCP87 modify, archive, last-access and creation date fields for the /DATES display, falling back to DOS findfirst timestamps when the NCP87 info request is not available. Tighten the /DATES layout so the full Created/Copied timestamp remains within an 80-column DOS screen.
This commit is contained in:
@@ -534,10 +534,10 @@ NDIR PUBLIC /DO
|
|||||||
|
|
||||||
The first version intentionally focuses on the common listing path. More
|
The first version intentionally focuses on the common listing path. More
|
||||||
advanced Novell NDIR features such as sorting and restrictions are accepted
|
advanced Novell NDIR features such as sorting and restrictions are accepted
|
||||||
only as future compatibility points or will be implemented in later revisions. The `/RIGHTS` display currently uses effective rights for both
|
only as future compatibility points or will be implemented in later revisions. The `/RIGHTS` display uses NCP87 information for inherited rights and
|
||||||
rights columns until inherited-right masks are exposed. The `/DATES` display
|
Client32 effective-rights calls for effective rights. The `/DATES` display
|
||||||
uses the DOS update timestamp and placeholder values for archive/access fields
|
uses NCP87 DOS info fields when available and falls back to DOS findfirst
|
||||||
until full NetWare namespace date fields are available.
|
timestamps otherwise.
|
||||||
|
|
||||||
|
|
||||||
### `DEBUG`
|
### `DEBUG`
|
||||||
|
|||||||
115
c32ncp.c
115
c32ncp.c
@@ -314,6 +314,121 @@ int c32_ncp87_obtain_rim_attributes(const char *name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int c32_ncp87_obtain_ndir_info(const char *path_name,
|
||||||
|
uint16 dir_handle,
|
||||||
|
C32_NDIR_INFO *info_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;
|
||||||
|
int namelen;
|
||||||
|
|
||||||
|
if (!info_out)
|
||||||
|
return(1);
|
||||||
|
|
||||||
|
memset(info_out, 0, sizeof(*info_out));
|
||||||
|
if (actual_out) *actual_out = 0;
|
||||||
|
if (handle_lo_out) *handle_lo_out = 0;
|
||||||
|
if (handle_hi_out) *handle_hi_out = 0;
|
||||||
|
|
||||||
|
rc = c32_get_ncp_handle(&handle_lo, &handle_hi);
|
||||||
|
if (rc)
|
||||||
|
return(10 + rc);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NCP87 subfunction 6: Obtain File or Subdirectory Information.
|
||||||
|
*
|
||||||
|
* This asks for the classic DOS info block (RIM_ALL). ncpfs' old
|
||||||
|
* nw_info_struct layout is:
|
||||||
|
* +00 space allocated
|
||||||
|
* +04 attributes
|
||||||
|
* +20 creation time/date/id
|
||||||
|
* +28 modify time/date/id
|
||||||
|
* +36 last access date
|
||||||
|
* +38 archive time/date/id
|
||||||
|
* +46 inherited rights mask
|
||||||
|
* +48 directory numbers
|
||||||
|
* +76 name length/name
|
||||||
|
*/
|
||||||
|
memset(hdr, 0, sizeof(hdr));
|
||||||
|
hdr[0] = 6; /* NCP87 subfunction 6 */
|
||||||
|
hdr[1] = 0; /* source namespace DOS */
|
||||||
|
hdr[2] = 0; /* target namespace DOS */
|
||||||
|
c32_put_word_lh(hdr + 3, 0x0006); /* SA_ALL */
|
||||||
|
c32_put_dword_lh(hdr + 5, 0x00000FFFUL); /* RIM_ALL */
|
||||||
|
|
||||||
|
path_len = c32_build_handle_path_from_dos_path(path, (uint8)dir_handle,
|
||||||
|
0, 0, path_name);
|
||||||
|
|
||||||
|
memset(rep0, 0, sizeof(rep0));
|
||||||
|
memset(rep1, 0, sizeof(rep1));
|
||||||
|
memset(rawout, 0, sizeof(rawout));
|
||||||
|
|
||||||
|
C32_NCP87_Raw5_Probe(handle_lo, handle_hi,
|
||||||
|
hdr, 9,
|
||||||
|
path, path_len,
|
||||||
|
rep0, sizeof(rep0),
|
||||||
|
rep1, sizeof(rep1),
|
||||||
|
rawout);
|
||||||
|
|
||||||
|
raw_ret_ax = c32_get_word_lh(rawout + 14);
|
||||||
|
raw_ret_dx = c32_get_word_lh(rawout + 16);
|
||||||
|
actual_lo = c32_get_word_lh(rawout + 18);
|
||||||
|
|
||||||
|
if (actual_out) *actual_out = actual_lo;
|
||||||
|
if (handle_lo_out) *handle_lo_out = handle_lo;
|
||||||
|
if (handle_hi_out) *handle_hi_out = handle_hi;
|
||||||
|
|
||||||
|
if (raw_ret_ax != 0 || raw_ret_dx != 0)
|
||||||
|
return(20);
|
||||||
|
|
||||||
|
info_out->space_allocated = c32_get_dword_lh(rep0 + 0);
|
||||||
|
info_out->attributes = c32_get_dword_lh(rep0 + 4);
|
||||||
|
info_out->flags = c32_get_word_lh(rep0 + 8);
|
||||||
|
info_out->data_size = c32_get_dword_lh(rep0 + 10);
|
||||||
|
info_out->total_size = c32_get_dword_lh(rep0 + 14);
|
||||||
|
info_out->number_of_streams = c32_get_word_lh(rep0 + 18);
|
||||||
|
info_out->creation_time = c32_get_word_lh(rep0 + 20);
|
||||||
|
info_out->creation_date = c32_get_word_lh(rep0 + 22);
|
||||||
|
info_out->creator_id = c32_get_dword_hl(rep0 + 24);
|
||||||
|
info_out->modify_time = c32_get_word_lh(rep0 + 28);
|
||||||
|
info_out->modify_date = c32_get_word_lh(rep0 + 30);
|
||||||
|
info_out->modifier_id = c32_get_dword_hl(rep0 + 32);
|
||||||
|
info_out->last_access_date = c32_get_word_lh(rep0 + 36);
|
||||||
|
info_out->archive_time = c32_get_word_lh(rep0 + 38);
|
||||||
|
info_out->archive_date = c32_get_word_lh(rep0 + 40);
|
||||||
|
info_out->archiver_id = c32_get_dword_hl(rep0 + 42);
|
||||||
|
info_out->inherited_rights = c32_get_word_lh(rep0 + 46);
|
||||||
|
info_out->dir_ent_num = c32_get_dword_lh(rep0 + 48);
|
||||||
|
info_out->dos_dir_num = c32_get_dword_lh(rep0 + 52);
|
||||||
|
info_out->vol_number = c32_get_dword_lh(rep0 + 56);
|
||||||
|
info_out->ea_data_size = c32_get_dword_lh(rep0 + 60);
|
||||||
|
info_out->ea_key_count = c32_get_dword_lh(rep0 + 64);
|
||||||
|
info_out->ea_key_size = c32_get_dword_lh(rep0 + 68);
|
||||||
|
info_out->ns_creator = c32_get_dword_lh(rep0 + 72);
|
||||||
|
|
||||||
|
namelen = rep0[76];
|
||||||
|
if (namelen > 255)
|
||||||
|
namelen = 255;
|
||||||
|
info_out->name_len = (uint8)namelen;
|
||||||
|
memcpy(info_out->name, rep0 + 77, namelen);
|
||||||
|
info_out->name[namelen] = '\0';
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int c32_ncp87_modify_dos_attributes(char *name,
|
int c32_ncp87_modify_dos_attributes(char *name,
|
||||||
uint16 dir_handle,
|
uint16 dir_handle,
|
||||||
uint32 attrs,
|
uint32 attrs,
|
||||||
|
|||||||
37
c32ncp.h
37
c32ncp.h
@@ -12,6 +12,43 @@ int c32_ncp87_obtain_rim_attributes(const char *name,
|
|||||||
uint16 *handle_hi_out);
|
uint16 *handle_hi_out);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct c32_ndir_info {
|
||||||
|
uint32 space_allocated;
|
||||||
|
uint32 attributes;
|
||||||
|
uint16 flags;
|
||||||
|
uint32 data_size;
|
||||||
|
uint32 total_size;
|
||||||
|
uint16 number_of_streams;
|
||||||
|
uint16 creation_time;
|
||||||
|
uint16 creation_date;
|
||||||
|
uint32 creator_id;
|
||||||
|
uint16 modify_time;
|
||||||
|
uint16 modify_date;
|
||||||
|
uint32 modifier_id;
|
||||||
|
uint16 last_access_date;
|
||||||
|
uint16 archive_time;
|
||||||
|
uint16 archive_date;
|
||||||
|
uint32 archiver_id;
|
||||||
|
uint16 inherited_rights;
|
||||||
|
uint32 dir_ent_num;
|
||||||
|
uint32 dos_dir_num;
|
||||||
|
uint32 vol_number;
|
||||||
|
uint32 ea_data_size;
|
||||||
|
uint32 ea_key_count;
|
||||||
|
uint32 ea_key_size;
|
||||||
|
uint32 ns_creator;
|
||||||
|
uint8 name_len;
|
||||||
|
char name[256];
|
||||||
|
} C32_NDIR_INFO;
|
||||||
|
|
||||||
|
int c32_ncp87_obtain_ndir_info(const char *path_name,
|
||||||
|
uint16 dir_handle,
|
||||||
|
C32_NDIR_INFO *info_out,
|
||||||
|
uint16 *actual_out,
|
||||||
|
uint16 *handle_lo_out,
|
||||||
|
uint16 *handle_hi_out);
|
||||||
|
|
||||||
|
|
||||||
int c32_ncp87_modify_dos_attributes(char *name,
|
int c32_ncp87_modify_dos_attributes(char *name,
|
||||||
uint16 dir_handle,
|
uint16 dir_handle,
|
||||||
uint32 attrs,
|
uint32 attrs,
|
||||||
|
|||||||
102
ndir.c
102
ndir.c
@@ -48,6 +48,7 @@
|
|||||||
#define NDIR_NCP_RIGHT_SUPER 0x0100
|
#define NDIR_NCP_RIGHT_SUPER 0x0100
|
||||||
|
|
||||||
static void ndir_dos_date(unsigned date, char *out);
|
static void ndir_dos_date(unsigned date, char *out);
|
||||||
|
static void ndir_dos_datetime(unsigned date, unsigned time, char *out);
|
||||||
|
|
||||||
#define NDIR_OLD_RIGHT_S 0x01
|
#define NDIR_OLD_RIGHT_S 0x01
|
||||||
#define NDIR_OLD_RIGHT_R 0x02
|
#define NDIR_OLD_RIGHT_R 0x02
|
||||||
@@ -207,6 +208,27 @@ static void ndir_dos_date(unsigned date, char *out)
|
|||||||
sprintf(out, "%02d-%02d-%02d", month, day, year % 100);
|
sprintf(out, "%02d-%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");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ndir_dos_datetime(date, time, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ndir_dos_date_or_blank(unsigned date, char *out)
|
||||||
|
{
|
||||||
|
if (!date) {
|
||||||
|
strcpy(out, "0-00-00");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ndir_dos_date(date, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void ndir_dos_datetime(unsigned date, unsigned time, char *out)
|
static void ndir_dos_datetime(unsigned date, unsigned time, char *out)
|
||||||
{
|
{
|
||||||
int year;
|
int year;
|
||||||
@@ -296,6 +318,35 @@ static void ndir_old_rights_string(uint8 old_rights, char *out)
|
|||||||
out[8] = '\0';
|
out[8] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ndir_get_ncp_info(char *path, C32_NDIR_INFO *info)
|
||||||
|
{
|
||||||
|
uint8 connid = 0;
|
||||||
|
uint8 dhandle = 0;
|
||||||
|
|
||||||
|
if (!info)
|
||||||
|
return(1);
|
||||||
|
|
||||||
|
memset(info, 0, sizeof(*info));
|
||||||
|
|
||||||
|
if (tool_current_dhandle(&connid, &dhandle))
|
||||||
|
return(1);
|
||||||
|
|
||||||
|
return(c32_ncp87_obtain_ndir_info(tool_is_current_path(path) ? "" : path,
|
||||||
|
(uint16)dhandle,
|
||||||
|
info,
|
||||||
|
NULL, NULL, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ndir_inherited_rights(char *path, char *out)
|
||||||
|
{
|
||||||
|
C32_NDIR_INFO info;
|
||||||
|
|
||||||
|
strcpy(out, "--------");
|
||||||
|
|
||||||
|
if (!ndir_get_ncp_info(path, &info))
|
||||||
|
ndir_old_rights_string((uint8)info.inherited_rights, out);
|
||||||
|
}
|
||||||
|
|
||||||
static void ndir_rights_string(uint16 ncp_rights, char *out)
|
static void ndir_rights_string(uint16 ncp_rights, char *out)
|
||||||
{
|
{
|
||||||
out[0] = (ncp_rights & NDIR_NCP_RIGHT_SUPER) ? 'S' : '-';
|
out[0] = (ncp_rights & NDIR_NCP_RIGHT_SUPER) ? 'S' : '-';
|
||||||
@@ -371,28 +422,45 @@ static void ndir_print_file(char *dir, struct find_t *ff, int options,
|
|||||||
char fl[20]; /* [RW-A------------] plus NUL */
|
char fl[20]; /* [RW-A------------] plus NUL */
|
||||||
char path[260];
|
char path[260];
|
||||||
char eff[10];
|
char eff[10];
|
||||||
|
char inh[10];
|
||||||
|
char arch[24];
|
||||||
|
char acc[12];
|
||||||
|
char crea[24];
|
||||||
|
C32_NDIR_INFO info;
|
||||||
|
int have_info = 0;
|
||||||
|
|
||||||
|
tool_join_path(path, dir, ff->name, sizeof(path));
|
||||||
|
have_info = !ndir_get_ncp_info(path, &info);
|
||||||
|
|
||||||
|
if (have_info)
|
||||||
|
ndir_dos_datetime(info.modify_date, info.modify_time, dt);
|
||||||
|
else
|
||||||
|
ndir_dos_datetime(ff->wr_date, ff->wr_time, dt);
|
||||||
|
|
||||||
ndir_dos_datetime(ff->wr_date, ff->wr_time, dt);
|
|
||||||
ndir_dos_date(ff->wr_date, d);
|
ndir_dos_date(ff->wr_date, d);
|
||||||
ndir_flags(ff->attrib, fl);
|
ndir_flags(ff->attrib, fl);
|
||||||
|
|
||||||
if (options & NDIR_OPT_RIGHTS) {
|
if (options & NDIR_OPT_RIGHTS) {
|
||||||
tool_join_path(path, dir, ff->name, sizeof(path));
|
|
||||||
ndir_effective_rights(path, eff);
|
ndir_effective_rights(path, eff);
|
||||||
/*
|
ndir_inherited_rights(path, inh);
|
||||||
* We do not have the inherited-rights mask yet. Use the effective
|
|
||||||
* rights in both columns for this first /RIGHTS implementation.
|
|
||||||
*/
|
|
||||||
fprintf(stdout, "%-16.16s %-18.18s [%8.8s] [%8.8s]\n",
|
fprintf(stdout, "%-16.16s %-18.18s [%8.8s] [%8.8s]\n",
|
||||||
ff->name, fl, eff, eff);
|
ff->name, fl, inh, eff);
|
||||||
} else if (options & NDIR_OPT_DATES) {
|
} else if (options & NDIR_OPT_DATES) {
|
||||||
/*
|
/*
|
||||||
* DOS findfirst gives us the update timestamp only. Keep the Novell
|
* DOS findfirst gives us the update timestamp only. Keep the Novell
|
||||||
* /DATES layout and use placeholders for archive/access data until
|
* /DATES layout and use placeholders for archive/access data until
|
||||||
* full NetWare namespace date fields are available.
|
* full NetWare namespace date fields are available.
|
||||||
*/
|
*/
|
||||||
fprintf(stdout, "%-16.16s %-17.17s 0-00-00 0:00 A %-8.8s %-17.17s\n",
|
if (have_info) {
|
||||||
ff->name, dt, d, dt);
|
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);
|
||||||
|
} else {
|
||||||
|
fprintf(stdout, "%-16.16s %-17.17s 0-00-00 0:00 A %-8.8s %-17.17s\n",
|
||||||
|
ff->name, dt, d, dt);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
fprintf(stdout, "%-16.16s %12lu %-17.17s %-18.18s\n",
|
fprintf(stdout, "%-16.16s %12lu %-17.17s %-18.18s\n",
|
||||||
ff->name, (unsigned long)ff->size, dt, fl);
|
ff->name, (unsigned long)ff->size, dt, fl);
|
||||||
@@ -407,14 +475,20 @@ static void ndir_print_dir(char *dir, struct find_t *ff, int options,
|
|||||||
char dt[24];
|
char dt[24];
|
||||||
char path[260];
|
char path[260];
|
||||||
char eff[10];
|
char eff[10];
|
||||||
|
char inh[10];
|
||||||
|
C32_NDIR_INFO info;
|
||||||
|
|
||||||
ndir_dos_datetime(ff->wr_date, ff->wr_time, dt);
|
tool_join_path(path, dir, 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)) {
|
if (options & (NDIR_OPT_RIGHTS | NDIR_OPT_DIRS_ONLY)) {
|
||||||
tool_join_path(path, dir, ff->name, sizeof(path));
|
|
||||||
ndir_effective_rights(path, eff);
|
ndir_effective_rights(path, eff);
|
||||||
|
ndir_inherited_rights(path, inh);
|
||||||
fprintf(stdout, "%-16.16s [%8.8s] [%8.8s] %-17.17s\n",
|
fprintf(stdout, "%-16.16s [%8.8s] [%8.8s] %-17.17s\n",
|
||||||
ff->name, eff, eff, dt);
|
ff->name, inh, eff, dt);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stdout, "%-16.16s <DIR> %-17.17s\n", ff->name, dt);
|
fprintf(stdout, "%-16.16s <DIR> %-17.17s\n", ff->name, dt);
|
||||||
}
|
}
|
||||||
@@ -499,8 +573,8 @@ static int ndir_list_one(char *spec, int options, int *continuous)
|
|||||||
fprintf(stdout, "Files: Flags Rights Rights Owner\n");
|
fprintf(stdout, "Files: Flags Rights Rights Owner\n");
|
||||||
fprintf(stdout, "---------------- ------------------ ----------- ----------- --------\n");
|
fprintf(stdout, "---------------- ------------------ ----------- ----------- --------\n");
|
||||||
} else if (options & NDIR_OPT_DATES) {
|
} else if (options & NDIR_OPT_DATES) {
|
||||||
fprintf(stdout, "Files: Last Updated Last Archived * Accessed Created/Copied\n");
|
fprintf(stdout, "Files: Last Updated Last Archived Accessed Created/Copied\n");
|
||||||
fprintf(stdout, "---------------- ----------------- ------------- -- -------- -----------------\n");
|
fprintf(stdout, "---------------- ----------------- ----------------- -------- -----------------\n");
|
||||||
} else {
|
} else {
|
||||||
fprintf(stdout, "Files: Size Last Updated Flags Owner\n");
|
fprintf(stdout, "Files: Size Last Updated Flags Owner\n");
|
||||||
fprintf(stdout, "---------------- ---------------- ----------------- ------------------ --------\n");
|
fprintf(stdout, "---------------- ---------------- ----------------- ------------------ --------\n");
|
||||||
|
|||||||
Reference in New Issue
Block a user