1 #include "inc.h" 2 3 static char getdents_buf[GETDENTS_BUFSIZ]; 4 5 ssize_t fs_read(ino_t ino_nr, struct fsdriver_data *data, size_t bytes, 6 off_t pos, int __unused call) 7 { 8 size_t off, chunk, block_size, cum_io; 9 off_t f_size; 10 struct inode *i_node; 11 struct buf *bp; 12 int r; 13 14 /* Try to get inode according to its index. */ 15 if ((i_node = get_inode(ino_nr)) == NULL) 16 return EINVAL; /* No inode found. */ 17 18 f_size = i_node->i_stat.st_size; 19 if (pos >= f_size) 20 return 0; /* EOF */ 21 22 /* Limit the request to the remainder of the file size. */ 23 if ((off_t)bytes > f_size - pos) 24 bytes = (size_t)(f_size - pos); 25 26 block_size = v_pri.logical_block_size_l; 27 cum_io = 0; 28 29 r = OK; 30 31 /* Split the transfer into chunks that don't span two blocks. */ 32 while (bytes > 0) { 33 off = pos % block_size; 34 35 chunk = block_size - off; 36 if (chunk > bytes) 37 chunk = bytes; 38 39 /* Read 'chunk' bytes. */ 40 bp = read_extent_block(&i_node->extent, pos); 41 if (bp == NULL) 42 panic("bp not valid in rw_chunk; this can't happen"); 43 44 r = fsdriver_copyout(data, cum_io, b_data(bp)+off, chunk); 45 46 lmfs_put_block(bp); 47 48 if (r != OK) 49 break; 50 51 /* Update counters and pointers. */ 52 bytes -= chunk; /* Bytes yet to be read. */ 53 cum_io += chunk; /* Bytes read so far. */ 54 pos += chunk; /* Position within the file. */ 55 } 56 57 return (r == OK) ? cum_io : r; 58 } 59 60 ssize_t fs_getdents(ino_t ino_nr, struct fsdriver_data *data, size_t bytes, 61 off_t *pos) 62 { 63 struct fsdriver_dentry fsdentry; 64 struct inode *i_node; 65 off_t cur_pos; 66 int r, len; 67 char *cp; 68 69 if ((i_node = get_inode(ino_nr)) == NULL) 70 return EINVAL; 71 72 if (*pos < 0 || *pos > SSIZE_MAX) 73 return EINVAL; 74 75 r = read_directory(i_node); 76 if (r != OK) 77 return r; 78 79 fsdriver_dentry_init(&fsdentry, data, bytes, getdents_buf, 80 sizeof(getdents_buf)); 81 82 r = OK; 83 84 for (cur_pos = *pos; cur_pos < i_node->dir_size; cur_pos++) { 85 /* Compute the length of the name */ 86 cp = memchr(i_node->dir_contents[cur_pos].name, '\0', NAME_MAX); 87 if (cp == NULL) 88 len = NAME_MAX; 89 else 90 len = cp - i_node->dir_contents[cur_pos].name; 91 92 r = fsdriver_dentry_add(&fsdentry, 93 i_node->dir_contents[cur_pos].i_node->i_stat.st_ino, 94 i_node->dir_contents[cur_pos].name, len, 95 IFTODT(i_node->dir_contents[cur_pos].i_node->i_stat.st_mode)); 96 97 if (r <= 0) 98 break; 99 } 100 101 if (r >= 0 && (r = fsdriver_dentry_finish(&fsdentry)) >= 0) 102 *pos = cur_pos; 103 104 return r; 105 } 106