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 = find_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 / block_size); 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, *i_node_tmp; 65 size_t cur_pos, new_pos; 66 int r, len; 67 char *cp; 68 69 if ((i_node = find_inode(ino_nr)) == NULL) 70 return EINVAL; 71 72 if (*pos < 0 || *pos > SSIZE_MAX) 73 return EINVAL; 74 75 fsdriver_dentry_init(&fsdentry, data, bytes, getdents_buf, 76 sizeof(getdents_buf)); 77 78 r = OK; 79 80 for (cur_pos = (size_t)*pos; ; cur_pos = new_pos) { 81 i_node_tmp = alloc_inode(); 82 r = read_inode(i_node_tmp, i_node->extent, cur_pos, &new_pos); 83 if ((r != OK) || (new_pos >= i_node->i_stat.st_size)) { 84 put_inode(i_node_tmp); 85 break; 86 } 87 88 /* Compute the length of the name */ 89 cp = memchr(i_node_tmp->i_name, '\0', NAME_MAX); 90 if (cp == NULL) 91 len = NAME_MAX; 92 else 93 len = cp - i_node_tmp->i_name; 94 95 r = fsdriver_dentry_add(&fsdentry, i_node_tmp->i_stat.st_ino, 96 i_node_tmp->i_name, len, 97 IFTODT(i_node_tmp->i_stat.st_mode)); 98 99 put_inode(i_node_tmp); 100 101 if (r <= 0) 102 break; 103 } 104 105 if (r >= 0 && (r = fsdriver_dentry_finish(&fsdentry)) >= 0) 106 *pos = cur_pos; 107 108 return r; 109 } 110