// Open a file (or directory). // // Returns: // The file descriptor index on success // -E_BAD_PATH if the path is too long (>= MAXPATHLEN) // < 0 for other errors. int open(const char *path, int mode) { // Find an unused file descriptor page using fd_alloc. // Then send a file-open request to the file server. // Include 'path' and 'omode' in request, // and map the returned file descriptor page // at the appropriate fd address. // FSREQ_OPEN returns 0 on success, < 0 on failure. // // (fd_alloc does not allocate a page, it just returns an // unused fd address. Do you need to allocate a page?) // // Return the file descriptor index. // If any step after fd_alloc fails, use fd_close to free the // file descriptor. // LAB 5: Your code here. struct Fd* retval; int r = fd_alloc(&retval); if(r<0) return r; fsipcbuf.open.req_omode = mode; strcpy(fsipcbuf.open.req_path, path); r = fsipc(FSREQ_OPEN, retval); if (r<0) { fd_close(retval, 0); return r; } return fd2num(retval); // panic("open not implemented"); }
// Open a file (or directory). // // Returns: // The file descriptor index on success // -E_BAD_PATH if the path is too long (>= MAXPATHLEN) // < 0 for other errors. int open(const char *path, int mode) { // Find an unused file descriptor page using fd_alloc. // Then send a file-open request to the file server. // Include 'path' and 'omode' in request, // and map the returned file descriptor page // at the appropriate fd address. // FSREQ_OPEN returns 0 on success, < 0 on failure. // // (fd_alloc does not allocate a page, it just returns an // unused fd address. Do you need to allocate a page?) // // Return the file descriptor index. // If any step after fd_alloc fails, use fd_close to free the struct Fd *f = NULL; int r = 0; if (!path) return -E_INVAL; if((r=fd_alloc(&f))<0) return r; strcpy(fsipcbuf.open.req_path, path); fsipcbuf.open.req_omode = mode; if ((r=fsipc(FSREQ_OPEN, f))<0) { fd_close(f, 0); return r; } return fd2num(f); }
// Open a file (or directory), // returning the file descriptor index on success, < 0 on failure. int open(const char *path, int mode) { // Find an unused file descriptor page using fd_alloc. // Then send a message to the file server to open a file // using a function in fsipc.c. // (fd_alloc does not allocate a page, it just returns an // unused fd address. Do you need to allocate a page? Look // at fsipc.c if you aren't sure.) // Then map the file data (you may find fmap() helpful). // Return the file descriptor index. // If any step fails, use fd_close to free the file descriptor. // LAB 5: Your code here. int r; struct Fd *fd; if ((r = fd_alloc(&fd)) < 0) return r; if ((r = fsipc_open(path, mode, fd)) < 0){ fd_close(fd, 0); return r; } if ((r = fmap(fd, 0, fd->fd_file.file.f_size) ) < 0){ fd_close(fd, 0); return r; } return fd2num(fd); }
// Open a file (or directory). // // Returns: // The file descriptor index on success // -E_BAD_PATH if the path is too long (>= MAXPATHLEN) // < 0 for other errors. int open(const char *path, int mode) { // Find an unused file descriptor page using fd_alloc. // Then send a file-open request to the file server. // Include 'path' and 'omode' in request, // and map the returned file descriptor page // at the appropriate fd address. // FSREQ_OPEN returns 0 on success, < 0 on failure. // // (fd_alloc does not allocate a page, it just returns an // unused fd address. Do you need to allocate a page?) // // Return the file descriptor index. // If any step after fd_alloc fails, use fd_close to free the // file descriptor. // LAB 5: Your code here. struct Fd *fd; int r; if((r = fd_alloc(&fd)) < 0) return r; strcpy(fsipcbuf.open.req_path, path); fsipcbuf.open.req_omode = mode; ipc_send(envs[1].env_id, FSREQ_OPEN, &fsipcbuf, PTE_P | PTE_W | PTE_U); if((r = ipc_recv(NULL, fd, NULL))<0) return r; return fd2num(fd); panic("open not implemented"); }
int pipe(int pfd[2]) { int r; struct Fd *fd0, *fd1; void *va; // allocate the file descriptor table entries if ((r = fd_alloc(&fd0)) < 0 || (r = sys_page_alloc(0, fd0, PTE_P|PTE_W|PTE_U|PTE_SHARE)) < 0) goto err; if ((r = fd_alloc(&fd1)) < 0 || (r = sys_page_alloc(0, fd1, PTE_P|PTE_W|PTE_U|PTE_SHARE)) < 0) goto err1; // allocate the pipe structure as first data page in both va = fd2data(fd0); if ((r = sys_page_alloc(0, va, PTE_P|PTE_W|PTE_U|PTE_SHARE)) < 0) goto err2; if ((r = sys_page_map(0, va, 0, fd2data(fd1), PTE_P|PTE_W|PTE_U|PTE_SHARE)) < 0) goto err3; // set up fd structures fd0->fd_dev_id = devpipe.dev_id; fd0->fd_omode = O_RDONLY; fd1->fd_dev_id = devpipe.dev_id; fd1->fd_omode = O_WRONLY; if (debug) cprintf("[%08x] pipecreate %08x\n", env->env_id, vpt[VPN(va)]); pfd[0] = fd2num(fd0); pfd[1] = fd2num(fd1); return 0; err3: sys_page_unmap(0, va); err2: sys_page_unmap(0, fd1); err1: sys_page_unmap(0, fd0); err: return r; }
int opencons(void) { int r; struct Fd* fd; if ((r = fd_find_unused(&fd)) < 0) return r; if ((r = sys_page_alloc(0, fd, PTE_P|PTE_U|PTE_W|PTE_SHARE)) < 0) return r; fd->fd_dev_id = devcons.dev_id; fd->fd_omode = O_RDWR; return fd2num(fd); }
int opencons(void) { int r; struct Fd *fd; if ((r = fd_alloc(&fd)) < 0) return r; if ((r = syscall_mem_alloc(0, (u_int)fd, PTE_V|PTE_R|PTE_LIBRARY)) < 0) return r; fd->fd_dev_id = devcons.dev_id; fd->fd_omode = O_RDWR; return fd2num(fd); }
// Frees file descriptor 'fd' by closing the corresponding file // and unmapping the file descriptor page. // If 'must_exist' is 0, then fd can be a closed or nonexistent file // descriptor; the function will return 0 and have no other effect. // If 'must_exist' is 1, then fd_close returns -E_INVAL when passed a // closed or nonexistent file descriptor. // Returns 0 on success, < 0 on error. int fd_close(struct Fd *fd, bool must_exist) { struct Fd *fd2; struct Dev *dev; int r; if ((r = fd_lookup(fd2num(fd), &fd2)) < 0 || fd != fd2) return (must_exist ? r : 0); if ((r = dev_lookup(fd->fd_dev_id, &dev)) >= 0) r = (*dev->dev_close)(fd); // Make sure fd is unmapped. Might be a no-op if // (*dev->dev_close)(fd) already unmapped it. (void) sys_page_unmap(0, fd); return r; }
// Open a file (or directory). // // Returns: // The file descriptor index on success // -E_BAD_PATH if the path is too long (>= MAXPATHLEN) // < 0 for other errors. int open(const char *path, int mode) { // Find an unused file descriptor page using fd_alloc. // Then send a file-open request to the file server. // Include 'path' and 'omode' in request, // and map the returned file descriptor page // at the appropriate fd address. // FSREQ_OPEN returns 0 on success, < 0 on failure. // // (fd_alloc does not allocate a page, it just returns an // unused fd address. Do you need to allocate a page?) // // Return the file descriptor index. // If any step after fd_alloc fails, use fd_close to free the // file descriptor. // LAB 5: Your code here. //panic("open not implemented"); int result; struct Fd *fd_instance; if(strlen(path) >= MAXPATHLEN) { cprintf("open() error: path is too long"); return -E_BAD_PATH; } if((result=fd_alloc(&fd_instance)) < 0) { return result; } strcpy(fsipcbuf.open.req_path, path); fsipcbuf.open.req_omode=mode; if((result=fsipc(FSREQ_OPEN, (void *)fd_instance)) < 0) { fd_close(fd_instance, 0); return result; } else { return fd2num(fd_instance); } }
// Open a file (or directory). // // Returns: // The file descriptor index on success // -E_BAD_PATH if the path is too long (>= MAXPATHLEN) // < 0 for other errors. int open(const char *path, int mode) { // Find an unused file descriptor page using fd_alloc. // Then send a file-open request to the file server. // Include 'path' and 'omode' in request, // and map the returned file descriptor page // at the appropriate fd address. // FSREQ_OPEN returns 0 on success, < 0 on failure. // // (fd_alloc does not allocate a page, it just returns an // unused fd address. Do you need to allocate a page?) // // Return the file descriptor index. // If any step after fd_alloc fails, use fd_close to free the // file descriptor. // LAB 5: Your code here. int r; struct Fd *fd; r = fd_alloc(&fd); if (r < 0) return r; // DO NOT ALLOCATE !! //r = sys_page_alloc(0, fd, PTE_U|PTE_W|PTE_P); //if (r < 0) goto out; if (strlen(path) >= MAXPATHLEN) return -E_BAD_PATH; strcpy(fsipcbuf.open.req_path, path); fsipcbuf.open.req_omode = mode; r = fsipc(FSREQ_OPEN, fd); if (r < 0) goto out; return fd2num(fd); out: assert(fd_close(fd, 0) == 0); return r; }
// Open a file (or directory). // // Returns: // The file descriptor index on success // -E_BAD_PATH if the path is too long (>= MAXPATHLEN) // < 0 for other errors. int open(const char *path, int mode) { // Find an unused file descriptor page using fd_alloc. // Then send a file-open request to the file server. // Include 'path' and 'omode' in request, // and map the returned file descriptor page // at the appropriate fd address. // FSREQ_OPEN returns 0 on success, < 0 on failure. // // (fd_alloc does not allocate a page, it just returns an // unused fd address. Do you need to allocate a page?) // // Return the file descriptor index. // If any step after fd_alloc fails, use fd_close to free the // file descriptor. if (strlen(path) > MAXPATHLEN) return -E_BAD_PATH; struct Fd *fd; int r; if ((r < fd_alloc(&fd)) < 0) return r; strcpy(fsipcbuf.open.req_path, path); fsipcbuf.open.req_omode = mode; if ((r = fsipc(FSREQ_OPEN, fd)) < 0) { fd_close(fd, 0); return r; } return fd2num(fd); panic("open not implemented"); }
char* fd2data(struct Fd *fd) { return INDEX2DATA(fd2num(fd)); }
// Return the file descriptor data pointer for a 'struct Fd'. // char * fd2data(struct Fd *fd) { int num = fd2num(fd); return (char *) (FDDATA + num * PGSIZE); }
// Open a file (or directory). // // Returns: // The file descriptor index on success // -E_BAD_PATH if the path is too long (>= MAXPATHLEN) // -E_BAD_PATH if an intermediate path component is not a directory // -E_MAX_FD if no more file descriptors // -E_NOT_FOUND if the file (or a path component) was not found // (and others) int open(const char *path, int mode) { // Find an unused file descriptor page using fd_find_unused // and allocate a page there (PTE_P|PTE_U|PTE_W|PTE_SHARE). // // LAB 5: Your code here int r; struct Fd *fd; if((r = fd_find_unused(&fd)) < 0 || (r = sys_page_alloc(0, fd, PTE_P|PTE_U|PTE_W|PTE_SHARE)) < 0) goto err1; // Check the pathname. Error if too long. // Use path_walk to find the corresponding directory entry. // If '(mode & O_CREAT) == 0' (Exercise 4), // Return -E_NOT_FOUND if the file is not found. // Otherwise, use inode_open to open the inode. // If '(mode & O_CREAT) != 0' (Exercise 7), // Create the file if it doesn't exist yet. // Allocate a new inode, initialize its fields, and // reference that inode from the new directory entry. // Flush any blocks you change. // Directories can be opened, but only as read-only: // return -E_IS_DIR if '(mode & O_ACCMODE) != O_RDONLY'. // // Check for errors. On error, make sure you clean up any // allocated objects. // // The root directory is a special case -- if you aren't careful, // you will deadlock when the root directory is opened. (Why?) // // LAB 5: Your code here. int i; for(i = 0; i < MAXNAMELEN && path[i]; i++); if(i == MAXNAMELEN) { r = -E_BAD_PATH; goto err2; } struct Inode *dirino; struct Direntry *de; if((r = path_walk(path, &dirino, &de, mode & O_CREAT))) goto err2; struct Inode *fileino; if(!(mode & O_CREAT)) { if(de == &super->s_root) fileino = dirino; else if((r = inode_open(de->de_inum, &fileino)) < 0) goto err3; if(fileino->i_ftype == FTYPE_DIR && ( mode & O_ACCMODE) != O_RDONLY) { r = -E_IS_DIR; goto err4; } } else { if((r = inode_alloc(&fileino)) < 0) goto err3; fileino->i_ftype = FTYPE_REG; fileino->i_refcount = 1; fileino->i_size = 0; memset(&fileino->i_direct, 0, NDIRECT * sizeof (blocknum_t)); de->de_inum = fileino->i_inum; bcache_ipc(fileino, BCREQ_FLUSH); bcache_ipc(dirino, BCREQ_FLUSH); } // If '(mode & O_TRUNC) != 0' and the open mode is not read-only, // set the file's length to 0. Flush any blocks you change. // // LAB 5: Your code here (Exercise 8). if((mode & O_TRUNC)) { inode_set_size(fileino, 0); } // The open has succeeded. // Fill in all parts of the 'fd' appropriately. Use 'devfile.dev_id'. // Copy the file's pathname into 'fd->fd_file.open_path' to improve // error messages later. // You must account for the open file reference in the inode as well. // Clean up any open inodes. // // LAB 5: Your code here (Exercise 4). fd->fd_dev_id = devfile.dev_id; fd->fd_offset = 0; fd->fd_omode = mode; fd->fd_file.inum = fileino->i_inum; strcpy(fd->fd_file.open_path, path); fileino->i_opencount++; inode_close(dirino); inode_close(fileino); return fd2num(fd); err4: inode_close(fileino); err3: inode_close(dirino); err2: sys_page_unmap(thisenv->env_id, fd); err1: return r; }