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