mirror of
https://git.checksum.fail/alec/neinterm.git
synced 2025-12-10 13:09:54 +02:00
557 lines
17 KiB
HolyC
557 lines
17 KiB
HolyC
U0 @nt_Rerror(@nt* nt, U8* data, U8* errormsg)
|
||
{
|
||
// size[4] Rerror tag[2] ename[s]
|
||
|
||
SET_MSGS
|
||
|
||
Rmsg->length = (4 + 1 + 2 + 2);
|
||
nt->out[4] = TERROR + 1; // RERROR
|
||
|
||
MemCpy(nt->out + (4 + 1 + 2 + 2), errormsg, StrLen(errormsg));
|
||
*(nt->out + (4 + 1 + 2))(U16*) = StrLen(errormsg);
|
||
|
||
SET_RESPONSE_TAG
|
||
Rmsg->length += StrLen(errormsg);
|
||
|
||
@9p_debug_dump(Rmsg, Rmsg->length, 1);
|
||
nt->s->send(Rmsg, Rmsg->length);
|
||
}
|
||
|
||
U0 @nt_Tversion(@nt* nt, U8* data)
|
||
{
|
||
SET_MSGS
|
||
|
||
// Special case; just increment Tmsg tag to Rmsg and echo back to client
|
||
data[4]++;
|
||
@9p_debug_dump(data, Tmsg->length, 1);
|
||
nt->s->send(data, Tmsg->length);
|
||
}
|
||
|
||
U0 @nt_Tattach(@nt* nt, U8* data)
|
||
{
|
||
SET_MSGS
|
||
@nt_zrmsg(nt, 20);
|
||
//@nt_tx_dbg(nt, "Tattach fid: %d", Tmsg->fid);
|
||
nt->attach_fid = Tmsg->fid;
|
||
|
||
// Map fid to qid
|
||
U8 fidbuf[16];
|
||
@9p_qid * qid = @nt_lookup_qid_by_path(nt, "/");
|
||
StrPrint(fidbuf, "%d", Tmsg->fid);
|
||
// nt->fids->set(fidbuf, qid, JSON_NUMBER);
|
||
@nt_fid_set(nt, fidbuf, qid);
|
||
|
||
MemCpy(nt->out + 7, qid, sizeof(@9p_qid));
|
||
SEND_RMSG
|
||
}
|
||
|
||
U0 @nt_Twalk(@nt* nt, U8* data)
|
||
{
|
||
// https://9fans.github.io/plan9port/man/man9/walk.html
|
||
|
||
// size[4] Twalk tag[2] fid[4] newfid[4] nwname[2] nwname*(wname[s])
|
||
// size[4] Rwalk tag[2] nwqid[2] nwqid*(qid[13])
|
||
|
||
// The fid must be valid in the current session and must not have been opened for I/O by an open or create message.
|
||
// If the full sequence of nwname elements is walked successfully, newfid will represent the file that results.
|
||
// If not, newfid (and fid) will be unaffected. However, if newfid is in use or otherwise illegal, an Rerror is returned.
|
||
|
||
// If the first element cannot be walked for any reason, Rerror is returned.
|
||
// Otherwise, the walk will return an Rwalk message containing:
|
||
// nwqid qids corresponding, in order, to the files that are visited by the nwqid successful elementwise walks;
|
||
// nwqid is therefore either nwname or the index of the first elementwise walk that failed.
|
||
|
||
// size[4] Rwalk tag[2] nwqid[2] nwqid*(qid[13])
|
||
|
||
// The value of nwqid cannot be zero unless nwname is zero.
|
||
// Also, nwqid will always be less than or equal to nwname.
|
||
// Only if it is equal, however, will newfid be affected, in which case newfid will represent:
|
||
// the file reached by the final elementwise walk requested in the message.
|
||
|
||
SET_MSGS
|
||
@9p_twalk * Twalk = data;
|
||
U8** wname = NULL;
|
||
|
||
I64 i, j;
|
||
U16 fid = Twalk->fid;
|
||
U16 newfid = Twalk->newfid;
|
||
U16 nwname = Twalk->nwname;
|
||
U16 nwqid = 0;
|
||
@9p_qid * qid = NULL;
|
||
|
||
U8 basepath[512];
|
||
U8 pathbuf[512];
|
||
U8 fidbuf[16];
|
||
|
||
Rmsg->length = (4 + 1 + 2 + 2);
|
||
//@nt_tx_dbg(nt, "Twalk fid: %d, newfid: %d, nwname: %d", fid, newfid, nwname);
|
||
|
||
if (fid != nt->attach_fid) {
|
||
// FIXME: Lookup base path from fid
|
||
StrPrint(fidbuf, "%d", fid);
|
||
qid = nt->fids->o(fidbuf)->@("qid");
|
||
if (!qid) {
|
||
@nt_tx_dbg(nt, "ERROR: !qid");
|
||
PressAKey;
|
||
}
|
||
StrCpy(basepath, qid->path);
|
||
if (qid->type != NT_IS_DIR) {
|
||
StrLastOcc(basepath, "/")[0] = NULL;
|
||
}
|
||
} else {
|
||
StrCpy(basepath, "");
|
||
}
|
||
|
||
if (nwname) {
|
||
wname = CAlloc(sizeof(U8*) * nwname, nt->main_task);
|
||
@nt_pascal_to_c_strings(nt, wname, &Twalk->wname, nwname);
|
||
|
||
for (i = 0; i < nwname; i++) {
|
||
StrCpy(pathbuf, basepath);
|
||
for (j = 0; j <= i; j++) {
|
||
StrPrint(pathbuf + StrLen(pathbuf), "/%s", wname[j]);
|
||
}
|
||
qid = @nt_lookup_qid_by_path(nt, pathbuf);
|
||
if (qid) {
|
||
// Copy the qid to Rwalk and increment nwqid, Rwalk length
|
||
MemCpy(nt->out + (4 + 1 + 2 + 2 + (nwqid * sizeof(@9p_qid))), qid, sizeof(@9p_qid));
|
||
nwqid++;
|
||
Rmsg->length += sizeof(@9p_qid);
|
||
} else {
|
||
|
||
// Rerror
|
||
Rmsg->length = (4 + 1 + 2 + 2);
|
||
Rmsg->type = 0x6b; // Rerror
|
||
SET_RESPONSE_TAG
|
||
StrPrint(nt->out + (4 + 1 + 2 + 2), "file does not exist: '.%s'", pathbuf);
|
||
//@nt_tx_dbg(nt, "newfid: %d, %s", newfid, nt->out + (4 + 1 + 2 + 2));
|
||
*(nt->out + (4 + 1 + 2))(U16*) = StrLen(nt->out + (4 + 1 + 2 + 2));
|
||
Rmsg->length += StrLen(nt->out + (4 + 1 + 2 + 2));
|
||
@9p_debug_dump(Rmsg, Rmsg->length, 1);
|
||
nt->s->send(Rmsg, Rmsg->length);
|
||
return;
|
||
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Map newfid to qid
|
||
StrPrint(fidbuf, "%d", newfid);
|
||
// nt->fids->set(fidbuf, qid, JSON_NUMBER);
|
||
@nt_fid_set(nt, fidbuf, qid);
|
||
|
||
// Set nwqid
|
||
*(nt->out + (4 + 1 + 2))(U16*) = nwqid;
|
||
|
||
//@nt_tx_dbg(nt, "newfid: %d, walked: %s", newfid, pathbuf);
|
||
|
||
SEND_RMSG
|
||
}
|
||
|
||
U0 @nt_Topen(@nt* nt, U8* data)
|
||
{
|
||
// https://9fans.github.io/plan9port/man/man9/open.html
|
||
|
||
// size[4] Topen tag[2] fid[4] mode[1]
|
||
// size[4] Ropen tag[2] qid[13] iounit[4]
|
||
|
||
SET_MSGS
|
||
|
||
U32 fid = *(data + (4 + 1 + 2))(U32*);
|
||
I64 mode = data[4 + 1 + 2 + 4];
|
||
|
||
U8 fidbuf[16];
|
||
StrPrint(fidbuf, "%d", fid);
|
||
|
||
Rmsg->length = (4 + 1 + 2 + 13 + 4);
|
||
//@nt_tx_dbg(nt, "Topen fid: %d, mode: %d", fid, mode);
|
||
|
||
@9p_qid * qid = nt->fids->o(fidbuf)->@("qid");
|
||
|
||
if (!qid) {
|
||
@nt_tx_dbg("ERROR: no qid for fid %d", fid);
|
||
PressAKey;
|
||
}
|
||
|
||
MemCpy(nt->out + 7, qid, sizeof(@9p_qid));
|
||
*(nt->out + (4 + 1 + 2 + 13))(U32*) = NULL; // set iounit to NULL for now
|
||
|
||
SEND_RMSG
|
||
}
|
||
|
||
U0 @nt_Tclunk(@nt* nt, U8* data)
|
||
{
|
||
// https://9fans.github.io/plan9port/man/man9/clunk.html
|
||
|
||
// size[4] Tclunk tag[2] fid[4]
|
||
// size[4] Rclunk tag[2]
|
||
|
||
SET_MSGS
|
||
|
||
U32 fid = *(data + (4 + 1 + 2))(U32*);
|
||
|
||
U8 fidbuf[16];
|
||
StrPrint(fidbuf, "%d", fid);
|
||
|
||
Rmsg->length = (4 + 1 + 2);
|
||
//@nt_tx_dbg(nt, "Tclunk fid: %d", fid);
|
||
|
||
nt->fids->unset(fidbuf);
|
||
|
||
SEND_RMSG
|
||
}
|
||
|
||
// I64 test_read_cnt = 0;
|
||
|
||
I64 test_read_cnt = 0;
|
||
// I64 test_entry_size = 0x45;
|
||
I64 test_entry_size = 0x41;
|
||
|
||
// U8 test_entry[test_entry_size] = { 0x3e, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x00, 0x27, 0xab, 0xe2, 0x68, 0x1b, 0xab, 0xe2, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x64, 0x72, 0x61, 0x04, 0x00, 0x61, 0x6c, 0x65, 0x63, 0x04, 0x00, 0x61, 0x6c, 0x65, 0x63, 0x04, 0x00, 0x61, 0x6c, 0x65, 0x63 };
|
||
U8 test_entry[test_entry_size] = { 0x3f, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x80, 0x27, 0xab, 0xe2, 0x68, 0x1b, 0xab, 0xe2, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x64, 0x72, 0x61, 0x77, 0x04, 0x00, 0x61, 0x6c, 0x65, 0x63, 0x04, 0x00, 0x61, 0x6c, 0x65, 0x63, 0x04, 0x00, 0x61, 0x6c, 0x65, 0x63 };
|
||
// U8 test_entry[test_entry_size] = { 0x3f, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x01, 0x00, 0x80, 0x4d, 0xb2, 0xe2, 0x68, 0x47, 0xb2, 0xe2, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x64, 0x72, 0x61, 0x77, 0x04, 0x00, 0x61, 0x6c, 0x65, 0x63, 0x04, 0x00, 0x61, 0x6c, 0x65, 0x63, 0x04, 0x00, 0x61, 0x6c, 0x65, 0x63, 0x42, 0x00, 0x69, 0x00 };
|
||
|
||
U0 @dev_draw_new_read(@nt* nt, U8* data)
|
||
{
|
||
SET_MSGS
|
||
|
||
U32 read_size = 144;
|
||
|
||
I64 i;
|
||
U8 newbuf[144];
|
||
U8 intbuf[16];
|
||
U8 pathbuf[128];
|
||
U8* chanstr = "x8r8g8b8";
|
||
JsonObject* tmpr;
|
||
I64 conn = nt->drawobjs->length + 1;
|
||
|
||
JsonObject* dobj = Json.CreateObject(nt->main_task);
|
||
dobj->set("conn", conn, JSON_NUMBER);
|
||
dobj->set("imageid", 0, JSON_NUMBER);
|
||
dobj->set("chan", chanstr, JSON_STRING);
|
||
dobj->set("r", Json.CreateObject(nt->main_task), JSON_OBJECT);
|
||
dobj->set("clipr", Json.CreateObject(nt->main_task), JSON_OBJECT);
|
||
|
||
tmpr = dobj->o("r");
|
||
tmpr->set("x0", 0, JSON_NUMBER);
|
||
tmpr->set("y0", 0, JSON_NUMBER);
|
||
tmpr->set("x1", GR_WIDTH, JSON_NUMBER);
|
||
tmpr->set("y1", GR_HEIGHT, JSON_NUMBER);
|
||
|
||
tmpr = dobj->o("clipr");
|
||
tmpr->set("x0", 0, JSON_NUMBER);
|
||
tmpr->set("y0", 0, JSON_NUMBER);
|
||
tmpr->set("x1", GR_WIDTH, JSON_NUMBER);
|
||
tmpr->set("y1", GR_HEIGHT, JSON_NUMBER);
|
||
|
||
dobj->set("imgs", Json.CreateObject(nt->main_task), JSON_OBJECT);
|
||
|
||
// Insert new draw object [/dev/draw/[conn#] to nt->drawobjs]
|
||
StrPrint(intbuf, "%d", conn);
|
||
nt->drawobjs->set(intbuf, dobj, JSON_OBJECT);
|
||
|
||
// Create path objects
|
||
StrPrint(pathbuf, "/dev/draw/%d", conn);
|
||
@nt_qid_create(nt, pathbuf, NT_IS_DIR);
|
||
StrPrint(pathbuf, "/dev/draw/%d/data", conn);
|
||
@nt_qid_create(nt, pathbuf, NT_IS_FILE);
|
||
StrPrint(pathbuf, "/dev/draw/%d/refresh", conn);
|
||
@nt_qid_create(nt, pathbuf, NT_IS_FILE);
|
||
|
||
// ** not yet implemented
|
||
// StrPrint(pathbuf, "/dev/draw/%d/colormap", conn);
|
||
// @nt_qid_create(nt, pathbuf, NT_IS_FILE);
|
||
// StrPrint(pathbuf, "/dev/draw/%d/ctl", conn);
|
||
// @nt_qid_create(nt, pathbuf, NT_IS_FILE);
|
||
|
||
// *** Build payload for Rread
|
||
|
||
// Default; set all fields to 0
|
||
MemSet(newbuf, ' ', read_size);
|
||
for (i = 0; i < 12; i++) {
|
||
newbuf[10 + (12 * i)] = '0';
|
||
}
|
||
|
||
// Set connection number
|
||
StrPrint(intbuf, "%d", conn);
|
||
MemCpy(newbuf + 11 - StrLen(intbuf), intbuf, StrLen(intbuf));
|
||
|
||
// Set chan string
|
||
MemCpy(newbuf + 11 - StrLen(chanstr) + (12 * 2), chanstr, StrLen(chanstr));
|
||
|
||
// Set max.x of display image and clipping rect
|
||
StrPrint(intbuf, "%d", GR_WIDTH);
|
||
MemCpy(newbuf + 11 - StrLen(intbuf) + (12 * 6), intbuf, StrLen(intbuf));
|
||
MemCpy(newbuf + 11 - StrLen(intbuf) + (12 * 10), intbuf, StrLen(intbuf));
|
||
|
||
// Set max.y of display image and clipping rect
|
||
StrPrint(intbuf, "%d", GR_HEIGHT);
|
||
MemCpy(newbuf + 11 - StrLen(intbuf) + (12 * 7), intbuf, StrLen(intbuf));
|
||
MemCpy(newbuf + 11 - StrLen(intbuf) + (12 * 11), intbuf, StrLen(intbuf));
|
||
|
||
Rmsg->length = (4 + 1 + 2 + 4);
|
||
MemCpy(nt->out + (4 + 1 + 2 + 4), newbuf, read_size);
|
||
*(nt->out + (4 + 1 + 2))(U32*) = read_size;
|
||
Rmsg->length += read_size;
|
||
|
||
SEND_RMSG
|
||
}
|
||
|
||
U0 @nt_Rread_dir(@nt* nt, U8* data, @9p_qid * qid)
|
||
{
|
||
SET_MSGS
|
||
|
||
Rmsg->length = (4 + 1 + 2 + 4);
|
||
|
||
if (test_read_cnt) {
|
||
*(nt->out + (4 + 1 + 2))(U32*) = 0;
|
||
SEND_RMSG
|
||
return;
|
||
}
|
||
|
||
U32 read_size = test_entry_size;
|
||
MemCpy(nt->out + (4 + 1 + 2 + 4), test_entry, read_size);
|
||
|
||
*(nt->out + (4 + 1 + 2))(U32*) = read_size;
|
||
Rmsg->length += read_size;
|
||
SEND_RMSG
|
||
|
||
test_read_cnt++;
|
||
}
|
||
|
||
// @9p_msg * Rmsg = nt->out;
|
||
//
|
||
// if (ev) {
|
||
// Rmsg->length = 0x0e;
|
||
// Rmsg->type = TREAD + 1; // RREAD
|
||
// Rmsg->tag = nt->kbd_read_tag;
|
||
// MemCpy(nt->out + (4 + 1 + 2), ev, 7);
|
||
// // nt->kbd_read_tag = NULL;
|
||
// nt->kbd_last_jiffies = cnts.jiffies;
|
||
// nt->s->send(Rmsg, Rmsg->length);
|
||
// Free(ev);
|
||
// }
|
||
|
||
U0 @nt_Tread(@nt* nt, U8* data)
|
||
{
|
||
// https://9fans.github.io/plan9port/man/man9/read.html
|
||
|
||
// size[4] Tread tag[2] fid[4] offset[8] count[4]
|
||
// size[4] Rread tag[2] count[4] data[count]
|
||
|
||
SET_MSGS
|
||
|
||
U32 _fid = *(data + (4 + 1 + 2))(U32*);
|
||
U64 offset = *(data + (4 + 1 + 2 + 4))(U64*);
|
||
U32 count = *(data + (4 + 1 + 2 + 4 + 8))(U32*);
|
||
|
||
//@nt_tx_dbg(nt, "Tread fid: %d, offset: %d, count: %d", fid, offset, count);
|
||
|
||
U8 fidbuf[16];
|
||
StrPrint(fidbuf, "%d", _fid);
|
||
|
||
JsonObject* fid = nt->fids->o(fidbuf);
|
||
|
||
if (!fid)
|
||
return;
|
||
|
||
@9p_qid * qid = fid->@("qid");
|
||
|
||
if (!qid)
|
||
return;
|
||
|
||
I64 read_count = fid->@("read_count");
|
||
|
||
if (qid) {
|
||
switch (qid->type) {
|
||
case NT_IS_DIR:
|
||
if (!StrCmp(qid->path, "/dev")) {
|
||
@nt_Rread_dir(nt, data, qid);
|
||
return;
|
||
}
|
||
//@nt_tx_dbg(nt, "got read on dir: %s", qid->path);
|
||
break;
|
||
default:
|
||
if (!StrCmp(qid->path, "/dev/kbd")) {
|
||
nt->kbd_read_tag = Tmsg->tag;
|
||
//@nt_tx_dbg(nt, "Set nt->kbd_read_tag: 0x%04x", Tmsg->tag);
|
||
}
|
||
if (!StrCmp(qid->path, "/dev/draw/new")) {
|
||
if (read_count) {
|
||
@nt_Rerror(nt, data, "unknown id for draw image");
|
||
} else {
|
||
@dev_draw_new_read(nt, data);
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
read_count++;
|
||
fid->set("read_count", read_count, JSON_NUMBER);
|
||
}
|
||
|
||
U0 @nt_Twrite(@nt* nt, U8* data)
|
||
{
|
||
// https://9fans.github.io/plan9port/man/man9/read.html
|
||
|
||
// size[4] Twrite tag[2] fid[4] offset[8] count[4] data[count]
|
||
// size[4] Rwrite tag[2] count[4]
|
||
|
||
SET_MSGS
|
||
|
||
U32 fid = *(data + (4 + 1 + 2))(U32*);
|
||
U64 offset = *(data + (4 + 1 + 2 + 4))(U64*);
|
||
U32 count = *(data + (4 + 1 + 2 + 4 + 8))(U32*);
|
||
U8* p = data + (4 + 1 + 2 + 4 + 8 + 4);
|
||
|
||
Rmsg->length = (4 + 1 + 2 + 4);
|
||
//@nt_tx_dbg(nt, "Twrite fid: %d, offset: %d, count: %d", fid, offset, count);
|
||
|
||
U8 fidbuf[16];
|
||
U8 errmsgbuf[256];
|
||
StrPrint(fidbuf, "%d", fid);
|
||
@9p_qid * qid = nt->fids->o(fidbuf)->@("qid");
|
||
|
||
I64 i;
|
||
|
||
if (qid) {
|
||
if (String.BeginsWith("/dev/draw", qid->path) && String.EndsWith("/data", qid->path)) {
|
||
}
|
||
if (!StrCmp(qid->path, "/dev/draw/1/data")) {
|
||
@nt_draw(nt, data, qid);
|
||
}
|
||
if (!StrCmp(qid->path, "/dev/cons")) {
|
||
for (i = 0; i < count; i++) {
|
||
DocPrint(nt->main_task->put_doc, "%c", p[i]);
|
||
}
|
||
}
|
||
if (!StrCmp(qid->path, "/dev/mousectl")) {
|
||
p[count] = NULL;
|
||
StrPrint(errmsgbuf, "unknown control message \"%s\"", p);
|
||
@nt_Rerror(nt, data, errmsgbuf);
|
||
return;
|
||
}
|
||
|
||
//@nt_tx_dbg(nt, "got write for path: %s", qid->path);
|
||
}
|
||
|
||
*(nt->out + (4 + 1 + 2))(U32*) = count;
|
||
|
||
SEND_RMSG
|
||
}
|
||
|
||
U0 @nt_Tflush(@nt* nt, U8* data)
|
||
{
|
||
// https://9fans.github.io/plan9port/man/man9/flush.html
|
||
|
||
// size[4] Tflush tag[2] oldtag[2]
|
||
// size[4] Rflush tag[2]
|
||
|
||
SET_MSGS
|
||
|
||
Rmsg->length = (4 + 1 + 2);
|
||
SEND_RMSG
|
||
}
|
||
|
||
U0 @nt_Tstat(@nt* nt, U8* data)
|
||
{
|
||
// https://9fans.github.io/plan9port/man/man9/stat.html
|
||
|
||
// size[4] Tstat tag[2] fid[4]
|
||
// size[4] Rstat tag[2] stat[n]
|
||
|
||
// The reply will contain a machine-independent directory entry, stat, laid out as follows:
|
||
// size[2]total byte count of the following data
|
||
// type[2]for kernel use
|
||
// dev[4]for kernel use
|
||
// qid.type[1]
|
||
// the type of the file (directory, etc.), represented as a bit vector corresponding to the high 8 bits of the file’s mode word.
|
||
// qid.vers[4]
|
||
// version number for given path
|
||
// qid.path[8]
|
||
// the file server’s unique identification for the file
|
||
// mode[4]
|
||
// permissions and flags
|
||
// atime[4]
|
||
// last access time
|
||
// mtime[4]
|
||
// last modification time
|
||
// length[8]
|
||
// length of file in bytes
|
||
// name[ s ]
|
||
// file name; must be / if the file is the root directory of the server
|
||
// uid[ s ]owner name
|
||
// gid[ s ]group name
|
||
// muid[ s ]
|
||
// name of the user who last modified the file
|
||
|
||
SET_MSGS
|
||
|
||
U32 fid = *(data + (4 + 1 + 2))(U32*);
|
||
|
||
Rmsg->length = (4 + 1 + 2 + sizeof(@9p_stat)); // set initial Rmsg length
|
||
//@nt_tx_dbg(nt, "Tstat fid: %d", fid);
|
||
// PressAKey;
|
||
|
||
U8 fidbuf[16];
|
||
StrPrint(fidbuf, "%d", fid);
|
||
|
||
@9p_qid * qid = nt->fids->o(fidbuf)->@("qid");
|
||
|
||
@9p_stat * stat = nt->out + (4 + 1 + 2);
|
||
stat->size = sizeof(@9p_stat) - 2;
|
||
stat->type = 0;
|
||
stat->dev = 0;
|
||
MemCpy(&stat->qid, qid, sizeof(@9p_qid));
|
||
stat->atime = 0;
|
||
stat->mtime = 0;
|
||
stat->length = 1024;
|
||
|
||
// add strings
|
||
U8* p = NULL;
|
||
U8* user = "alec";
|
||
|
||
// name[ s ]
|
||
p = nt->out + Rmsg->length;
|
||
U8* path = qid->path;
|
||
if (StrCmp(path, "/")) {
|
||
path = StrLastOcc(path, "/") + 1;
|
||
}
|
||
*(p)(U16*) = StrLen(path);
|
||
p += 2;
|
||
MemCpy(p, path, StrLen(path));
|
||
p += StrLen(path);
|
||
stat->size += StrLen(path) + 2;
|
||
Rmsg->length += StrLen(path) + 2;
|
||
|
||
// uid[ s ]owner name
|
||
p = nt->out + Rmsg->length;
|
||
*(p)(U16*) = StrLen(user);
|
||
p += 2;
|
||
MemCpy(p, user, StrLen(user));
|
||
p += StrLen(user);
|
||
stat->size += StrLen(user) + 2;
|
||
Rmsg->length += StrLen(user) + 2;
|
||
|
||
// uid[ s ]group name
|
||
p = nt->out + Rmsg->length;
|
||
*(p)(U16*) = StrLen(user);
|
||
p += 2;
|
||
MemCpy(p, user, StrLen(user));
|
||
p += StrLen(user);
|
||
stat->size += StrLen(user) + 2;
|
||
Rmsg->length += StrLen(user) + 2;
|
||
|
||
// muid[ s ]
|
||
p = nt->out + Rmsg->length;
|
||
*(p)(U16*) = StrLen(user);
|
||
p += 2;
|
||
MemCpy(p, user, StrLen(user));
|
||
p += StrLen(user);
|
||
stat->size += StrLen(user) + 2;
|
||
Rmsg->length += StrLen(user) + 2;
|
||
|
||
SEND_RMSG
|
||
} |