Fixes insert_file()
[akaros.git] / kern / src / vfs.c
index 9a2de2a..bc43859 100644 (file)
@@ -1330,7 +1330,16 @@ struct file *do_file_open(char *path, int flags, int mode)
        nd->intent = LOOKUP_OPEN;
        error = path_lookup(path, LOOKUP_FOLLOW, nd);
        if (!error) {
-               /* Still need to make sure we didn't want to O_EXCL create */
+               /* If this is a directory, make sure we are opening with O_RDONLY.
+                * Unfortunately we can't just check for O_RDONLY directly because its
+                * value is 0x0.  We instead have to make sure it's not O_WRONLY and
+                * not O_RDWR explicitly. */
+               if (S_ISDIR(nd->dentry->d_inode->i_mode) &&
+                   ((flags & O_WRONLY) || (flags & O_RDWR))) {
+                       set_errno(EISDIR);
+                       goto out_path_only;
+               }
+               /* Also need to make sure we didn't want to O_EXCL create */
                if ((flags & O_CREAT) && (flags & O_EXCL)) {
                        set_errno(EEXIST);
                        goto out_path_only;
@@ -2217,7 +2226,8 @@ static int __claim_fd(struct files_struct *open_files, int file_desc)
                return -ENFILE; /* Should never really happen. Here to catch bugs. */
 
        SET_BITMASK_BIT(open_files->open_fds->fds_bits, file_desc);
-       assert(file_desc < open_files->max_files && open_files->fd[0].fd_file == 0);
+       assert(file_desc < open_files->max_files &&
+              open_files->fd[file_desc].fd_file == 0);
        if (file_desc >= open_files->next_fd)
                open_files->next_fd = file_desc + 1;
        return 0;
@@ -2235,11 +2245,23 @@ int claim_fd(struct files_struct *open_files, int file_desc)
 
 /* Inserts the file in the files_struct, returning the corresponding new file
  * descriptor, or an error code.  We start looking for open fds from low_fd. */
-int insert_file(struct files_struct *open_files, struct file *file, int low_fd)
+int insert_file(struct files_struct *open_files, struct file *file, int low_fd,
+                bool must)
 {
-       int slot;
+       int slot, ret;
        spin_lock(&open_files->lock);
-       slot = __get_fd(open_files, low_fd);
+       if (must) {
+               ret = __claim_fd(open_files, low_fd);
+               if (ret < 0) {
+                       spin_unlock(&open_files->lock);
+                       return ret;
+               }
+               assert(!ret);   /* issues with claim_fd returning status, not the fd */
+               slot = low_fd;
+       } else {
+               slot = __get_fd(open_files, low_fd);
+       }
+
        if (slot < 0) {
                spin_unlock(&open_files->lock);
                return slot;