Files
neinterm/System/9P/Requests.HC
2025-10-07 10:51:07 -04:00

557 lines
17 KiB
HolyC
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 files mode word.
// qid.vers[4]
// version number for given path
// qid.path[8]
// the file servers 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
}