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:
Mario Fetka
2026-05-25 09:17:56 +02:00
parent 7117bfff68
commit 6d2d3f367f
5 changed files with 244 additions and 18 deletions

102
ndir.c
View File

@@ -48,6 +48,7 @@
#define NDIR_NCP_RIGHT_SUPER 0x0100
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_R 0x02
@@ -207,6 +208,27 @@ static void ndir_dos_date(unsigned date, char *out)
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)
{
int year;
@@ -296,6 +318,35 @@ static void ndir_old_rights_string(uint8 old_rights, char *out)
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)
{
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 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;
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_flags(ff->attrib, fl);
if (options & NDIR_OPT_RIGHTS) {
tool_join_path(path, dir, ff->name, sizeof(path));
ndir_effective_rights(path, eff);
/*
* We do not have the inherited-rights mask yet. Use the effective
* rights in both columns for this first /RIGHTS implementation.
*/
ndir_inherited_rights(path, inh);
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) {
/*
* 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.
*/
fprintf(stdout, "%-16.16s %-17.17s 0-00-00 0:00 A %-8.8s %-17.17s\n",
ff->name, dt, d, dt);
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);
} else {
fprintf(stdout, "%-16.16s %-17.17s 0-00-00 0:00 A %-8.8s %-17.17s\n",
ff->name, dt, d, dt);
}
} else {
fprintf(stdout, "%-16.16s %12lu %-17.17s %-18.18s\n",
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 path[260];
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)) {
tool_join_path(path, dir, ff->name, sizeof(path));
ndir_effective_rights(path, eff);
ndir_inherited_rights(path, inh);
fprintf(stdout, "%-16.16s [%8.8s] [%8.8s] %-17.17s\n",
ff->name, eff, eff, dt);
ff->name, inh, eff, dt);
} else {
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, "---------------- ------------------ ----------- ----------- --------\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");