pipe.c (2777B)
1 /* 2 * core/pipe.c 3 * 4 * Copyright (C) 2010 stateless 5 */ 6 7 #include <pipe.h> 8 #include <ext2.h> 9 #include <common.h> 10 #include <errno.h> 11 #include <string.h> 12 #include <heap.h> 13 #include <x86.h> 14 #include <tss.h> 15 16 extern spinlock_t flist_lock; 17 extern struct list_head flist; 18 19 static int 20 pipealloc(void) 21 { 22 struct file_t *f; 23 int i; 24 25 acquire(&flist_lock); 26 for (i = 3; i < NR_MAX_OPEN_FILES; ++i) { 27 if (curr_proc->fdtable[i] 28 && curr_proc->fdtable[i]->f_state != FILE_NONE) 29 continue; 30 if (!curr_proc->fdtable[i]) { 31 f = kmalloc(sizeof(struct file_t)); 32 if (IS_ERR(f)) { 33 release(&flist_lock); 34 return PTR_ERR(f); 35 } 36 f->f_state = FILE_NONE; 37 list_add_tail(&f->f_listopen, &flist); 38 curr_proc->fdtable[i] = f; 39 } 40 f = curr_proc->fdtable[i]; 41 assert(f->f_state == FILE_NONE); 42 f->f_refcount = 1; 43 f->f_off = 0; 44 f->f_state = FILE_ALLOC; 45 f->f_type = FILE_PIPE; 46 f->f_inode = NULL; 47 f->f_inode_nr = 0; 48 curr_proc->pipebufs[i] = NULL; 49 release(&flist_lock); 50 return i; 51 } 52 release(&flist_lock); 53 return -EMFILE; 54 } 55 56 int 57 pipe(int pipefd[2]) 58 { 59 int ret; 60 char *buf; 61 62 pipefd[0] = pipealloc(); 63 if (pipefd[0] < 0) 64 return pipefd[0]; 65 pipefd[1] = pipealloc(); 66 if (pipefd[1] < 0) { 67 ret = pipefd[1]; 68 goto err; 69 } 70 buf = kmalloc(PIPE_SIZ); 71 if (IS_ERR(buf)) { 72 ret = PTR_ERR(buf); 73 goto err1; 74 } 75 curr_proc->pipebufs[pipefd[0]] = buf; 76 curr_proc->pipebufs[pipefd[1]] = buf; 77 return 0; 78 err1: 79 fileclose(pipefd[1]); 80 err: 81 fileclose(pipefd[0]); 82 return ret; 83 } 84 85 /* must be called with flist_lock acquired */ 86 ssize_t 87 piperead(int fd, void *buf, size_t count) 88 { 89 size_t i; 90 struct file_t *f = NULL; 91 char *pbuf; 92 93 pbuf = curr_proc->pipebufs[fd]; 94 for (i = 0; i < NR_MAX_OPEN_FILES; ++i) 95 if (curr_proc->pipebufs[i] == pbuf && i != (size_t)fd) { 96 f = curr_proc->fdtable[i]; 97 break; 98 } 99 if (!f) f = curr_proc->fdtable[i]; 100 for (i = 0; i < count && i < (size_t)f->f_off; ++i) { 101 ((char *)buf)[i] = *pbuf; 102 memcpy(pbuf, pbuf + 1, PIPE_SIZ - 1); 103 } 104 f->f_off -= i; 105 return i; 106 } 107 108 /* must be called with flist_lock acquired */ 109 ssize_t 110 pipewrite(int fd, const void *buf, size_t count) 111 { 112 size_t i; 113 char *pbuf; 114 ssize_t r; 115 116 pbuf = curr_proc->pipebufs[fd]; 117 for (i = 0; i < NR_MAX_OPEN_FILES; ++i) 118 if (curr_proc->pipebufs[i] == pbuf && i != (size_t)fd) 119 break; 120 /* read end has been closed */ 121 if (i != NR_MAX_OPEN_FILES 122 && curr_proc->fdtable[i]->f_state == FILE_NONE) 123 return -EPIPE; 124 for (i = 0; i < count && curr_proc->fdtable[fd]->f_off + i < PIPE_SIZ; ++i) 125 pbuf[curr_proc->fdtable[fd]->f_off + i] = ((char *)buf)[i]; 126 curr_proc->fdtable[fd]->f_off += i; 127 r = i; 128 for (i = 0; i < NR_MAX_OPEN_FILES; ++i) 129 if (curr_proc->pipebufs[i] == pbuf && i != (size_t)fd) 130 curr_proc->fdtable[i]->f_off = curr_proc->fdtable[fd]->f_off; 131 return r; 132 } 133