nwconn: route AFP backup timestamps through nwarchive
All checks were successful
Source release / source-package (push) Successful in 48s

Implement the WebSDK AFP Set File Information Backup Date/Time request bitmap as a narrow metadata write that reuses mars_nwe's existing archive metadata helper instead of adding a new AFP-specific storage path.

The AFP Attributes word already maps Archive through the NetWare FILE_ATTR_A path; Backup Date/Time is a separate SetInfo field and belongs in the existing nwarchive.c archive date/time metadata.  Include nwarchive.h in nwconn, fill the AFP information record's Backup Date/Time fields from mars_nwe_get_archive_info(), and accept the SetInfo 0x2000 bitmap by calling mars_nwe_set_archive_info() after the normal AFP path resolution and Modify-rights gate.

Extend the Linux Set File Information smoke helper with --backup-time-epoch/--backup-time-only, verify the returned 120-byte file information record at offsets 28/30, and have afp_smoke_suite.sh dump user.org.mars-nwe.netware.archive so reports prove that the WebSDK field is stored through the NetWare archive metadata path.

Tests: git diff --check; bash -n tests/linux/afp_smoke_suite.sh; gcc -Iinclude -I/mnt/data/stubs -fsyntax-only tests/linux/afp_set_file_info_smoke.c
This commit is contained in:
OpenAI
2026-05-30 16:20:28 +00:00
committed by Mario Fetka
parent 3f3a3ce832
commit bbc37565c8
5 changed files with 135 additions and 12 deletions

View File

@@ -50,6 +50,7 @@
#include "trustee.h"
#include "nwatalk.h"
#include "nwattrib.h"
#include "nwarchive.h"
#include "namedos.h"
int act_pid = 0;
@@ -1114,6 +1115,7 @@ static void afp_leaf_name_from_path(uint8 *dst, int dst_len,
#define AFP_FILE_BITMAP_ATTRIBUTES 0x0100
#define AFP_FILE_BITMAP_MODIFY_DATE 0x1000
#define AFP_FILE_BITMAP_BACKUP_DATE 0x2000
#define AFP_FILE_BITMAP_FINDER_INFO 0x4000
#define AFP_ATTR_HIDDEN 0x0200
#define AFP_ATTR_SYSTEM 0x0400
@@ -1205,8 +1207,18 @@ static int afp_fill_file_info_response(const char *unixname,
un_date_2_nw(stbuff.st_atime, response + 22, 1);
un_date_2_nw(stbuff.st_mtime, response + 24, 1);
un_time_2_nw(stbuff.st_mtime, response + 26, 1);
U16_TO_BE16(0, response + 28); /* Backup Date */
U16_TO_BE16(0, response + 30); /* Backup Time */
{
uint16 archive_date = 0;
uint16 archive_time = 0;
uint8 archive_flags = 0;
mars_nwe_get_archive_info((char *)unixname, &archive_date, &archive_time,
NULL, &archive_flags);
U16_TO_BE16((archive_flags & MARS_NWE_ARCHIVE_HAS_DATE) ? archive_date : 0,
response + 28);
U16_TO_BE16((archive_flags & MARS_NWE_ARCHIVE_HAS_TIME) ? archive_time : 0,
response + 30);
}
memset(finder_info, 0, sizeof(finder_info));
(void)nwatalk_get_finder_info(unixname, finder_info, sizeof(finder_info));
@@ -1388,7 +1400,7 @@ static int afp_set_file_information(uint8 *afp_req, int afp_len,
}
if (request_mask & ~(AFP_FILE_BITMAP_ATTRIBUTES | AFP_FILE_BITMAP_MODIFY_DATE |
AFP_FILE_BITMAP_FINDER_INFO)) {
AFP_FILE_BITMAP_BACKUP_DATE | AFP_FILE_BITMAP_FINDER_INFO)) {
XDPRINTF((2,0, "%s rejected: unsupported bitmap vol=%d entry=0x%08x mask=0x%04x path='%s'",
call_name, (int)volume_number, request_entry_id, request_mask,
visable_data(afp_req + 9, path_len)));
@@ -1427,6 +1439,15 @@ static int afp_set_file_information(uint8 *afp_req, int afp_len,
}
if (request_mask & AFP_FILE_BITMAP_MODIFY_DATE)
data_off += 4;
if ((request_mask & AFP_FILE_BITMAP_BACKUP_DATE) && afp_len < data_off + 4) {
XDPRINTF((2,0, "%s rejected: short backup timestamp data len=%d data_off=%d",
call_name, afp_len, data_off));
return(-0x7e);
}
if (request_mask & AFP_FILE_BITMAP_BACKUP_DATE) {
needs_afp_metadata_modify = 1;
data_off += 4;
}
if ((request_mask & AFP_FILE_BITMAP_FINDER_INFO) && data_off & 1) data_off++;
if (request_mask & AFP_FILE_BITMAP_FINDER_INFO)
needs_afp_metadata_modify = 1;
@@ -1495,6 +1516,18 @@ static int afp_set_file_information(uint8 *afp_req, int afp_len,
if (!stat(unixname, &stbuff)) {}
data_off += 4;
}
if (request_mask & AFP_FILE_BITMAP_BACKUP_DATE) {
uint16 archive_date = GET_BE16(afp_req + data_off);
uint16 archive_time = GET_BE16(afp_req + data_off + 2);
result = mars_nwe_set_archive_info(unixname,
1, archive_date,
1, archive_time,
0, 0);
if (result < 0)
return(result);
data_off += 4;
}
if ((request_mask & AFP_FILE_BITMAP_FINDER_INFO) && data_off & 1) data_off++;
if (request_mask & AFP_FILE_BITMAP_FINDER_INFO) {
result = nwatalk_set_finder_info(unixname, afp_req + data_off,
@@ -1508,6 +1541,7 @@ static int afp_set_file_information(uint8 *afp_req, int afp_len,
request_mask, visable_data(afp_req + 9, path_len),
(request_mask & AFP_FILE_BITMAP_ATTRIBUTES) ? " attributes" : "",
(request_mask & AFP_FILE_BITMAP_MODIFY_DATE) ? " modify_time" : "",
(request_mask & AFP_FILE_BITMAP_BACKUP_DATE) ? " backup_time" : "",
(request_mask & AFP_FILE_BITMAP_FINDER_INFO) ? " finder_info" : "",
log_attrs, (long)log_mtime));
return(0);