flag
This commit is contained in:
343
flag.c
343
flag.c
@@ -4,35 +4,54 @@
|
||||
#include <dos.h>
|
||||
|
||||
/*
|
||||
* NetWare old file-info attributes.
|
||||
* NCP 23/15 returns FileAttributes byte and ExtendedFileAttributes byte.
|
||||
* NCP 23/16 writes them back while preserving the rest of the scanned info.
|
||||
* FLAG v4b: NCP 87 namespace DOS info.
|
||||
*
|
||||
* This gives us real NetWare flags for:
|
||||
* S Shareable byte0 bit7
|
||||
* T Transactional byte1 bit4
|
||||
* RA Read Audit byte1 bit6
|
||||
* WA Write Audit byte1 bit7
|
||||
* ncpfs reference:
|
||||
* ncp_ns_modify_entry_dos_info():
|
||||
* subfunction 7, namespace DOS, search attrs SA_ALL,
|
||||
* ModifyInformationMask, struct ncp_dos_info, handle/path.
|
||||
*
|
||||
* Full 386 byte2 flags P/CI/DI/RI need NCP 87/35 later.
|
||||
* We use dirstyle=0 (short directory handle) against the current DOS
|
||||
* directory handle and a one-component DOS filename.
|
||||
*/
|
||||
#define NWFA_RO 0x0001UL
|
||||
#define NWFA_H 0x0002UL
|
||||
#define NWFA_SY 0x0004UL
|
||||
#define NWFA_A 0x0020UL
|
||||
#define NWFA_S 0x0080UL
|
||||
#define NWFA_T 0x1000UL
|
||||
#define NWFA_RA 0x4000UL
|
||||
#define NWFA_WA 0x8000UL
|
||||
#define FLAG_NW_NS_DOS 0x00
|
||||
#define FLAG_SA_ALL 0x0006
|
||||
#define FLAG_RIM_ATTRIBUTES 0x00000004UL
|
||||
|
||||
typedef struct {
|
||||
uint16 next_index;
|
||||
char name[15];
|
||||
uint8 attr;
|
||||
uint8 extattr;
|
||||
uint8 raw[76]; /* file size + dates + owner + archive + reserved */
|
||||
} FLAG_NWINFO;
|
||||
#define NWFA_RO 0x00000001UL
|
||||
#define NWFA_H 0x00000002UL
|
||||
#define NWFA_SY 0x00000004UL
|
||||
#define NWFA_A 0x00000020UL
|
||||
#define NWFA_S 0x00000080UL
|
||||
#define NWFA_T 0x00001000UL
|
||||
#define NWFA_RA 0x00004000UL
|
||||
#define NWFA_WA 0x00008000UL
|
||||
#define NWFA_P 0x00010000UL
|
||||
#define NWFA_RI 0x00020000UL
|
||||
#define NWFA_DI 0x00040000UL
|
||||
#define NWFA_CI 0x00080000UL
|
||||
|
||||
static void flag_put_word_lh(uint8 *p, uint16 v)
|
||||
{
|
||||
p[0] = (uint8)(v & 0xff);
|
||||
p[1] = (uint8)((v >> 8) & 0xff);
|
||||
}
|
||||
|
||||
static void flag_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 flag_get_dword_lh(uint8 *p)
|
||||
{
|
||||
return((uint32)p[0] |
|
||||
((uint32)p[1] << 8) |
|
||||
((uint32)p[2] << 16) |
|
||||
((uint32)p[3] << 24));
|
||||
}
|
||||
|
||||
static int flag_get_current_drive(void)
|
||||
{
|
||||
@@ -50,137 +69,134 @@ static int flag_current_dhandle(uint8 *dhandle)
|
||||
uint8 flags = 0;
|
||||
int drive;
|
||||
|
||||
drive = flag_get_current_drive(); /* 0=A */
|
||||
drive = flag_get_current_drive();
|
||||
if (get_drive_info((uint8)drive, &connid, dhandle, &flags))
|
||||
return(-1);
|
||||
|
||||
if (!connid || (flags & 0x80))
|
||||
return(-1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int flag_ncp23_scan(uint8 dhandle, char *name, FLAG_NWINFO *info)
|
||||
static int flag_add_handle_path(uint8 *p, uint8 dhandle, char *name)
|
||||
{
|
||||
int nlen;
|
||||
|
||||
nlen = strlen(name);
|
||||
if (nlen > 255) nlen = 255;
|
||||
|
||||
/*
|
||||
* handle/path:
|
||||
* volume/handle byte
|
||||
* dir base dword
|
||||
* dirstyle byte (0 = short dir handle)
|
||||
* path components: 1 component, length, bytes
|
||||
*/
|
||||
*p++ = dhandle;
|
||||
flag_put_dword_lh(p, 0L); p += 4;
|
||||
*p++ = 0; /* dirstyle = handle */
|
||||
*p++ = 1; /* one path component */
|
||||
*p++ = (uint8)nlen;
|
||||
memcpy(p, name, nlen);
|
||||
p += nlen;
|
||||
|
||||
return(1 + 4 + 1 + 1 + 1 + nlen);
|
||||
}
|
||||
|
||||
static int flag_ncp87_obtain_attrs(char *name, uint32 *attrs)
|
||||
{
|
||||
struct {
|
||||
uint16 len;
|
||||
uint8 func;
|
||||
uint8 last[2];
|
||||
uint8 dhandle;
|
||||
uint8 searchattr;
|
||||
uint8 namelen;
|
||||
uint8 name[255];
|
||||
uint8 data[320];
|
||||
} req;
|
||||
struct {
|
||||
uint16 len;
|
||||
uint8 next[2];
|
||||
uint8 fname[14];
|
||||
uint8 attr;
|
||||
uint8 extattr;
|
||||
uint8 raw[76];
|
||||
uint8 data[128];
|
||||
} repl;
|
||||
int nlen;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
memset(&repl, 0, sizeof(repl));
|
||||
|
||||
nlen = strlen(name); if (nlen > 255) nlen = 255;
|
||||
req.func = 0x0f;
|
||||
req.last[0] = 0xff;
|
||||
req.last[1] = 0xff;
|
||||
req.dhandle = dhandle;
|
||||
req.searchattr = 0x06; /* include hidden/system */
|
||||
req.namelen = (uint8)nlen;
|
||||
memcpy(req.name, name, nlen);
|
||||
req.len = 6 + nlen;
|
||||
|
||||
repl.len = sizeof(repl) - sizeof(uint16);
|
||||
|
||||
neterrno = Net_Call(0xE300, &req, &repl);
|
||||
if (neterrno) return(-1);
|
||||
|
||||
if (info) {
|
||||
info->next_index = GET_16(repl.next);
|
||||
memcpy(info->name, repl.fname, 14);
|
||||
info->name[14] = '\0';
|
||||
info->attr = repl.attr;
|
||||
info->extattr = repl.extattr;
|
||||
memcpy(info->raw, repl.raw, sizeof(info->raw));
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int flag_ncp23_set(uint8 dhandle, char *name, FLAG_NWINFO *info, uint32 attrs)
|
||||
{
|
||||
struct {
|
||||
uint16 len;
|
||||
uint8 func;
|
||||
uint8 attr;
|
||||
uint8 extattr;
|
||||
uint8 raw[76];
|
||||
uint8 dhandle;
|
||||
uint8 searchattr;
|
||||
uint8 namelen;
|
||||
uint8 name[255];
|
||||
} req;
|
||||
struct {
|
||||
uint16 len;
|
||||
} repl;
|
||||
int nlen;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
memset(&repl, 0, sizeof(repl));
|
||||
|
||||
nlen = strlen(name); if (nlen > 255) nlen = 255;
|
||||
|
||||
req.func = 0x10;
|
||||
req.attr = (uint8)(attrs & 0xff);
|
||||
req.extattr = (uint8)((attrs >> 8) & 0xff);
|
||||
memcpy(req.raw, info->raw, sizeof(req.raw));
|
||||
req.dhandle = dhandle;
|
||||
req.searchattr = 0x06;
|
||||
req.namelen = (uint8)nlen;
|
||||
memcpy(req.name, name, nlen);
|
||||
req.len = 82 + nlen;
|
||||
|
||||
repl.len = 0;
|
||||
|
||||
neterrno = Net_Call(0xE300, &req, &repl);
|
||||
if (neterrno) return(-1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int flag_get_nw_attrs(char *name, uint32 *attrs, FLAG_NWINFO *info)
|
||||
{
|
||||
uint8 dhandle = 0;
|
||||
FLAG_NWINFO local;
|
||||
uint8 *p;
|
||||
int hlen;
|
||||
|
||||
if (flag_current_dhandle(&dhandle))
|
||||
return(-1);
|
||||
|
||||
if (!info) info = &local;
|
||||
memset(&req, 0, sizeof(req));
|
||||
memset(&repl, 0, sizeof(repl));
|
||||
|
||||
if (flag_ncp23_scan(dhandle, name, info))
|
||||
p = req.data;
|
||||
*p++ = 6; /* subfunction: obtain file/subdir info */
|
||||
*p++ = FLAG_NW_NS_DOS; /* source namespace */
|
||||
*p++ = FLAG_NW_NS_DOS; /* target namespace */
|
||||
flag_put_word_lh(p, FLAG_SA_ALL); p += 2;
|
||||
flag_put_dword_lh(p, FLAG_RIM_ATTRIBUTES); p += 4;
|
||||
hlen = flag_add_handle_path(p, dhandle, name);
|
||||
p += hlen;
|
||||
|
||||
req.len = (uint16)(p - req.data);
|
||||
repl.len = sizeof(repl.data);
|
||||
|
||||
neterrno = Net_Call(0x5700, &req, &repl);
|
||||
if (neterrno)
|
||||
return(-1);
|
||||
|
||||
/*
|
||||
* With RIM_ATTRIBUTES only, ncpfs expects NSI_Attributes first.
|
||||
* First dword is the 32-bit Attributes field.
|
||||
*/
|
||||
if (attrs)
|
||||
*attrs = ((uint32)info->attr) | (((uint32)info->extattr) << 8);
|
||||
*attrs = flag_get_dword_lh(repl.data);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int flag_set_nw_attrs(char *name, uint32 attrs)
|
||||
static int flag_ncp87_modify_attrs(char *name, uint32 attrs)
|
||||
{
|
||||
struct {
|
||||
uint16 len;
|
||||
uint8 data[384];
|
||||
} req;
|
||||
struct {
|
||||
uint16 len;
|
||||
uint8 data[8];
|
||||
} repl;
|
||||
uint8 dhandle = 0;
|
||||
FLAG_NWINFO info;
|
||||
uint8 *p;
|
||||
int hlen;
|
||||
|
||||
if (flag_current_dhandle(&dhandle))
|
||||
return(-1);
|
||||
|
||||
if (flag_ncp23_scan(dhandle, name, &info))
|
||||
memset(&req, 0, sizeof(req));
|
||||
memset(&repl, 0, sizeof(repl));
|
||||
|
||||
p = req.data;
|
||||
*p++ = 7; /* subfunction: modify DOS info */
|
||||
*p++ = FLAG_NW_NS_DOS;
|
||||
*p++ = 0; /* reserved */
|
||||
flag_put_word_lh(p, FLAG_SA_ALL); p += 2;
|
||||
|
||||
flag_put_dword_lh(p, FLAG_RIM_ATTRIBUTES); p += 4; /* modify mask */
|
||||
flag_put_dword_lh(p, attrs); p += 4; /* Attributes */
|
||||
|
||||
/*
|
||||
* Remaining ncp_dos_info fields. Mask says only Attributes is valid,
|
||||
* so these should be ignored, but ncpfs still sends the full structure.
|
||||
*/
|
||||
memset(p, 0, 34);
|
||||
p += 34;
|
||||
|
||||
hlen = flag_add_handle_path(p, dhandle, name);
|
||||
p += hlen;
|
||||
|
||||
req.len = (uint16)(p - req.data);
|
||||
repl.len = sizeof(repl.data);
|
||||
|
||||
neterrno = Net_Call(0x5700, &req, &repl);
|
||||
if (neterrno)
|
||||
return(-1);
|
||||
|
||||
return(flag_ncp23_set(dhandle, name, &info, attrs));
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -258,45 +274,53 @@ static int flag_attr_mask(char *s, unsigned *setbits, unsigned *clearbits)
|
||||
|
||||
if (flag_same(p, "RO")) {
|
||||
if (set) {
|
||||
*setbits |= NWFA_RO;
|
||||
/*
|
||||
* Novell FLAG also shows DI/RI for +RO on real NetWare.
|
||||
* Those are byte2 flags and need NCP87/35 later.
|
||||
*/
|
||||
} else *clearbits |= NWFA_RO;
|
||||
*setbits |= (unsigned)(NWFA_RO | NWFA_DI | NWFA_RI);
|
||||
} else {
|
||||
*clearbits |= (unsigned)(NWFA_RO | NWFA_DI | NWFA_RI);
|
||||
}
|
||||
} else if (flag_same(p, "RW")) {
|
||||
*clearbits |= NWFA_RO;
|
||||
*clearbits |= (unsigned)(NWFA_RO | NWFA_DI | NWFA_RI);
|
||||
} else if (flag_same(p, "S")) {
|
||||
if (set) *setbits |= NWFA_S;
|
||||
else *clearbits |= NWFA_S;
|
||||
if (set) *setbits |= (unsigned)NWFA_S;
|
||||
else *clearbits |= (unsigned)NWFA_S;
|
||||
} else if (flag_same(p, "H")) {
|
||||
if (set) *setbits |= NWFA_H;
|
||||
else *clearbits |= NWFA_H;
|
||||
if (set) *setbits |= (unsigned)NWFA_H;
|
||||
else *clearbits |= (unsigned)NWFA_H;
|
||||
} else if (flag_same(p, "SY") || flag_same(p, "SYS") || flag_same(p, "SYSTEM")) {
|
||||
if (set) *setbits |= NWFA_SY;
|
||||
else *clearbits |= NWFA_SY;
|
||||
if (set) *setbits |= (unsigned)NWFA_SY;
|
||||
else *clearbits |= (unsigned)NWFA_SY;
|
||||
} else if (flag_same(p, "T")) {
|
||||
if (set) *setbits |= NWFA_T;
|
||||
else *clearbits |= NWFA_T;
|
||||
if (set) *setbits |= (unsigned)NWFA_T;
|
||||
else *clearbits |= (unsigned)NWFA_T;
|
||||
} else if (flag_same(p, "P")) {
|
||||
if (set) *setbits |= (unsigned)NWFA_P;
|
||||
else *clearbits |= (unsigned)NWFA_P;
|
||||
} else if (flag_same(p, "A")) {
|
||||
if (set) *setbits |= NWFA_A;
|
||||
else *clearbits |= NWFA_A;
|
||||
if (set) *setbits |= (unsigned)NWFA_A;
|
||||
else *clearbits |= (unsigned)NWFA_A;
|
||||
} else if (flag_same(p, "RA")) {
|
||||
if (set) *setbits |= NWFA_RA;
|
||||
else *clearbits |= NWFA_RA;
|
||||
if (set) *setbits |= (unsigned)NWFA_RA;
|
||||
else *clearbits |= (unsigned)NWFA_RA;
|
||||
} else if (flag_same(p, "WA")) {
|
||||
if (set) *setbits |= NWFA_WA;
|
||||
else *clearbits |= NWFA_WA;
|
||||
if (set) *setbits |= (unsigned)NWFA_WA;
|
||||
else *clearbits |= (unsigned)NWFA_WA;
|
||||
} else if (flag_same(p, "CI")) {
|
||||
if (set) *setbits |= (unsigned)NWFA_CI;
|
||||
else *clearbits |= (unsigned)NWFA_CI;
|
||||
} else if (flag_same(p, "DI")) {
|
||||
if (set) *setbits |= (unsigned)NWFA_DI;
|
||||
else *clearbits |= (unsigned)NWFA_DI;
|
||||
} else if (flag_same(p, "RI")) {
|
||||
if (set) *setbits |= (unsigned)NWFA_RI;
|
||||
else *clearbits |= (unsigned)NWFA_RI;
|
||||
} else if (flag_same(p, "N") || flag_same(p, "NORMAL")) {
|
||||
*clearbits |= (NWFA_RO | NWFA_H | NWFA_SY | NWFA_A |
|
||||
NWFA_S | NWFA_T | NWFA_RA | NWFA_WA);
|
||||
*clearbits |= (unsigned)(NWFA_RO | NWFA_H | NWFA_SY | NWFA_A |
|
||||
NWFA_S | NWFA_T | NWFA_P |
|
||||
NWFA_RA | NWFA_WA | NWFA_CI | NWFA_DI | NWFA_RI);
|
||||
} else if (flag_same(p, "ALL")) {
|
||||
*setbits |= (NWFA_RO | NWFA_H | NWFA_SY | NWFA_A |
|
||||
NWFA_S | NWFA_T | NWFA_RA | NWFA_WA);
|
||||
} else if (flag_same(p, "P") || flag_same(p, "CI") ||
|
||||
flag_same(p, "DI") || flag_same(p, "RI")) {
|
||||
fprintf(stderr, "Attribute not supported on this version of NetWare\n");
|
||||
return(1);
|
||||
*setbits |= (unsigned)(NWFA_RO | NWFA_H | NWFA_SY | NWFA_A |
|
||||
NWFA_S | NWFA_T | NWFA_P |
|
||||
NWFA_RA | NWFA_WA | NWFA_CI | NWFA_DI | NWFA_RI);
|
||||
} else {
|
||||
fprintf(stderr, "Unknown attribute encountered in command line.\n");
|
||||
return(-1);
|
||||
@@ -318,12 +342,12 @@ static void flag_print_attrs(unsigned attr)
|
||||
fprintf(stdout, "%c ", (attr & NWFA_H) ? 'H' : '-');
|
||||
fprintf(stdout, "%s ", (attr & NWFA_SY) ? "Sy" : "-");
|
||||
fprintf(stdout, "%c ", (attr & NWFA_T) ? 'T' : '-');
|
||||
fprintf(stdout, "-- "); /* P needs NCP87 */
|
||||
fprintf(stdout, "%c ", (attr & NWFA_P) ? 'P' : '-');
|
||||
fprintf(stdout, "%s ", (attr & NWFA_RA) ? "Ra" : "--");
|
||||
fprintf(stdout, "%s ", (attr & NWFA_WA) ? "Wa" : "--");
|
||||
fprintf(stdout, "-- "); /* CI needs NCP87 */
|
||||
fprintf(stdout, "-- "); /* DI needs NCP87 */
|
||||
fprintf(stdout, "-- "); /* RI needs NCP87 */
|
||||
fprintf(stdout, "%s ", (attr & NWFA_CI) ? "CI" : "--");
|
||||
fprintf(stdout, "%s ", (attr & NWFA_DI) ? "DI" : "--");
|
||||
fprintf(stdout, "%s ", (attr & NWFA_RI) ? "RI" : "--");
|
||||
fprintf(stdout, "]");
|
||||
}
|
||||
|
||||
@@ -356,7 +380,7 @@ static int flag_list(char *pattern)
|
||||
if (!(ff.attrib & _A_SUBDIR)) {
|
||||
uint32 nwattrs;
|
||||
|
||||
if (flag_get_nw_attrs(ff.name, &nwattrs, NULL))
|
||||
if (flag_ncp87_obtain_attrs(ff.name, &nwattrs))
|
||||
nwattrs = (uint32)ff.attrib;
|
||||
|
||||
flag_display_one(ff.name, (unsigned)nwattrs);
|
||||
@@ -385,16 +409,13 @@ static int flag_apply(char *pattern, unsigned setbits, unsigned clearbits)
|
||||
|
||||
strmaxcpy(fname, ff.name, sizeof(fname) - 1);
|
||||
|
||||
if (flag_get_nw_attrs(fname, &attrs, NULL))
|
||||
if (flag_ncp87_obtain_attrs(fname, &attrs))
|
||||
attrs = (uint32)ff.attrib;
|
||||
|
||||
newattrs = (attrs | setbits) & ~clearbits;
|
||||
newattrs = (attrs | (uint32)setbits) & ~((uint32)clearbits);
|
||||
|
||||
if (newattrs != attrs) {
|
||||
if (flag_set_nw_attrs(fname, newattrs)) {
|
||||
/*
|
||||
* Fallback for local/DOS-visible bits. This keeps old behavior alive.
|
||||
*/
|
||||
if (flag_ncp87_modify_attrs(fname, newattrs)) {
|
||||
unsigned dosattr = (unsigned)(newattrs & (_A_RDONLY|_A_HIDDEN|_A_SYSTEM|_A_ARCH));
|
||||
if (_dos_setfileattr(fname, dosattr)) {
|
||||
fprintf(stderr, "You don't have rights to change : %s\n", fname);
|
||||
@@ -403,7 +424,7 @@ static int flag_apply(char *pattern, unsigned setbits, unsigned clearbits)
|
||||
}
|
||||
}
|
||||
|
||||
if (flag_get_nw_attrs(fname, &attrs, NULL))
|
||||
if (flag_ncp87_obtain_attrs(fname, &attrs))
|
||||
attrs = newattrs;
|
||||
|
||||
flag_display_one(fname, (unsigned)attrs);
|
||||
|
||||
Reference in New Issue
Block a user