BigOS/kernel/fs.c
2023-01-15 16:10:09 +08:00

1624 lines
48 KiB
C

/// 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"
#include "x86.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
*****************************************************************************/
/**
* <Ring 1> 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
*****************************************************************************/
/**
* <Ring 1> 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;
disable_int();
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);
enable_int();
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. */
disable_int();
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);
enable_int();
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
*****************************************************************************/
/**
* <Ring 1> 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
*****************************************************************************/
/**
* <Ring 1> 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
*****************************************************************************/
/**
* <Ring 1> 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
*****************************************************************************/
/**
* <Ring 1> 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(get_tty(nr_tty), buf, len);
}
else if (fs_msg->type == DEV_WRITE)
{
// kprintf("pid %d, tty %d; ", p_proc_current->task.pid, nr_tty);
tty_write(get_tty(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;
}