Move the common NCP22 DOS name buffer helper into tools.c and declare it in net.h. Replace the local copy/uppercase implementations in CREATOR, FLAG, FLAGDIR, NDIR and NWTESTS with tool_copy_ncp22_name(). The helper keeps the existing behavior: uppercase conversion, path separator rejection and the 1..12 byte DOS name length limit. NCOPY is intentionally left untouched while its NCP copy path remains under investigation.
691 lines
17 KiB
C
691 lines
17 KiB
C
/*
|
|
* mars-nwe-dosutils - NetWare/DOS utility tools.
|
|
*
|
|
* Copyright (C) 2026 Mario Fetka
|
|
*
|
|
* 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, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/*
|
|
* Purpose: FLAG utility for displaying and changing NetWare DOS file attributes.
|
|
* Depends on: net.h, c32ncp.h, netcall.c requester helpers, c32ncp.c namespace/NCP helpers, tools.c shared utility routines.
|
|
*/
|
|
/* flag.c - Novell FLAG-like DOS utility, stage 1 */
|
|
|
|
#include "net.h"
|
|
#include "c32ncp.h"
|
|
#include <dos.h>
|
|
|
|
/*
|
|
* FLAG v4b: NCP 87 namespace DOS info.
|
|
*
|
|
* ncpfs reference:
|
|
* ncp_ns_modify_entry_dos_info():
|
|
* subfunction 7, namespace DOS, search attrs SA_ALL,
|
|
* ModifyInformationMask, struct ncp_dos_info, handle/path.
|
|
*
|
|
* We use dirstyle=0 (short directory handle) against the current DOS
|
|
* directory handle and a one-component DOS filename.
|
|
*/
|
|
#define FLAG_NW_NS_DOS 0x00
|
|
#define FLAG_SA_ALL 0x0006
|
|
#define FLAG_RIM_ATTRIBUTES 0x00000004UL
|
|
#define FLAG_DM_ATTRIBUTES 0x00000002UL
|
|
|
|
#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 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;
|
|
tool_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 data[320];
|
|
} req;
|
|
struct {
|
|
uint16 len;
|
|
uint8 data[128];
|
|
} repl;
|
|
uint8 connid = 0;
|
|
uint8 dhandle = 0;
|
|
uint8 *p;
|
|
int hlen;
|
|
|
|
if (tool_current_dhandle(&connid, &dhandle))
|
|
return(-1);
|
|
|
|
/*
|
|
* Prefer the verified Client32 NCP87 path. If it is not available,
|
|
* fall back to the historical INT 21h/Net_Call path below.
|
|
*/
|
|
if (c32_ncp87_obtain_rim_attributes(name, (uint16)dhandle,
|
|
attrs, NULL, NULL, NULL) == 0)
|
|
return(0);
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
memset(&repl, 0, sizeof(repl));
|
|
|
|
p = req.data;
|
|
*p++ = 6; /* subfunction: obtain file/subdir info */
|
|
*p++ = FLAG_NW_NS_DOS; /* source namespace */
|
|
*p++ = FLAG_NW_NS_DOS; /* target namespace */
|
|
tool_put_word_lh(p, FLAG_SA_ALL); p += 2;
|
|
tool_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(0xF257, &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 = tool_get_dword_lh(repl.data);
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
static int flag_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 (tool_copy_ncp22_name(req.name, name, &namlen))
|
|
return(-1);
|
|
|
|
req.func = 0x1e; /* Scan directory */
|
|
req.dirhandle = dhandle;
|
|
req.search_attributes = 0x06; /* hidden/system */
|
|
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:
|
|
* dword searchsequence
|
|
* dword subdir
|
|
* dword attributes
|
|
* ...
|
|
*/
|
|
if (attrs)
|
|
*attrs = tool_get_dword_lh(repl.data + 8);
|
|
|
|
return(0);
|
|
}
|
|
|
|
static int flag_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 = 0x06; /* hidden/system */
|
|
U32_TO_BE32(0xffffffffUL, req.searchsequence);
|
|
U32_TO_32(FLAG_DM_ATTRIBUTES, req.change_bits);
|
|
U32_TO_32(attrs, req.attributes);
|
|
|
|
if (tool_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 int flag_obtain_attrs(char *name, uint32 *attrs)
|
|
{
|
|
if (!flag_ncp22_1e_obtain_attrs(name, attrs))
|
|
return(0);
|
|
|
|
return(flag_ncp87_obtain_attrs(name, 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 connid = 0;
|
|
uint8 dhandle = 0;
|
|
uint8 *p;
|
|
int hlen;
|
|
|
|
if (tool_current_dhandle(&connid, &dhandle))
|
|
return(-1);
|
|
|
|
/*
|
|
* Prefer verified Client32 modify path. The old INT 21h/F257 modify path
|
|
* can hang under DOS Client32 for high FLAG bits such as T/P/DI/RI.
|
|
*/
|
|
{
|
|
uint16 actual = 0;
|
|
uint16 hlo = 0;
|
|
uint16 hhi = 0;
|
|
if (!c32_ncp87_modify_dos_attributes(name, (uint16)dhandle, attrs,
|
|
&actual, &hlo, &hhi))
|
|
return(0);
|
|
}
|
|
|
|
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 */
|
|
tool_put_word_lh(p, FLAG_SA_ALL); p += 2;
|
|
|
|
tool_put_dword_lh(p, FLAG_DM_ATTRIBUTES); p += 4; /* modify mask: DM_ATTRIBUTES */
|
|
tool_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(0xF257, &req, &repl);
|
|
if (neterrno)
|
|
return(-1);
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
#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
|
|
|
|
static void flag_help(void)
|
|
{
|
|
fprintf(stdout, "USAGE: FLAG [path [ option | [+|-] attribute(s) ] [SUB]]\n");
|
|
fprintf(stdout, "\n");
|
|
fprintf(stdout, "386 Attributes:\n");
|
|
fprintf(stdout, "--------------\n");
|
|
fprintf(stdout, "\n");
|
|
fprintf(stdout, "RO Read Only\n");
|
|
fprintf(stdout, "RW Read Write\n");
|
|
fprintf(stdout, "S Sharable\n");
|
|
fprintf(stdout, "H Hidden\n");
|
|
fprintf(stdout, "Sy System\n");
|
|
fprintf(stdout, "T Transactional\n");
|
|
fprintf(stdout, "P Purge\n");
|
|
fprintf(stdout, "A Archive Needed\n");
|
|
fprintf(stdout, "RA Read Audit\n");
|
|
fprintf(stdout, "WA Write Audit\n");
|
|
fprintf(stdout, "CI Copy Inhibit\n");
|
|
fprintf(stdout, "DI Delete Inhibit\n");
|
|
fprintf(stdout, "RI Rename Inhibit\n");
|
|
fprintf(stdout, "\n");
|
|
fprintf(stdout, "All All\n");
|
|
fprintf(stdout, "N Normal\n");
|
|
fprintf(stdout, "SUB\n");
|
|
}
|
|
|
|
static int flag_attr_mask(char *s, uint32 *setbits, uint32 *clearbits)
|
|
{
|
|
int set = 1;
|
|
char *p = s;
|
|
|
|
if (*p == '+') {
|
|
set = 1;
|
|
p++;
|
|
} else if (*p == '-') {
|
|
set = 0;
|
|
p++;
|
|
}
|
|
|
|
if (!*p) return(-1);
|
|
|
|
if (tool_strsame(p, "RO")) {
|
|
if (set) {
|
|
*setbits |= (NWFA_RO | NWFA_DI | NWFA_RI);
|
|
} else {
|
|
*clearbits |= (NWFA_RO | NWFA_DI | NWFA_RI);
|
|
}
|
|
} else if (tool_strsame(p, "RW")) {
|
|
*clearbits |= (NWFA_RO | NWFA_DI | NWFA_RI);
|
|
} else if (tool_strsame(p, "S")) {
|
|
if (set) *setbits |= NWFA_S;
|
|
else *clearbits |= NWFA_S;
|
|
} else if (tool_strsame(p, "H")) {
|
|
if (set) *setbits |= NWFA_H;
|
|
else *clearbits |= NWFA_H;
|
|
} else if (tool_strsame(p, "SY") || tool_strsame(p, "SYS") || tool_strsame(p, "SYSTEM")) {
|
|
if (set) *setbits |= NWFA_SY;
|
|
else *clearbits |= NWFA_SY;
|
|
} else if (tool_strsame(p, "T")) {
|
|
if (set) *setbits |= NWFA_T;
|
|
else *clearbits |= NWFA_T;
|
|
} else if (tool_strsame(p, "P")) {
|
|
if (set) *setbits |= NWFA_P;
|
|
else *clearbits |= NWFA_P;
|
|
} else if (tool_strsame(p, "A")) {
|
|
if (set) *setbits |= NWFA_A;
|
|
else *clearbits |= NWFA_A;
|
|
} else if (tool_strsame(p, "RA")) {
|
|
if (set) *setbits |= NWFA_RA;
|
|
else *clearbits |= NWFA_RA;
|
|
} else if (tool_strsame(p, "WA")) {
|
|
if (set) *setbits |= NWFA_WA;
|
|
else *clearbits |= NWFA_WA;
|
|
} else if (tool_strsame(p, "CI")) {
|
|
if (set) *setbits |= NWFA_CI;
|
|
else *clearbits |= NWFA_CI;
|
|
} else if (tool_strsame(p, "DI")) {
|
|
if (set) *setbits |= NWFA_DI;
|
|
else *clearbits |= NWFA_DI;
|
|
} else if (tool_strsame(p, "RI")) {
|
|
if (set) *setbits |= NWFA_RI;
|
|
else *clearbits |= NWFA_RI;
|
|
} else if (tool_strsame(p, "N") || tool_strsame(p, "NORMAL")) {
|
|
*clearbits |= (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 (tool_strsame(p, "ALL")) {
|
|
*setbits |= (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);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
static void flag_print_attrs(uint32 attr)
|
|
{
|
|
/*
|
|
* Novell order:
|
|
* Ro/Rw S A - H Sy T P Ra Wa CI DI RI
|
|
*/
|
|
fprintf(stdout, "[ ");
|
|
fprintf(stdout, "%s ", (attr & NWFA_RO) ? "Ro" : "Rw");
|
|
fprintf(stdout, "%c ", (attr & NWFA_S) ? 'S' : '-');
|
|
fprintf(stdout, "%c ", (attr & NWFA_A) ? 'A' : '-');
|
|
fprintf(stdout, "- ");
|
|
fprintf(stdout, "%c ", (attr & NWFA_H) ? 'H' : '-');
|
|
fprintf(stdout, "%s ", (attr & NWFA_SY) ? "Sy" : "--");
|
|
fprintf(stdout, "%c ", (attr & NWFA_T) ? 'T' : '-');
|
|
fprintf(stdout, "%c ", (attr & NWFA_P) ? 'P' : '-');
|
|
fprintf(stdout, "%s ", (attr & NWFA_RA) ? "Ra" : "--");
|
|
fprintf(stdout, "%s ", (attr & NWFA_WA) ? "Wa" : "--");
|
|
fprintf(stdout, "%s ", (attr & NWFA_CI) ? "CI" : "--");
|
|
fprintf(stdout, "%s ", (attr & NWFA_DI) ? "DI" : "--");
|
|
fprintf(stdout, "%s ", (attr & NWFA_RI) ? "RI" : "--");
|
|
fprintf(stdout, "]");
|
|
}
|
|
|
|
static void flag_display_one(char *name, uint32 attr)
|
|
{
|
|
fprintf(stdout, " %-23s ", name);
|
|
flag_print_attrs(attr);
|
|
fprintf(stdout, " \n");
|
|
}
|
|
|
|
static void flag_display_one_paged(char *name, uint32 attr,
|
|
int *line_count, int *continuous)
|
|
{
|
|
flag_display_one(name, attr);
|
|
tool_page_line(line_count, continuous);
|
|
}
|
|
|
|
|
|
static char *flag_last_sep(char *s)
|
|
{
|
|
char *last = NULL;
|
|
char *p;
|
|
|
|
for (p = s; *p; p++) {
|
|
if (*p == '\\' || *p == '/' || *p == ':')
|
|
last = p;
|
|
}
|
|
|
|
return(last);
|
|
}
|
|
|
|
static void flag_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 = flag_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);
|
|
|
|
/*
|
|
* Keep drive-root paths as "F:\" rather than "F:".
|
|
*/
|
|
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 flag_enter_parent(char *pattern, char *leaf, int leaf_size,
|
|
char *oldcwd, int oldcwd_size)
|
|
{
|
|
char parent[260];
|
|
|
|
oldcwd[0] = '\0';
|
|
flag_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 flag_leave_parent(char *oldcwd)
|
|
{
|
|
if (oldcwd[0])
|
|
chdir(oldcwd);
|
|
}
|
|
|
|
|
|
static int flag_list(char *pattern)
|
|
{
|
|
struct find_t ff;
|
|
unsigned findattr = _A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_ARCH;
|
|
int found = 0;
|
|
int line_count = 0;
|
|
int continuous = 0;
|
|
|
|
if (_dos_findfirst(pattern, findattr, &ff))
|
|
return(-1);
|
|
|
|
do {
|
|
if (!(ff.attrib & _A_SUBDIR)) {
|
|
uint32 nwattrs;
|
|
|
|
if (flag_obtain_attrs(ff.name, &nwattrs))
|
|
nwattrs = (uint32)ff.attrib;
|
|
|
|
flag_display_one_paged(ff.name, nwattrs, &line_count, &continuous);
|
|
found++;
|
|
}
|
|
} while (!_dos_findnext(&ff));
|
|
|
|
return(found);
|
|
}
|
|
|
|
static int flag_apply(char *pattern, uint32 setbits, uint32 clearbits)
|
|
{
|
|
struct find_t ff;
|
|
unsigned findattr = _A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_ARCH;
|
|
int shown = 0;
|
|
|
|
if (_dos_findfirst(pattern, findattr, &ff))
|
|
return(-1);
|
|
|
|
do {
|
|
uint32 attrs;
|
|
uint32 newattrs;
|
|
char fname[260];
|
|
|
|
if (ff.attrib & _A_SUBDIR) continue;
|
|
|
|
strmaxcpy(fname, ff.name, sizeof(fname) - 1);
|
|
|
|
if (flag_obtain_attrs(fname, &attrs))
|
|
attrs = (uint32)ff.attrib;
|
|
|
|
newattrs = (attrs | (uint32)setbits) & ~((uint32)clearbits);
|
|
|
|
if (newattrs != attrs) {
|
|
if (flag_ncp22_25_modify_attrs(fname, newattrs) &&
|
|
flag_ncp87_modify_attrs(fname, newattrs)) {
|
|
unsigned dosattr = (newattrs & (_A_RDONLY|_A_HIDDEN|_A_SYSTEM|_A_ARCH));
|
|
if (_dos_setfileattr(fname, dosattr)) {
|
|
fprintf(stdout, "You don't have rights to change : %s\n", fname);
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (flag_obtain_attrs(fname, &attrs))
|
|
attrs = newattrs;
|
|
|
|
flag_display_one(fname, newattrs);
|
|
shown++;
|
|
|
|
} while (!_dos_findnext(&ff));
|
|
|
|
return(shown);
|
|
}
|
|
|
|
int func_flag(int argc, char *argv[], int mode)
|
|
{
|
|
char *path = "*.*";
|
|
int i;
|
|
uint32 setbits = 0;
|
|
uint32 clearbits = 0;
|
|
int have_change = 0;
|
|
int rc;
|
|
|
|
(void)mode;
|
|
|
|
if (argc > 1 && (tool_strsame(argv[1], "/?") || tool_strsame(argv[1], "-?") ||
|
|
tool_strsame(argv[1], "?"))) {
|
|
flag_help();
|
|
return(0);
|
|
}
|
|
|
|
if (argc > 1) {
|
|
path = argv[1];
|
|
if (tool_strsame(path, "SUB")) path = "*.*";
|
|
}
|
|
|
|
for (i = 2; i < argc; i++) {
|
|
if (tool_strsame(argv[i], "SUB")) continue;
|
|
|
|
rc = flag_attr_mask(argv[i], &setbits, &clearbits);
|
|
if (rc < 0) return(1);
|
|
if (rc > 0) continue;
|
|
have_change = 1;
|
|
}
|
|
|
|
{
|
|
char leaf[260];
|
|
char oldcwd[260];
|
|
|
|
if (flag_enter_parent(path, leaf, sizeof(leaf), oldcwd, sizeof(oldcwd))) {
|
|
flag_split_pattern(path, oldcwd, sizeof(oldcwd), leaf, sizeof(leaf));
|
|
fprintf(stdout, "Files could not be found with pattern \"%s\"\a", leaf);
|
|
return(1);
|
|
}
|
|
|
|
if (have_change) {
|
|
rc = flag_apply(leaf, setbits, clearbits);
|
|
flag_leave_parent(oldcwd);
|
|
if (rc < 0) {
|
|
fprintf(stdout, "Files could not be found with pattern \"%s\"\a", leaf);
|
|
return(1);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
rc = flag_list(leaf);
|
|
flag_leave_parent(oldcwd);
|
|
if (rc < 0) {
|
|
fprintf(stdout, "Files could not be found with pattern \"%s\"\a", leaf);
|
|
return(1);
|
|
}
|
|
}
|
|
|
|
return(0);
|
|
}
|