ot_int sub_fileheaders( alp_tmpl* alp, id_tmpl* user_id, ot_u8 respond, ot_u8 cmd_in, ot_int data_in ) { ot_int data_out = 0; vlBLOCK file_block = (vlBLOCK)((cmd_in >> 4) & 0x07); /// Only run if respond bit is set! if (respond) { while ((data_in > 0) && sub_qnotfull(respond, 6, alp->outq)) { vaddr header; ot_bool allow_output = True; data_in--; // one for the file id allow_output = (ot_bool)(vl_getheader_vaddr(&header, file_block, \ q_readbyte(alp->inq), VL_ACCESS_R, NULL) == 0); if (allow_output) { q_writeshort_be(alp->outq, vworm_read(header + 4)); // id & mod q_writeshort(alp->outq, vworm_read(header + 0)); // length q_writeshort(alp->outq, vworm_read(header + 2)); // alloc data_out += 6; } } //alp->BOOKMARK_IN = (void*)sub_testchunk(data_in); } return data_out; }
vlFILE* vl_open(vlBLOCK block_id, ot_u8 data_id, ot_u8 mod, id_tmpl* user_id) { vaddr header = NULL_vaddr; if (vl_getheader_vaddr(&header, block_id, data_id, mod, user_id) == 0) { return vl_open_file(header); } return NULL; }
ot_u8 vl_getheader(vl_header* header, vlBLOCK block_id, ot_u8 data_id, ot_u8 mod, id_tmpl* user_id) { vaddr header_vaddr = NULL_vaddr; ot_u8 output; output = vl_getheader_vaddr(&header_vaddr, block_id, data_id, mod, user_id); if (output == 0) { sub_copy_header( header_vaddr, (ot_u16*)header ); } return output; }
ot_u8 vl_chmod(vlBLOCK block_id, ot_u8 data_id, ot_u8 mod, id_tmpl* user_id) { vaddr header = NULL_vaddr; ot_u8 output; output = vl_getheader_vaddr(&header, block_id, data_id, VL_ACCESS_RW, user_id); if (output == 0) { Twobytes idmod; idmod.ubyte[0] = data_id; idmod.ubyte[1] = mod; sub_write_header((header+4), &idmod.ushort, 2); } return output; }
ot_int sub_fileperms( alp_tmpl* alp, id_tmpl* user_id, ot_u8 respond, ot_u8 cmd_in, ot_int data_in ) { ot_int data_out = 0; vlBLOCK file_block = (vlBLOCK)((cmd_in >> 4) & 0x07); ot_u8 file_mod = ((cmd_in & 0x02) ? VL_ACCESS_W : VL_ACCESS_R); /// Loop through all the listed file ids and process permissions. while ((data_in > 0) && sub_qnotfull(respond, 2, alp->outq)) { ot_u8 file_id = q_readbyte(alp->inq); ot_bool allow_write = respond; vaddr header; data_in--; // one for the file id if (file_mod == VL_ACCESS_W ) { /// run the chmod and return the error code (0 is no error) data_in--; // two for the new mod file_mod = vl_chmod(file_block, file_id, q_readbyte(alp->inq), user_id); } else if (allow_write) { /// Get the header address and return mod (offset 5). The root user /// (NULL) is used because this is only for reading filemod. /// Note: This is a hack that is extremely optimized for speed allow_write = (ot_bool)(vl_getheader_vaddr(&header, file_block, file_id, \ VL_ACCESS_R, NULL) == 0); if (allow_write) { Twobytes filemod; filemod.ushort = vworm_read(header + 4); //shortcut to idmod, hack-ish but fast file_mod = filemod.ubyte[1]; } } if (allow_write) { /// load the data onto the output, if response enabled q_writebyte(alp->outq, file_id); q_writebyte(alp->outq, file_mod); data_out += 2; } } /// return number of bytes put onto the output (always x2) //alp->BOOKMARK_IN = (void*)sub_testchunk(data_in); return data_out; }
ot_int sub_filedata( alp_tmpl* alp, id_tmpl* user_id, ot_u8 respond, ot_u8 cmd_in, ot_int data_in ) { vlFILE* fp; ot_u16 offset; ot_u16 span; ot_int data_out = 0; ot_bool inc_header = (ot_bool)((cmd_in & 0x0F) == 0x0C); vlBLOCK file_block = (vlBLOCK)((cmd_in >> 4) & 0x07); ot_u8 file_mod = ((cmd_in & 0x02) ? VL_ACCESS_W : VL_ACCESS_R); ot_queue* inq = alp->inq; ot_queue* outq = alp->outq; sub_filedata_TOP: while (data_in > 0) { vaddr header; ot_u8 err_code; ot_u8 file_id; ot_u16 limit; //alp->BOOKMARK_IN = inq->getcursor; //alp->BOOKMARK_OUT = NULL; file_id = q_readbyte(inq); offset = q_readshort(inq); span = q_readshort(inq); limit = offset + span; err_code = vl_getheader_vaddr(&header, file_block, file_id, file_mod, user_id); file_mod = ((file_mod & VL_ACCESS_W) != 0); //fp = NULL; // A. File error catcher Stage // (In this case, gotos make it more readable) /// Make sure file header was retrieved properly, or goto error if (err_code != 0) { goto sub_filedata_senderror; } /// Make sure file opens properly, or goto error fp = vl_open_file(header); if (fp == NULL) { err_code = 0xFF; goto sub_filedata_senderror; } /// Make sure offset is within file bounds, or goto error if (offset >= fp->alloc) { err_code = 0x07; goto sub_filedata_senderror; } if (limit > fp->alloc) { limit = fp->alloc; err_code = 0x08; } // B. File Writing or Reading Stage // Write to file // 1. Process error on bad ALP parameters, but still do partial write // 2. offset, span are adjusted to convey leftover data // 3. miscellaneous write error occurs when vl_write fails if (file_mod) { for (; offset<limit; offset+=2, span-=2, data_in-=2) { if (inq->getcursor >= inq->back) { goto sub_filedata_overrun; } err_code |= vl_write(fp, offset, q_readshort_be(inq)); } } // Read from File // 1. No error for bad read parameter, just fix the limit // 2. If inc_header param is set, include the file header in output // 3. Read out file data else { ot_u8 overhead; //limit = (limit > fp->length) ? fp->length : limit; overhead = 6; overhead += (inc_header != 0) << 2; if ((outq->putcursor+overhead) >= outq->back) { goto sub_filedata_overrun; } q_writeshort_be(outq, vworm_read(header + 4)); // id & mod if (inc_header) { q_writeshort(outq, vworm_read(header + 0)); // length q_writeshort(outq, vworm_read(header + 2)); // alloc data_out += 4; } q_writeshort(outq, offset); q_writeshort(outq, span); data_out += 6; for (; offset<limit; offset+=2, span-=2, data_out+=2) { if ((outq->putcursor+2) >= outq->back) { goto sub_filedata_overrun; } q_writeshort_be(outq, vl_read(fp, offset)); } } // C. Error Sending Stage sub_filedata_senderror: if ((respond != 0) && (err_code | file_mod)) { if ((outq->putcursor+2) >= outq->back) { goto sub_filedata_overrun; } q_writebyte(outq, file_id); q_writebyte(outq, err_code); q_markbyte(inq, span); // go past any leftover input data data_out += 2; } data_in -= 5; // 5 bytes input header vl_close(fp); } // Total Completion: // Set bookmark to NULL, because the record was completely processed //alp->BOOKMARK_IN = NULL; return data_out; // Partial or Non Completion: // Reconfigure last ALP operation, because it was not completely processed ///@todo Bookmarking is obsolete, because the way Chunking is done has /// been revised. Chunked records must be contiguous. ALP-Main will not /// call this app, and thus not call this function, until the message-end /// bit is detected, therefore meaning that all data is received and /// contiguous. This overrun block, thus, should only check the flags for /// chunking, bypass them, and loop back to the top of this function. sub_filedata_overrun: vl_close(fp); ///@todo alp_next_chunk(alp); // { // ot_u8* scratch; // inq->getcursor = (ot_u8*)alp->BOOKMARK_IN; // scratch = inq->getcursor + 1; // *scratch++ = ((ot_u8*)&offset)[UPPER]; // *scratch++ = ((ot_u8*)&offset)[LOWER]; // *scratch++ = ((ot_u8*)&span)[UPPER]; // *scratch = ((ot_u8*)&span)[LOWER]; // } return data_out; }