/* 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; /* 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; }
int unregister_blockdriver(FAR const char *path) { int ret; inode_semtake(); ret = inode_remove(path); inode_semgive(); return ret; }
/* 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); //lock the directory for the rest of the lookup operation inode_lock(dir->inode); name = getfilename(name); /* 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 it is still open don't allow deletion if(inode_type(inode) == FILE_DIR) { //is file in use? if(inode_opencnt(inode) > 1) goto done; char * temp = (char *)malloc(sizeof(char) * (NAME_MAX + 1) ); struct dir * dirtemp = dir_open(inode); //is dir empty? if (dir_readdir(dirtemp,temp)) { free(temp); dir_close(dirtemp); goto done; } free(temp); dir_close(dirtemp); } /* 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: //unlock the directory inode_unlock(dir->inode); inode_close (inode); return success; }
/* Deletes NAME from 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); lock_acquire (&dir->l); /* 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 directory, make sure it's empty */ if (inode_is_directory (inode)) { struct dir *inner = dir_open (inode_open (e.inode_sector)); int size = dir_size (inner); dir_close (inner); if (size != 0) goto done; } /* Erase directory entry. */ e.in_use = false; if (inode_write_at (dir->inode, &e, sizeof e, ofs) != sizeof e) goto done; /* Remove inode. */ success = inode_remove (inode); done: lock_release (&dir->l); inode_close (inode); return success; }
/* 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 file *dir, const char *name) { ASSERT (file_is_dir (dir)); struct dir_entry e; struct inode *inode = NULL; bool success = false; off_t ofs; int sector; ASSERT (dir != NULL); ASSERT (name != NULL); bool locked = file_lock (dir); /* Find directory entry. */ if ((sector = lookup (dir, name, &ofs, &e)) < 0) goto done; /* Open inode. */ inode = inode_open (sector); if (inode == NULL) goto done; /* 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: if (locked) file_unlock (dir); if (inode) inode_close (inode); return success; }
int unlink(FAR const char *pathname) { FAR struct inode *inode; const char *relpath = NULL; int errcode; int ret; /* Get an inode for this file */ inode = inode_find(pathname, &relpath); if (!inode) { /* There is no inode that includes in this path */ errcode = ENOENT; goto errout; } #ifndef CONFIG_DISABLE_MOUNTPOINT /* Check if the inode is a valid mountpoint. */ if (INODE_IS_MOUNTPT(inode) && inode->u.i_mops) { /* Perform the unlink operation using the relative path at the * mountpoint. */ if (inode->u.i_mops->unlink) { ret = inode->u.i_mops->unlink(inode, relpath); if (ret < 0) { errcode = -ret; goto errout_with_inode; } } else { errcode = ENOSYS; goto errout_with_inode; } } else #endif #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS /* If this is a "dangling" pseudo-file node (i.e., it has operations) then rm * should remove the node. */ if (!INODE_IS_SPECIAL(inode) && inode->u.i_ops) { /* If this is a pseudo-file node (i.e., it has no operations) * then rmdir should remove the node. */ if (inode->u.i_ops) { inode_semtake(); /* Refuse to unlink the inode if it has children. I.e., if it is * functioning as a directory and the directory is not empty. */ if (inode->i_child != NULL) { errcode = ENOTEMPTY; inode_semgive(); goto errout_with_inode; } /* Remove the old inode. Because we hold a reference count on the * inode, it will not be deleted now. It will be deleted when all * of the references to to the inode have been released (perhaps * when inode_release() is called below). inode_remove() will * return -EBUSY to indicate that the inode was not deleted now. */ ret = inode_remove(pathname); inode_semgive(); if (ret < 0 && ret != -EBUSY) { errcode = -ret; goto errout_with_inode; } } else { errcode = EISDIR; goto errout_with_inode; } } else #endif { errcode = ENXIO; goto errout_with_inode; } /* Successfully unlinked */ inode_release(inode); return OK; errout_with_inode: inode_release(inode); errout: set_errno(errcode); return ERROR; }
int sem_unlink(FAR const char *name) { FAR struct inode *inode; FAR const char *relpath = NULL; char fullpath[MAX_SEMPATH]; int errcode; int ret; /* Get the full path to the semaphore */ snprintf(fullpath, MAX_SEMPATH, CONFIG_FS_NAMED_SEMPATH "/%s", name); /* Get the inode for this semaphore. */ sched_lock(); inode = inode_find(fullpath, &relpath); if (!inode) { /* There is no inode that includes in this path */ errcode = ENOENT; goto errout; } /* Verify that what we found is, indeed, a semaphore */ if (!INODE_IS_NAMEDSEM(inode)) { errcode = ENXIO; goto errout_with_inode; } /* Refuse to unlink the inode if it has children. I.e., if it is * functioning as a directory and the directory is not empty. */ inode_semtake(); if (inode->i_child != NULL) { errcode = ENOTEMPTY; goto errout_with_semaphore; } /* Remove the old inode from the tree. Because we hold a reference count * on the inode, it will not be deleted now. This will set the * FSNODEFLAG_DELETED bit in the inode flags. */ ret = inode_remove(fullpath); /* inode_remove() should always fail with -EBUSY because we hae a reference * on the inode. -EBUSY means taht the inode was, indeed, unlinked but * thatis could not be freed because there are refrences. */ DEBUGASSERT(ret >= 0 || ret == -EBUSY); UNUSED(ret); /* Now we do not release the reference count in the normal way (by calling * inode release. Rather, we call sem_close(). sem_close will decrement * the reference count on the inode. But it will also free the semaphore * if that reference count decrements to zero. Since we hold one reference, * that can only occur if the semaphore is not in-use. */ inode_semgive(); ret = sem_close((FAR sem_t *)inode->u.i_nsem); sched_unlock(); return ret; errout_with_semaphore: inode_semgive(); errout_with_inode: inode_release(inode); errout: set_errno(errcode); sched_unlock(); return ERROR; }
int mount(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, const void *data) { #if defined(BDFS_SUPPORT) || defined(NONBDFS_SUPPORT) #ifdef BDFS_SUPPORT FAR struct inode *blkdrvr_inode = NULL; #endif FAR struct inode *mountpt_inode; FAR const struct mountpt_operations *mops; void *fshandle; int errcode; int status; /* Verify required pointer arguments */ DEBUGASSERT(target && filesystemtype); /* Find the specified filesystem. Try the block driver file systems first */ #ifdef BDFS_SUPPORT if ((mops = mount_findfs(g_bdfsmap, filesystemtype)) != NULL) { /* Make sure that a block driver argument was provided */ DEBUGASSERT(source); /* Find the block driver */ status = find_blockdriver(source, mountflags, &blkdrvr_inode); if (status < 0) { fdbg("Failed to find block driver %s\n", source); errcode = -status; goto errout; } } else #endif /* BDFS_SUPPORT */ #ifdef NONBDFS_SUPPORT if ((mops = mount_findfs(g_nonbdfsmap, filesystemtype)) != NULL) { } else #endif /* NONBDFS_SUPPORT */ { fdbg("Failed to find file system %s\n", filesystemtype); errcode = ENODEV; goto errout; } /* Insert a dummy node -- we need to hold the inode semaphore * to do this because we will have a momentarily bad structure. */ inode_semtake(); mountpt_inode = inode_reserve(target); if (!mountpt_inode) { /* inode_reserve can fail for a couple of reasons, but the most likely * one is that the inode already exists. */ fdbg("Failed to reserve inode\n"); errcode = EBUSY; goto errout_with_semaphore; } /* Bind the block driver to an instance of the file system. The file * system returns a reference to some opaque, fs-dependent structure * that encapsulates this binding. */ if (!mops->bind) { /* The filesystem does not support the bind operation ??? */ fdbg("Filesystem does not support bind\n"); errcode = EINVAL; goto errout_with_mountpt; } /* Increment reference count for the reference we pass to the file system */ #ifdef BDFS_SUPPORT #ifdef NONBDFS_SUPPORT if (blkdrvr_inode) #endif { blkdrvr_inode->i_crefs++; } #endif /* On failure, the bind method returns -errorcode */ #ifdef BDFS_SUPPORT status = mops->bind(blkdrvr_inode, data, &fshandle); #else status = mops->bind(NULL, data, &fshandle); #endif if (status != 0) { /* The inode is unhappy with the blkdrvr for some reason. Back out * the count for the reference we failed to pass and exit with an * error. */ fdbg("Bind method failed: %d\n", status); #ifdef BDFS_SUPPORT #ifdef NONBDFS_SUPPORT if (blkdrvr_inode) #endif { blkdrvr_inode->i_crefs--; } #endif errcode = -status; goto errout_with_mountpt; } /* We have it, now populate it with driver specific information. */ INODE_SET_MOUNTPT(mountpt_inode); mountpt_inode->u.i_mops = mops; #ifdef CONFIG_FILE_MODE mountpt_inode->i_mode = mode; #endif mountpt_inode->i_private = fshandle; inode_semgive(); /* We can release our reference to the blkdrver_inode, if the filesystem * wants to retain the blockdriver inode (which it should), then it must * have called inode_addref(). There is one reference on mountpt_inode * that will persist until umount() is called. */ #ifdef BDFS_SUPPORT #ifdef NONBDFS_SUPPORT if (blkdrvr_inode) #endif { inode_release(blkdrvr_inode); } #endif return OK; /* A lot of goto's! But they make the error handling much simpler */ errout_with_mountpt: mountpt_inode->i_crefs = 0; inode_remove(target); inode_semgive(); #ifdef BDFS_SUPPORT #ifdef NONBDFS_SUPPORT if (blkdrvr_inode) #endif { inode_release(blkdrvr_inode); } #endif inode_release(mountpt_inode); goto errout; errout_with_semaphore: inode_semgive(); #ifdef BDFS_SUPPORT #ifdef NONBDFS_SUPPORT if (blkdrvr_inode) #endif { inode_release(blkdrvr_inode); } #endif errout: errno = errcode; return ERROR; #else fdbg("No filesystems enabled\n"); ernno = ENOSYS; return error; #endif /* BDFS_SUPPORT || NONBDFS_SUPPORT */ }
/* Creates a file named NAME with the given INITIAL_SIZE. Returns true if successful, false otherwise. Fails if a file named NAME already exists, or if internal memory allocation fails. */ static bool _filesys_create (const char *full_path, off_t initial_size, bool is_dir) { block_sector_t cwd = thread_current ()->cwd_sector; bool found = true; if (cwd != (block_sector_t) ROOT_DIR_SECTOR) { struct inode *curr = NULL; curr = inode_open (cwd); struct dir *p; p = dir_open (inode_open (curr->data.parent_dir_sector)); struct dir_entry e; size_t ofs; ASSERT (p != NULL); found = false; for (ofs = 0; inode_read_at (p->inode, &e, sizeof e, ofs) == sizeof e; ofs += sizeof e) { if (e.inode_sector == cwd && e.in_use) { found = true; break; } } } if (!found) return false; char leaf_name[NAME_MAX + 1]; if (!dir_get_leaf_name (full_path, leaf_name)) return false; struct dir *parent_dir = dir_get_parent_dir (full_path); if (parent_dir == NULL) return false; block_sector_t inode_sector = 0; if (!free_map_allocate_one (&inode_sector)) { dir_close (parent_dir); return false; } bool success = is_dir? dir_create (inode_sector, BLOCK_SECTOR_SIZE / sizeof (struct dir_entry)) : inode_create (inode_sector, initial_size); if (!success) { free_map_release (inode_sector, 1); dir_close (parent_dir); return false; } if (!dir_add (parent_dir, leaf_name, inode_sector)) { inode_remove (inode_open (inode_sector)); free_map_release (inode_sector, 1); dir_close (parent_dir); return false; } dir_close (parent_dir); return true; }
int rename(FAR const char *oldpath, FAR const char *newpath) { FAR struct inode *oldinode; FAR struct inode *newinode; const char *oldrelpath = NULL; #ifndef CONFIG_DISABLE_MOUNTPOINT const char *newrelpath = NULL; #endif int errcode; int ret; /* Ignore paths that are interpreted as the root directory which has no name * and cannot be moved */ if (!oldpath || *oldpath == '\0' || oldpath[0] != '/' || !newpath || *newpath == '\0' || newpath[0] != '/') { return -EINVAL; } /* Get an inode that includes the oldpath */ oldinode = inode_find(oldpath, &oldrelpath); if (!oldinode) { /* There is no inode that includes in this path */ errcode = ENOENT; goto errout; } #ifndef CONFIG_DISABLE_MOUNTPOINT /* Verify that the old inode is a valid mountpoint. */ if (INODE_IS_MOUNTPT(oldinode) && oldinode->u.i_mops) { /* Get an inode for the new relpath -- it should like on the same * mountpoint */ newinode = inode_find(newpath, &newrelpath); if (!newinode) { /* There is no mountpoint that includes in this path */ errcode = ENOENT; goto errout_with_oldinode; } /* Verify that the two paths lie on the same mountpoint inode */ if (oldinode != newinode) { errcode = EXDEV; goto errout_with_newinode; } /* Perform the rename operation using the relative paths * at the common mountpoint. */ if (oldinode->u.i_mops->rename) { ret = oldinode->u.i_mops->rename(oldinode, oldrelpath, newrelpath); if (ret < 0) { errcode = -ret; goto errout_with_newinode; } } else { errcode = ENOSYS; goto errout_with_newinode; } /* Successfully renamed */ inode_release(newinode); } else #endif #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS { /* Create a new, empty inode at the destination location. * NOTE that the new inode will be created with a reference count * of zero. */ inode_semtake(); ret = inode_reserve(newpath, &newinode); if (ret < 0) { /* It is an error if a node at newpath already exists in the tree * OR if we fail to allocate memory for the new inode (and possibly * any new intermediate path segments). */ inode_semgive(); errcode = EEXIST; goto errout_with_oldinode; } /* Copy the inode state from the old inode to the newly allocated inode */ newinode->i_child = oldinode->i_child; /* Link to lower level inode */ newinode->i_flags = oldinode->i_flags; /* Flags for inode */ newinode->u.i_ops = oldinode->u.i_ops; /* Inode operations */ #ifdef CONFIG_FILE_MODE newinode->i_mode = oldinode->i_mode; /* Access mode flags */ #endif newinode->i_private = oldinode->i_private; /* Per inode driver private data */ /* We now have two copies of the inode. One with a reference count of * zero (the new one), and one that may have multiple references * including one by this logic (the old one) * * Remove the old inode. Because we hold a reference count on the * inode, it will not be deleted now. It will be deleted when all of * the references to to the inode have been released (perhaps when * inode_release() is called below). inode_remove() should return * -EBUSY to indicate that the inode was not deleted now. */ ret = inode_remove(oldpath); if (ret < 0 && ret != -EBUSY) { /* Remove the new node we just recreated */ (void)inode_remove(newpath); inode_semgive(); errcode = -ret; goto errout_with_oldinode; } /* Remove all of the children from the unlinked inode */ oldinode->i_child = NULL; inode_semgive(); } #else { errcode = ENXIO; goto errout; } #endif /* Successfully renamed */ inode_release(oldinode); return OK; #ifndef CONFIG_DISABLE_MOUNTPOINT errout_with_newinode: inode_release(newinode); #endif errout_with_oldinode: inode_release(oldinode); errout: set_errno(errcode); return ERROR; }
int umount(const char *target) { FAR struct inode *mountpt_inode; FAR struct inode *blkdrvr_inode = NULL; int errcode = OK; int status; /* Verify required pointer arguments */ if (!target) { errcode = EFAULT; goto errout; } /* Find the mountpt */ mountpt_inode = inode_find(target, NULL); if (!mountpt_inode) { errcode = ENOENT; goto errout; } /* Verify that the inode is a mountpoint */ if (!INODE_IS_MOUNTPT(mountpt_inode)) { errcode = EINVAL; goto errout_with_mountpt; } /* Unbind the block driver from the file system (destroying any fs * private data. */ if (!mountpt_inode->u.i_mops->unbind) { /* The filesystem does not support the unbind operation ??? */ errcode = EINVAL; goto errout_with_mountpt; } /* The unbind method returns the number of references to the * filesystem (i.e., open files), zero if the unbind was * performed, or a negated error code on a failure. */ inode_semtake(); /* Hold the semaphore through the unbind logic */ status = mountpt_inode->u.i_mops->unbind( mountpt_inode->i_private, &blkdrvr_inode); if (status < 0) { /* The inode is unhappy with the blkdrvr for some reason */ errcode = -status; goto errout_with_semaphore; } else if (status > 0) { errcode = EBUSY; goto errout_with_semaphore; } /* Successfully unbound */ mountpt_inode->i_private = NULL; /* Successfully unbound, remove the mountpoint inode from * the inode tree. The inode will not be deleted yet because * there is still at least reference on it (from the mount) */ status = inode_remove(target); inode_semgive(); /* The return value of -EBUSY is normal (in fact, it should * not be OK) */ if (status != OK && status != -EBUSY) { errcode = -status; goto errout_with_mountpt; } /* Release the mountpoint inode and any block driver inode * returned by the file system unbind above. This should cause * the inode to be deleted (unless there are other references) */ inode_release(mountpt_inode); /* Did the unbind method return a contained block driver */ if (blkdrvr_inode) { inode_release(blkdrvr_inode); } return OK; /* A lot of goto's! But they make the error handling much simpler */ errout_with_semaphore: inode_semgive(); errout_with_mountpt: inode_release(mountpt_inode); if (blkdrvr_inode) { inode_release(blkdrvr_inode); } errout: set_errno(errcode); return ERROR; }
int umount2(FAR const char *target, unsigned int flags) { FAR struct inode *mountpt_inode; FAR struct inode *blkdrvr_inode = NULL; struct inode_search_s desc; int errcode = OK; int ret; /* Verify required pointer arguments */ if (!target) { errcode = EFAULT; goto errout; } /* Find the mountpt */ SETUP_SEARCH(&desc, target, false); ret = inode_find(&desc); if (ret < 0) { errcode = ENOENT; goto errout_with_search; } /* Get the search results */ mountpt_inode = desc.node; DEBUGASSERT(mountpt_inode != NULL); /* Verify that the inode is a mountpoint */ if (!INODE_IS_MOUNTPT(mountpt_inode)) { errcode = EINVAL; goto errout_with_mountpt; } /* Unbind the block driver from the file system (destroying any fs * private data. */ if (!mountpt_inode->u.i_mops->unbind) { /* The filesystem does not support the unbind operation ??? */ errcode = EINVAL; goto errout_with_mountpt; } /* The unbind method returns the number of references to the * filesystem (i.e., open files), zero if the unbind was * performed, or a negated error code on a failure. */ inode_semtake(); /* Hold the semaphore through the unbind logic */ ret = mountpt_inode->u.i_mops->unbind(mountpt_inode->i_private, &blkdrvr_inode, flags); if (ret < 0) { /* The inode is unhappy with the blkdrvr for some reason */ errcode = -ret; goto errout_with_semaphore; } else if (ret > 0) { errcode = EBUSY; goto errout_with_semaphore; } /* Successfully unbound. Convert the mountpoint inode to regular * pseudo-file inode. */ mountpt_inode->i_flags &= ~FSNODEFLAG_TYPE_MASK; mountpt_inode->i_private = NULL; mountpt_inode->u.i_mops = NULL; #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS /* If the node has children, then do not delete it. */ if (mountpt_inode->i_child != NULL) { /* Just decrement the reference count (without deleting it) */ DEBUGASSERT(mountpt_inode->i_crefs > 0); mountpt_inode->i_crefs--; } else #endif { /* Remove the mountpoint inode from the inode tree. The inode will * not be deleted yet because there is still at least reference on * it (from the mount) */ ret = inode_remove(target); inode_semgive(); /* The return value of -EBUSY is normal (in fact, it should * not be OK) */ if (ret != OK && ret != -EBUSY) { errcode = -ret; goto errout_with_mountpt; } /* Release the mountpoint inode and any block driver inode * returned by the file system unbind above. This should cause * the inode to be deleted (unless there are other references) */ inode_release(mountpt_inode); } /* Did the unbind method return a contained block driver */ if (blkdrvr_inode) { inode_release(blkdrvr_inode); } RELEASE_SEARCH(&desc); return OK; /* A lot of goto's! But they make the error handling much simpler */ errout_with_semaphore: inode_semgive(); errout_with_mountpt: inode_release(mountpt_inode); if (blkdrvr_inode) { inode_release(blkdrvr_inode); } errout_with_search: RELEASE_SEARCH(&desc); errout: set_errno(errcode); return ERROR; }
int rmdir(FAR const char *pathname) { FAR struct inode *inode; const char *relpath = NULL; int errcode; /* Get an inode for this file. inode_find() automatically increments the * reference count on the inode if one is found. */ inode = inode_find(pathname, &relpath); if (!inode) { /* There is no inode that includes in this path */ errcode = ENOENT; goto errout; } #ifndef CONFIG_DISABLE_MOUNTPOINT /* Check if the inode is a valid mountpoint. */ if (INODE_IS_MOUNTPT(inode) && inode->u.i_mops) { /* Perform the rmdir operation using the relative path * from the mountpoint. */ if (inode->u.i_mops->rmdir) { int ret = inode->u.i_mops->rmdir(inode, relpath); if (ret < 0) { errcode = -ret; goto errout_with_inode; } } else { errcode = ENOSYS; goto errout_with_inode; } } else #endif #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS /* If this is a "dangling" pseudo-directory node (i.e., it has no operations) * then rmdir should remove the node. */ if (!inode->u.i_ops) { int ret; /* If the directory inode has children, however, then it cannot be * removed. */ if (inode->i_child) { errcode = ENOTEMPTY; goto errout_with_inode; } /* Remove the inode. NOTE: Because we hold a reference count on the * inode, it will not be deleted now. But probably when inode_release() * is called below. inode_remove should return -EBUSY to indicate that * the inode was not deleted now. */ inode_semtake(); ret = inode_remove(pathname); inode_semgive(); if (ret < 0 && ret != -EBUSY) { errcode = -ret; goto errout_with_inode; } } else { errcode = ENOTDIR; goto errout_with_inode; } #else { errcode = ENXIO; goto errout_with_inode; } #endif /* Successfully removed the directory */ inode_release(inode); return OK; errout_with_inode: inode_release(inode); errout: set_errno(errcode); return ERROR; }
bool dir_remove (struct dir *directory, const char *file) { struct dir_entry directory_element_1, directory_element_2; struct inode *inode = NULL; bool present = false; off_t offset_1, offset_2; int count; ASSERT(directory != NULL); ASSERT(file != NULL); acquire_inode_lock (directory->inode); for (offset_2 = 0; inode_read_at (directory->inode, &directory_element_2, sizeof directory_element_2, offset_2) == sizeof directory_element_2; offset_2 += sizeof directory_element_2) if (directory_element_2.in_use && !strcmp (file, directory_element_2.name)) { directory_element_1 = directory_element_2; offset_1 = offset_2; present = true; } if (!present) { inode_close (inode); release_inode_lock (directory->inode); return false; } inode = inode_open (directory_element_1.inode_sector); if (inode == NULL) { inode_close (inode); release_inode_lock (directory->inode); return false; } if (is_inode_dir (inode) && get_inode_open_cnt (inode) > 1) { inode_close (inode); release_inode_lock (directory->inode); return false; } if (is_inode_dir (inode) && !dir_is_empty (inode)) { inode_close (inode); release_inode_lock (directory->inode); return false; } directory_element_1.in_use = false; offset_2 = inode_write_at (directory->inode, &directory_element_1, sizeof directory_element_1, offset_1); if (sizeof directory_element_1 != offset_2) { inode_close (inode); release_inode_lock (directory->inode); return false; } inode_remove (inode); inode_close (inode); release_inode_lock (directory->inode); return true; }