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

📄 core.c

📁 是一个手机功能的模拟程序
💻 C
📖 第 1 页 / 共 5 页
字号:
    offset_t offset = 0;
    int free;

    tw(tr(TR_BEGIN, TrData, "data_reserved_alloc(%d) {\n", size));
    ttw(ttr(TTrData, "dra(%d) {" NL, size));

    tw(tr(TR_NULL, TrData, "block:free,objects: "));
    for (b = 0; b < dev.numblocks; b++) {
        if (is_block(b, BF_IS_DATA)) {
            free = dev.blocksize - bstat[b].used;
            tw(tr(TR_NULL, TrData, "%d:%d,%d ", b, free, bstat[b].objects));
            if (free >= size) {
                offset = dev.binfo[b].offset + bstat[b].used;
                break;
            }
        } 
    }

    if (offset == 0) {
        // If we couldn't allocate data space we are guaranteed (by design)
        // that we can allocate a block!
        b = block_alloc(0, BF_DATA);
        if (b >= 0)
            offset = dev.binfo[b].offset + bstat[b].used;
    }

    // If we did allocate the space, we update bstat[]
    if (offset != 0) {
        b = offset2block(offset);
        bstat[b].used += size;
        stats.data_allocated += size; // STATS
    }

    tw(tr(TR_END, TrData, "} 0x%04x\n", offset));
    ttw(ttr(TTrData, "} %x" NL, offset));

    return offset;
}


iref_t chunk_alloc(int realsize, int is_journal, offset_t *offset) 
{
    iref_t i;

    if (realsize < 0)
        return EFFS_INVALID;

	// Have we reached objects_max? We make a similar test in
	// inode_alloc_try(), however we need to do it here or else we risk to start
	// a data_reclaim we not can finish.
	if (bstat[fs.inodes].used - bstat[fs.inodes].lost >= fs.objects_max) {
		tw(tr(TR_END, TrObject, "} %d\n", EFFS_FSFULL));
        ttw(ttr(TTrObj, "} %d" NL, EFFS_FSFULL));
        return EFFS_FSFULL;
	}

    // Allocate space for the object name (and object data)
    if (is_journal)
        *offset = data_reserved_alloc(realsize);
    else
        *offset = data_alloc(realsize);

    if (*offset == 0) {
        tw(tr(TR_END, TrObject, "} %d\n", EFFS_NOSPACE));
        ttw(ttr(TTrObj, "} %d" NL, EFFS_NOSPACE));
        return EFFS_NOSPACE;
    }
    fs.journal.location = offset2location(*offset);

    // Allocate an inode for the object
    i = fs.journal.i = inode_alloc();
    if (i == 0) {
        tw(tr(TR_END, TrObject, "} %d\n", EFFS_FSFULL));
        ttw(ttr(TTrObj, "} %d" NL, EFFS_FSFULL));
        return EFFS_FSFULL;
    }

    return i;
}

/******************************************************************************
 * query and fcontrol
 ******************************************************************************/

extern uint16 ffs_flash_device;
extern uint16 ffs_flash_manufact;

effs_t object_control(iref_t i, int8 action, int value)
{
    effs_t error = EFFS_OK;

    tw(tr(TR_BEGIN, TrOther, "object_control(%d, %d, 0x%x) {\n",
          i, action, value));
    ttw(ttr(TTrApi, "obj_control(%d,%d,0x%x)" NL, i, action, value));

    switch (action) {
    case OC_FLAGS:
        // Set/clear object flags. Attempting to modify the "/dev/ffs"
        // object (i = 0) or any non-defined flags is an invalid operation.
        if (i <= 0 || value & ~OF_ALL) {
            error = EFFS_INVALID;
        }
        else {
            // there are two cases; either we only set bits in the flags.
            // This is simple, as we just have to update the flags byte. The
            // other case is harder because we have to clear bits and for
            // this we have to copy the old inode to a new inode, setting
            // the flags appropriately. For now we always just allocate a
            // new inode and set the flags according to the <value>
            // argument.
            journal_begin(i);
            fs.journal.flags |= OF_MASK; // reset all flags
            fs.journal.flags = BIT_SET(fs.journal.flags, value);
            if ((fs.journal.i = inode_alloc()) == 0)
                error = EFFS_FSFULL;
            else {
                fs.journal.diri = dir_traverse(fs.journal.diri, 0);
                journal_end(0);
            }
        }
        break;

    case OC_FS_FLAGS:      fs.flags           = value; break;
    case OC_DEV_MANUFACT:  ffs_flash_manufact = value; break;
    case OC_DEV_DEVICE:    ffs_flash_device   = value; break;
    case OC_FS_TESTFLAGS:  fs.testflags       = value; break;
    case OC_DEBUG_0:
    case OC_DEBUG_1:
    case OC_DEBUG_2:
    case OC_DEBUG_3:       fs.debug[action - OC_DEBUG_FIRST] = value; break;
    case OC_TRACE_INIT:
#if (TARGET == 1)
        ttr_init(value);
#endif
        break;
    default:
        error = EFFS_INVALID;
    }

    tw(tr(TR_END, TrOther, "} %d\n", error));

    return error;
}

extern int tmffs_bufsize(void); // used by ffs_query()
extern unsigned char *tmffs_bufaddr(void); // used by ffs_query()

#if (TARGET == 1)
// request_id_last is only used in TARGET not to any use on the PC side
extern req_id_t request_id_last;   // from task.c
#else
req_id_t request_id_last;
#endif

// If tmffs not is represented we define a dummy tm version
#ifndef FFS_TM_VERSION 
#define FFS_TM_VERSION   ((uint16) 0x0BAD)
#endif

effs_t ffs_query(int8 query, void *p)
{
    tw(tr(TR_FUNC, TrOther, "query(%d) (?)\n", query));

    if (p == NULL)
        return EFFS_INVALID;

    switch (query)
    {
    case Q_BYTES_FREE:
    case Q_BYTES_USED:
    case Q_BYTES_LOST:
    case Q_BYTES_MAX:
    case Q_OBJECTS_TOTAL:
    case Q_BLOCKS_FREE:
    case Q_BYTES_FREE_RAW:
    {
        bref_t b;
        bref_t blocks_free = 0;
        iref_t objects = 0;
        offset_t max, used = 0, lost = 0;
        struct block_stat_s *bp;

		// Don't count free blocks, inode block, block header and reserved space.
		max = (dev.numblocks - fs.blocks_free_min - 1) * 
            (dev.blocksize - BHEADER_SIZE) - fs.reserved_space;

        // Furthermore don't count the ovewrhead from each chunk (alignment)
        // NOTE: If we call query while FFS not is formatted there is a risk
        // of deviding with zero!
        if (fs.chunk_size_max > 0)
            max -= ((max / fs.chunk_size_max + 1) * dev.atomsize);

        for (b = 0, bp = &bstat[0]; b < dev.numblocks; b++, bp++) {
            if (is_block(b, BF_IS_FREE))
                blocks_free++;
            if (is_block(b, BF_IS_DATA)) {
                objects += bp->objects;
                used    += bp->used;
                lost    += bp->lost;
            }
        }
		
        switch (query) {
        case Q_BYTES_FREE:    *(uint32*)p = max - (used - lost) - FFS_FILENAME_MAX; 
            break;
        case Q_BYTES_FREE_RAW:*(uint32*)p = max - (used - lost); break;
        case Q_BYTES_USED:    *(uint32*)p = used; break;
        case Q_BYTES_LOST:    *(uint32*)p = lost; break;
        case Q_BYTES_MAX:     *(uint32*)p = max; break;
        case Q_OBJECTS_TOTAL: *(uint16*)p = objects; break;
        case Q_BLOCKS_FREE:   *(uint16*)p = blocks_free; break;
        }
        break;
    }

    case Q_TM_BUFADDR:       *(uint32*)p = (uint32) tmffs_bufaddr(); break;
    case Q_TM_BUFSIZE:       *(uint32*)p = tmffs_bufsize(); break;
    case Q_DEV_BASE:         *(uint32*)p = (uint32) dev.base; break;

		// FFS versions
    case Q_FFS_API_VERSION:  *(uint16*)p = FFS_API_VERSION; break;
    case Q_FFS_DRV_VERSION:  *(uint16*)p = FFS_DRV_VERSION; break;
    case Q_FFS_REVISION:     *(uint16*)p = ffs_revision; break;
    case Q_FFS_FORMAT_WRITE: *(uint16*)p = FFS_FORMAT_VERSION; break;
    case Q_FFS_FORMAT_READ:  *(uint16*)p = fs.format; break;
    case Q_FFS_LASTERROR:    *(int16*)p  = fs.initerror; break;
	case Q_FFS_TM_VERSION:   *(int16*)p  = FFS_TM_VERSION; break;

		// File system queries
    case Q_FILENAME_MAX:     *(uint16*)p = fs.filename_max; break;
    case Q_PATH_DEPTH_MAX:   *(uint16*)p = fs.path_depth_max; break;

    case Q_OBJECTS_FREE:     *(uint16*)p = fs.objects_max - 
                                 (bstat[fs.inodes].used -
                                  bstat[fs.inodes].lost); break;
    case Q_INODES_USED:      *(uint16*)p = bstat[fs.inodes].used; break;
    case Q_INODES_LOST:      *(uint16*)p = bstat[fs.inodes].lost; break;
    case Q_OBJECTS_MAX:      *(uint16*)p = fs.objects_max; break;

    case Q_INODES_MAX:       *(uint16*)p = fs.inodes_max; break;
    case Q_CHUNK_SIZE_MAX:   *(uint16*)p = fs.chunk_size_max; break;

		// File descriptor queris 
    case Q_FD_BUF_SIZE:      *(uint32*)p = fs.fd_buf_size; break;  
    case Q_FD_MAX:           *(uint16*)p = fs.fd_max; break;
	
		// device queries
    case Q_DEV_MANUFACTURER: *(uint16*)p = dev.manufact; break;
    case Q_DEV_DEVICE:       *(uint16*)p = dev.device; break;
    case Q_DEV_BLOCKS:       *(uint16*)p = dev.numblocks; break;
    case Q_DEV_ATOMSIZE:     *(uint16*)p = dev.atomsize; break;
    case Q_DEV_DRIVER:       *(uint16*)p = dev.driver; break;

		// Miscellaneous/Internal
    case Q_BLOCKS_FREE_MIN:  *(uint16*)p = fs.blocks_free_min; break;
    case Q_LOST_HIGH:        *(uint16*)p = fs.lost_threshold; break;

		// Debug queries
    case Q_FS_FLAGS:         *(uint16*)p = fs.flags; break;
    case Q_FS_INODES:        *(uint16*)p = fs.inodes; break;
    case Q_FS_ROOT:          *(uint16*)p = fs.root; break;

    case Q_STATS_DRECLAIMS:        *(uint32*)p = stats.drec.most_lost + 
                                       stats.drec.most_unused + 
                                       stats.drec.youngest; break;
    case Q_STATS_IRECLAIMS:        *(uint32*)p = stats.irec.num; break;
    case Q_STATS_DATA_RECLAIMED:   *(uint32*)p = stats.drec.valid[0] + 
                                       stats.drec.lost[0]; break;
    case Q_STATS_INODES_RECLAIMED: *(uint32*)p = stats.irec.valid + stats.irec.lost;
        break;
    case Q_STATS_DATA_ALLOCATED:   *(uint32*)p = stats.data_allocated; break;
    case Q_REQUEST_ID_LAST:        *(uint32*)p = request_id_last; break;

    default:
        if (query >= Q_BSTAT && (query - Q_BSTAT) < dev.numblocks)
        {
            struct block_header_s *bhp;
            uint32 *myp = p;
            
            query -= Q_BSTAT;
            bhp = (struct block_header_s *) offset2addr(dev.binfo[query].offset);

            *myp++ = bstat[query].used;
            *myp++ = bstat[query].lost;
            // If we are in READ mode or this block is not lost, we can
            // safely read the age. Otherwise it is maybe currently erasing
            // and thus we cannot read the age.
			// NOTEME: Should this not have been handled by a driver function?
            if (dev.state == DEV_READ || !is_block_flag(query, BF_LOST))
                *myp++ = (bhp->age << 16) | bstat[query].flags;
            else 
                *myp++ = (  0xFFFE << 16) | bstat[query].flags;
            *myp++ = bstat[query].objects;
        }
        else if (query >= Q_DEBUG_FIRST && query < Q_DEBUG_LAST) {
            *(uint32*)p = fs.debug[query - Q_DEBUG_FIRST];
        }
        else
            return EFFS_INVALID;
    }

    return EFFS_OK;
}


/******************************************************************************
 * Miscellaneous Helper Functions
 ******************************************************************************/

// Check if an object is read-only. Note that the root inode is always
// readonly, no matter what! Returns error or original <i>.
iref_t is_readonly(iref_t i, const char *path)
{
    struct inode_s *ip = inode_addr(i);

    tw(tr(TR_FUNC, TrObject, "is_readonly(%d, '%s') ", i, path));

    if (i == fs.root || i == fs.ijournal ||
        (IS_BIT_SET(ip->flags, OF_READONLY) && !ffs_is_modifiable(path)))
        i = EFFS_ACCESS;

    tw(tr(TR_NULL, TrObject, "(0x%X) %d\n", ip->flags, i));

    return i;
}


// Check if filename is valid. Return EFFS_BADNAME if name contains
// invalid chars. Return RFFS_NAMETOOLONG if name is too
// long. Otherwise return filename length.
effs_t is_filename(const char *s)
{
    char *p = (char *) s;
    int n = 0;
    
    while ( (*s >= 'a' && *s <= 'z') ||
            (*s >= 'A' && *s <= 'Z') ||
            (*s >= '0' && *s <= '9') ||
            *s == '.' ||
            *s == ',' ||
            *s == '_' ||
            *s == '-' ||
            *s == '+' ||
            *s == '%' ||
            *s == '$' ||
            *s == '#' )
    {
        s++;
    }
    
    if (*s != 0)
        n = EFFS_BADNAME;  // invalid file name character found
    else {
        n = s - p;
        if (n > fs.filename_max)
            n = EFFS_NAMETOOLONG;
        if (n == 0)
            n = EFFS_BADNAME;
    }

    tw(tr(TR_FUNC, TrUtil, "is_filename('%s') %d\n", p, n));

    return n;
}

int ffs_strlen(const char *s)
{
    const char *p = s;

    while (*p++)
        ;

    tw(tr(TR_FUNC, TrUtil, "strlen('%s') %d\n", s, p-s-1));

    return p-s-1;
}

// Return zero if strings are equal, otherwise return non-zero.
int ffs_strcmp(const char *s, const char *p)
{
    int8 n = 1;

    tw(tr(TR_FUNC, TrUtil, "strcmp('%s', '%s') ", s, p));

    while (*s == *p && *p != 0) {
        s++;
        p++;
    }
    if (*s == *p)
        n = 0;

    tw(tr(TR_NULL, TrUtil, "(%d)\n", n));

    return n;
}

// Note: rename function? like get_fdi..
fd_t get_fdi(iref_t i)
{
    int j;

    tw(tr(TR_FUNC, TrUtil, "get_fdi(%d)\n", i));
    
	if (i > 0) {
		for (j = 0; j < fs.fd_max; j++) {
			if (i == fs.fd[j].seghead) {
				return j;  // Return fdi without offset
			}
		}
	}
    return -1;
}    


⌨️ 快捷键说明

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