Beispiel #1
0
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; 
}
Beispiel #2
0
vlFILE* vl_open_file(vaddr header) {
    vlFILE* fp;

    fp = sub_new_fp();
    
    if (fp != NULL) {
        fp->header  = header;
        fp->alloc   = vworm_read(header + 2);               //alloc
        fp->idmod   = vworm_read(header + 4);
        fp->start   = vworm_read(header + 8);               //mirror base addr
        
        if (fp->start != NULL_vaddr) {
            ot_u16 mlen = fp->start;
            fp->start  += 2;
            fp->write   = &vsram_mark;
            fp->read    = &vsram_read;
            fp->length  = vsram_read(mlen);
        }
        else {
            fp->write   = &vworm_write;
            fp->read    = &vworm_read;
            fp->length  = vworm_read(header + 0);           //length
            fp->start   = vworm_read(header + 6);           //vworm base addr
        }
    }
    return fp;
}
Beispiel #3
0
void sub_delete_file(vaddr del_header) { 
#if (OT_FEATURE(VLNEW) == ENABLED)
    vaddr   header_base;
    ot_u16  header_alloc;
    
    header_alloc    = (ot_u16)vworm_read(del_header+2);
    header_base     = (vaddr)vworm_read(del_header+6);
    
    // Wipe the old data and mark header as deleted
    vworm_wipeblock(header_base, header_alloc);
    vworm_mark((del_header+2), 0);                //alloc
    vworm_mark((del_header+6), NULL_vaddr);       //base
#endif
}
Beispiel #4
0
ot_u8 sub_isf_mirror(ot_u8 direction) {
    vaddr   header;
    vaddr   header_base;
    vaddr   header_alloc;
    vaddr   header_mirror;
    //vaddr   header_end;
    ot_int  i;
    ot_u16* mirror_ptr;
    
    // Go through ISF Header array
    header = ISF_Header_START; 
    for (i=0; i<ISF_NUM_STOCK_FILES; i++, header+=sizeof(vl_header)) {
    
        //get header data
        header_alloc    = vworm_read(header+2);
        header_base     = vworm_read(header+6);
        header_mirror   = vworm_read(header+8);

        // Copy vworm to mirror if there is a mirror
        // 0. Skip unmirrored or uninitialized, or unallocated files
        // 1. Resolve Mirror Length (in vsram it is right ahead of the data)
        // 2. Load/Save Mirror Data (header_alloc is repurposed)
        if ((header_mirror != NULL_vaddr) && (header_alloc  != 0)) {
        	mirror_ptr = (ot_u16*)vsram_get(header_mirror);
            if (direction == MIRROR_TO_SRAM) {  // LOAD
                *mirror_ptr = vworm_read(header+0);
            }
            if (header_base == NULL_vaddr) {	// EXIT if file is mirror-only
            	continue;
            }
            if (direction != MIRROR_TO_SRAM) {  // SAVE
                vworm_write((header+0), *mirror_ptr);
            }
            
            header_alloc = header_base + *mirror_ptr;
            mirror_ptr++;
            for ( ; header_base<header_alloc; header_base+=2, mirror_ptr++) {
                if (direction == MIRROR_TO_SRAM) {
                    *mirror_ptr = vworm_read(header_base);
                }
                else { 
                    vworm_write(header_base, *mirror_ptr);
                }
            }
        }
    }
    
    return 0;
}
Beispiel #5
0
ot_u8 vl_getheader_vaddr(vaddr* header, vlBLOCK block_id, ot_u8 data_id, ot_u8 mod, id_tmpl* user_id) {

    /// 1. Get the header from the supplied Block ID & Data ID
    switch (block_id) {
        case VL_GFB_BLOCKID:    *header = sub_gfb_search(data_id);      break;
        case VL_ISFS_BLOCKID:   *header = sub_isfs_search(data_id);     break;
        case VL_ISF_BLOCKID:    *header = sub_isf_search(data_id);      break;
        default:                return 255;
    }

    /// 2. Bail if header is NULL
    if (*header == NULL_vaddr) {
        return 0x01;
    }
    
    /// 3. Authenticate, when it's not a su call
    if (user_id != NULL) {
        Twobytes filemod;
        filemod.ushort = vworm_read(*header + 4);
    
        if ( auth_check(filemod.ubyte[1], mod, user_id) == 0 ) {
            return 0x04;
        }
    }

    return 0;
}
Beispiel #6
0
vaddr sub_header_search(vaddr header, ot_u8 search_id, ot_int num_headers) {
    Twobytes    idmod;
    ot_u16      base;

    for (; num_headers > 0; num_headers--) {
        base            = vworm_read(header + 6);
        idmod.ushort    = vworm_read(header + 4);
        
        if ( base != 0 && base != 0xFFFF) {
            if (idmod.ubyte[0] == search_id) 
                return header;
        }
        
        header += sizeof(vl_header);
    }
    return NULL_vaddr;
}
Beispiel #7
0
void sub_copy_header( vaddr header, ot_u16* output_header ) {
    ot_int i;
    ot_int copy_length = sizeof(vl_header) / 2;

    for (i=0; i<copy_length; i++) {
        output_header[i] = vworm_read(header);
        header += 2;
    }
}
Beispiel #8
0
vaddr sub_find_empty_header(vaddr header, ot_int num_headers) {
    vaddr header_base;
    
    for (; num_headers>0; num_headers--) {
        header_base = vworm_read( (header+6) );
        
        if ( header_base == NULL_vaddr ) {
            return header;
        }
        header += sizeof(vl_header);
    }
    
    return NULL_vaddr;
}
Beispiel #9
0
ot_u8 vl_delete(vlBLOCK block_id, ot_u8 data_id, id_tmpl* user_id) {
#if (OT_FEATURE(VLNEW) == ENABLED)
    vaddr header = NULL_vaddr;
    sub_vaddr   search_fn;
    sub_check   check_fn;

    /// 1. Get the header from the supplied Block ID & Data ID
    block_id--;
    switch (block_id) {
        case 0: check_fn    = &sub_gfb_delete_check;
                search_fn   = &sub_gfb_search;
                break;
                
        case 1: check_fn    = &sub_isfs_delete_check;
                search_fn   = &sub_isfs_search;
                break;
                
        case 2: check_fn    = &sub_isf_delete_check;
                search_fn   = &sub_isf_search;
                break;
                
       default: return 255;
    }
    
    if (check_fn(data_id) != 0) {
        header = search_fn(data_id);
    }
    
    /// 2. Bail if header is NULL
    if (header == NULL_vaddr) {
        return 0x01;
    }
    
    /// 3. Authenticate, when it's not a su call
    if (user_id != NULL) {
        Twobytes filemod;
        filemod.ushort = vworm_read(header + 4);
         
        if ( auth_check(filemod.ubyte[1], VL_ACCESS_RW, user_id) == 0 ) {
            return 0x04;
        }
    }
    
    sub_delete_file(header);
    return 0;
#else
    return 255; //error, delete disabled
#endif
}
Beispiel #10
0
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;
}
Beispiel #11
0
ot_u8 vl_close( vlFILE* fp ) {
    if (FP_ISVALID(fp)) {        
        if (fp->read == &vsram_read) {
            ot_u16* mhead;
            mhead   = (ot_u16*)vsram_get(fp->start-2);
            *mhead  = (*mhead != fp->length) ? fp->length : *mhead;
        }
        else if ( vworm_read(fp->header+0) != fp->length ) {
            sub_write_header( (fp->header+0), &(fp->length), 2);
        }
            
        // Kill file attributes
        fp->start   = 0;
        fp->length  = 0;
        //fp->header  = NULL_vaddr;
        fp->read    = NULL;
        fp->write   = NULL;
        
        return 0;
    }
    return 255;
}
Beispiel #12
0
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;
}
Beispiel #13
0
/// @todo This checks out in testing, although it is a complex function that
///       probably merits further testing
vaddr sub_find_empty_heap(  vaddr heap_base, vaddr heap_end, 
                        vaddr header, ot_uint new_alloc, ot_int num_headers) {
#if (OT_FEATURE(VLNEW) == ENABLED)
    //Search all header combinations to find:
    // - pairs of adjacent files in the heap
    // - gaps between these pairs
    // - the smallest gap that is big enough.
    vaddr   loop1           = header;
    vaddr   loop1_base;
    ot_uint loop1_alloc;
    vaddr   loop2;
    vaddr   loop2_base;
    //ot_uint loop2_alloc;	///@todo figure out why this is disused
    
    ot_int  i;
    ot_int  j;
    ot_int  gap;
    ot_int  closest_gap     = (ot_int)(heap_end - heap_base);
    ot_int  bestfit_alloc   = (ot_int)(32767);
    vaddr   bestfit_base    = NULL_vaddr;
    //vaddr   loop1_end       = heap_base;
    
    for (i=0; i<num_headers; i++, loop1+=sizeof(vl_header) ) {
        loop1_alloc = vworm_read(loop1 + 2);                                    // load alloc (max) from header
        loop1_base  = vworm_read(loop1 + 6);                                    // load base from header
        
        if ( loop1_base != NULL_vaddr ) {                                       // skip if header is deleted, or empty
            heap_base   = (vaddr)(loop1_base + loop1_alloc);
            loop2       = header;
        
            for (j=0; j<num_headers; j++, loop2+=sizeof(vl_header) ) {
                //loop2_alloc = vworm_read(loop2 + 2);
                loop2_base  = vworm_read(loop2 + 6);
            
                if ( (loop2_base != NULL_vaddr) && (loop2_base > heap_base) ) { // if header is valid ...
                    gap = (ot_int)(loop2_base - heap_base);                     // calc gap between the two files
                
                    if (gap < closest_gap) {                                    // The closest gap ...
                        closest_gap = gap;                                      // will be between two adjacent ...
                        //heap_base   = loop1_end;                                // files in the heap.
                    }
                }
            }
        }
        //if (closest_gap >= new_alloc) {                                         // If the gap between loop1 and next file ...
        //    if (closest_gap < bestfit_alloc) {                                  // is big enough for the data we need ...
        //        bestfit_alloc   = closest_gap;                                  // and is smaller than other big-enough gaps ...
        //        bestfit_base    = heap_base;                                    // then it is the gap we will write into.
        //    }
        //}
        if ((closest_gap >= new_alloc) && (closest_gap < bestfit_alloc))  {
            bestfit_alloc   = closest_gap;
            bestfit_base    = heap_base;
        }

    }
    
    return bestfit_base;
#else
    return NULL_vaddr;
#endif
}