⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 core.c

📁 MMI层OBJ不能完全编译
💻 C
📖 第 1 页 / 共 5 页
字号:
					{

						/* cache the complete chunk data from nor flash  */
        				memcpy(fs.fd[fdi].cache_read_buf,p,fs.fd[fdi].cache_read_buf_size);

		        		/* copy from buf --- parameter to this function  */
						/* At this point , offset will be zero */
    					memcpy(buf,fs.fd[fdi].cache_read_buf+offset, size);
						
					}	/* End of if (fs.fd[fdi])*/
				
			} /* End of if (size > ...)*/	

	   
 	}

  return size;  /* return the size read */

}


#endif


int segment_read(iref_t i, char *buf, int size, int offset)
{
    struct inode_s *ip;
    char *p;
    int chunk_size;

    tw(tr(TR_BEGIN, TrObject, "segment_read(%d, 0x%x, %d, %d) {\n",
       i, buf, offset, size));

    if (buf == NULL) {
        tw(tr(TR_END, TrObject, "} %d\n", EFFS_INVALID));
        return EFFS_INVALID;
    }

    ip = inode_addr(i);
    
    chunk_size = segment_datasize(ip);
    
    // Saturate read buffer
    if (size > chunk_size - offset)
        size = chunk_size - offset;
   
    p = offset2addr(location2offset(ip->location));    
    p = addr2data(p, ip);

    memcpy(buf, &p[offset], size);

    tw(tr(TR_END, TrObject, "} %d\n", size));
    return size;
}

// Find next valid chunk
iref_t segment_next(iref_t i)
{
    struct inode_s *ip = inode_addr(i);
    
    tw(tr(TR_BEGIN, TrDirHigh, "ffs_segment_next(%d) {\n", i));

    // Dir is not allowed to contain data
    if (is_object(ip, OTE_DIR)) {
        tw(tr(TR_END, TrDirHigh, "} 0\n"));
        return 0;
    }

    // Is this the last/only segment
    if ((i = get_child(ip)) == (iref_t) IREF_NULL) {
        tw(tr(TR_END, TrDirHigh, "} 0\n"));
        return 0;
    }

    // Get child (is valid?), search though segment by sibling link(is
    // valid?), and again..
    do {
        i = get_child(ip);
        ip = inode_addr(i);
        if (is_object_valid(ip)) {
            tw(tr(TR_END, TrDirHigh,"} %d\n", i));
            return i;
        }

        while (get_sibling(ip) != (iref_t) IREF_NULL) {  
            i = get_sibling(ip);
            ip = inode_addr(i);
            if (is_object_valid(ip)) {
                tw(tr(TR_END, TrDirHigh,"} %d\n", i));
                return i;
            }
        }
    } while (get_child(ip) != (iref_t) IREF_NULL); 

    // No segment found
    tw(tr(TR_END, TrDirHigh,"} %d\n", i));
    return 0;
}

// The output "inode" will be the inode that contains the requested data or
// the last inode in the segmentfile. The segmenthead will be skiped if it
// don't contains any data. inode_offset is the offset in the found inode
// pointed to by target_offset. If target_offset point past the last segment
// inode_offset will be the size of the last inode. The return value will be
// the same as target_offset but maximum the total size of the object.
int segfile_seek(iref_t seghead, int target_offset, 
                     iref_t *inode, int *inode_offset)
{
    int priv_count = 0, count_size = 0;
    iref_t i = seghead;
    struct inode_s *ip;

    tw(tr(TR_BEGIN, TrObject, "segfile_seek(%d, %d, ?, ?) {\n", 
          seghead, target_offset));
    
    if (!is_object_valid(inode_addr(seghead))) {
        ffs_panic(EFFS_INVSEGHEAD);
        return 0;
    }
    *inode = seghead;

    while (1)
    {
        ip = inode_addr(i);
        count_size += segment_datasize(ip);
        
        // Seghead will be skiped if it don't contain any data  
        if (count_size > target_offset && count_size != 0) {

            if (inode_offset != 0)
                *inode_offset = target_offset - priv_count;

            tw(tr(TR_END, TrObject, "} %d\n", target_offset));
            return target_offset;
        }

        if ((i = segment_next(i)) == 0) {
            tw(tr(TR_END, TrObject, "} (eof!?) %d\n", count_size));
            if (inode_offset != 0)
                *inode_offset = count_size - priv_count;
            // *inode = 0;
            return count_size; // No more segments
        }
        priv_count = count_size;

        *inode = i;
    }
}

// Calculate exact size of file data; without filename and null terminator
// and without data null terminator and succeeding alignment padding.
// NOTEME: Does this also work for empty files and directories?
int segment_datasize(const struct inode_s *ip)
{
    char *p, *q;
    int size;

    p = offset2addr(location2offset(ip->location));
    q = p + ip->size - 1;

    // Segments is not allowed to contain any name
    if (!is_object(ip, OTE_SEGMENT)) {
        // skip filename at start of data
        while (*p)
            p++;
    }
    else 
        // If it contained a name would p pointe to the null terminator of
        // the name but because chunks don't have a name decrement we p to get
        // the size correct
        p--;
    
    // skip padding at end of data
    while (*q)
        q--;
    
    // If there are data, there is also a null-terminator. Otherwise
    // there is no null-terminator
    size = q - p;
    if (size > 0)
        size--;

    tw(tr(TR_FUNC, TrObject, "segment_datasize(0x%x) %d\n", ip, size));
    return size;
}


int object_truncate(const char *pathname, fd_t fdi, offset_t length)
{
    int segment_offset, flength, realsize, offset;
    iref_t i, dir, next_i;
    char *name = 0, *olddata;
    struct inode_s *oldip;
    effs_t error; 
    
    tw(tr(TR_FUNC, TrObject, "ffs_object_truncate('%s', %d, %d) \n", 
          pathname, fdi, length));
    if (length < 0) return EFFS_INVALID;
    
    if (pathname == 0) {
        // File descriptor must be open and it have to be in write mode
        if (!is_fd_valid(fdi)) 
            return EFFS_BADFD;;
       
        if (!is_open_option(fs.fd[fdi].options, FFS_O_WRONLY))
            return EFFS_INVALID; 
          
        // It is not possible to truncate an open file to a size less than
        // the current file pointer
        if (length < fs.fd[fdi].fp)
            return EFFS_INVALID;

        i = fs.fd[fdi].seghead;
    }
    else {
        // File must exists and not be open
        if ((i = object_lookup(pathname, &name, &dir)) < 0)
            return i;

        if (get_fdi(i) >= 0) 
            return EFFS_LOCKED;

        oldip = inode_addr(i);
        // Even though the ffs architecture allows to have data in directory
        // objects, we don't want to complicate matters, so we return an error
        if (is_object(oldip, OTE_DIR) && !(fs.flags & FS_DIR_DATA)) 
            return EFFS_NOTAFILE;
        
        if ((i = is_readonly(i, pathname)) < 0) 
            return i;
    }
    // Find the segment which length points in to
    flength = segfile_seek(i, length, &i, &segment_offset);

    if (pathname == 0) {
        if (is_offset_in_buf(length, fdi) == 1) {
            fs.fd[fdi].size = (length > fs.fd[fdi].size ? 
                               fs.fd[fdi].size : length); // Truncate the buffer 
            
            if (i == fs.fd[fdi].wch) {
                next_i = segment_next(i);
                if (next_i > 0) 
                    if ((error = object_remove(next_i)) < 0)
                        return error;
            }
            return EFFS_OK;
        } 
    }
    
    if (flength < length)
        return EFFS_OK;
    
    journal_begin(i);
    
    // Realsize do not always need to include a name but we simplify it. 
    realsize = atomalign(segment_offset + 1 + fs.filename_max + 1); 

    // Make sure that there is enough space to make the rename without
    // object_create() trigger a data_reclaim() (awoid relocate oldi/data
    // source)
    if ((offset = data_prealloc(realsize)) <= 0)
        return EFFS_NOSPACE;

    // Find the next segment if any.
    next_i = segment_next(fs.journal.oldi);
    
    // Find old data source
    oldip = inode_addr(fs.journal.oldi);
    olddata = offset2addr(location2offset(oldip->location));
    name = addr2name(olddata);   // reinit name (maybe relocated)
    olddata = addr2data(olddata, oldip);
    
    if (is_object(oldip, OTE_SEGMENT)) {
        if (segment_offset == 0)
            next_i = fs.journal.oldi; // Remove the found object
        else {
            if ((i = segment_create(olddata, segment_offset, 
                                        -fs.journal.oldi)) < 0)
                return i;
            
            fs.link_child = 0;  //Do not link child
            journal_end(0);
        }
    }
    else {
        if ((i = object_create(name, olddata, length, fs.journal.oldi)) < 0)
            return i;
        fs.link_child = 0;  //Do not link child
        journal_end(0);
        
        if (is_fd_valid(fdi))
            fs.fd[fdi].seghead = i;
    }

    if (is_fd_valid(fdi))
        fs.fd[fdi].size = length;

    // If any remaning segment exists then remove them 
    if (next_i > 0) 
        if ((error = object_remove(next_i)) < 0)
            return error;

    return EFFS_OK;
}


// Find the last segment valid or not valid
iref_t chunk_traverse(iref_t i)
{
    struct inode_s *ip = inode_addr(i);
    
    tw(tr(TR_BEGIN, TrDirHigh, "ffs_chunk_traverse(%d) {\n", i));
    // Is this the last/only segment?
    if (get_child(ip) == (iref_t) IREF_NULL) {
        tw(tr(TR_END, TrDirHigh, "} %d\n", i));
        return i;
    }
        
    // Get child, find the last segment by sibling link, and again..
    do {
        i = get_child(ip);
        ip = inode_addr(i);

        while (get_sibling(ip) != (iref_t) IREF_NULL) {  
            i = get_sibling(ip);
            ip = inode_addr(i);
        }
    } while (get_child(ip) != (iref_t) IREF_NULL); 

    tw(tr(TR_END, TrDirHigh, "} %d\n", i));

    return i;
}

// fdi include offset now but change this so core use pure fdi.
effs_t datasync(fd_t fdi) 
{
    int chunk_size;
    iref_t i;
    struct inode_s *ip;
    char *name;

    tw(tr(TR_FUNC, TrObject, "datasync(%d) \n", fdi));
    ttw(ttr(TTrApi, "datasync(%d) {" NL, fdi)); 

    // NOTEME: is this necessary?
    if (!is_fd_valid(fdi))
        return EFFS_BADFD;

    if (fs.fd[fdi].dirty == 0) 
        return EFFS_OK;

    // If size - wfp is more than max is the complete buffer valid or else
    // is it only a part of it that consist valid data
        chunk_size = fs.fd[fdi].size - fs.fd[fdi].wfp;
        if (chunk_size > fs.chunk_size_max)
            chunk_size = fs.chunk_size_max;

      ip = inode_addr(fs.fd[fdi].wch);        

    // Create new chunk or update a old one
    if (fs.fd[fdi].wch > 0) {
        // Update existing chunk
        // Negativ dir input because it is a update (do not traverse)
        if (is_object(ip, OTE_SEGMENT)) {
            journal_begin(fs.fd[fdi].wch);
    
            if ((i = segment_create(fs.fd[fdi].buf, chunk_size,
                                   -fs.fd[fdi].wch)) < 0)
                return i;
        }

        else {
            // Seghead update (like a normal file)
            ip = inode_addr(fs.fd[fdi].seghead);        
            name = addr2name(offset2addr(location2offset(ip->location)));
            journal_begin(fs.fd[fdi].seghead);

            if ((i = object_create(name, fs.fd[fdi].buf, chunk_size, 
                                      fs.fd[fdi].seghead)) < 0)
                return i;
                
            fs.fd[fdi].seghead = i;
        }
        journal_end(0);
    }        

    else {
        // Create new chunk at the end of the existing ones.
        // BTW: A seghead will always have been made before this one.
        journal_begin(0);

        if ((i = segment_create(fs.fd[fdi].buf, chunk_size, 
                                    fs.fd[fdi].seghead)) < 0)
            return i;

        journal_end(OTE_SEGMENT);
    }
    fs.fd[fdi].dirty = fs.fd[fdi].wch = 0;
#if (FFS_SEEK_OPT == 1)
	fs.fd[fdi].rch = i;
	fs.fd[fdi].roffset = (fs.fd[fdi].fp - fs.fd[fdi].wfp);
#endif

    ttw(ttr(TTrApi, "} 0" NL)); 
    return EFFS_OK;
}

/******************************************************************************
 * Development and Tracing
 ******************************************************************************/

#if (TARGET == 0)

void tr_bstat(void)
{
    int i, n;
  

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -