Files
ncpfs/util/nwdir.c
ncpfs archive import b48389be22 Import ncpfs 2.2.5
2026-04-28 20:40:00 +02:00

1014 lines
26 KiB
C

/*
nwdir.c - list contents of directory
Copyright (c) 1998 Milan Vandrovec
Copyright (c) 1999-2001 Petr Vandrovec
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Revision history:
0.00 1998 Milan Vandrovec
Initial revision.
0.01 1999 Petr Vandrovec <vandrove@vc.cvut.cz>
Updated for new ncp_ns_* interface.
1.00 1999, November 20 Petr Vandrovec <vandrove@vc.cvut.cz>
Added license.
1.01 2000, August 24 Petr Vandrovec <vandrove@vc.cvut.cz>
Updated to ncp_ns_search_init/ncp_ns_search_next/
ncp_ns_search_end.
Updated to ncp_ns_extract_info_field.
1.02 2000, August 27 Petr Vandrovec <vandrove@vc.cvut.cz>
Added ncp_ea_enumerate code.
1.03 2001, January 27 Petr Vandrovec <vandrove@vc.cvut.cz>
Updated to use getopt interface.
Added ncp_ns_scan_connections_using_file dump code.
1.04 2001, February 4 Petr Vandrovec <vandrove@vc.cvut.cz>
Added ncp_ns_scan_physical_locks_by_file dump code.
1.05 2001, May 31 Petr Vandrovec <vandrove@vc.cvut.cz>
Use unistd.h and not getopt.h for getopt().
1.06 2002, February 4 Petr Vandrovec <vandrove@vc.cvut.cz>
Do not dump core when file opened for nothing is found.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <ncp/nwcalls.h>
#include <ncp/nwnet.h>
#include <ncp/eas.h>
#include "private/libintl.h"
#define _(X) gettext(X)
#define N_(X) (X)
#ifndef A_DONT_SUBALLOCATE
#define A_DONT_SUBALLOCATE 0x00000800L
#endif
#ifdef N_PLAT_DOS
#ifndef NTYPES_H
typedef unsigned int nuint16;
#endif
typedef unsigned long nuint32;
typedef unsigned int nuint;
#define P08X "(%08lX)"
#define P32U "lu"
#else
#define stricmp(A,B) strcasecmp(A,B)
#define P08X "(%08X)"
#define P32U "u"
#endif
static int opt_t = 0;
static int opt_l = 0;
static int opt_v = 0;
static int opt_e = 0;
static int opt_f = 0;
static int opt_p = 0;
static void ncpb_add_byte(unsigned char** c, int v) {
*(*c)++ = v;
}
static void ncpb_add_word_lh(unsigned char** c, nuint v) {
WSET_LH(*c, 0, v);
(*c)+=2;
}
static void ncpb_add_dword_lh(unsigned char** c, nuint32 v) {
DSET_LH(*c, 0, v);
(*c)+=4;
}
static nuint16 ncpb_get_word_lh(unsigned char** c) {
nuint16 tmp;
tmp = WVAL_LH(*c, 0);
(*c)+=2;
return tmp;
}
u_int32_t img;
struct nsInfo {
struct NSI_Name name;
struct NSI_Directory dir;
int valid;
};
static struct nsInfo os2, mac, nfs;
static unsigned char buf[1024];
static unsigned char buf2[1024];
static NWCCODE NWNSEntryInfo2(NWCONN_HANDLE conn, nuint32 vol, nuint32 dosdir, nuint ns, struct NSI_Name* name, struct NSI_Directory* dir) {
struct nw_info_struct3 info;
NWCCODE err;
info.len = 0;
info.data = NULL;
err = ncp_ns_obtain_entry_info(conn, NW_NS_DOS, SA_ALL,
1, vol, dosdir, NULL, 0, ns, RIM_NAME | RIM_DIRECTORY,
&info, sizeof(info));
if (err)
return err;
err = ncp_ns_extract_info_field(&info, NSIF_NAME, name, sizeof(*name));
if (!err) {
err = ncp_ns_extract_info_field(&info, NSIF_DIRECTORY, dir, sizeof(*dir));
}
free(info.data);
return err;
}
static NWCCODE NWNSScanForTrustees(NWCONN_HANDLE conn,
nuint32 vol, nuint32 dosdir,
nuint32* iter, nuint* no_tstees, TRUSTEE_INFO* tstees) {
return ncp_ns_trustee_scan(conn, NW_NS_DOS, SA_ALL,
1, vol, dosdir, NULL, 0, iter, tstees, no_tstees);
}
static NWCCODE NWNSGetEffectiveRights(NWCONN_HANDLE conn, nuint32 vol, nuint32 dosdir, nuint16* eff) {
unsigned char* c=buf2;
NW_FRAGMENT rq;
NW_FRAGMENT rp;
NWCCODE err;
ncpb_add_byte(&c, 0x1D);
ncpb_add_byte(&c, NW_NS_DOS);
ncpb_add_byte(&c, 0); /* ?? */
ncpb_add_word_lh(&c, SA_ALL);
ncpb_add_dword_lh(&c, 0); /* ReturnInfoMask=0, we are not interested in anything */
ncpb_add_byte(&c, vol);
ncpb_add_dword_lh(&c, dosdir);
ncpb_add_byte(&c, 1);
ncpb_add_byte(&c, 0);
rq.fragAddress = buf2;
rq.fragSize = c-buf2;
rp.fragAddress = buf;
rp.fragSize = sizeof(buf);
err = NWRequest(conn, 0x57, 1, &rq, 1, &rp);
if (err) return err;
c = buf;
*eff = ncpb_get_word_lh(&c);
return 0;
}
static char* createMask311(nuint mask) {
static char r[9];
r[0] = (mask&TR_SUPERVISOR) ?'S':'-';
r[1] = (mask&TR_READ) ?'R':'-',
r[2] = (mask&TR_WRITE) ?'W':'-',
r[3] = (mask&TR_CREATE) ?'C':'-',
r[4] = (mask&TR_ERASE) ?'E':'-',
r[5] = (mask&TR_MODIFY) ?'M':'-',
r[6] = (mask&TR_SEARCH) ?'F':'-',
r[7] = (mask&TR_ACCESS_CTRL)?'A':'-',
r[8] = 0;
return r;
}
static void doID(NWCONN_HANDLE conn, nuint32 id) {
NWCCODE err;
char user[MAX_DN_BYTES];
nuint16 type;
if (opt_t)
printf(P08X " ", id);
if (!id) {
printf(_("Nobody"));
} else {
#ifdef N_PLAT_DOS
id = ntohl(id);
#endif
err = NWGetObjectName(conn, id, user, &type);
if (err) {
NWDSContextHandle ctx;
sprintf(user, _("Unknown:N/A"));
err = NWDSCreateContextHandle(&ctx);
if (!err) {
NWDSAddConnection(ctx, conn);
err = NWDSMapIDToName(ctx, conn, id, user);
if (err)
sprintf(user, _("Unknown:<%s>"), strnwerror(err));
NWDSFreeContext(ctx);
}
} else {
switch (type) {
case OT_USER: printf(_("User:"));break;
case OT_USER_GROUP: printf(_("Group:"));break;
case OT_FILE_SERVER:printf(_("FileServer:"));break;
default: printf(_("Unknown(%04X):"), type);break;
}
}
printf("%s", user);
}
}
static inline size_t my_strftime(char *s, size_t max, const char *fmt, const struct tm *tm) {
return strftime(s, max, fmt, tm);
}
static void dodate(nuint date) {
static const time_t zero_time_t = 0;
struct tm* tm;
char text[100];
tm = gmtime(&zero_time_t);
tm->tm_year = (date>>9)+80;
tm->tm_mon = ((date>>5) & 0xF) - 1;
tm->tm_mday = date & 0x1F;
tm->tm_isdst = 0;
my_strftime(text, sizeof(text), "%x", tm);
printf("%s", text);
}
static void dotime(nuint dtime) {
static const time_t zero_time_t = 0;
struct tm* tm;
char text[100];
tm = gmtime(&zero_time_t);
tm->tm_hour = dtime >> 11;
tm->tm_min = (dtime >> 5) & 0x3F;
tm->tm_sec = (dtime << 1) & 0x3F;
tm->tm_isdst = 0;
my_strftime(text, sizeof(text), "%X", tm);
printf("%s", text);
}
static void dodatesTimesID(NWCONN_HANDLE conn, nuint dtime, nuint date, nuint32 id) {
if (dtime || date) {
dodate(date);
printf(" ");
dotime(dtime);
} else {
printf("%-17s", _("never"));
}
if (id) {
printf(" ");
doID(conn, id);
}
printf("\n");
}
static void eaenum(NWCONN_HANDLE conn, u_int32_t volume, u_int32_t dirent) {
unsigned char vv[2048];
size_t pos;
struct ncp_ea_enumerate_info winfo;
NWCCODE err;
int sawtitle = 0;
size_t eaid = 1;
winfo.enumSequence = 0;
err = ncp_ea_enumerate(conn,
NWEA_FL_INFO1 | NWEA_FL_CLOSE_ERR | NWEA_FL_SRC_DIRENT,
volume, dirent, -1, NULL, 0, &winfo, vv, sizeof(vv), &pos);
do {
size_t rinfo;
const unsigned char* p;
if (err) {
//fprintf(stderr, "Enumeration failed: %s\n",
// strnwerror(err));
return;
}
if (winfo.errorCode) {
/* should not happen as we used NWEA_FL_CLOSE_ERR */
//fprintf(stderr, "Enumeration extended fail: %s\n",
// strnwerror((winfo.errorCode & 0xFF) | NWE_SERVER_ERROR));
break;
}
/* no extended attributes */
if (!winfo.totalEAs)
break;
if (!sawtitle) {
printf(_("Extended attributes: %u attributes\n"
" %u bytes in keys, %u bytes in data\n"),
winfo.totalEAs, winfo.totalEAsKeySize, winfo.totalEAsDataSize);
sawtitle = 1;
}
p = vv;
for (rinfo = 0; rinfo < winfo.returnedItems; rinfo++) {
struct ncp_ea_info_level1 ppp;
err = ncp_ea_extract_info_level1(p,
vv + pos, &ppp, sizeof(ppp), NULL, &p);
if (err)
printf(" Key %u: Cannot retrieve: %s\n",
eaid, strnwerror(err));
else {
printf(_(" Key %u:\n"
" Name: %s\n"
" Access Flag: 0x%08X\n"
" Value Length: %u\n"),
eaid, ppp.key, ppp.accessFlag,
ppp.valueLength);
}
eaid++;
}
if (!winfo.enumSequence)
break;
err = ncp_ea_enumerate(conn,
NWEA_FL_INFO1 | NWEA_FL_CLOSE_ERR | NWEA_FL_SRC_EAHANDLE,
winfo.newEAhandle, 0, -1, NULL, 0,
&winfo, vv, sizeof(vv), &pos);
} while (1);
if (winfo.newEAhandle) {
err = ncp_ea_close(conn, winfo.newEAhandle);
// if (err) {
// fprintf(stderr, "Close EA failed: %s\n",
// strnwerror(err));
// }
}
if (sawtitle)
printf("\n");
}
static void dumpDataSizes(const struct nw_info_struct3* info) {
NWCCODE err;
struct NSI_DatastreamLogicals* logical;
size_t tmplen;
if (!(img & RIM_DATASTREAM_LOGICALS)) {
ncp_off64_t off;
err = ncp_ns_extract_info_field(info, NSIF_DATA_SIZE,
&off, sizeof(off));
if (err) {
printf(_(" Cannot determine file size: %s\n"), strnwerror(err));
} else {
printf(_(" File size: %10Lu"), off);
err = ncp_ns_extract_info_field(info, NSIF_SPACE_ALLOCATED,
&off, sizeof(off));
if (!err) {
printf(_(" (allocated %Lu)"), off * 8ULL);
}
printf("\n");
}
return;
}
err = ncp_ns_extract_info_field_size(info, NSIF_DATASTREAM_LOGICALS,
&tmplen);
if (err)
return;
logical = (struct NSI_DatastreamLogicals*)malloc(tmplen);
if (!logical)
return;
err = ncp_ns_extract_info_field(info, NSIF_DATASTREAM_LOGICALS,
logical, tmplen);
if (err) {
printf(_(" Cannot determine file size: %s\n"), strnwerror(err));
} else if (!logical->NumberOfDatastreams) {
printf(_(" No datastream exist\n"));
} else {
struct NSI_DatastreamSizes* size;
size_t i;
size = NULL;
err = ncp_ns_extract_info_field_size(info, NSIF_DATASTREAM_SIZES,
&tmplen);
if (!err) {
size = (struct NSI_DatastreamSizes*)malloc(tmplen);
if (size) {
err = ncp_ns_extract_info_field(info,
NSIF_DATASTREAM_SIZES, size, tmplen);
if (err) {
free(size);
size = NULL;
}
}
}
for (i = 0; i < logical->NumberOfDatastreams; i++) {
size_t j;
u_int32_t num = logical->ds[i].Number;
if (num) {
printf(_(" Stream %3u size: %10Lu"), num,
logical->ds[i].Size);
} else {
printf(_(" File size: %10Lu"),
logical->ds[i].Size);
}
if (size) {
for (j = 0; j < size->NumberOfDatastreams; j++) {
if (size->ds[j].Number == num) {
printf(_(" (allocated %Lu)"),
((ncp_off64_t)size->ds[j].FATBlockSize) * 512ULL);
break;
}
}
}
printf("\n");
}
if (size)
free(size);
}
free(logical);
}
static void dumpit(NWCONN_HANDLE conn, const struct nw_info_struct3* info) {
NWCCODE err;
struct NSI_Attributes attr;
struct NSI_Name name;
struct NSI_Directory dir;
err = ncp_ns_extract_info_field(info, NSIF_ATTRIBUTES, &attr, sizeof(attr));
if (err) {
fprintf(stderr, _("Cannot retrieve file attributes: %s\n"),
strnwerror(err));
return;
}
err = ncp_ns_extract_info_field(info, NSIF_DIRECTORY, &dir, sizeof(dir));
if (err) {
fprintf(stderr, _("Cannot retrieve file number: %s\n"),
strnwerror(err));
return;
}
err = ncp_ns_extract_info_field(info, NSIF_NAME, &name, sizeof(name));
if (err) {
fprintf(stderr, _("Cannot retrieve file name: %s\n"),
strnwerror(err));
return;
}
if (attr.Attributes & A_DIRECTORY) {
printf(_("Directory:\n"));
} else {
printf(_("File:\n"));
}
if (opt_v || opt_l) {
err = NWNSEntryInfo2(conn, dir.volNumber, dir.DosDirNum, NW_NS_OS2, &os2.name, &os2.dir);
os2.valid = err==0;
err = NWNSEntryInfo2(conn, dir.volNumber, dir.DosDirNum, NW_NS_MAC, &mac.name, &mac.dir);
mac.valid = err==0;
err = NWNSEntryInfo2(conn, dir.volNumber, dir.DosDirNum, NW_NS_NFS, &nfs.name, &nfs.dir);
nfs.valid = err==0;
} else {
os2.valid = 0;
mac.valid = 0;
nfs.valid = 0;
}
printf(_(" DOS: "));
if (opt_t)
printf(P08X " ", dir.dirEntNum);
printf("%s\n", name.Name);
if (os2.valid) {
printf(_(" OS/2: "));
if (opt_t)
printf(P08X " ", os2.dir.dirEntNum);
printf("%s\n", os2.name.Name);
}
if (nfs.valid) {
printf(_(" NFS: "));
if (opt_t)
printf(P08X " ", nfs.dir.dirEntNum);
printf("%s\n", nfs.name.Name);
}
if (mac.valid) {
printf(_(" MAC: "));
if (opt_t)
printf(P08X " ", mac.dir.dirEntNum);
printf("%s\n", mac.name.Name);
}
printf("\n");
if (opt_v) {
u_int32_t inheritedRightsMask;
printf(_("Rights:\n"));
printf(_(" Inherited: "));
err = ncp_ns_extract_info_field(info, NSIF_RIGHTS,
&inheritedRightsMask, sizeof(inheritedRightsMask));
if (err) {
printf(_("Cannot determine: %s\n"), strnwerror(err));
} else {
nuint32 eff32;
if (opt_t)
printf("(%04X) ", inheritedRightsMask);
printf("[%s]\n", createMask311(inheritedRightsMask));
err = ncp_ns_extract_info_field(info, NSIF_EFFECTIVE_RIGHTS,
&eff32, sizeof(eff32));
if (err) {
nuint16 eff;
err = NWNSGetEffectiveRights(conn,
dir.volNumber, dir.DosDirNum, &eff);
eff32 = eff;
}
printf(_(" Effective: "));
if (err) {
printf(_("Cannot determine: %s\n"), strnwerror(err));
} else {
if (opt_t)
printf("(%04X) ", eff32);
printf("[%s]\n", createMask311(eff32));
}
}
printf("\n");
}
if (opt_l || opt_v) {
u_int32_t ns;
printf(_("Owning namespace: "));
err = ncp_ns_extract_info_field(info, NSIF_OWNING_NAMESPACE,
&ns, sizeof(ns));
if (err) {
printf(_("Cannot determine: %s\n"), strnwerror(err));
} else {
if (opt_t)
printf("(%" P32U ") ", ns);
printf("%s\n", ncp_namespace_to_str(NULL, ns));
}
printf("\n");
}
if (opt_v) {
struct NSI_Modify modify;
struct NSI_Change change;
NWCCODE moderr;
printf(_("Miscellaneous NetWare Information:\n"));
printf(_(" Last update: "));
moderr = ncp_ns_extract_info_field(info, NSIF_MODIFY,
&modify, sizeof(modify));
if (moderr) {
printf(_("Cannot determine: %s\n"), strnwerror(moderr));
} else {
dodatesTimesID(conn, modify.Modify.Time, modify.Modify.Date, modify.Modify.ID);
}
printf(_(" Last archived: "));
err = ncp_ns_extract_info_field(info, NSIF_ARCHIVE,
&change, sizeof(change));
if (err) {
printf(_("Cannot determine: %s\n"), strnwerror(err));
} else {
dodatesTimesID(conn, change.Time, change.Date, change.ID);
}
if (1 || !(attr.Attributes&A_DIRECTORY)) {
printf(_(" Last accessed: "));
if (moderr) {
printf(_("Cannot determine: %s\n"), strnwerror(moderr));
} else {
dodatesTimesID(conn, modify.LastAccess.Time, modify.LastAccess.Date, 0);
}
}
printf(_(" Created/Copied: "));
err = ncp_ns_extract_info_field(info, NSIF_CREATION,
&change, sizeof(change));
if (err) {
printf(_("Cannot determine: %s\n"), strnwerror(err));
} else {
dodatesTimesID(conn, change.Time, change.Date, change.ID);
}
printf(_(" Flags: [%s%s%s%s]"),
(attr.Attributes&A_READ_ONLY )?"Ro":"Rw",
(attr.Attributes&A_SYSTEM )?"Sy":"--",
(attr.Attributes&A_HIDDEN )?"H" :"-",
(attr.Attributes&A_NEEDS_ARCHIVED)?"A" :"-");
printf(" [%s%s%s%s" "%s%s%s" "%s" "%s%s%s%s%s]",
(attr.Attributes&A_EXECUTE_ONLY )?"X" :"-",
(attr.Attributes&A_TRANSACTIONAL )?"T" :"-",
(attr.Attributes&A_IMMEDIATE_PURGE)?"P":"-",
(attr.Attributes&A_SHAREABLE )?"Sh":"--",
(attr.Attributes&A_DELETE_INHIBIT)?"Di":"--",
(attr.Attributes&A_COPY_INHIBIT )?"Ci":"--",
(attr.Attributes&A_RENAME_INHIBIT)?"Ri":"--",
(attr.Attributes&A_DONT_COMPRESS )?"Dc":
(attr.Attributes&A_IMMEDIATE_COMPRESS)?"Ic":"--",
(attr.Attributes&A_DONT_MIGRATE )?"Dm":"--",
(attr.Attributes&A_DONT_SUBALLOCATE)?"Ds":"--",
(attr.Attributes&A_INDEXED )?"I":"--",
(attr.Attributes&A_READ_AUDIT )?"Ra":"--",
(attr.Attributes&A_WRITE_AUDIT )?"Wa":"--");
printf(" [%s%s]",
(attr.Attributes&A_FILE_COMPRESSED)?"Co":
(attr.Attributes&A_CANT_COMPRESS)?"Cc":"--",
(attr.Attributes&A_FILE_MIGRATED )?"M":"-");
if (opt_t)
printf(" " P08X, attr.Attributes);
printf("\n");
if (!(attr.Attributes&A_DIRECTORY)) {
dumpDataSizes(info);
}
printf("\n");
{
nuint32 iter = 0;
int first = 1;
while (1) {
nuint tcount;
nuint i;
TRUSTEE_INFO tstees[40];
tcount = 40;
err = NWNSScanForTrustees(conn, dir.volNumber,
dir.DosDirNum, &iter, &tcount, tstees);
if (err)
break;
for (i=0; i<tcount; i++) {
if (first) {
printf(_("Trustees:\n"));
first = 0;
}
printf(" [%s] ", createMask311(tstees[i].objectRights));
doID(conn, tstees[i].objectID);
printf("\n");
}
}
if (!first)
printf("\n");
}
}
if (opt_e)
eaenum(conn, dir.volNumber, dir.DosDirNum);
if (opt_f) {
u_int16_t iterHandle = 0;
CONN_USING_FILE cf;
CONNS_USING_FILE cfa;
int first = 1;
while (ncp_ns_scan_connections_using_file(conn, dir.volNumber, dir.DosDirNum, 0, &iterHandle, &cf, &cfa) == 0) {
if (cfa.connCount != 0) {
time_t t;
struct ncp_bindery_object o;
if (first) {
printf(_("File Usage:\n"));
printf(_(" Use Count: %5u Open Count: %5u\n"
" Open For Reading Count: %5u Open For Writting Count: %5u\n"
" Deny Read Count: %5u Deny Write Count: %5u\n"
" Locked: %-15s Fork Count: %5u\n"),
cfa.useCount, cfa.openCount, cfa.openForReadCount, cfa.openForWriteCount,
cfa.denyReadCount, cfa.denyWriteCount, cfa.locked ? "exclusive" : "no",
cfa.forkCount);
printf(_(" Connection Count: %10u\n"), cfa.connCount);
first = 0;
}
printf(_(" Connection: %u/%u"), cf.connNumber, cf.taskNumber);
err = ncp_get_stations_logged_info(conn, cf.connNumber, &o, &t);
if (!err) {
printf(_(", "));
doID(conn, o.object_id);
}
printf("\n");
{
static const char* lock_bits[] = {N_("locked"), N_("open shareable"),
N_("logged"), N_("open normal"),
N_("rsvd"), N_("rsvd"),
N_("TTS locked"), N_("TTS")};
static const char* acc_bits[] = {N_("read"), N_("write"),
N_("deny read"), N_("deny write"),
N_("detached"), N_("TTS holding detach"),
N_("TTS holding open"), N_("rsvd")};
char lstr[200];
char accstr[200];
char* l2str;
char* p;
int i;
p = NULL;
for (i = 0; i < 8; i++) {
if (cf.lockType & (1 << i)) {
if (p) {
strcpy(p, ", ");
p = strchr(p, 0);
} else {
p = lstr;
}
strcpy(p, _(lock_bits[i]));
p = strchr(p, 0);
}
}
if (!p) {
strcpy(lstr, _("unlocked"));
}
switch (cf.lockFlag) {
case 0x00: l2str = _("Not locked"); break;
case 0xFE: l2str = _("Locked by a file lock"); break;
case 0xFF: l2str = _("Locked by Begin Share File Set"); break;
default: l2str = _("Unknown lock state"); break;
}
p = NULL;
for (i = 0; i < 8; i++) {
if (cf.accessControl & (1 << i)) {
if (p) {
strcpy(p, ", ");
p = strchr(p, 0);
} else {
p = accstr;
}
strcpy(p, _(acc_bits[i]));
p = strchr(p, 0);
}
}
if (!p) {
strcpy(accstr, _("unlocked"));
}
if (opt_t) {
printf(_(" Lock: (%02X) %s\n"), cf.lockType, lstr);
printf(_(" (%02X) %s\n"), cf.lockFlag, l2str);
printf(_(" Access: (%02X) %s\n"), cf.accessControl, accstr);
} else {
printf(_(" Lock: %s\n"), lstr);
printf(_(" %s\n"), l2str);
printf(_(" Access: %s\n"), accstr);
}
}
}
}
if (!first) {
printf("\n");
}
}
if (opt_p) {
u_int16_t iterHandle = 0;
PHYSICAL_LOCK pl;
PHYSICAL_LOCKS pls;
int first = 1;
while (ncp_ns_scan_physical_locks_by_file(conn, dir.volNumber, dir.DosDirNum, 0, &iterHandle, &pl, &pls) == 0) {
if (pls.numRecords != 0) {
time_t t;
struct ncp_bindery_object o;
if (first) {
printf(_("File Physical Locks:\n"));
first = 0;
}
printf(_(" Connection: %u/%u"), pl.connNumber, pl.taskNumber);
err = ncp_get_stations_logged_info(conn, pl.connNumber, &o, &t);
if (!err) {
printf(_(", "));
doID(conn, o.object_id);
}
printf("\n");
printf(_(" Range: 0x%08LX-0x%08LX\n"), pl.recordStart, pl.recordEnd);
}
}
if (!first) {
printf("\n");
}
}
}
static void listdir(NWCONN_HANDLE conn, nuint32 volume, nuint32 dirent, char* mask) {
NWDIRLIST_HANDLE h;
NWCCODE err;
size_t maskl = strlen(mask);
err = ncp_ns_search_init(conn, NW_NS_DOS, SA_ALL, 1,
volume, dirent, NULL, 0,
0, mask, maskl, img, &h);
if (err) {
fprintf(stderr, _("Unable to begin scandir: 0x%04X\n"), err);
return;
}
while (1) {
struct nw_info_struct3 info;
info.len = 0;
info.data = NULL;
err = ncp_ns_search_next(h, &info, sizeof(info));
if (err) {
if (err != NWE_SERVER_FAILURE) {
/* Non-standard error code */
fprintf(stderr, _("Unexpected error in NextDir: %s\n"), strnwerror(err));
}
break;
}
dumpit(conn, &info);
if (info.data)
free(info.data);
}
ncp_ns_search_end(h);
}
static char volname[17];
static char dirpath[512];
static char fullpath[600];
static struct nw_info_struct2 dosNS2;
static void usage(void) {
fprintf(stderr, _("nwdir [options] [path]\n"
"\n"
" -d List information about directory itself instead\n"
" of directory content\n"
" -l List namespace informations\n"
" -e List extended attributes informations\n"
" -v Verbose listing\n"
" -f List connections using file\n"
" -p List physical locks on file\n"
" -t Technical - show values and their meaning\n"
" -h This help\n"
" path Path to list, may contain wildcards\n"
"\n"
"(c) 1998 Milan Vandrovec for ncpfs-2.0.12.8\n"));
}
static char dwild[200];
static void makewild(char* wildout, const char* wildin) {
unsigned char c;
while ((c=*wildin++)!=0) {
switch (c) {
#ifdef N_PLAT_DOS
case '.':
#endif
case '*':
case '?':*wildout++ = '\377';
#ifdef N_PLAT_DOS
*wildout++ = c | 0x80;
#else
*wildout++ = c;
#endif
break;
case 0xFF:*wildout++ = 0xFF;
default:*wildout++ =c;
break;
}
}
*wildout=0;
}
int main(int argc, char* argv[]) {
NWCCODE err;
NWCONN_HANDLE conn;
char* path;
char* xpath;
char* lst;
const char* dpath;
int wild;
int opt_d = 0;
int i;
u_int16_t nwver;
setlocale(LC_ALL, "");
bindtextdomain(NCPFS_PACKAGE, LOCALEDIR);
textdomain(NCPFS_PACKAGE);
while ((i = getopt(argc, argv, "dltvefph")) != -1) {
switch (i) {
case 'd': opt_d = 1; break;
case 'l': opt_l = 1; break;
case 't': opt_t = 1; break;
case 'v': opt_v = 1; break;
case 'e': opt_e = 1; break;
case 'f': opt_f = 1; break;
case 'p': opt_p = 1; break;
case 'h': usage(); return 123;
}
}
i = optind;
if (i < argc) {
path = argv[i++];
} else {
path = (char*)".";
}
err = NWCallsInit(NULL, NULL);
if (err) {
fprintf(stderr, _("Unable to initialize: 0x%04X\n"), err);
return 123;
}
xpath = path;
lst = xpath;
wild = 0;
for (path=xpath; *path; path++) {
switch (*path) {
#ifdef N_PLAT_DOS
case '\\':
#endif
case '/': lst=path; wild=0; break;
case '?':
case '*': wild=1; break;
default: break;
}
}
if (wild) {
if (lst == xpath) {
makewild(dwild, lst);
dpath = ".";
} else {
makewild(dwild, lst+1);
dpath = xpath;
lst[1] = 0;
}
opt_d = 0;
} else {
dpath = xpath;
strcpy(dwild, "\377*");
}
err = NWParsePath(dpath, NULL, &conn, volname, dirpath);
if (err) {
fprintf(stderr, _("Invalid path: %s\n"), strnwerror(err));
return 123;
}
if (!conn) {
fprintf(stderr, _("Specified path is not remote\n"));
return 123;
}
xpath = dirpath;
for (path=xpath; *path; path++) {
*path = toupper(*path);
}
if (*volname) {
sprintf(fullpath, "%s:%s", volname, dirpath);
} else {
strcpy(fullpath, dirpath);
}
printf(_("Directory %s\n"), fullpath);
err = ncp_ns_obtain_entry_info(conn, NW_NS_DOS, SA_ALL, NCP_DIRSTYLE_NOHANDLE, 0, 0,
fullpath, NCP_PATH_STD, NW_NS_DOS, RIM_ATTRIBUTES | RIM_DIRECTORY,
&dosNS2, sizeof(dosNS2));
if (err) {
fprintf(stderr, _("Path does not exist: %s\n"), strnwerror(err));
return 123;
}
img = RIM_NAME | RIM_ATTRIBUTES | RIM_DIRECTORY;
if (opt_l) {
img |= RIM_OWNING_NAMESPACE;
}
if (opt_v) {
img |= RIM_SPACE_ALLOCATED | RIM_DATA_SIZE |
RIM_ARCHIVE | RIM_MODIFY | RIM_CREATION |
RIM_OWNING_NAMESPACE | RIM_RIGHTS;
}
err = NWGetFileServerVersion(conn, &nwver);
if (err) {
nwver = 0;
}
if (nwver >= 0x400) {
img |= RIM_COMPRESSED_INFO;
if (opt_v) {
img |= RIM_DATASTREAM_SIZES | RIM_DATASTREAM_LOGICALS;
}
}
if (nwver >= 0x40B) {
if (opt_v) {
img |= RIM_MAC_FINDER_INFO | RIM_EFFECTIVE_RIGHTS |
RIM_MAC_TIMES;
}
}
if (nwver >= 0x500) {
if (opt_v) {
img |= RIM_LAST_ACCESS_TIME;
}
}
if ((dosNS2.Attributes.Attributes & A_DIRECTORY) && !opt_d) {
listdir(conn, dosNS2.Directory.volNumber, dosNS2.Directory.DosDirNum, dwild);
} else {
struct nw_info_struct3 info;
info.len = 0;
info.data = NULL;
err = ncp_ns_obtain_entry_info(conn, NW_NS_DOS, SA_ALL,
1, dosNS2.Directory.volNumber, dosNS2.Directory.DosDirNum,
NULL, 0,
NW_NS_DOS,
IM_ALL,
&info, sizeof(info));
if (err) {
fprintf(stderr, _("Cannot retrieve info: %s\n"), strnwerror(err));
} else {
dumpit(conn, &info);
free(info.data);
}
}
return 0;
}