/// zcr copy from chapter9/d fs/main.c and modified it. #include "type.h" #include "const.h" #include "protect.h" #include "string.h" #include "proc.h" #include "global.h" #include "proto.h" #include "fs_const.h" #include "hd.h" #include "fs.h" #include "fs_misc.h" #include "stdio.h" #include "assert.h" // added by xw, 18/8/28 /* data */ static struct inode *root_inode; // static struct file_desc f_desc_table[NR_FILE_DESC]; //deleted by mingxuan 2020-10-30 extern struct file_desc f_desc_table[NR_FILE_DESC]; // modified by mingxuan 2020-10-30 static struct inode inode_table[NR_INODE]; // static struct super_block super_block[NR_SUPER_BLOCK]; //deleted by mingxuan 2020-10-30 extern struct super_block super_block[NR_SUPER_BLOCK]; // modified by mingxuan 2020-10-30 /* functions */ static void mkfs(); // static void read_super_block(int dev); void read_super_block(int dev); // modified by mingxuan 2020-10-30 // static struct super_block* get_super_block(int dev); struct super_block *get_super_block(int dev); // modified by mingxuan 2020-10-30 static int do_open(MESSAGE *fs_msg); static int do_close(int fd); static int do_lseek(MESSAGE *fs_msg); static int do_rdwt(MESSAGE *fs_msg); static int do_unlink(MESSAGE *fs_msg); int real_open(const char *pathname, int flags); // modified by mingxuan 2019-5-17 int real_close(int fd); // modified by mingxuan 2019-5-17 int real_read(int fd, void *buf, int count); // 注意:buf的类型被修改成char //modified by mingxuan 2019-5-17 int real_write(int fd, const void *buf, int count); // 注意:buf的类型被修改成char //modified by mingxuan 2019-5-17 int real_unlink(const char *pathname); // modified by mingxuan 2019-5-17 int real_lseek(int fd, int offset, int whence); // modified by mingxuan 2019-5-17 static int rw_sector(int io_type, int dev, u64 pos, int bytes, int proc_nr, void *buf); static int rw_sector_sched(int io_type, int dev, int pos, int bytes, int proc_nr, void *buf); static int strip_path(char *filename, const char *pathname, struct inode **ppinode); static int search_file(char *path); static struct inode *create_file(char *path, int flags); static struct inode *get_inode(int dev, int num); static struct inode *get_inode_sched(int dev, int num); static struct inode *new_inode(int dev, int inode_nr, int start_sect); static void put_inode(struct inode *pinode); static void sync_inode(struct inode *p); static void new_dir_entry(struct inode *dir_inode, int inode_nr, char *filename); static int alloc_imap_bit(int dev); static int alloc_smap_bit(int dev, int nr_sects_to_alloc); static int memcmp(const void *s1, const void *s2, int n); //~xw int get_fs_dev(int drive, int fs_type); // added by mingxuan 2020-10-27 // added by mingxuan 2020-10-27 int get_fs_dev(int drive, int fs_type) { int i = 0; for (i = 0; i < NR_PRIM_PER_DRIVE; i++) { if (hd_info[drive].primary[i].fs_type == fs_type) return ((DEV_HD << MAJOR_SHIFT) | i); } // added by mingxuan 2020-10-29 for (i = 0; i < NR_SUB_PER_DRIVE; i++) { if (hd_info[drive].logical[i].fs_type == fs_type) return ((DEV_HD << MAJOR_SHIFT) | (i + MINOR_hd1a)); // logic的下标i加上hd1a才是该逻辑分区的次设备号 } return 0; } /// zcr added void init_fs() { kprintf("Initializing file system... "); int i; for (i = 0; i < NR_INODE; i++) memset(&inode_table[i], 0, sizeof(struct inode)); struct super_block *sb = super_block; // deleted by mingxuan 2020-10-30 int orange_dev = get_fs_dev(PRIMARY_MASTER, ORANGE_TYPE); // added by mingxuan 2020-10-27 /* load super block of ROOT */ read_super_block(orange_dev); // modified by mingxuan 2020-10-27 sb = get_super_block(orange_dev); // modified by mingxuan 2020-10-27 kprintf("Superblock Address:0x%x \n", sb); if (sb->magic != MAGIC_V1) { // deleted by mingxuan 2019-5-20 mkfs(); kprintf("Make file system Done.\n"); read_super_block(orange_dev); // modified by mingxuan 2020-10-27 } root_inode = get_inode(orange_dev, ROOT_INODE); // modified by mingxuan 2020-10-27 } /***************************************************************************** * mkfs *****************************************************************************/ /** * Make a available Orange'S FS in the disk. It will * - Write a super block to sector 1. * - Create three special files: dev_tty0, dev_tty1, dev_tty2 * - Create the inode map * - Create the sector map * - Create the inodes of the files * - Create `/', the root directory *****************************************************************************/ static void mkfs() { MESSAGE driver_msg; int i, j; int bits_per_sect = SECTOR_SIZE * 8; /* 8 bits per byte */ // local array, to substitute global fsbuf. added by xw, 18/12/27 char fsbuf[SECTOR_SIZE]; int orange_dev = get_fs_dev(PRIMARY_MASTER, ORANGE_TYPE); // added by mingxuan 2020-10-27 /* get the geometry of ROOTDEV */ struct part_info geo; driver_msg.type = DEV_IOCTL; // driver_msg.DEVICE = MINOR(ROOT_DEV); // deleted by mingxuan 2020-10-27 driver_msg.DEVICE = MINOR(orange_dev); // modified by mingxuan 2020-10-27 driver_msg.REQUEST = DIOCTL_GET_GEO; driver_msg.BUF = &geo; driver_msg.PROC_NR = proc2pid(p_proc_current); // assert(dd_map[MAJOR(ROOT_DEV)].driver_nr != INVALID_DRIVER); // send_recv(BOTH, dd_map[MAJOR(ROOT_DEV)].driver_nr, &driver_msg); hd_ioctl(&driver_msg); kprintf("dev size: 0x%x sectors\n", geo.size); /************************/ /* super block */ /************************/ struct super_block sb; sb.magic = MAGIC_V1; sb.nr_inodes = bits_per_sect; sb.nr_inode_sects = sb.nr_inodes * INODE_SIZE / SECTOR_SIZE; sb.nr_sects = geo.size; /* partition size in sector */ sb.nr_imap_sects = 1; sb.nr_smap_sects = sb.nr_sects / bits_per_sect + 1; sb.n_1st_sect = 1 + 1 + /* boot sector & super block */ sb.nr_imap_sects + sb.nr_smap_sects + sb.nr_inode_sects; sb.root_inode = ROOT_INODE; sb.inode_size = INODE_SIZE; struct inode x; sb.inode_isize_off = (int)&x.i_size - (int)&x; sb.inode_start_off = (int)&x.i_start_sect - (int)&x; sb.dir_ent_size = DIR_ENTRY_SIZE; struct dir_entry de; sb.dir_ent_inode_off = (int)&de.inode_nr - (int)&de; sb.dir_ent_fname_off = (int)&de.name - (int)&de; sb.sb_dev = orange_dev; // added by mingxuan 2020-10-30 sb.fs_type = ORANGE_TYPE; // added by mingxuan 2020-10-30 memset(fsbuf, 0x90, SECTOR_SIZE); memcpy(fsbuf, &sb, SUPER_BLOCK_SIZE); /* write the super block */ WR_SECT(orange_dev, 1, fsbuf); // modified by mingxuan 2020-10-27 kprintf("devbase:0x%x00", (geo.base + 0) * 2); kprintf(" sb:0x%x00", (geo.base + 1) * 2); kprintf(" imap:0x%x00", (geo.base + 2) * 2); kprintf(" smap:0x%x00\n", (geo.base + 2 + sb.nr_imap_sects) * 2); kprintf(" inodes:0x%x00", (geo.base + 2 + sb.nr_imap_sects + sb.nr_smap_sects) * 2); kprintf(" 1st_sector:0x%x00\n", (geo.base + sb.n_1st_sect) * 2); /************************/ /* inode map */ /************************/ memset(fsbuf, 0, SECTOR_SIZE); for (i = 0; i < (NR_CONSOLES + 3); i++) // modified by mingxuan 2019-5-22 fsbuf[0] |= 1 << i; WR_SECT(orange_dev, 2, fsbuf); // modified by mingxuan 2020-10-27 /************************/ /* secter map */ /************************/ memset(fsbuf, 0, SECTOR_SIZE); int nr_sects = NR_DEFAULT_FILE_SECTS + 1; for (i = 0; i < nr_sects / 8; i++) fsbuf[i] = 0xFF; for (j = 0; j < nr_sects % 8; j++) fsbuf[i] |= (1 << j); WR_SECT(orange_dev, 2 + sb.nr_imap_sects, fsbuf); // modified by mingxuan 2020-10-27 /* zeromemory the rest sector-map */ memset(fsbuf, 0, SECTOR_SIZE); for (i = 1; i < sb.nr_smap_sects; i++) WR_SECT(orange_dev, 2 + sb.nr_imap_sects + i, fsbuf); // modified by mingxuan 2020-10-27 /* app.tar */ // added by mingxuan 2019-5-19 int bit_offset = INSTALL_START_SECTOR - sb.n_1st_sect + 1; /* sect M <-> bit (M - sb.n_1stsect + 1) */ int bit_off_in_sect = bit_offset % (SECTOR_SIZE * 8); int bit_left = INSTALL_NR_SECTORS; int cur_sect = bit_offset / (SECTOR_SIZE * 8); RD_SECT(orange_dev, 2 + sb.nr_imap_sects + cur_sect, fsbuf); // modified by mingxuan 2020-10-27 while (bit_left) { int byte_off = bit_off_in_sect / 8; /* this line is ineffecient in a loop, but I don't care */ fsbuf[byte_off] |= 1 << (bit_off_in_sect % 8); bit_left--; bit_off_in_sect++; if (bit_off_in_sect == (SECTOR_SIZE * 8)) { WR_SECT(orange_dev, 2 + sb.nr_imap_sects + cur_sect, fsbuf); // modified by mingxuan 2020-10-27 cur_sect++; RD_SECT(orange_dev, 2 + sb.nr_imap_sects + cur_sect, fsbuf); // modified by mingxuan 2020-10-27 bit_off_in_sect = 0; } } WR_SECT(orange_dev, 2 + sb.nr_imap_sects + cur_sect, fsbuf); // modified by mingxuan 2020-10-27 /************************/ /* inodes */ /************************/ /* inode of `/' */ memset(fsbuf, 0, SECTOR_SIZE); struct inode *pi = (struct inode *)fsbuf; pi->i_mode = I_DIRECTORY; // modified by mingxuan 2019-5-21 pi->i_size = DIR_ENTRY_SIZE * 5; /* 5 files: (预定义5个文件) * `.', * `dev_tty0', `dev_tty1', `dev_tty2','app.tar' */ pi->i_start_sect = sb.n_1st_sect; pi->i_nr_sects = NR_DEFAULT_FILE_SECTS; /* inode of `/dev_tty0~2' */ for (i = 0; i < NR_CONSOLES; i++) { pi = (struct inode *)(fsbuf + (INODE_SIZE * (i + 1))); pi->i_mode = I_CHAR_SPECIAL; pi->i_size = 0; pi->i_start_sect = MAKE_DEV(DEV_CHAR_TTY, i); pi->i_nr_sects = 0; } /* inode of /app.tar */ // added by mingxuan 2019-5-19 pi = (struct inode *)(fsbuf + (INODE_SIZE * (NR_CONSOLES + 1))); pi->i_mode = I_REGULAR; pi->i_size = INSTALL_NR_SECTORS * SECTOR_SIZE; pi->i_start_sect = INSTALL_START_SECTOR; pi->i_nr_sects = INSTALL_NR_SECTORS; WR_SECT(orange_dev, 2 + sb.nr_imap_sects + sb.nr_smap_sects, fsbuf); // modified by mingxuan 2020-10-27 /************************/ /* `/' */ /************************/ memset(fsbuf, 0, SECTOR_SIZE); struct dir_entry *pde = (struct dir_entry *)fsbuf; pde->inode_nr = 1; strcpy(pde->name, "."); /* dir entries of `/dev_tty0~2' */ for (i = 0; i < NR_CONSOLES; i++) { pde++; pde->inode_nr = i + 2; /* dev_tty0's inode_nr is 2 */ switch (i) { case 0: strcpy(pde->name, "dev_tty0"); break; case 1: strcpy(pde->name, "dev_tty1"); break; case 2: strcpy(pde->name, "dev_tty2"); break; } } (++pde)->inode_nr = NR_CONSOLES + 2; // added by mingxuan 2019-5-19 strcpy(pde->name, INSTALL_FILENAME); // added by mingxuan 2019-5-19 // WR_SECT(ROOT_DEV, sb.n_1st_sect, fsbuf); //modified by xw, 18/12/27 //deleted by mingxuan 2020-10-27 WR_SECT(orange_dev, sb.n_1st_sect, fsbuf); // modified by mingxuan 2020-10-27 } /***************************************************************************** * rw_sector *****************************************************************************/ /** * R/W a sector via messaging with the corresponding driver. * * @param io_type DEV_READ or DEV_WRITE * @param dev device nr * @param pos Byte offset from/to where to r/w. * @param bytes r/w count in bytes. * @param proc_nr To whom the buffer belongs. * @param buf r/w buffer. * * @return Zero if success. *****************************************************************************/ /// zcr: change the "u64 pos" to "int pos" static int rw_sector(int io_type, int dev, u64 pos, int bytes, int proc_nr, void *buf) { MESSAGE driver_msg; driver_msg.type = io_type; driver_msg.DEVICE = MINOR(dev); driver_msg.POSITION = pos; driver_msg.CNT = bytes; /// hu is: 512 driver_msg.PROC_NR = proc_nr; driver_msg.BUF = buf; hd_rdwt(&driver_msg); return 0; } // added by xw, 18/8/27 static int rw_sector_sched(int io_type, int dev, int pos, int bytes, int proc_nr, void *buf) { MESSAGE driver_msg; driver_msg.type = io_type; driver_msg.DEVICE = MINOR(dev); driver_msg.POSITION = pos; driver_msg.CNT = bytes; /// hu is: 512 driver_msg.PROC_NR = proc_nr; driver_msg.BUF = buf; hd_rdwt_sched(&driver_msg); return 0; } //~xw // added by zcr from chapter9/e/lib/open.c and modified it. /***************************************************************************** * open *****************************************************************************/ /** * open/create a file. * * @param pathname The full path of the file to be opened/created. * @param flags O_CREAT, O_RDWR, etc. * * @return File descriptor if successful, otherwise -1. *****************************************************************************/ // open is a syscall interface now. added by xw, 18/6/18 // int open(const char *pathname, int flags) // static int real_open(const char *pathname, int flags) //deleted by mingxuan 2019-5-17 int real_open(const char *pathname, int flags) // modified by mingxuan 2019-5-17 { // added by xw, 18/8/27 MESSAGE fs_msg; fs_msg.type = OPEN; fs_msg.PATHNAME = (void *)pathname; fs_msg.FLAGS = flags; fs_msg.NAME_LEN = strlen(pathname); fs_msg.source = proc2pid(p_proc_current); int fd = do_open(&fs_msg); return fd; } /***************************************************************************** * do_open *****************************************************************************/ /** * Open a file and return the file descriptor. * * @return File descriptor if successful, otherwise a negative error code. *****************************************************************************/ /// zcr modified. static int do_open(MESSAGE *fs_msg) { /*caller_nr is the process number of the */ int fd = -1; /* return value */ char pathname[MAX_PATH]; /* get parameters from the message */ int flags = fs_msg->FLAGS; /* access mode */ int name_len = fs_msg->NAME_LEN; /* length of filename */ int src = fs_msg->source; /* caller proc nr. */ memcpy((void *)va2la(src, pathname), (void *)va2la(src, fs_msg->PATHNAME), name_len); pathname[name_len] = 0; /* find a free slot in PROCESS::filp[] */ int i; for (i = 0; i < NR_FILES; i++) { // modified by mingxuan 2019-5-20 if (p_proc_current->task.filp[i] == 0) { fd = i; break; } } // printf("%d\n", fd); assert(0 <= fd && fd < NR_FILES); /* find a free slot in f_desc_table[] */ for (i = 0; i < NR_FILE_DESC; i++) // modified by mingxuan 2019-5-17 if (f_desc_table[i].flag == 0) break; assert(i < NR_FILE_DESC); int inode_nr = search_file(pathname); struct inode *pin = 0; if (flags & O_CREAT) { if (inode_nr) { return -1; } else { pin = create_file(pathname, flags); } } else { char filename[MAX_PATH]; struct inode *dir_inode; if (strip_path(filename, pathname, &dir_inode) != 0) return -1; pin = get_inode(dir_inode->i_dev, inode_nr); // modified by mingxuan 2019-5-20 } if (pin) { /* connects proc with file_descriptor */ p_proc_current->task.filp[fd] = &f_desc_table[i]; f_desc_table[i].flag = 1; // added by mingxuan 2019-5-17 /* connects file_descriptor with inode */ f_desc_table[i].fd_node.fd_inode = pin; // modified by mingxuan 2019-5-17 f_desc_table[i].fd_mode = flags; f_desc_table[i].fd_pos = 0; int imode = pin->i_mode & I_TYPE_MASK; if (imode == I_CHAR_SPECIAL) { // MESSAGE driver_msg; // int dev = pin->i_start_sect; //? } else if (imode == I_DIRECTORY) { if (pin->i_num != ROOT_INODE) { panic("pin->i_num != ROOT_INODE"); } } else { if (pin->i_mode != I_REGULAR) { panic("Panic: pin->i_mode != I_REGULAR"); } } } else { return -1; } return fd; } /***************************************************************************** * create_file *****************************************************************************/ /** * Create a file and return it's inode ptr. * * @param[in] path The full path of the new file * @param[in] flags Attribiutes of the new file * * @return Ptr to i-node of the new file if successful, otherwise 0. * * @see open() * @see do_open() *****************************************************************************/ static struct inode *create_file(char *path, int flags) { char filename[MAX_PATH]; struct inode *dir_inode; if (strip_path(filename, path, &dir_inode) != 0) return 0; int inode_nr = alloc_imap_bit(dir_inode->i_dev); int free_sect_nr = alloc_smap_bit(dir_inode->i_dev, NR_DEFAULT_FILE_SECTS); struct inode *newino = new_inode(dir_inode->i_dev, inode_nr, free_sect_nr); new_dir_entry(dir_inode, newino->i_num, filename); return newino; } /// zcr copied from ch9/e/fs/misc.c /***************************************************************************** * memcmp *****************************************************************************/ /** * Compare memory areas. * * @param s1 The 1st area. * @param s2 The 2nd area. * @param n The first n bytes will be compared. * * @return an integer less than, equal to, or greater than zero if the first * n bytes of s1 is found, respectively, to be less than, to match, * or be greater than the first n bytes of s2. *****************************************************************************/ static int memcmp(const void *s1, const void *s2, int n) { if ((s1 == 0) || (s2 == 0)) { /* for robustness */ return (s1 - s2); } const char *p1 = (const char *)s1; const char *p2 = (const char *)s2; int i; for (i = 0; i < n; i++, p1++, p2++) { if (*p1 != *p2) { return (*p1 - *p2); } } return 0; } /***************************************************************************** * search_file *****************************************************************************/ /** * Search the file and return the inode_nr. * * @param[in] path The full path of the file to search. * @return Ptr to the i-node of the file if successful, otherwise zero. * * @see open() * @see do_open() *****************************************************************************/ static int search_file(char *path) { int i, j; char filename[MAX_PATH]; memset(filename, 0, MAX_FILENAME_LEN); struct inode *dir_inode; if (strip_path(filename, path, &dir_inode) != 0) return 0; if (filename[0] == 0) /* path: "/" */ return dir_inode->i_num; /** * Search the dir for the file. */ int dir_blk0_nr = dir_inode->i_start_sect; int nr_dir_blks = (dir_inode->i_size + SECTOR_SIZE - 1) / SECTOR_SIZE; int nr_dir_entries = dir_inode->i_size / DIR_ENTRY_SIZE; /** * including unused slots * (the file has been deleted * but the slot is still there) */ int m = 0; struct dir_entry *pde; char fsbuf[SECTOR_SIZE]; // local array, to substitute global fsbuf. added by xw, 18/12/27 for (i = 0; i < nr_dir_blks; i++) { // RD_SECT_SCHED(dir_inode->i_dev, dir_blk0_nr + i, fsbuf); //modified by xw, 18/12/27 RD_SECT(dir_inode->i_dev, dir_blk0_nr + i, fsbuf); // modified by mingxuan 2019-5-20 pde = (struct dir_entry *)fsbuf; for (j = 0; j < SECTOR_SIZE / DIR_ENTRY_SIZE; j++, pde++) { if (memcmp(filename, pde->name, MAX_FILENAME_LEN) == 0) return pde->inode_nr; if (++m > nr_dir_entries) break; } if (m > nr_dir_entries) /* all entries have been iterated */ break; } /* file not found */ return 0; } /***************************************************************************** * strip_path *****************************************************************************/ /** * Get the basename from the fullpath. * * In Orange'S FS v1.0, all files are stored in the root directory. * There is no sub-folder thing. * * This routine should be called at the very beginning of file operations * such as open(), read() and write(). It accepts the full path and returns * two things: the basename and a ptr of the root dir's i-node. * * e.g. After stip_path(filename, "/blah", ppinode) finishes, we get: * - filename: "blah" * - *ppinode: root_inode * - ret val: 0 (successful) * * Currently an acceptable pathname should begin with at most one `/' * preceding a filename. * * Filenames may contain any character except '/' and '\\0'. * * @param[out] filename The string for the result. * @param[in] pathname The full pathname. * @param[out] ppinode The ptr of the dir's inode will be stored here. * * @return Zero if success, otherwise the pathname is not valid. *****************************************************************************/ static int strip_path(char *filename, const char *pathname, struct inode **ppinode) { const char *s = pathname; char *t = filename; if (s == 0) return -1; if (*s == '/') s++; while (*s) { /* check each character */ if (*s == '/') return -1; *t++ = *s++; /* if filename is too long, just truncate it */ if (t - filename >= MAX_FILENAME_LEN) break; } *t = 0; *ppinode = root_inode; return 0; } /***************************************************************************** * read_super_block *****************************************************************************/ /** * Read super block from the given device then write it into a free * super_block[] slot. * * @param dev From which device the super block comes. *****************************************************************************/ // static void read_super_block(int dev) void read_super_block(int dev) // modified by mingxuan 2020-10-30 { int i; MESSAGE driver_msg; char fsbuf[SECTOR_SIZE]; // local array, to substitute global fsbuf. added by xw, 18/12/27 driver_msg.type = DEV_READ; driver_msg.DEVICE = MINOR(dev); driver_msg.POSITION = SECTOR_SIZE * 1; driver_msg.BUF = fsbuf; driver_msg.CNT = SECTOR_SIZE; driver_msg.PROC_NR = proc2pid(p_proc_current); /// TASK_A hd_rdwt(&driver_msg); for (i = 0; i < NR_SUPER_BLOCK; i++) if (super_block[i].fs_type == ORANGE_TYPE) break; if (i == NR_SUPER_BLOCK) panic("Cannot find orange's superblock!"); struct super_block *psb = (struct super_block *)fsbuf; super_block[i] = *psb; super_block[i].sb_dev = dev; super_block[i].fs_type = ORANGE_TYPE; // added by mingxuan 2020-10-30 } /***************************************************************************** * get_super_block *****************************************************************************/ /** * Get the super block from super_block[]. * * @param dev Device nr. * * @return Super block ptr. *****************************************************************************/ struct super_block *get_super_block(int dev) // modified by mingxuan 2020-10-30 { struct super_block *sb = super_block; for (; sb < &super_block[NR_SUPER_BLOCK]; sb++) { if (sb->sb_dev == dev) return sb; } return 0; } /***************************************************************************** * get_inode *****************************************************************************/ /** * Get the inode ptr of given inode nr. A cache -- inode_table[] -- is * maintained to make things faster. If the inode requested is already there, * just return it. Otherwise the inode will be read from the disk. * * @param dev Device nr. * @param num I-node nr. * * @return The inode ptr requested. *****************************************************************************/ static struct inode *get_inode(int dev, int num) { if (num == 0) return 0; struct inode *p; struct inode *q = 0; for (p = &inode_table[0]; p < &inode_table[NR_INODE]; p++) { if (p->i_cnt) { /* not a free slot */ if ((p->i_dev == dev) && (p->i_num == num)) { /* this is the inode we want */ p->i_cnt++; return p; } } else { /* a free slot */ if (!q) /* q hasn't been assigned yet */ q = p; /* q <- the 1st free slot */ } } if (!q) panic("the inode table is full"); q->i_dev = dev; q->i_num = num; q->i_cnt = 1; struct super_block *sb = get_super_block(dev); int blk_nr = 1 + 1 + sb->nr_imap_sects + sb->nr_smap_sects + ((num - 1) / (SECTOR_SIZE / INODE_SIZE)); char fsbuf[SECTOR_SIZE]; // local array, to substitute global fsbuf. added by xw, 18/12/27 RD_SECT(dev, blk_nr, fsbuf); // added by xw, 18/12/27 struct inode *pinode = (struct inode *)((u8 *)fsbuf + ((num - 1) % (SECTOR_SIZE / INODE_SIZE)) * INODE_SIZE); q->i_mode = pinode->i_mode; q->i_size = pinode->i_size; q->i_start_sect = pinode->i_start_sect; q->i_nr_sects = pinode->i_nr_sects; return q; } // added by xw, 18/8/27 static struct inode *get_inode_sched(int dev, int num) { if (num == 0) return 0; struct inode *p; struct inode *q = 0; for (p = &inode_table[0]; p < &inode_table[NR_INODE]; p++) { if (p->i_cnt) { /* not a free slot */ if ((p->i_dev == dev) && (p->i_num == num)) { /* this is the inode we want */ p->i_cnt++; return p; } } else { /* a free slot */ if (!q) /* q hasn't been assigned yet */ q = p; /* q <- the 1st free slot */ } } if (!q) panic("the inode table is full"); q->i_dev = dev; q->i_num = num; q->i_cnt = 1; struct super_block *sb = get_super_block(dev); int blk_nr = 1 + 1 + sb->nr_imap_sects + sb->nr_smap_sects + ((num - 1) / (SECTOR_SIZE / INODE_SIZE)); char fsbuf[SECTOR_SIZE]; // local array, to substitute global fsbuf. added by xw, 18/12/27 RD_SECT_SCHED(dev, blk_nr, fsbuf); // added by xw, 18/12/27 struct inode *pinode = (struct inode *)((u8 *)fsbuf + ((num - 1) % (SECTOR_SIZE / INODE_SIZE)) * INODE_SIZE); q->i_mode = pinode->i_mode; q->i_size = pinode->i_size; q->i_start_sect = pinode->i_start_sect; q->i_nr_sects = pinode->i_nr_sects; return q; } /***************************************************************************** * put_inode *****************************************************************************/ /** * Decrease the reference nr of a slot in inode_table[]. When the nr reaches * zero, it means the inode is not used any more and can be overwritten by * a new inode. * * @param pinode I-node ptr. *****************************************************************************/ static void put_inode(struct inode *pinode) { // assert(pinode->i_cnt > 0); pinode->i_cnt--; } /***************************************************************************** * sync_inode *****************************************************************************/ /** * Write the inode back to the disk. Commonly invoked as soon as the * inode is changed. * * @param p I-node ptr. *****************************************************************************/ static void sync_inode(struct inode *p) { struct inode *pinode; struct super_block *sb = get_super_block(p->i_dev); int blk_nr = 1 + 1 + sb->nr_imap_sects + sb->nr_smap_sects + ((p->i_num - 1) / (SECTOR_SIZE / INODE_SIZE)); char fsbuf[SECTOR_SIZE]; // local array, to substitute global fsbuf. added by xw, 18/12/27 RD_SECT(p->i_dev, blk_nr, fsbuf); // modified by mingxuan 2019-5-20 pinode = (struct inode *)((u8 *)fsbuf + (((p->i_num - 1) % (SECTOR_SIZE / INODE_SIZE)) * INODE_SIZE)); pinode->i_mode = p->i_mode; pinode->i_size = p->i_size; pinode->i_start_sect = p->i_start_sect; pinode->i_nr_sects = p->i_nr_sects; WR_SECT(p->i_dev, blk_nr, fsbuf); // modified by mingxuan 2019-5-20 } /// added by zcr (from ch9/e/fs/open.c) /***************************************************************************** * new_inode *****************************************************************************/ /** * Generate a new i-node and write it to disk. * * @param dev Home device of the i-node. * @param inode_nr I-node nr. * @param start_sect Start sector of the file pointed by the new i-node. * * @return Ptr of the new i-node. *****************************************************************************/ static struct inode *new_inode(int dev, int inode_nr, int start_sect) { // struct inode * new_inode = get_inode_sched(dev, inode_nr); //modified by xw, 18/8/28 struct inode *new_inode = get_inode(dev, inode_nr); // modified by mingxuan 2019-5-20 new_inode->i_mode = I_REGULAR; new_inode->i_size = 0; new_inode->i_start_sect = start_sect; new_inode->i_nr_sects = NR_DEFAULT_FILE_SECTS; new_inode->i_dev = dev; new_inode->i_cnt = 1; new_inode->i_num = inode_nr; /* write to the inode array */ sync_inode(new_inode); return new_inode; } /***************************************************************************** * new_dir_entry *****************************************************************************/ /** * Write a new entry into the directory. * * @param dir_inode I-node of the directory. * @param inode_nr I-node nr of the new file. * @param filename Filename of the new file. *****************************************************************************/ static void new_dir_entry(struct inode *dir_inode, int inode_nr, char *filename) { /* write the dir_entry */ int dir_blk0_nr = dir_inode->i_start_sect; int nr_dir_blks = (dir_inode->i_size + SECTOR_SIZE) / SECTOR_SIZE; int nr_dir_entries = dir_inode->i_size / DIR_ENTRY_SIZE; /** * including unused slots * (the file has been * deleted but the slot * is still there) */ int m = 0; struct dir_entry *pde; struct dir_entry *new_de = 0; int i, j; char fsbuf[SECTOR_SIZE]; // local array, to substitute global fsbuf. added by xw, 18/12/27 for (i = 0; i < nr_dir_blks; i++) { RD_SECT(dir_inode->i_dev, dir_blk0_nr + i, fsbuf); // modified by mingxuan 2019-5-20 pde = (struct dir_entry *)fsbuf; for (j = 0; j < SECTOR_SIZE / DIR_ENTRY_SIZE; j++, pde++) { if (++m > nr_dir_entries) break; if (pde->inode_nr == 0) { /* it's a free slot */ new_de = pde; break; } } if (m > nr_dir_entries || /* all entries have been iterated or */ new_de) /* free slot is found */ break; } if (!new_de) { /* reached the end of the dir */ new_de = pde; dir_inode->i_size += DIR_ENTRY_SIZE; } new_de->inode_nr = inode_nr; strcpy(new_de->name, filename); /* write dir block -- ROOT dir block */ WR_SECT(dir_inode->i_dev, dir_blk0_nr + i, fsbuf); // added by mingxuan 2019-5-20 /* update dir inode */ sync_inode(dir_inode); } /***************************************************************************** * alloc_imap_bit *****************************************************************************/ /** * Allocate a bit in inode-map. * * @param dev In which device the inode-map is located. * * @return I-node nr. *****************************************************************************/ static int alloc_imap_bit(int dev) { int inode_nr = 0; int i, j, k; int imap_blk0_nr = 1 + 1; /* 1 boot sector & 1 super block */ struct super_block *sb = get_super_block(dev); char fsbuf[SECTOR_SIZE]; // local array, to substitute global fsbuf. added by xw, 18/12/27 for (i = 0; i < sb->nr_imap_sects; i++) { RD_SECT(dev, imap_blk0_nr + i, fsbuf); // modified by mingxuan 2019-5-20 for (j = 0; j < SECTOR_SIZE; j++) { if (fsbuf[j] == '\xFF') // modified by xw, 18/12/28 continue; /* skip `1' bits */ for (k = 0; ((fsbuf[j] >> k) & 1) != 0; k++) { } /* i: sector index; j: byte index; k: bit index */ inode_nr = (i * SECTOR_SIZE + j) * 8 + k; fsbuf[j] |= (1 << k); /* write the bit to imap */ WR_SECT(dev, imap_blk0_nr + i, fsbuf); // added by mingxuan 2019-5-20 break; } return inode_nr; } /* no free bit in imap */ panic("inode-map is probably full.\n"); return 0; } /***************************************************************************** * alloc_smap_bit *****************************************************************************/ /** * Allocate a bit in sector-map. * * @param dev In which device the sector-map is located. * @param nr_sects_to_alloc How many sectors are allocated. * * @return The 1st sector nr allocated. *****************************************************************************/ static int alloc_smap_bit(int dev, int nr_sects_to_alloc) { /* int nr_sects_to_alloc = NR_DEFAULT_FILE_SECTS; */ int i; /* sector index */ int j; /* byte index */ int k; /* bit index */ struct super_block *sb = get_super_block(dev); int smap_blk0_nr = 1 + 1 + sb->nr_imap_sects; int free_sect_nr = 0; char fsbuf[SECTOR_SIZE]; // local array, to substitute global fsbuf. added by xw, 18/12/27 for (i = 0; i < sb->nr_smap_sects; i++) { /* smap_blk0_nr + i : current sect nr. */ // RD_SECT_SCHED(dev, smap_blk0_nr + i, fsbuf); //modified by xw, 18/12/27 RD_SECT(dev, smap_blk0_nr + i, fsbuf); // modified by mingxuan 2019-5-20 /* byte offset in current sect */ for (j = 0; j < SECTOR_SIZE && nr_sects_to_alloc > 0; j++) { k = 0; if (!free_sect_nr) { /* loop until a free bit is found */ // if (fsbuf[j] == 0xFF) continue; if (fsbuf[j] == '\xFF') continue; // modified by xw, 18/12/28 for (; ((fsbuf[j] >> k) & 1) != 0; k++) { } free_sect_nr = (i * SECTOR_SIZE + j) * 8 + k - 1 + sb->n_1st_sect; } for (; k < 8; k++) { /* repeat till enough bits are set */ // assert(((fsbuf[j] >> k) & 1) == 0); fsbuf[j] |= (1 << k); if (--nr_sects_to_alloc == 0) break; } } if (free_sect_nr) /* free bit found, write the bits to smap */ // WR_SECT_SCHED(dev, smap_blk0_nr + i, fsbuf); //modified by xw, 18/12/27 WR_SECT(dev, smap_blk0_nr + i, fsbuf); // added by mingxuan 2019-5-20 if (nr_sects_to_alloc == 0) break; } // assert(nr_sects_to_alloc == 0); return free_sect_nr; } /// zcr added and modified from ch9/e/fs.open.c and close.c /***************************************************************************** * close *****************************************************************************/ /** * Close a file descriptor. * * @param fd File descriptor. * * @return Zero if successful, otherwise -1. *****************************************************************************/ // close is a syscall interface now. added by xw, 18/6/18 // int close(int fd) // static int real_close(int fd) //deleted by mingxuan 2019-5-17 int real_close(int fd) // modified by mingxuan 2019-5-17 { return do_close(fd); // terrible(always returns 0) } /***************************************************************************** * do_close *****************************************************************************/ /** * Handle the message CLOSE. * * @return Zero if success. *****************************************************************************/ static int do_close(int fd) { put_inode(p_proc_current->task.filp[fd]->fd_node.fd_inode); // modified by mingxuan 2019-5-17 p_proc_current->task.filp[fd]->fd_node.fd_inode = 0; // modified by mingxuan 2019-5-17 p_proc_current->task.filp[fd]->flag = 0; // added by mingxuan 2019-5-17 p_proc_current->task.filp[fd] = 0; return 0; } /// zcr copied from ch9/f/fs/read_write.c and modified it. /***************************************************************************** * read *****************************************************************************/ /** * Read from a file descriptor. * * @param fd File descriptor. * @param buf Buffer to accept the bytes read. * @param count How many bytes to read. * * @return On success, the number of bytes read are returned. * On error, -1 is returned. *****************************************************************************/ int real_read(int fd, void *buf, int count) // 注意:buf的类型被修改成char //modified by mingxuan 2019-5-17 { // added by xw, 18/8/27 MESSAGE fs_msg; fs_msg.type = READ; fs_msg.FD = fd; fs_msg.BUF = buf; fs_msg.CNT = count; fs_msg.source = proc2pid(p_proc_current); // added by xw, 18/12/22 // send_recv(BOTH, TASK_FS, &msg); do_rdwt(&fs_msg); return fs_msg.CNT; } /***************************************************************************** * write *****************************************************************************/ /** * Write to a file descriptor. * * @param fd File descriptor. * @param buf Buffer including the bytes to write. * @param count How many bytes to write. * * @return On success, the number of bytes written are returned. * On error, -1 is returned. *****************************************************************************/ int real_write(int fd, const void *buf, int count) // 注意:buf的类型被修改成char //modified by mingxuan 2019-5-17 { // added by xw, 18/8/27 MESSAGE fs_msg; fs_msg.type = WRITE; fs_msg.FD = fd; fs_msg.BUF = (void *)buf; fs_msg.CNT = count; fs_msg.source = proc2pid(p_proc_current); // added by xw, 18/12/22 // send_recv(BOTH, TASK_FS, &msg); /// zcr added do_rdwt(&fs_msg); return fs_msg.CNT; } /***************************************************************************** * do_rdwt *****************************************************************************/ /** * Read/Write file and return byte count read/written. * * Sector map is not needed to update, since the sectors for the file have been * allocated and the bits are set when the file was created. * * @return How many bytes have been read/written. *****************************************************************************/ static int do_rdwt(MESSAGE *fs_msg) { int fd = fs_msg->FD; /**< file descriptor. */ void *buf = fs_msg->BUF; /**< r/w buffer */ int len = fs_msg->CNT; /**< r/w bytes */ int src = fs_msg->source; /* caller proc nr. */ if (!(p_proc_current->task.filp[fd]->fd_mode & O_RDWR)) return -1; int pos = p_proc_current->task.filp[fd]->fd_pos; // struct inode * pin = p_proc_current->task.filp[fd]->fd_inode; //deleted by mingxuan 2019-5-17 struct inode *pin = p_proc_current->task.filp[fd]->fd_node.fd_inode; // modified by mingxuan 2019-5-17 int imode = pin->i_mode & I_TYPE_MASK; if (imode == I_CHAR_SPECIAL) { int t = fs_msg->type == READ ? DEV_READ : DEV_WRITE; fs_msg->type = t; // added by mingxuan 2019-5-19 int dev = pin->i_start_sect; int nr_tty = MINOR(dev); if (MAJOR(dev) != DEV_CHAR_TTY) { panic("Error: MAJOR(dev) should be DEV_CHAR_TTY(4)\n"); } if (fs_msg->type == DEV_READ) { fs_msg->CNT = tty_read(&tty_table[nr_tty], buf, len); } else if (fs_msg->type == DEV_WRITE) { tty_write(&tty_table[nr_tty], buf, len); } return fs_msg->CNT; } else { int pos_end; if (fs_msg->type == READ) pos_end = min(pos + len, pin->i_size); else /* WRITE */ pos_end = min(pos + len, pin->i_nr_sects * SECTOR_SIZE); int off = pos % SECTOR_SIZE; int rw_sect_min = pin->i_start_sect + (pos >> SECTOR_SIZE_SHIFT); int rw_sect_max = pin->i_start_sect + (pos_end >> SECTOR_SIZE_SHIFT); // modified by xw, 18/12/27 int chunk = min(rw_sect_max - rw_sect_min + 1, SECTOR_SIZE >> SECTOR_SIZE_SHIFT); int bytes_rw = 0; int bytes_left = len; int i; char fsbuf[SECTOR_SIZE]; // local array, to substitute global fsbuf. added by xw, 18/12/27 for (i = rw_sect_min; i <= rw_sect_max; i += chunk) { /* read/write this amount of bytes every time */ int bytes = min(bytes_left, chunk * SECTOR_SIZE - off); rw_sector(DEV_READ, // modified by mingxuan 2019-5-21 pin->i_dev, i * SECTOR_SIZE, chunk * SECTOR_SIZE, proc2pid(p_proc_current), /// TASK_FS fsbuf); if (fs_msg->type == READ) { memcpy((void *)va2la(src, buf + bytes_rw), (void *)va2la(proc2pid(p_proc_current), fsbuf + off), bytes); } else { /* WRITE */ memcpy((void *)va2la(proc2pid(p_proc_current), fsbuf + off), (void *)va2la(src, buf + bytes_rw), bytes); rw_sector(DEV_WRITE, // modified by mingxuan 2019-5-21 pin->i_dev, i * SECTOR_SIZE, chunk * SECTOR_SIZE, proc2pid(p_proc_current), fsbuf); } off = 0; bytes_rw += bytes; p_proc_current->task.filp[fd]->fd_pos += bytes; bytes_left -= bytes; } if (p_proc_current->task.filp[fd]->fd_pos > pin->i_size) { /* update inode::size */ pin->i_size = p_proc_current->task.filp[fd]->fd_pos; sync_inode(pin); } return bytes_rw; } } /// zcr copied from ch9/h/lib/unlink.c and modified it /***************************************************************************** * unlink *****************************************************************************/ /** * Delete a file. * * @param pathname The full path of the file to delete. * * @return Zero if successful, otherwise -1. *****************************************************************************/ int real_unlink(const char *pathname) // modified by mingxuan 2019-5-17 { // added by xw, 18/8/27 MESSAGE fs_msg; fs_msg.type = UNLINK; fs_msg.PATHNAME = (void *)pathname; fs_msg.NAME_LEN = strlen(pathname); fs_msg.source = proc2pid(p_proc_current); // added by xw, 18/12/22 // send_recv(BOTH, TASK_FS, &msg); // return fs_msg.RETVAL; /// zcr added return do_unlink(&fs_msg); } /// zcr copied from the ch9/h/fs/link.c and modified it /***************************************************************************** * do_unlink *****************************************************************************/ /** * Remove a file. * * @note We clear the i-node in inode_array[] although it is not really needed. * We don't clear the data bytes so the file is recoverable. * * @return On success, zero is returned. On error, -1 is returned. *****************************************************************************/ static int do_unlink(MESSAGE *fs_msg) { char pathname[MAX_PATH]; /* get parameters from the message */ int name_len = fs_msg->NAME_LEN; /* length of filename */ int src = fs_msg->source; /* caller proc nr. */ // assert(name_len < MAX_PATH); memcpy((void *)va2la(proc2pid(p_proc_current), pathname), (void *)va2la(src, fs_msg->PATHNAME), name_len); pathname[name_len] = 0; if (strcmp(pathname, "/") == 0) { kprintf("FS:do_unlink():: cannot unlink the root\n"); return -1; } int inode_nr = search_file(pathname); if (inode_nr == INVALID_INODE) { /* file not found */ kprintf("FS::do_unlink():: search_file() returns invalid inode: %s\n", pathname); return -1; } char filename[MAX_PATH]; struct inode *dir_inode; if (strip_path(filename, pathname, &dir_inode) != 0) return -1; struct inode *pin = get_inode_sched(dir_inode->i_dev, inode_nr); // modified by xw, 18/8/28 if (pin->i_mode != I_REGULAR) { /* can only remove regular files */ kprintf("cannot remove file %s, because it is not a regular file.\n", pathname); return -1; } if (pin->i_cnt > 1) { /* the file was opened */ kprintf("cannot remove file %s, because pin->i_cnt is %d\n", pathname, pin->i_cnt); return -1; } struct super_block *sb = get_super_block(pin->i_dev); /*************************/ /* free the bit in i-map */ /*************************/ int byte_idx = inode_nr / 8; int bit_idx = inode_nr % 8; // assert(byte_idx < SECTOR_SIZE); /* we have only one i-map sector */ /* read sector 2 (skip bootsect and superblk): */ char fsbuf[SECTOR_SIZE]; // local array, to substitute global fsbuf. added by xw, 18/12/27 RD_SECT_SCHED(pin->i_dev, 2, fsbuf); // modified by xw, 18/12/27 // assert(fsbuf[byte_idx % SECTOR_SIZE] & (1 << bit_idx)); fsbuf[byte_idx % SECTOR_SIZE] &= ~(1 << bit_idx); WR_SECT_SCHED(pin->i_dev, 2, fsbuf); // modified by xw, 18/12/27 /**************************/ /* free the bits in s-map */ /**************************/ /* * bit_idx: bit idx in the entire i-map * ... ____|____ * \ .-- byte_cnt: how many bytes between * \ | the first and last byte * +-+-+-+-+-+-+-+-+ V +-+-+-+-+-+-+-+-+ * ... | | | | | |*|*|*|...|*|*|*|*| | | | | * +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ * 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 * ...__/ * byte_idx: byte idx in the entire i-map */ bit_idx = pin->i_start_sect - sb->n_1st_sect + 1; byte_idx = bit_idx / 8; int bits_left = pin->i_nr_sects; int byte_cnt = (bits_left - (8 - (bit_idx % 8))) / 8; /* current sector nr. */ int s = 2 /* 2: bootsect + superblk */ + sb->nr_imap_sects + byte_idx / SECTOR_SIZE; RD_SECT_SCHED(pin->i_dev, s, fsbuf); // modified by xw, 18/12/27 int i; /* clear the first byte */ for (i = bit_idx % 8; (i < 8) && bits_left; i++, bits_left--) { // assert((fsbuf[byte_idx % SECTOR_SIZE] >> i & 1) == 1); fsbuf[byte_idx % SECTOR_SIZE] &= ~(1 << i); } /* clear bytes from the second byte to the second to last */ int k; i = (byte_idx % SECTOR_SIZE) + 1; /* the second byte */ for (k = 0; k < byte_cnt; k++, i++, bits_left -= 8) { if (i == SECTOR_SIZE) { i = 0; WR_SECT_SCHED(pin->i_dev, s, fsbuf); // modified by xw, 18/12/27 RD_SECT_SCHED(pin->i_dev, ++s, fsbuf); // modified by xw, 18/12/27 } // assert(fsbuf[i] == 0xFF); fsbuf[i] = 0; } /* clear the last byte */ if (i == SECTOR_SIZE) { i = 0; WR_SECT_SCHED(pin->i_dev, s, fsbuf); // modified by xw, 18/12/27 RD_SECT_SCHED(pin->i_dev, ++s, fsbuf); // modified by xw, 18/12/27 } // assert((fsbuf[i] & mask) == mask); fsbuf[i] &= (~0) << bits_left; WR_SECT_SCHED(pin->i_dev, s, fsbuf); // modified by xw, 18/12/27 /***************************/ /* clear the i-node itself */ /***************************/ pin->i_mode = 0; pin->i_size = 0; pin->i_start_sect = 0; pin->i_nr_sects = 0; sync_inode(pin); /* release slot in inode_table[] */ put_inode(pin); /************************************************/ /* set the inode-nr to 0 in the directory entry */ /************************************************/ int dir_blk0_nr = dir_inode->i_start_sect; int nr_dir_blks = (dir_inode->i_size + SECTOR_SIZE) / SECTOR_SIZE; int nr_dir_entries = dir_inode->i_size / DIR_ENTRY_SIZE; /* including unused slots * (the file has been * deleted but the slot * is still there) */ int m = 0; struct dir_entry *pde = 0; int flg = 0; int dir_size = 0; for (i = 0; i < nr_dir_blks; i++) { RD_SECT_SCHED(dir_inode->i_dev, dir_blk0_nr + i, fsbuf); // modified by xw, 18/12/27 pde = (struct dir_entry *)fsbuf; int j; for (j = 0; j < SECTOR_SIZE / DIR_ENTRY_SIZE; j++, pde++) { if (++m > nr_dir_entries) break; if (pde->inode_nr == inode_nr) { /* pde->inode_nr = 0; */ memset(pde, 0, DIR_ENTRY_SIZE); WR_SECT_SCHED(dir_inode->i_dev, dir_blk0_nr + i, fsbuf); // modified by xw, 18/12/27 flg = 1; break; } if (pde->inode_nr != INVALID_INODE) dir_size += DIR_ENTRY_SIZE; } if (m > nr_dir_entries || /* all entries have been iterated OR */ flg) /* file is found */ break; } // assert(flg); if (m == nr_dir_entries) { /* the file is the last one in the dir */ dir_inode->i_size = dir_size; sync_inode(dir_inode); } return 0; } int real_lseek(int fd, int offset, int whence) // modified by mingxuan 2019-5-17 { // added by xw, 18/8/27 MESSAGE fs_msg; fs_msg.FD = fd; fs_msg.OFFSET = offset; fs_msg.WHENCE = whence; return do_lseek(&fs_msg); } /// zcr copied from ch9/j/fs/open.c /***************************************************************************** * do_lseek *****************************************************************************/ /** * Handle the message LSEEK. * * @return The new offset in bytes from the beginning of the file if successful, * otherwise a negative number. *****************************************************************************/ static int do_lseek(MESSAGE *fs_msg) { int fd = fs_msg->FD; int off = fs_msg->OFFSET; int whence = fs_msg->WHENCE; int pos = p_proc_current->task.filp[fd]->fd_pos; // int f_size = p_proc_current->task.filp[fd]->fd_inode->i_size; //deleted by mingxuan 2019-5-17 int f_size = p_proc_current->task.filp[fd]->fd_node.fd_inode->i_size; // modified by mingxuan 2019-5-17 switch (whence) { case SEEK_SET: pos = off; break; case SEEK_CUR: pos += off; break; case SEEK_END: pos = f_size + off; break; default: return -1; break; } if ((pos > f_size) || (pos < 0)) { return -1; } p_proc_current->task.filp[fd]->fd_pos = pos; return pos; }