Skip to content
Snippets Groups Projects
Select Git revision
  • 95dd9143b713ab04f3f8545242c1bb3a4f221db3
  • master default protected
  • scalp_fast_router_firmware_petalinux
  • scalp_router_firmware_petalinux
  • feature-mipi
  • SCALP-USER-USB
  • SCALP_ROUTER_DMA-v0.3
  • SCALP_ROUTER_DMA-v0.2
  • SCALP-FAST-ROUTER-v0.1
  • SCALP_ROUTER_SLOW-v0.3
  • SCALP_ROUTER_SLOW-v0.2
  • SCALP_ROUTER_SLOW-v0.1
  • SCALP-USER-v0.5.1
  • SCALP-SAFE-v0.5.1
  • SCALP-SAFE-v0.5
  • SCALP-USER-v0.5
  • SCALP-SAFE-v0.4.3
  • SCALP-USER-v0.1
  • SCALP-SAFE-v0.4.2
  • SCALP-SAFE-v0.4.1
  • SCALP-SAFE-v0.4
  • SCALP-SAFE-v0.3
  • SCALP-SAFE-v0.2
  • SCALP-SAFE-DEBUG-SJA1105-v0.01
  • SCALP-SAFE-v0.01
25 results

system.xsa

Blame
  • minix.c 11.23 KiB
    #include "minix.h"
    #include <fcntl.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <string.h>
    #include <sys/stat.h>
    #include <unistd.h>
    
    int unmarshal_sb(struct minix_super_block *sb, const char *img_filepath) {
        int fd = open(img_filepath, O_RDONLY);
    
        if (fd == -1) {
            perror("open");
            close(fd);
            return -1;
        }
    
        lseek(fd, BLOCK_SIZE, SEEK_SET);
    
        if (read(fd, sb, sizeof(struct minix_super_block)) == -1) {
            perror("read");
            close(fd);
            return -1;
        }
    
        if (sb->s_magic != MINIX_MAGIC) {
            fprintf(stderr, "The provided image isn't a minix-FS image whose magic "
                            "value is 0x137F\n");
            close(fd);
            return -1;
        }
    
        close(fd);
        return 0;
    }
    
    int unmarshal_inode(struct minix_inode *inode, const uint32_t inode_nb,
                        const char *img_filepath) {
        struct minix_super_block sb = {0};
    
        if (unmarshal_sb(&sb, img_filepath) == -1) {
            perror("marshal_sb");
            return -1;
        }
    
        int fd = open(img_filepath, O_RDONLY);
    
        if (fd == -1) {
            perror("open");
            close(fd);
            return -1;
        }
    
        lseek(fd, BLOCK_SIZE * BITMAP_INODE_FIRST_IDX, SEEK_SET);
    
        if (inode_nb == 0 || inode_nb > sb.s_ninodes ||
            !is_inode_allocated(inode_nb, img_filepath)) {
            fprintf(stderr, "Inode isn't allocated or inode value is invalid\n");
            return -1;
        }
    
        uint16_t inode_table_size = sb.s_ninodes / sizeof(struct minix_inode);
        uint16_t idx_first_block_inode_table =
            sb.s_firstdatazone - inode_table_size;
    
        lseek(fd,
              BLOCK_SIZE * idx_first_block_inode_table +
                  ((inode_nb - 1) * sizeof(struct minix_inode)),
              SEEK_SET);
    
        if (read(fd, inode, sizeof(struct minix_inode)) == -1) {
            perror("open");
            close(fd);
            return -1;
        }
    
        close(fd);
        return 0;
    }
    
    bool is_inode_allocated(const uint32_t inode_nb, const char *img_filepath) {
        int fd = open(img_filepath, O_RDONLY);
    
        if (fd == -1) {
            perror("open");
            close(fd);
            return -1;
        }
    
        // Computes in which block of the inode's bitmap is the bit associated
        // to the given inode number
        int inode_bitmap_block = (inode_nb / (BLOCK_SIZE * BYTE_BITSIZE)) + 1;
    
        char buf[BLOCK_SIZE] = {0};
    
        lseek(fd, BLOCK_SIZE * BITMAP_INODE_FIRST_IDX * inode_bitmap_block,
              SEEK_SET);
    
        // Checking if we've read an entire block or not
        ssize_t bytes_read = read(fd, buf, BLOCK_SIZE);
        if (bytes_read == -1) {
            perror("read");
            close(fd);
            return false;
        }
    
        if (bytes_read == BLOCK_SIZE) {
            uint16_t byte_idx = inode_nb / BYTE_BITSIZE;
            uint8_t bit_idx = inode_nb % BYTE_BITSIZE;
    
            close(fd);
            return buf[byte_idx] & (0x01 << bit_idx);
        }
    
        close(fd);
        return false;
    }
    
    int read_sb(const struct minix_super_block *sb) {
        if (sb->s_magic != MINIX_MAGIC) {
            fprintf(stdout, "Wrong magic value\n");
            return -1;
        }
    
        uint16_t inode_table_size = sb->s_ninodes / sizeof(struct minix_inode);
        uint16_t idx_first_block_inode_table =
            sb->s_firstdatazone - inode_table_size;
    
        fprintf(stdout, "========= MINIX Superblock =========\n");
        fprintf(stdout, "Signature (Magic) :\t0x%x\n", sb->s_magic);
        fprintf(stdout, "Total number of inodes :\t%d\n", sb->s_ninodes);
        fprintf(stdout, "Total number of blocks :\t%d\n", sb->s_nzones);
        fprintf(stdout, "Size of inode bitmap (in blocks) :\t%d\n",
                sb->s_imap_blocks);
        fprintf(stdout, "Size of data bitmap (in blocks) :\t%d\n",
                sb->s_zmap_blocks);
        fprintf(stdout, "Size of inode table (in blocks) :\t%d\n",
                inode_table_size);
        fprintf(stdout, "Index of first inode bitmap block :\t%d\n",
                BITMAP_INODE_FIRST_IDX);
        fprintf(stdout, "Index of first data bitmap block :\t%d\n",
                BITMAP_INODE_FIRST_IDX + sb->s_imap_blocks);
        fprintf(stdout, "Index of first inode table block:\t%d\n",
                idx_first_block_inode_table);
        fprintf(stdout, "Index of first data block:\t%d\n", sb->s_firstdatazone);
    
        return 0;
    }
    
    int read_inode(const struct minix_inode *inode) {
        uint16_t file_type = inode->i_mode >> 12;
    
        fprintf(stdout, "========= MINIX inode =========\n");
        fprintf(stdout, "File type : ");
    
        switch (file_type) {
        case 0x1:
            fprintf(stdout, "named pipe (FIFO)\n");
            break;
        case 0x2:
            fprintf(stdout, "char device\n");
            break;
        case 0x4:
            fprintf(stdout, "directory\n");
            break;
        case 0x6:
            fprintf(stdout, "block device\n");
            break;
        case 0x8:
            fprintf(stdout, "regular file\n");
            break;
        case 0xA:
            fprintf(stdout, "symbolic link\n");
            break;
        default:
            fprintf(stdout, "invalid file type\n");
            return -1;
        }
    
        // User Group Other (ugo) - permissions
        char permissions[12] = {0};
        uint16_t ugo = inode->i_mode & 0x1FF;
    
        uint8_t user = (ugo >> 6) & 0x7;
        uint8_t group = (ugo >> 3) & 0x7;
        uint8_t other = ugo & 0x7;
    
        uint8_t buf[3] = {user, group, other};
    
        for (size_t i = 0; i < 3; i++) {
            switch (buf[i]) {
            case 0:
                strncat(permissions, "___", 3);
                break;
            case 1:
                strncat(permissions, "__x", 3);
                break;
            case 2:
                strncat(permissions, "_w_", 3);
                break;
            case 3:
                strncat(permissions, "_wx", 3);
                break;
            case 4:
                strncat(permissions, "r__", 3);
                break;
            case 5:
                strncat(permissions, "r_x", 3);
                break;
            case 6:
                strncat(permissions, "rw_", 3);
                break;
            case 7:
                strncat(permissions, "rwx", 3);
                break;
            }
            strncat(permissions, " ", 1);
        }
    
        fprintf(stdout, "Permissions : %s\n", permissions);
        fprintf(stdout, "UID : %d\n", inode->i_uid);
        fprintf(stdout, "GID : %d\n", inode->i_gid);
        fprintf(stdout, "Size (in bytes) : %d\n", inode->i_size);
        fprintf(stdout, "NB links : %d\n", inode->i_nlinks);
    
        return 0;
    }
    
    int read_indir_block(uint16_t *buf, const char *img_filepath,
                         const size_t block_number) {
        int fd = open(img_filepath, O_RDONLY);
    
        if (fd == -1) {
            perror("open");
            close(fd);
            return -1;
        }
    
        lseek(fd, BLOCK_SIZE * block_number, SEEK_SET);
    
        ssize_t bytes_read = read(fd, buf, BLOCK_SIZE);
    
        if (bytes_read == -1) {
            perror("read");
            close(fd);
            return -1;
        }
    
        if (bytes_read < BLOCK_SIZE) {
            fprintf(stderr, "The entire block hasn't been read\n");
            close(fd);
            return -1;
        }
    
        close(fd);
        return 0;
    }
    
    ssize_t bmap(const struct minix_inode *inode, const char *img_filepath,
                 size_t logical_block) {
    
        size_t direct_zone_len = sizeof(inode->i_zone) / sizeof(inode->i_zone[0]);
        size_t ptr_by_block = BLOCK_SIZE / sizeof(inode->i_indir_zone);
    
        if (logical_block < direct_zone_len) {
            return inode->i_zone[logical_block];
        }
    
        logical_block -= direct_zone_len;
    
        if (logical_block < ptr_by_block) {
            uint16_t buf[BLOCK_SIZE] = {0};
    
            if (read_indir_block(buf, img_filepath, inode->i_indir_zone) == -1) {
                fprintf(stderr, "read_indir_block failed\n");
                return -1;
            }
    
            return buf[logical_block];
        }
    
        logical_block -= ptr_by_block;
    
        if (logical_block < (ptr_by_block * ptr_by_block)) {
            uint16_t buf1[BLOCK_SIZE] = {0};
            uint16_t buf2[BLOCK_SIZE] = {0};
    
            if (read_indir_block(buf1, img_filepath, inode->i_dbl_indir_zone) ==
                -1) {
                fprintf(stderr, "read_indir_block failed\n");
                return -1;
            }
    
            if (read_indir_block(buf2, img_filepath,
                                 buf1[logical_block / ptr_by_block]) == -1) {
                fprintf(stderr, "read_indir_block failed\n");
                return -1;
            }
    
            return buf2[logical_block % BLOCK_SIZE * sizeof(uint16_t)];
        }
    
        return 0;
    }
    
    int read_data_block(char *buf, const char *img_filepath,
                        size_t phys_num_block) {
        int fd = open(img_filepath, O_RDONLY);
    
        if (fd == -1) {
            perror("open");
            close(fd);
            return -1;
        }
    
        lseek(fd, BLOCK_SIZE * phys_num_block, SEEK_SET);
    
        ssize_t bytes_read = read(fd, buf, BLOCK_SIZE);
    
        if (bytes_read == -1) {
            perror("open");
            close(fd);
            return -1;
        }
    
        if (bytes_read != BLOCK_SIZE) {
            close(fd);
            return -1;
        }
    
        close(fd);
        return 0;
    }
    
    int lookup_entry(const struct minix_inode *inode, const char *token,
                     const char *img_filepath) {
        int nb_blocks_used = inode->i_size / BLOCK_SIZE;
        if (inode->i_size % BLOCK_SIZE != 0) {
            nb_blocks_used++;
        }
    
        for (int i = 0; i < nb_blocks_used; i++) {
            ssize_t phys_num = bmap(inode, img_filepath, i);
    
            if (phys_num == -1) {
                fprintf(stderr, "bmap has failed...\n");
                return -1;
            }
    
            char buf[BLOCK_SIZE + 1] = {0};
    
            if (read_data_block(buf, img_filepath, phys_num) == -1) {
                fprintf(stderr, "read_data_block has failed...\n");
                return -1;
            }
    
            struct minix_dir_entry dir_entry = {0};
            for (size_t j = 0; j < BLOCK_SIZE / sizeof(struct minix_dir_entry);
                 j++) {
                memcpy(&dir_entry, &buf[j * sizeof(struct minix_dir_entry)],
                       sizeof(struct minix_dir_entry));
    
                if (strncmp(dir_entry.name, token, strlen(dir_entry.name)) == 0) {
                    return dir_entry.inode;
                }
            }
        }
    
        return -1;
    }
    
    int namei(const char *img_filepath, char *filepath) {
        struct minix_inode inode = {0};
        if (unmarshal_inode(&inode, 1, img_filepath) == -1) {
            fprintf(stderr, "marshal_inode has failed\n");
            return -1;
        }
    
        char *token = strtok(filepath, "/");
        int next_inode = 0;
    
        while (token != NULL) {
            // fprintf(stdout, "token = %s\n\n", token);
            next_inode = lookup_entry(&inode, token, img_filepath);
    
            switch (next_inode) {
            case -1:
                fprintf(stderr, "lookup_entry has failed\n");
                return -1;
            case 0:
                fprintf(stderr, "file doesn't exist\n");
                return -1;
            default:
                token = strtok(NULL, "/");
    
                memset(&inode, 0, sizeof(struct minix_inode));
                if (unmarshal_inode(&inode, next_inode, img_filepath) == -1) {
                    fprintf(stderr, "marshal_inode has failed\n");
                    return -1;
                }
            }
        }
    
        int nb_blocks_used = inode.i_size / BLOCK_SIZE;
        if (inode.i_size % BLOCK_SIZE != 0) {
            nb_blocks_used++;
        }
    
        for (int i = 0; i < nb_blocks_used; i++) {
            ssize_t phys_num = bmap(&inode, img_filepath, i);
    
            if (phys_num == -1) {
                fprintf(stderr, "bmap has failed...\n");
                return -1;
            }
    
            char buf[BLOCK_SIZE + 1] = {0};
    
            if (read_data_block(buf, img_filepath, phys_num) == -1) {
                fprintf(stderr, "read_data_block has failed...\n");
                return -1;
            }
    
            fprintf(stdout, "%s", buf);
        }
    
        fprintf(stdout, "\n");
    
        return 0;
    }