nwconn: route AFP set file timestamps via NetWare helper
All checks were successful
Source release / source-package (push) Successful in 51s
All checks were successful
Source release / source-package (push) Successful in 51s
Extend the conservative AFP Set File Information implementation to accept the file modification timestamp bitmap for path-backed file requests. The WebSDK/NWAFP Set File Information payload carries the timestamp in the same bitmap-ordered parameter stream as file attributes and FinderInfo, so the parser now admits the documented modification timestamp field while continuing to reject every other Set File Information bitmap bit. Do not implement a new AFP-specific timestamp backend. After resolving the raw VOL:-style smoke path to the effective mars_nwe volume and Unix path, convert the AFP/NW DOS date+time fields to time_t and route the update through the existing nw_utime_node() helper. That keeps trustee Modify-right checks and the established utime(2) fallback behavior shared with classic NetWare/NCP timestamp updates. Keep the implementation deliberately file-only and path-backed. Directory timestamps, create/access/backup timestamp fields, Entry-ID-only Set File Information, resource-fork semantics, DOS attribute mapping, Delete, Rename, Create, and Remove stay TODO so later patches can wire them to the existing NetWare helpers with focused smoke coverage. Update afp_set_file_info_smoke with --mtime-epoch and --timestamp-only, verify the written AFP date/time via the follow-up Get File Information record, and extend afp_smoke_suite.sh to run the timestamp probe and record the backing Linux stat output. The suite helper is already copied as a build target, so the new test is propagated into the build tree by the normal tests build. 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:
23
TODO.md
23
TODO.md
@@ -112,6 +112,29 @@ Follow-up:
|
||||
a real requester, especially where MARS-NWE currently relies on the existing
|
||||
underlying share implementation.
|
||||
|
||||
### AFP Set File Information timestamp coverage
|
||||
|
||||
Current status:
|
||||
|
||||
- AFP Set File Information (`0x09`) and AFP 2.0 Set File Information (`0x10`)
|
||||
now accept the file modification timestamp bitmap (`0x0010`) for path-backed
|
||||
file requests.
|
||||
- Timestamp writes are routed through the existing NetWare `nw_utime_node()`
|
||||
helper so trustee Modify rights and the established Unix `utime(2)` fallback
|
||||
behavior are reused instead of inventing AFP-specific timestamp handling.
|
||||
- The Linux smoke helper verifies the AFP date/time fields via the follow-up
|
||||
Get File Information response, and the smoke suite also records `stat -c %Y`
|
||||
for the backing Unix file.
|
||||
|
||||
Follow-up:
|
||||
|
||||
- Add directory timestamp handling once the shared AFP path/object resolver grows
|
||||
directory-specific Set File Information semantics.
|
||||
- Keep create/access/backup timestamp writes disabled until their exact AFP to
|
||||
NetWare/Unix metadata mapping is deliberately wired and tested.
|
||||
- Keep Delete/Rename/Create/Remove for later patches that can reuse the existing
|
||||
NetWare server helpers and trustee checks.
|
||||
|
||||
### Extended volume information field mapping
|
||||
|
||||
Current status:
|
||||
|
||||
40
src/nwconn.c
40
src/nwconn.c
@@ -1095,6 +1095,7 @@ static int afp_get_file_information(uint8 *afp_req, int afp_len,
|
||||
|
||||
|
||||
#define AFP_FILE_BITMAP_ATTRIBUTES 0x0001
|
||||
#define AFP_FILE_BITMAP_MODIFY_DATE 0x0010
|
||||
#define AFP_FILE_BITMAP_FINDER_INFO 0x0020
|
||||
#define AFP_ATTR_INVISIBLE 0x0001
|
||||
#define AFP_ATTR_SYSTEM 0x0004
|
||||
@@ -1111,9 +1112,12 @@ static int afp_set_file_information(uint8 *afp_req, int afp_len,
|
||||
* Netatalk's FPSetFileParams tests use the FinderInfo bitmap as a small,
|
||||
* metadata-only write probes. Mirror the safest slices for the NCP AFP
|
||||
* extension: accept the same path-backed VOL:-style smoke requests as Get File
|
||||
* Information, persist only the file attribute word and/or 32-byte FinderInfo
|
||||
* block in mars_nwe's private xattr namespace, and reject all other bitmap
|
||||
* bits until DOS attribute, timestamp, resource-fork, and entry-id lookup
|
||||
* Information, persist only the file attribute word, the file modification timestamp,
|
||||
* and/or 32-byte FinderInfo block. Attribute and FinderInfo data live in
|
||||
* mars_nwe's private xattr namespace; the modification timestamp is routed
|
||||
* through the existing NetWare timestamp helper so trustee Modify rights and
|
||||
* utime handling stay shared with the classic NCP paths. Reject all other
|
||||
* bitmap bits until DOS attribute, resource-fork, and entry-id lookup
|
||||
* semantics are deliberately wired in.
|
||||
*/
|
||||
{
|
||||
@@ -1127,6 +1131,7 @@ static int afp_set_file_information(uint8 *afp_req, int afp_len,
|
||||
struct stat stbuff;
|
||||
int result;
|
||||
uint16 log_attrs = 0;
|
||||
time_t log_mtime = (time_t)-1;
|
||||
|
||||
if (afp_len < 9) {
|
||||
XDPRINTF((2,0, "%s rejected: short request len=%d",
|
||||
@@ -1155,7 +1160,8 @@ static int afp_set_file_information(uint8 *afp_req, int afp_len,
|
||||
return(-0x9c); /* Invalid Path until persistent entry-id lookup exists */
|
||||
}
|
||||
|
||||
if (request_mask & ~(AFP_FILE_BITMAP_ATTRIBUTES | AFP_FILE_BITMAP_FINDER_INFO)) {
|
||||
if (request_mask & ~(AFP_FILE_BITMAP_ATTRIBUTES | AFP_FILE_BITMAP_MODIFY_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)));
|
||||
@@ -1185,6 +1191,13 @@ static int afp_set_file_information(uint8 *afp_req, int afp_len,
|
||||
}
|
||||
data_off += 2;
|
||||
}
|
||||
if ((request_mask & AFP_FILE_BITMAP_MODIFY_DATE) && afp_len < data_off + 4) {
|
||||
XDPRINTF((2,0, "%s rejected: short modify timestamp data len=%d data_off=%d",
|
||||
call_name, afp_len, data_off));
|
||||
return(-0x7e);
|
||||
}
|
||||
if (request_mask & AFP_FILE_BITMAP_MODIFY_DATE)
|
||||
data_off += 4;
|
||||
if ((request_mask & AFP_FILE_BITMAP_FINDER_INFO) && data_off & 1) data_off++;
|
||||
if ((request_mask & AFP_FILE_BITMAP_FINDER_INFO) &&
|
||||
afp_len < data_off + NWATALK_FINDER_INFO_LEN) {
|
||||
@@ -1225,6 +1238,20 @@ static int afp_set_file_information(uint8 *afp_req, int afp_len,
|
||||
return(result);
|
||||
data_off += 2;
|
||||
}
|
||||
if (request_mask & AFP_FILE_BITMAP_MODIFY_DATE) {
|
||||
time_t new_mtime = nw_2_un_time(afp_req + data_off, afp_req + data_off + 2);
|
||||
if (new_mtime == (time_t)-1) {
|
||||
XDPRINTF((2,0, "%s rejected: invalid modify timestamp path='%s'",
|
||||
call_name, visable_data(afp_req + 9, path_len)));
|
||||
return(-0x8c);
|
||||
}
|
||||
result = nw_utime_node(path_volume, (uint8 *)unixname, &stbuff, new_mtime);
|
||||
if (result < 0)
|
||||
return(result);
|
||||
log_mtime = new_mtime;
|
||||
if (!stat(unixname, &stbuff)) {}
|
||||
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,
|
||||
@@ -1233,12 +1260,13 @@ static int afp_set_file_information(uint8 *afp_req, int afp_len,
|
||||
return(result);
|
||||
}
|
||||
|
||||
XDPRINTF((3,0, "%s: vol=%d request_vol=%d entry=0x%08x mask=0x%04x path='%s'%s%s attrs=0x%04x",
|
||||
XDPRINTF((3,0, "%s: vol=%d request_vol=%d entry=0x%08x mask=0x%04x path='%s'%s%s%s attrs=0x%04x mtime=%ld",
|
||||
call_name, path_volume, (int)volume_number, request_entry_id,
|
||||
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_FINDER_INFO) ? " finder_info" : "",
|
||||
log_attrs));
|
||||
log_attrs, (long)log_mtime));
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -489,13 +489,14 @@ NCP 0x2222/35/16 AFP 2.0 Set File Information
|
||||
```
|
||||
|
||||
The helper exercises two deliberately narrow write-safe AFP metadata subsets:
|
||||
the file FinderInfo bitmap (`0x0020`) and the file Attributes bitmap (`0x0001`)
|
||||
restricted to metadata-only file flags: Finder Invisible, System, and Backup.
|
||||
It sends path-backed raw `VOL:`-style requests, writes the 32-byte FinderInfo
|
||||
block to mars_nwe's private
|
||||
`org.mars-nwe.afp.finder-info` metadata key, writes the narrow AFP attribute word
|
||||
to `org.mars-nwe.afp.attributes`, and immediately verifies the updates through
|
||||
AFP 2.0 Get File Information. On Linux the source-level `org.mars-nwe.afp.*` name is stored via the
|
||||
the file FinderInfo bitmap (`0x0020`), the file Attributes bitmap (`0x0001`)
|
||||
restricted to metadata-only file flags: Finder Invisible, System, and Backup,
|
||||
and the file modification timestamp bitmap (`0x0010`). It sends path-backed
|
||||
raw `VOL:`-style requests, writes the 32-byte FinderInfo block to mars_nwe's
|
||||
private `org.mars-nwe.afp.finder-info` metadata key, writes the narrow AFP
|
||||
attribute word to `org.mars-nwe.afp.attributes`, routes modification timestamp
|
||||
writes through the existing NetWare timestamp helper, and immediately verifies
|
||||
the updates through AFP 2.0 Get File Information. On Linux the source-level `org.mars-nwe.afp.*` name is stored via the
|
||||
portable `user.` xattr namespace by mars_nwe's local xattr wrapper, the same
|
||||
pattern Netatalk uses for its `org.netatalk.*` metadata names.
|
||||
|
||||
@@ -614,15 +615,36 @@ AFP 2.0 Set File Information: vol=0 request_vol=0 entry=0x00000000 mask=0x0001 p
|
||||
AFP 2.0 Set File Information: vol=0 request_vol=0 entry=0x00000000 mask=0x0001 path='SYS:PUBLIC/pmdflts.ini' attributes attrs=0x0004
|
||||
AFP 2.0 Set File Information: vol=0 request_vol=0 entry=0x00000000 mask=0x0001 path='SYS:PUBLIC/pmdflts.ini' attributes attrs=0x8040
|
||||
```
|
||||
|
||||
Modification timestamp writes are deliberately routed through the existing
|
||||
NetWare `nw_utime_node()` path so trustee Modify rights and the established
|
||||
`utime(2)` fallback behavior stay shared with classic NCP timestamp updates.
|
||||
The first timestamp smoke uses a fixed Unix epoch that the helper converts into
|
||||
the AFP/NW DOS date+time fields and verifies through the follow-up Get File
|
||||
Information response:
|
||||
|
||||
```sh
|
||||
./tests/linux/afp_set_file_info_smoke \
|
||||
-S MARS -U SUPERVISOR -P secret \
|
||||
--timestamp-only --mtime-epoch 1700000000 \
|
||||
SYS:PUBLIC/pmdflts.ini
|
||||
|
||||
stat -c 'mtime_epoch=%Y mtime=%y' /var/mars_nwe/SYS/public/pmdflts.ini
|
||||
```
|
||||
|
||||
This currently remains file-only and path-backed, just like the FinderInfo and
|
||||
metadata-attribute Set File Information probes; directory timestamps and
|
||||
Entry-ID-only Set File Information are left for later resolver work.
|
||||
|
||||
The legacy `0x09` endpoint is deliberately routed through the same narrow
|
||||
metadata-only implementation as AFP 2.0 `0x10`; it does not add create, rename,
|
||||
delete, timestamp, or fork-write semantics.
|
||||
implementation as AFP 2.0 `0x10`; it does not add create, rename, delete,
|
||||
directory timestamp, or fork-write semantics.
|
||||
|
||||
All other Set File Information bitmap bits and AFP attribute bits, including
|
||||
NoWrite, NoRename, NoDelete, NoCopy, and the computed data/resource-fork-open
|
||||
flags, are intentionally rejected for now. That keeps timestamp,
|
||||
DOS/NetWare mode-bit mapping, enforcement, resource-fork, and Entry-ID-only
|
||||
write semantics out of this metadata-only smoke path.
|
||||
flags, are intentionally rejected for now. That keeps create/access/backup
|
||||
timestamps, DOS/NetWare mode-bit mapping, enforcement, resource-fork, and
|
||||
Entry-ID-only write semantics out of this conservative smoke path.
|
||||
|
||||
If the server was built without the optional Netatalk/libatalk backend, use
|
||||
`--allow-invalid-namespace` for the expected negative test. Use
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <ncp/nwcalls.h>
|
||||
#include <ncp/ncplib.h>
|
||||
@@ -23,6 +24,7 @@
|
||||
#define AFP_SET_FILE_INFORMATION 0x09
|
||||
#define AFP20_SET_FILE_INFORMATION 0x10
|
||||
#define AFP_ATTRIBUTES_MASK 0x0001
|
||||
#define AFP_MODIFY_DATE_MASK 0x0010
|
||||
#define AFP_FINDER_INFO_MASK 0x0020
|
||||
#define AFP_ATTR_INVISIBLE 0x0001
|
||||
#define AFP_ATTR_SYSTEM 0x0004
|
||||
@@ -39,7 +41,7 @@ static void usage(const char *prog)
|
||||
"Usage: %s [--afp09|--afp20] [--allow-invalid-namespace] [--allow-invalid-path] "
|
||||
"[--volume N] [--entry-id ID] [--type FOUR] [--creator FOUR] "
|
||||
"[--invisible|--clear-invisible|--system|--clear-system|--backup|--clear-backup] "
|
||||
"[--finder-info-only|--attributes-only] "
|
||||
"[--mtime-epoch SECONDS] [--finder-info-only|--attributes-only|--timestamp-only] "
|
||||
"[ncpfs options] PATH\n"
|
||||
"\n"
|
||||
"ncpfs options are parsed by ncp_initialize(), for example:\n"
|
||||
@@ -49,8 +51,9 @@ static void usage(const char *prog)
|
||||
" %s -S MARS -U SUPERVISOR -P secret --type TEXT --creator MARS SYS:PUBLIC/pmdflts.ini\n"
|
||||
" %s -S MARS -U SUPERVISOR -P secret --invisible --attributes-only SYS:PUBLIC/pmdflts.ini\n"
|
||||
" %s -S MARS -U SUPERVISOR -P secret --backup --attributes-only SYS:PUBLIC/pmdflts.ini\n"
|
||||
" %s -S MARS -U SUPERVISOR -P secret --mtime-epoch 1700000000 --timestamp-only SYS:PUBLIC/pmdflts.ini\n"
|
||||
" %s --allow-invalid-namespace -S MARS SYS:PUBLIC/pmdflts.ini\n",
|
||||
prog, prog, prog, prog, prog);
|
||||
prog, prog, prog, prog, prog, prog);
|
||||
}
|
||||
|
||||
static int parse_u32(const char *text, uint32_t *value)
|
||||
@@ -103,6 +106,27 @@ static int copy_fourcc(const char *text, uint8_t out[4])
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int epoch_to_nw_time(uint32_t epoch, uint8_t out[4])
|
||||
{
|
||||
time_t t = (time_t)epoch;
|
||||
struct tm *tmv = localtime(&t);
|
||||
uint16_t date;
|
||||
uint16_t timev;
|
||||
|
||||
if (!tmv || tmv->tm_year + 1900 < 1980 || tmv->tm_year + 1900 > 2107)
|
||||
return -1;
|
||||
|
||||
date = (uint16_t)(((tmv->tm_year + 1900 - 1980) << 9) |
|
||||
((tmv->tm_mon + 1) << 5) |
|
||||
tmv->tm_mday);
|
||||
timev = (uint16_t)((tmv->tm_hour << 11) |
|
||||
(tmv->tm_min << 5) |
|
||||
(tmv->tm_sec / 2));
|
||||
cpu_to_be16(date, out + 0);
|
||||
cpu_to_be16(timev, out + 2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static NWCCODE afp_get_file_info(NWCONN_HANDLE conn, const char *path,
|
||||
uint32_t volume_number, uint32_t entry_id,
|
||||
uint8_t reply_buf[AFP_REPLY_LEN])
|
||||
@@ -144,8 +168,10 @@ int main(int argc, char **argv)
|
||||
uint16_t attr_request = 0;
|
||||
uint16_t attr_verify_mask = 0;
|
||||
uint16_t attr_expected = 0;
|
||||
uint8_t modify_time[4];
|
||||
int have_modify_time = 0;
|
||||
uint8_t verify_buf[AFP_REPLY_LEN];
|
||||
uint8_t request[1 + 4 + 2 + 1 + 255 + 1 + 2 + 1 + 32];
|
||||
uint8_t request[1 + 4 + 2 + 1 + 255 + 1 + 2 + 4 + 1 + 32];
|
||||
size_t path_len;
|
||||
size_t afp_data_off;
|
||||
size_t data_off;
|
||||
@@ -153,6 +179,7 @@ int main(int argc, char **argv)
|
||||
NWCCODE err;
|
||||
|
||||
memset(finder_info, 0, sizeof(finder_info));
|
||||
memset(modify_time, 0, sizeof(modify_time));
|
||||
memcpy(finder_info + 0, "TEXT", 4);
|
||||
memcpy(finder_info + 4, "MARS", 4);
|
||||
|
||||
@@ -219,10 +246,22 @@ int main(int argc, char **argv)
|
||||
attr_request = AFP_ATTR_BACKUP;
|
||||
attr_verify_mask = AFP_ATTR_BACKUP;
|
||||
attr_expected = 0;
|
||||
} else if (!strcmp(argv[i], "--mtime-epoch")) {
|
||||
uint32_t epoch;
|
||||
if (++i >= argc || parse_u32(argv[i], &epoch) || epoch_to_nw_time(epoch, modify_time)) {
|
||||
fprintf(stderr, "invalid --mtime-epoch value\n");
|
||||
ncp_close(conn);
|
||||
return 2;
|
||||
}
|
||||
request_mask |= AFP_MODIFY_DATE_MASK;
|
||||
have_modify_time = 1;
|
||||
} else if (!strcmp(argv[i], "--attributes-only")) {
|
||||
request_mask &= ~AFP_FINDER_INFO_MASK;
|
||||
request_mask &= ~(AFP_FINDER_INFO_MASK | AFP_MODIFY_DATE_MASK);
|
||||
} else if (!strcmp(argv[i], "--finder-info-only")) {
|
||||
request_mask &= ~AFP_ATTRIBUTES_MASK;
|
||||
request_mask &= ~(AFP_ATTRIBUTES_MASK | AFP_MODIFY_DATE_MASK);
|
||||
} else if (!strcmp(argv[i], "--timestamp-only")) {
|
||||
request_mask &= ~(AFP_ATTRIBUTES_MASK | AFP_FINDER_INFO_MASK);
|
||||
request_mask |= AFP_MODIFY_DATE_MASK;
|
||||
} else if (!strcmp(argv[i], "--type")) {
|
||||
if (++i >= argc || copy_fourcc(argv[i], finder_info + 0)) {
|
||||
fprintf(stderr, "invalid --type value, expected four characters\n");
|
||||
@@ -285,7 +324,17 @@ int main(int argc, char **argv)
|
||||
cpu_to_be16(attr_request, request + data_off);
|
||||
data_off += 2;
|
||||
}
|
||||
if ((request_mask & AFP_FINDER_INFO_MASK) && (request_mask & AFP_ATTRIBUTES_MASK) &&
|
||||
if (request_mask & AFP_MODIFY_DATE_MASK) {
|
||||
if (!have_modify_time) {
|
||||
fprintf(stderr, "--timestamp-only requires --mtime-epoch\n");
|
||||
ncp_close(conn);
|
||||
return 2;
|
||||
}
|
||||
memcpy(request + data_off, modify_time, sizeof(modify_time));
|
||||
data_off += sizeof(modify_time);
|
||||
}
|
||||
if ((request_mask & AFP_FINDER_INFO_MASK) &&
|
||||
(request_mask & (AFP_ATTRIBUTES_MASK | AFP_MODIFY_DATE_MASK)) &&
|
||||
((data_off + 1) & 1))
|
||||
data_off++;
|
||||
if (request_mask & AFP_FINDER_INFO_MASK) {
|
||||
@@ -334,6 +383,16 @@ int main(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((request_mask & AFP_MODIFY_DATE_MASK) &&
|
||||
memcmp(verify_buf + 24, modify_time, sizeof(modify_time))) {
|
||||
fprintf(stderr,
|
||||
"AFP Set File Information timestamp verify mismatch: path=%s got=0x%04x%04x expected=0x%04x%04x\n",
|
||||
path, be16_to_cpu(verify_buf + 24), be16_to_cpu(verify_buf + 26),
|
||||
be16_to_cpu(modify_time + 0), be16_to_cpu(modify_time + 2));
|
||||
ncp_close(conn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((request_mask & AFP_ATTRIBUTES_MASK) &&
|
||||
((be16_to_cpu(verify_buf + 8) & attr_verify_mask) != attr_expected)) {
|
||||
fprintf(stderr,
|
||||
@@ -343,8 +402,9 @@ int main(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("AFP Set File Info subfunction=0x%02x path=%s bitmap=0x%04x attrs=0x%04x finder_type=%.4s finder_creator=%.4s entry_id=0x%08x verified\n",
|
||||
printf("AFP Set File Info subfunction=0x%02x path=%s bitmap=0x%04x attrs=0x%04x modify=0x%04x%04x finder_type=%.4s finder_creator=%.4s entry_id=0x%08x verified\n",
|
||||
set_subfunction, path, request_mask, be16_to_cpu(verify_buf + 8),
|
||||
be16_to_cpu(verify_buf + 24), be16_to_cpu(verify_buf + 26),
|
||||
finder_info + 0, finder_info + 4, be32_to_cpu(verify_buf + 0));
|
||||
|
||||
ncp_close(conn);
|
||||
|
||||
@@ -17,6 +17,7 @@ LOG_FILE="/var/log/mars_nwe/nw.log"
|
||||
OUT_FILE=""
|
||||
FINDER_TYPE="TEXT"
|
||||
FINDER_CREATOR="MARS"
|
||||
TIMESTAMP_EPOCH="1700000000"
|
||||
KEEP_GOING=1
|
||||
CAPTURE_LOG=1
|
||||
|
||||
@@ -31,6 +32,7 @@ Options:
|
||||
--out FILE Write the complete report to FILE as well as stdout
|
||||
--type FOURCC FinderInfo type written by Set File Info (default: $FINDER_TYPE)
|
||||
--creator FOURCC FinderInfo creator written by Set File Info (default: $FINDER_CREATOR)
|
||||
--mtime-epoch SECONDS AFP modify timestamp to write (default: $TIMESTAMP_EPOCH)
|
||||
--no-log Do not tail/grep the server log
|
||||
--stop-on-failure Stop after the first failing smoke command
|
||||
-h, --help Show this help
|
||||
@@ -61,6 +63,8 @@ while [ $# -gt 0 ]; do
|
||||
FINDER_TYPE=$2; shift 2 ;;
|
||||
--creator)
|
||||
FINDER_CREATOR=$2; shift 2 ;;
|
||||
--mtime-epoch)
|
||||
TIMESTAMP_EPOCH=$2; shift 2 ;;
|
||||
--no-log)
|
||||
CAPTURE_LOG=0; shift ;;
|
||||
--stop-on-failure)
|
||||
@@ -170,6 +174,7 @@ emit "unix_path=$UNIX_PATH"
|
||||
emit "log=$LOG_FILE"
|
||||
emit "finder_type=$FINDER_TYPE"
|
||||
emit "finder_creator=$FINDER_CREATOR"
|
||||
emit "mtime_epoch=$TIMESTAMP_EPOCH"
|
||||
|
||||
for helper in \
|
||||
afp_entry_id_smoke \
|
||||
@@ -265,6 +270,12 @@ run_cmd \
|
||||
"$SCRIPT_DIR/afp_set_file_info_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" \
|
||||
--afp09 --attributes-only --clear-invisible "$NETWARE_PATH"
|
||||
|
||||
run_cmd \
|
||||
"AFP Set File Information Modify Timestamp" \
|
||||
"./afp_set_file_info_smoke $COMMON_PRINT --timestamp-only --mtime-epoch '$TIMESTAMP_EPOCH' '$NETWARE_PATH'" \
|
||||
"$SCRIPT_DIR/afp_set_file_info_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" \
|
||||
--timestamp-only --mtime-epoch "$TIMESTAMP_EPOCH" "$NETWARE_PATH"
|
||||
|
||||
run_cmd \
|
||||
"AFP Set File Information System" \
|
||||
"./afp_set_file_info_smoke $COMMON_PRINT --attributes-only --system '$NETWARE_PATH'" \
|
||||
@@ -289,6 +300,13 @@ run_cmd \
|
||||
"$SCRIPT_DIR/afp_set_file_info_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" \
|
||||
--attributes-only --clear-backup "$NETWARE_PATH"
|
||||
|
||||
if command -v stat >/dev/null 2>&1; then
|
||||
run_cmd \
|
||||
"Linux stat: AFP Modify Timestamp" \
|
||||
"stat -c 'mtime_epoch=%Y mtime=%y' '$UNIX_PATH'" \
|
||||
stat -c 'mtime_epoch=%Y mtime=%y' "$UNIX_PATH"
|
||||
fi
|
||||
|
||||
if command -v getfattr >/dev/null 2>&1; then
|
||||
run_cmd \
|
||||
"Linux xattr: AFP FinderInfo" \
|
||||
|
||||
Reference in New Issue
Block a user