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

📄 ffs.c

📁 是一个手机功能的模拟程序
💻 C
📖 第 1 页 / 共 3 页
字号:
            tw(tr_bstat());
            fs.fd[fdi].seghead = i;
        }
        else 
            return EFFS_NOTFOUND;    
    }
    else {
        if (is_open_option(option, FFS_O_WRONLY)) {
            if (is_open_option(option, (FFS_O_CREATE | FFS_O_EXCL)))
                return EFFS_EXISTS;   
            if ((i = is_readonly(i, pathname)) < 0)
                return i;
        }
        ip = inode_addr(i);
        
        if (is_object(ip, OT_DIR))
            return EFFS_NOTAFILE;

        if (is_open_option(option, FFS_O_TRUNC)) { 
            // Save the segment (if any) in the global variable because this
            // global variable will be updated if the inode is relocated by
            // an inode_reclaim() triggeret by object_create()
            fs.i_backup = segment_next(i);

            // Replace old seghead with a new and remove all old segments
            journal_begin(i);

            if ((i = object_create(name, 0, 0, -dir)) < 0)
                return i;

            // Do not link child
            fs.link_child = 0;  
            journal_end(0);

			// If any further segments exist then remove them now
            if (fs.i_backup > 0) 
                if ((error = object_remove(fs.i_backup)) < 0)
                    return error;

            tw(tr_bstat());
        }

        else {
            // Get total size of the file.    
            fs.fd[fdi].size = segfile_seek(i, INT_MAX, &dummy, 0);
        }
        
        if (is_open_option(option, FFS_O_APPEND)) { 
            fs.fd[fdi].fp = fs.fd[fdi].size;
        }
    }
    
    if (is_open_option(option, FFS_O_WRONLY)) {
#if (TARGET == 1)
        if ((fs.fd[fdi].buf = (char *) target_malloc(fs.fd_buf_size)) == 0)
            return EFFS_MEMORY;
#else
        if ((fs.fd[fdi].buf = malloc(fs.fd_buf_size)) == 0)
            return EFFS_MEMORY;
#endif
    }

    // Save data in file descriptor     
	fs.fd[fdi].seghead = i;    
	fs.fd[fdi].options = option;  
 
    return fdi + FFS_FD_OFFSET;

    // TASKEND
}

fd_t ffs_open(const char *pathname, ffs_options_t option)
{
    FFS_BLOCKING_CALL_BEGIN();
    
    result = ffs_open_b(pathname, option, 0, &fb);

    FFS_BLOCKING_CALL_END();

    return result;             
}


req_id_t ffs_open_nb(const char *pathname, ffs_options_t option,
         T_RV_RETURN *cp)
{
    return ffs_open_b(pathname, option, cp, 0);
}

req_id_t ffs_close_b(fd_t fdi, T_RV_RETURN *cp, struct ffs_blocking_s *fb)
{
    int error;

    tw(tr(TR_FUNC, TrApi, "ffs_close(%d) ?\n", fdi));  
	ttw(ttr(TTrApi, "ffs_close(%d) ?" NL, fdi)); 

    // TASKBEGIN effs_t CLOSE(fdi=fdi) iref_t i; int error;

    if (fs.initerror)
        return fs.initerror;

    fdi -= FFS_FD_OFFSET;

    if (!is_fd_valid(fdi))
        return EFFS_BADFD;
    
    if (is_open_option(fs.fd[fdi].options, FFS_O_WRONLY )) {
        if ((error = datasync(fdi)) < 0)
            return error;

#if (TARGET == 1)
        target_free(fs.fd[fdi].buf);
#else
        free(fs.fd[fdi].buf);
#endif
    }

    // Clear all data in file descriptor
    fs.fd[fdi].seghead = 0;
    fs.fd[fdi].options = fs.fd[fdi].fp = 0;

    return EFFS_OK;

    // TASKEND
}

effs_t ffs_close(fd_t fdi)
{
    FFS_BLOCKING_CALL_BEGIN();

    result = ffs_close_b(fdi, 0, &fb);

    FFS_BLOCKING_CALL_END();

    return result;             
}


req_id_t ffs_close_nb(fd_t fdi, T_RV_RETURN *cp)
{
    return ffs_close_b( fdi, cp, 0);
}

req_id_t ffs_write_b(fd_t fdi, void *src, int amount, 
        T_RV_RETURN *cp, struct ffs_blocking_s *fb)
{
    effs_t error;
    iref_t i; 
    int size_remaining, fp_offset;
    int size, size_done;
    offset_t chunk_offset;

    tw(tr(TR_BEGIN, TrApi, "ffs_write_b(%d, 0x%x, %d) ?{\n", fdi, src, amount));
    ttw(ttr(TTrApi, "ffs_write_b(%d, 0x%x, %d) ?" NL, fdi, src, amount)); 

    // TASKBEGIN int WRITE(fdi=fdi, src=src, size=amount) effs_t error; iref_t i; int size_remaining, fp_offset; int size, size_done; offset_t chunk_offset; 

    if (fs.initerror)
        return fs.initerror;

    if (amount < 0 || src == NULL)
        return EFFS_INVALID;
  
    fdi -= FFS_FD_OFFSET;
    
    if (!is_fd_valid(fdi))
        return EFFS_BADFD;

    if (!is_open_option(fs.fd[fdi].options, FFS_O_WRONLY ))
        return EFFS_INVALID; // not opened with write flag

    // If FFS_O_APPEEND is specified move fp to eof
    if (is_open_option(fs.fd[fdi].options, FFS_O_APPEND ))
        fs.fd[fdi].fp = fs.fd[fdi].size;

    // If fp has been moved outside the write buf (by a read) then flush the
    // write buffer.
    if (fs.fd[fdi].fp >= (fs.fd[fdi].wfp + fs.chunk_size_max)) {
        if ((error = datasync(fdi)) < 0)
            return error;
    }

	size_done = 0;
	size_remaining = amount;
    
    do {       
        if (!fs.fd[fdi].dirty ) {   
            // Buffer is not dirty so find the chunk that fp points to.
            segfile_seek(fs.fd[fdi].seghead, fs.fd[fdi].fp, &i, 
                             &chunk_offset);

            if ((fs.fd[fdi].size == fs.fd[fdi].fp && 
                 chunk_offset == fs.chunk_size_max) || fs.fd[fdi].size == 0 ) {
                // End of file and last chunk is full or empty seghead.
                fs.fd[fdi].wfp = fs.fd[fdi].size;
                fs.fd[fdi].wch = 0;  // Create new chunk (not update).
            }
            else {
                // Work on this chunk and update it later by datasyns
                segment_read(i, fs.fd[fdi].buf, fs.fd_buf_size, 0);
                fs.fd[fdi].wfp = fs.fd[fdi].fp - chunk_offset;
                fs.fd[fdi].wch = i;
            }
        }
       
		fs.fd[fdi].dirty = 1;
		fp_offset = fs.fd[fdi].fp - fs.fd[fdi].wfp;

        // Fill the buffer to max or just add the rest
        size = fs.chunk_size_max - fp_offset;

		if (size_remaining <= fs.chunk_size_max - fp_offset)
                size = size_remaining;
       
		tw(tr(TR_FUNC, TrApi, "Copy data to buffer (size: %d)\n", size));

        memcpy(fs.fd[fdi].buf + fp_offset, src + size_done, 
               size);
        
        fs.fd[fdi].fp += size;
        if (fs.fd[fdi].fp > fs.fd[fdi].size)
            fs.fd[fdi].size = fs.fd[fdi].fp;

        size_done += size;         // FIXME: remove size_done or size_remaining
        size_remaining -= size;
        
        // If wrbuf is full (size = chunk_size_max) so create a chunk.
        if (fs.fd[fdi].fp >= (fs.fd[fdi].wfp + fs.chunk_size_max)) {
            if ((error = datasync(fdi)) < 0)
                return error;
        }
    } while(size_remaining > 0);
    
    tw(tr(TR_END, TrApi, "} %d\n", amount));
    return amount;         

    // TASKEND
}

int ffs_write(fd_t fdi, void *src, int amount)
{
    FFS_BLOCKING_CALL_BEGIN();

    result = ffs_write_b(fdi, src, amount, 0, &fb);

    FFS_BLOCKING_CALL_END();

    return result;             
}

req_id_t ffs_write_nb(fd_t fdi, void *src, int amount, T_RV_RETURN *cp)
{
    
    tw(tr(TR_FUNC, TrApi, "ffs_write_nb(%d, 0x%x, %d) ?\n", fdi, src, amount));

    return ffs_write_b(fdi, src, amount, cp, 0);      
}

int ffs_read(fd_t fdi, void *src, int size)
{
    int error;
    
    tw(tr(TR_BEGIN, TrApi, "ffs_read(%d, 0x%x, %d) {\n", fdi, src, size));
    ttw(ttr(TTrApi, "ffs_read(%d, 0x%x, %d) ?" NL, fdi, src, size)); 

    if ((error = ffs_begin()) == EFFS_OK)    
    {
        error = stream_read(fdi - FFS_FD_OFFSET, src, size);
    }

    tw(tr(TR_END, TrApi, "} %d\n", error));
    return ffs_end(error);     // number of bytes read  
}

// The seek function will not allow the file offset to be set beyond the end
// of the existing data in the file or the final offset to be negative.
req_id_t ffs_seek_b(fd_t fdi, int offset, int whence, T_RV_RETURN *cp, 
               struct ffs_blocking_s *fb)
{
	effs_t error;
    int fp_new;

    tw(tr(TR_FUNC, TrApi, "ffs_seek(%d, %d, %d) ?\n", fdi, offset, whence));
    ttw(ttr(TTrApi, "ffs_seek(%d, %d, %d) ?" NL, fdi, offset, whence)); 

    // TASKBEGIN int SEEK(fdi=fdi, size=offset, value16=whence) effs_t error; iref_t i; int fp_new, foffset;

    if (fs.initerror)
        return fs.initerror;

    fdi -= FFS_FD_OFFSET;

    if (!is_fd_valid(fdi))
        return EFFS_BADFD;
    
    switch(whence) {
    case FFS_SEEK_SET:
        if (offset < 0 || offset > fs.fd[fdi].size)
            return EFFS_INVALID;  
        fp_new = offset;
        break;
    case FFS_SEEK_CUR:
        if (fs.fd[fdi].fp + offset < 0 || 
            fs.fd[fdi].fp + offset > fs.fd[fdi].size)
            return EFFS_INVALID;  
        fp_new = fs.fd[fdi].fp + offset;
        break;
    case FFS_SEEK_END:
        if (offset > 0 || fs.fd[fdi].size < -offset)
            return EFFS_INVALID;
        fp_new = (offset + fs.fd[fdi].size);
        break;
    default:
        return EFFS_INVALID;
    }
    
    if (!is_offset_in_buf(fp_new, fdi))
        if ((error = datasync(fdi)) < 0)
            return error;
    
    return fs.fd[fdi].fp = fp_new;
    
    // TASKEND
}

int ffs_seek(fd_t fdi, int offset, int whence) 
{
    FFS_BLOCKING_CALL_BEGIN();

    result = ffs_seek_b(fdi, offset, whence, 0, &fb);

    FFS_BLOCKING_CALL_END();

    return result;             
}

req_id_t ffs_seek_nb(fd_t fdi, int offset, int whence, T_RV_RETURN *cp) 
{
    return ffs_seek_b(fdi, offset, whence, cp, 0);
}

req_id_t ffs_truncate_b(const char *path, offset_t length, T_RV_RETURN *cp, 
                      struct ffs_blocking_s *fb) 
{
    tw(tr(TR_FUNC, TrApi, "ffs_truncate('%s', %d) \n", path, length));
    ttw(ttr(TTrApi, "ffs_ftruncate('%s', %d) ?" NL, path, length)); 

    // TASKBEGIN effs_t TRUNC(path=path, size=length) iref_t i;

    if (fs.initerror)
        return fs.initerror;

    if (path == NULL)
        return EFFS_BADNAME;

    return object_truncate(path, -1, length);
        
    // TASKEND
}

effs_t ffs_truncate(const char *path, offset_t length) 
{
    FFS_BLOCKING_CALL_BEGIN();

    result = ffs_truncate_b(path, length, 0, &fb);

    FFS_BLOCKING_CALL_END();

    return result;             
}

req_id_t ffs_truncate_nb(const char *path, offset_t length, T_RV_RETURN *cp) 
{
    return ffs_truncate_b(path, length, cp, 0);
}

req_id_t ffs_ftruncate_b(fd_t fdi, offset_t length, T_RV_RETURN *cp, 
                       struct ffs_blocking_s *fb)
{
    tw(tr(TR_FUNC, TrApi, "ffs_ftruncate(%d, %d) \n", fdi, length));
    ttw(ttr(TTrApi, "ffs_ftruncate(%d, %d) ?" NL, fdi, length)); 

    // TASKBEGIN effs_t FTRUNC(fdi=fdi, size=length) iref_t i;

    if (fs.initerror)
        return fs.initerror;    
    
    return object_truncate(0, fdi - FFS_FD_OFFSET, length);
    
    // TASKEND
}

effs_t ffs_ftruncate(fd_t fdi, offset_t length)
{
    FFS_BLOCKING_CALL_BEGIN();

    result = ffs_ftruncate_b(fdi, length, 0, &fb);

    FFS_BLOCKING_CALL_END();

    return result;             
}

req_id_t ffs_ftruncate_nb(fd_t fdi, offset_t length, T_RV_RETURN *cp)
{
    return ffs_ftruncate_b(fdi, length, cp, 0);
}

req_id_t ffs_fdatasync_b(fd_t fdi, T_RV_RETURN *cp, struct ffs_blocking_s *fb) 
{
    tw(tr(TR_FUNC, TrApi, "ffs_fdatasync(%d) \n", fdi));
    ttw(ttr(TTrApi, "ffs_fdatasync(%d) ?" NL, fdi)); 
    
    // TASKBEGIN effs_t FDATASYNC(fdi=fdi) effs_t error;

    if (fs.initerror)
        return fs.initerror;
  
    return datasync(fdi - FFS_FD_OFFSET);
    
    // TASKEND
}

effs_t ffs_fdatasync(fd_t fdi) 
{
    FFS_BLOCKING_CALL_BEGIN();

    result = ffs_fdatasync_b(fdi, 0, &fb);

    FFS_BLOCKING_CALL_END();

    return result;             
}

req_id_t ffs_fdatasync_nb(fd_t fdi, T_RV_RETURN *cp) 
{
    return ffs_fdatasync_b(fdi, cp, 0);
}

⌨️ 快捷键说明

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