/* Open system call. */ static int sys_open (const char *ufile) { char *kfile = copy_in_string (ufile); struct file_descriptor *fd; int handle = -1; fd = calloc (1, sizeof *fd); if (fd != NULL) { struct inode *inode = filesys_open (kfile); if (inode != NULL) { if (inode_get_type (inode) == FILE_INODE) fd->file = file_open (inode); else fd->dir = dir_open (inode); if (fd->file != NULL || fd->dir != NULL) { struct thread *cur = thread_current (); handle = fd->handle = cur->next_handle++; list_push_front (&cur->fds, &fd->elem); } else { free (fd); inode_close (inode); } } } palloc_free_page (kfile); return handle; }
/******************************************************************************* fs_ialloc: allocates any free disk inode. It allocates the -first- free inode it finds on disk. *******************************************************************************/ struct inode * fs_ialloc(dev_nr_t dev_nr) { struct super *sp; struct inode *ip; uint16_t nr_imap_blocks; struct buffer *bp; mfs_inode_nr_t inode_nr; unsigned long int nr_inodes; unsigned int i; assert(dev_nr, "fs_ialloc(): Zero device number"); sp = fs_mount_table_get_super(dev_nr); /* POSSIBLE INCREMENT OF THE SUPERBLOCK REFERENCE COUNT */ /* IT SHOULD BE ANY WAY OF LOCKING THIS DEVICE SO NO OTHER PROCESS COULD UNMOUNT IT */ repeat: nr_imap_blocks = super_get_nr_imap_blocks(sp); assert(nr_imap_blocks, "fs_ialloc(): Zero # of inode bitmap blocks"); nr_inodes = super_get_nr_inodes(sp); /* search for any free inode on disk */ for (i = 0; i < nr_imap_blocks; i++) { if( !(bp = cache_bread(dev_nr, FIRST_IMAP_BLOCK_NR + i)) ) { assert(0, "fs_ialloc(): Unable to get inode map block"); if ( (inode_nr = inode_bitmap_get_zero(bp, i)) ) break; /* found free inode on inode bitmap */ /* do not release the bitmap block yet, so we can * mark that free inode as busy later */ /* did not find a free inode in this inode bitmap */ cache_brelse(bp); } } /* search for a free inode completed */ if (!inode_nr) return NULL; /* there are no available free inodes */ assert(inode_nr <= nr_inodes, "fs_ialloc(): wrong inode number"); /* update the inode bitmap, so no other process tries to allocate this inode */ bitmap_set_bit(bp, inode_nr % NR_BITS_PER_BLOCK); buffer_set_dirty(bp); cache_brelse(bp); if ( (ip = fs_iget(dev_nr, inode_nr)) ) assert(0, "fs_ialloc(): Unable to read inode"); /* check whether the inode is actually free */ if (0 != inode_get_type(ip)) { /* the inode bitmap is corrupted */ fs_iput(ip); /* release the inode */ goto repeat; } return ip; }
/* Removes any entry for NAME in DIR. Returns true if successful, false on failure, which occurs only if there is no file with the given NAME. */ bool dir_remove (struct dir *dir, const char *name) { struct dir_entry e; struct inode *inode = NULL; bool success = false; off_t ofs; ASSERT (dir != NULL); ASSERT (name != NULL); /* Find directory entry. */ if (!lookup (dir, name, &e, &ofs)) goto done; /* Open inode. */ inode = inode_open (e.inode_sector); if (inode == NULL) goto done; if (inode_get_type(inode) == TYPE_DIRECTORY) { struct dir *dir = dir_open(inode); if (dir_is_empty(dir) == false) { dir_close(dir); goto done; } dir_close(dir); } /* Erase directory entry. */ e.in_use = false; if (inode_write_at (dir->inode, &e, sizeof e, ofs) != sizeof e) goto done; /* Remove inode. */ inode_remove (inode); success = true; done: inode_close (inode); return success; }