Files
neinterm/System/9P/Requests.HC

557 lines
17 KiB
HolyC
Raw Permalink Normal View History

2025-10-07 10:51:07 -04:00
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
}