nwconn: scan volume user disk restrictions
All checks were successful
Source release / source-package (push) Successful in 49s

Wire NCP 0x16/0x20 Scan Volume's User Disk Restrictions to the existing
quota backend when quota support is available.

The WebSDK documents NCP 0x2222/22/32 as taking a Volume Number and a Sequence
value, and returning a Number Of Entries byte followed by up to twelve Object
ID / Restriction pairs. The Sequence starts at zero and is incremented by the
number of entries returned by previous calls. Restrictions are reported in 4K
blocks.

The SDK headers expose the same call as NWScanVolDiskRestrictions() and
NWScanVolDiskRestrictions2(). The Rust nwserver implementation and lwared both
validate the volume and return an empty list, which is compatible with an
unrestricted server but does not expose configured quotas.

Keep that empty-list behavior for non-quota builds. When QUOTA_SUPPORT is
enabled, scan bindery user objects, map each object through its UNIX_USER
property to a Unix uid, query nw_get_vol_restrictions(), and return entries for
users with an actual finite restriction. Use the request Sequence as an index
into the restricted-entry stream and return at most the SDK maximum of twelve
entries per reply.

Add the SDK request/reply semantics to the inline endpoint comment.

This enables the documented endpoint path while preserving the existing
no-restrictions result for builds without quota support.
This commit is contained in:
Mario Fetka
2026-05-30 00:43:38 +02:00
parent 297bb192f8
commit 98f45194b1

View File

@@ -43,6 +43,7 @@
#include "nwqconn.h"
#include "namspace.h"
#include "nwshare.h"
#include "nwdbm.h"
#include "nwconn.h"
#include "trustee.h"
@@ -77,6 +78,77 @@ static char *prog_title;
static int req_printed=0;
static int scan_volume_user_disk_restrictions(uint8 volnr, uint32 sequence,
uint8 *response)
{
struct XDATA {
uint8 entries;
struct {
uint8 id[4];
uint8 restriction[4];
} entry[12];
} *xdata = (struct XDATA *)response;
int result = nw_get_volume_name(volnr, NULL, 0);
if (result < 0)
return result;
xdata->entries = 0;
#if QUOTA_SUPPORT
{
NETOBJ obj;
uint32 last_obj_id = MAX_U32;
uint32 restricted_index = 0;
uint8 wild[] = "*";
int scan_result;
memset(&obj, 0, sizeof(obj));
obj.type = 1; /* user */
xstrcpy(obj.name, wild);
scan_result = scan_for_obj(&obj, last_obj_id, 1);
while (!scan_result && xdata->entries < 12) {
uint8 more_segments = 0;
uint8 property_flags = 0;
char unix_user[128];
uint32 restriction = 0x40000000;
uint32 inuse = 0;
memset(unix_user, 0, sizeof(unix_user));
if (!nw_get_prop_val_by_obj_id(obj.id, 1,
(uint8 *)"UNIX_USER", 9,
(uint8 *)unix_user, &more_segments, &property_flags)) {
struct passwd *pw;
unix_user[sizeof(unix_user)-1] = '\0';
pw = getpwnam(unix_user);
if (pw && !nw_get_vol_restrictions(volnr, pw->pw_uid,
&restriction, &inuse) &&
restriction < 0x40000000) {
if (restricted_index >= sequence) {
U32_TO_BE32(obj.id, xdata->entry[xdata->entries].id);
U32_TO_BE32(restriction, xdata->entry[xdata->entries].restriction);
xdata->entries++;
}
restricted_index++;
}
}
last_obj_id = obj.id;
memset(&obj, 0, sizeof(obj));
obj.type = 1;
xstrcpy(obj.name, wild);
scan_result = scan_for_obj(&obj, last_obj_id, 1);
}
}
#endif
return 1 + (8 * xdata->entries);
}
static int trustee_v3_to_ncp22_rights(int rights)
{
int ncp22 = 0;
@@ -1215,21 +1287,32 @@ static int handle_ncp_serv(void)
}
break;
case 0x20 : { /* scan volume user disk restrictions */
case 0x20 : { /* Scan Volume's User Disk Restrictions */
/*
* NCP 0x2222/22/32 Scan Volume's User Disk Restrictions.
*
* WebSDK / headers:
* Request: Volume Number, Sequence. Sequence starts at
* zero and is incremented by the number of entries returned
* by previous calls.
* Reply: Number Of Entries followed by up to twelve
* Object ID / Restriction pairs. Restrictions are reported
* in 4K blocks.
*
* The Rust nwserver and lwared implementations both return
* an empty list after validating the volume. MARS-NWE keeps
* that SDK-compatible unrestricted result for non-quota
* builds, and fills entries from the existing Linux quota
* backend when QUOTA_SUPPORT is enabled and a restricted
* bindery user maps to a Unix uid.
*/
uint8 volnr = *(p+1);
/* uint32 sequence = GET_BE32(p+2); */
struct XDATA {
uint8 entries; /* 0x0 */
/*--- per entry (max.entries = 12) ----*/
uint8 id[4];
uint8 restriction[4];
} *xdata = (struct XDATA*) responsedata;
int result = nw_get_volume_name(volnr, NULL, 0);
if (result > -1) {
xdata->entries = 0x0;
data_len = (8 * xdata->entries) + 1;
} else completition = (uint8) (-result);
}
uint32 sequence = GET_BE32(p+2);
int result = scan_volume_user_disk_restrictions(
volnr, sequence, responsedata);
if (result > -1) data_len = result;
else completition = (uint8) (-result);
}
break;
case 0x21 : { /* change Vol restrictions for Obj */