121e1553eSJérôme Duval /* 221e1553eSJérôme Duval ** Copyright 1999, Be Incorporated. All Rights Reserved. 321e1553eSJérôme Duval ** This file may be used under the terms of the Be Sample Code License. 421e1553eSJérôme Duval ** 521e1553eSJérôme Duval ** Copyright 2001, pinc Software. All Rights Reserved. 621e1553eSJérôme Duval ** 721e1553eSJérôme Duval ** iso9960/multi-session, 1.0.0 821e1553eSJérôme Duval ** 2001-03-11: added multi-session support, axeld. 921e1553eSJérôme Duval */ 1021e1553eSJérôme Duval 1121e1553eSJérôme Duval #include <stdlib.h> 1221e1553eSJérôme Duval #include <unistd.h> 1321e1553eSJérôme Duval #include <fcntl.h> 1421e1553eSJérôme Duval #include <errno.h> 1521e1553eSJérôme Duval #include <string.h> 1621e1553eSJérôme Duval #include <ctype.h> 1721e1553eSJérôme Duval #include <stdio.h> 1821e1553eSJérôme Duval #include <dirent.h> 1921e1553eSJérôme Duval #include <sys/stat.h> 2021e1553eSJérôme Duval #include <time.h> 2121e1553eSJérôme Duval #include <lock.h> 2221e1553eSJérôme Duval #include <malloc.h> 2321e1553eSJérôme Duval 2421e1553eSJérôme Duval #include <KernelExport.h> 2521e1553eSJérôme Duval #include <NodeMonitor.h> 2621e1553eSJérôme Duval #include <fs_interface.h> 2721e1553eSJérôme Duval #include <fs_cache.h> 2821e1553eSJérôme Duval 2921e1553eSJérôme Duval #include <fs_attr.h> 3021e1553eSJérôme Duval #include <fs_info.h> 3121e1553eSJérôme Duval #include <fs_index.h> 3221e1553eSJérôme Duval #include <fs_query.h> 3321e1553eSJérôme Duval #include <fs_volume.h> 3421e1553eSJérôme Duval 3521e1553eSJérôme Duval #include <util/kernel_cpp.h> 3621e1553eSJérôme Duval 3721e1553eSJérôme Duval #include "iso.h" 3821e1553eSJérôme Duval #include "iso9660.h" 3921e1553eSJérôme Duval 4021e1553eSJérôme Duval //#define TRACE_ISO9660 1 4121e1553eSJérôme Duval #if TRACE_ISO9660 4221e1553eSJérôme Duval # define TRACE(x) dprintf x 4321e1553eSJérôme Duval #else 4421e1553eSJérôme Duval # define TRACE(x) ; 4521e1553eSJérôme Duval #endif 4621e1553eSJérôme Duval 4721e1553eSJérôme Duval 4821e1553eSJérôme Duval /* Start of fundamental (read-only) required functions */ 4921e1553eSJérôme Duval static status_t fs_mount(mount_id mountID, const char *device, uint32 flags, 5021e1553eSJérôme Duval const char *args, void **_data, vnode_id *_rootID); 5121e1553eSJérôme Duval static status_t fs_unmount(void *ns); 5221e1553eSJérôme Duval 533b723f79SJérôme Duval static status_t fs_get_vnode_name(void *_ns, void *_node, 543b723f79SJérôme Duval char *buffer, size_t bufferSize); 5521e1553eSJérôme Duval static status_t fs_walk(void *_ns, void *_base, const char *file, 5621e1553eSJérôme Duval vnode_id *_vnodeID, int *_type); 5721e1553eSJérôme Duval 5821e1553eSJérôme Duval static status_t fs_read_vnode(void *_ns, vnode_id vnid, void **node, bool reenter); 5921e1553eSJérôme Duval static status_t fs_release_vnode(void *_ns, void *_node, bool reenter); 60*5b4cb109SJérôme Duval static status_t fs_get_file_map(fs_volume _fs, fs_vnode _node, off_t offset, size_t size, 61*5b4cb109SJérôme Duval struct file_io_vec *vecs, size_t *_count); 6221e1553eSJérôme Duval static status_t fs_read_stat(void *_ns, void *_node, struct stat *st); 6321e1553eSJérôme Duval static status_t fs_open(void *_ns, void *_node, int omode, void **cookie); 6421e1553eSJérôme Duval static status_t fs_read(void *_ns, void *_node, void *cookie, off_t pos, 6521e1553eSJérôme Duval void *buf, size_t *len); 6621e1553eSJérôme Duval /// fs_free_cookie - free cookie for file created in open. 6721e1553eSJérôme Duval static status_t fs_free_cookie(void *ns, void *node, void *cookie); 6821e1553eSJérôme Duval static status_t fs_close(void *ns, void *node, void *cookie); 6921e1553eSJérôme Duval 7021e1553eSJérôme Duval // fs_access - checks permissions for access. 7121e1553eSJérôme Duval static status_t fs_access(void *_ns, void *_node, int mode); 7221e1553eSJérôme Duval 7321e1553eSJérôme Duval // fs_opendir - creates fs-specific "cookie" struct that can tell where 7421e1553eSJérôme Duval // we are at in the directory list. 7521e1553eSJérôme Duval static status_t fs_open_dir(void* _ns, void* _node, void** cookie); 7621e1553eSJérôme Duval // fs_readdir - read 1 or more dirents, keep state in cookie, return 7721e1553eSJérôme Duval // 0 when no more entries. 7821e1553eSJérôme Duval static status_t fs_read_dir(void *_ns, void *_node, void *cookie, struct dirent *buf, 7921e1553eSJérôme Duval size_t bufsize, uint32 *_num); 8021e1553eSJérôme Duval // fs_rewinddir - set cookie to represent beginning of directory, so 8121e1553eSJérôme Duval // later fs_readdir calls start at beginning. 8221e1553eSJérôme Duval static status_t fs_rewind_dir(void *_ns, void *_node, void *cookie); 8321e1553eSJérôme Duval // fs_closedir - Do whatever you need to to close a directory (sometimes 8421e1553eSJérôme Duval // nothing), but DON'T free the cookie! 8521e1553eSJérôme Duval static status_t fs_close_dir(void *_ns, void *_node, void *cookie); 863b723f79SJérôme Duval // fs_free_dircookie - Free the fs-specific cookie struct 8721e1553eSJérôme Duval static status_t fs_free_dir_cookie(void *_ns, void *_node, void *cookie); 8821e1553eSJérôme Duval 8921e1553eSJérôme Duval // fs_rfsstat - Fill in fs_info struct for device. 9021e1553eSJérôme Duval static status_t fs_read_fs_stat(void *_ns, struct fs_info *); 9121e1553eSJérôme Duval 9221e1553eSJérôme Duval // fs_readlink - Read in the name of a symbolic link. 9321e1553eSJérôme Duval static status_t fs_read_link(void *_ns, void *_node, char *buf, size_t *bufsize); 9421e1553eSJérôme Duval 9521e1553eSJérôme Duval 9621e1553eSJérôme Duval // #pragma mark - Scanning 9721e1553eSJérôme Duval 9821e1553eSJérôme Duval struct identify_cookie { 9921e1553eSJérôme Duval iso9660_info info; 10021e1553eSJérôme Duval }; 10121e1553eSJérôme Duval 10221e1553eSJérôme Duval 10321e1553eSJérôme Duval static float 10421e1553eSJérôme Duval fs_identify_partition(int fd, partition_data *partition, void **_cookie) 10521e1553eSJérôme Duval { 10621e1553eSJérôme Duval iso9660_info info; 10721e1553eSJérôme Duval status_t status = iso9660_fs_identify(fd, &info); 10821e1553eSJérôme Duval if (status != B_OK) 10921e1553eSJérôme Duval return status; 11021e1553eSJérôme Duval 11121e1553eSJérôme Duval identify_cookie *cookie = new identify_cookie; 11221e1553eSJérôme Duval memcpy(&cookie->info, &info, sizeof(info)); 11321e1553eSJérôme Duval 11421e1553eSJérôme Duval *_cookie = cookie; 11521e1553eSJérôme Duval return 0.8f; 11621e1553eSJérôme Duval } 11721e1553eSJérôme Duval 11821e1553eSJérôme Duval 11921e1553eSJérôme Duval static status_t 12021e1553eSJérôme Duval fs_scan_partition(int fd, partition_data *partition, void *_cookie) 12121e1553eSJérôme Duval { 12221e1553eSJérôme Duval identify_cookie *cookie = (identify_cookie *)_cookie; 12321e1553eSJérôme Duval 12421e1553eSJérôme Duval partition->status = B_PARTITION_VALID; 12521e1553eSJérôme Duval partition->flags |= B_PARTITION_FILE_SYSTEM | B_PARTITION_READ_ONLY ; 12621e1553eSJérôme Duval partition->block_size = ISO_PVD_SIZE; 12721e1553eSJérôme Duval partition->content_size = ISO_PVD_SIZE * cookie->info.maxBlocks; 12821e1553eSJérôme Duval partition->content_name = strdup(cookie->info.get_preferred_volume_name()); 12921e1553eSJérôme Duval if (partition->content_name == NULL) 13021e1553eSJérôme Duval return B_NO_MEMORY; 13121e1553eSJérôme Duval 13221e1553eSJérôme Duval return B_OK; 13321e1553eSJérôme Duval } 13421e1553eSJérôme Duval 13521e1553eSJérôme Duval 13621e1553eSJérôme Duval static void 13721e1553eSJérôme Duval fs_free_identify_partition_cookie(partition_data *partition, void *_cookie) 13821e1553eSJérôme Duval { 13921e1553eSJérôme Duval identify_cookie *cookie = (identify_cookie *)_cookie; 14021e1553eSJérôme Duval 14121e1553eSJérôme Duval delete cookie; 14221e1553eSJérôme Duval } 14321e1553eSJérôme Duval 14421e1553eSJérôme Duval 14521e1553eSJérôme Duval static status_t 14621e1553eSJérôme Duval fs_mount(mount_id mountID, const char *device, uint32 flags, 14721e1553eSJérôme Duval const char *args, void **_data, vnode_id *_rootID) 14821e1553eSJérôme Duval { 14921e1553eSJérôme Duval /* 15021e1553eSJérôme Duval Kernel passes in nspace_id, (representing a disk or partition?) 15121e1553eSJérôme Duval and a string representing the device (eg, "/dev/scsi/disk/030/raw) 15221e1553eSJérôme Duval Flags will be used for things like specifying read-only mounting. 15321e1553eSJérôme Duval parms is parameters passed in as switches from the mount command, 15421e1553eSJérôme Duval and len is the length of the otions. data is a pointer to a 15521e1553eSJérôme Duval driver-specific struct that should be allocated in this routine. 15621e1553eSJérôme Duval It will then be passed back in by the kernel to a number of the other 15721e1553eSJérôme Duval fs driver functions. vnid should also be passed back to the kernel, 15821e1553eSJérôme Duval representing the vnode id of the root vnode. 15921e1553eSJérôme Duval */ 16021e1553eSJérôme Duval status_t result = EINVAL; 16121e1553eSJérôme Duval // return EINVAL if it's not a device compatible with the driver. 16221e1553eSJérôme Duval bool allow_joliet = true; 16321e1553eSJérôme Duval nspace *vol; 16421e1553eSJérôme Duval 16521e1553eSJérôme Duval (void)flags; 16621e1553eSJérôme Duval 16721e1553eSJérôme Duval /* Create semaphore if it's not already created. When do we need to 16821e1553eSJérôme Duval use semaphores? */ 16921e1553eSJérôme Duval 17021e1553eSJérôme Duval // Check for a 'nojoliet' parm 17121e1553eSJérôme Duval // all we check for is the existance of 'nojoliet' in the parms. 17221e1553eSJérôme Duval if (args != NULL) { 17321e1553eSJérôme Duval uint32 i; 17421e1553eSJérôme Duval char *spot; 17521e1553eSJérôme Duval char *buf = strdup(args); 17621e1553eSJérôme Duval 17721e1553eSJérôme Duval uint32 len = strlen(buf); 17821e1553eSJérôme Duval // lower case the parms data 17921e1553eSJérôme Duval for (i = 0; i < len + 1; i++) 18021e1553eSJérôme Duval buf[i] = tolower(buf[i]); 18121e1553eSJérôme Duval 18221e1553eSJérôme Duval // look for nojoliet 18321e1553eSJérôme Duval spot = strstr(buf, "nojoliet"); 18421e1553eSJérôme Duval if (spot != NULL) 18521e1553eSJérôme Duval allow_joliet = false; 18621e1553eSJérôme Duval 18721e1553eSJérôme Duval free(buf); 18821e1553eSJérôme Duval } 18921e1553eSJérôme Duval 19021e1553eSJérôme Duval // Try and mount volume as an ISO volume. 19121e1553eSJérôme Duval result = ISOMount(device, O_RDONLY, &vol, allow_joliet); 19221e1553eSJérôme Duval 19321e1553eSJérôme Duval // If it is ISO … 19421e1553eSJérôme Duval if (result == B_NO_ERROR) { 19521e1553eSJérôme Duval //vnode_id rootID = vol->rootDirRec.startLBN[FS_DATA_FORMAT]; 19621e1553eSJérôme Duval //*vnid = rootID; 19721e1553eSJérôme Duval *_rootID = ISO_ROOTNODE_ID; 19821e1553eSJérôme Duval *_data = (void*)vol; 19921e1553eSJérôme Duval 20021e1553eSJérôme Duval vol->id = mountID; 20121e1553eSJérôme Duval 20221e1553eSJérôme Duval // You MUST do this. Create the vnode for the root. 20321e1553eSJérôme Duval result = publish_vnode(mountID, *_rootID, (void*)&(vol->rootDirRec)); 20421e1553eSJérôme Duval if (result != B_NO_ERROR) { 20521e1553eSJérôme Duval block_cache_delete(vol->fBlockCache, false); 20621e1553eSJérôme Duval free(vol); 20721e1553eSJérôme Duval result = EINVAL; 20821e1553eSJérôme Duval } else 20921e1553eSJérôme Duval result = B_NO_ERROR; 21021e1553eSJérôme Duval } 21121e1553eSJérôme Duval return result; 21221e1553eSJérôme Duval } 21321e1553eSJérôme Duval 21421e1553eSJérôme Duval 21521e1553eSJérôme Duval static status_t 21621e1553eSJérôme Duval fs_unmount(void *_ns) 21721e1553eSJérôme Duval { 21821e1553eSJérôme Duval status_t result = B_NO_ERROR; 21921e1553eSJérôme Duval nspace *ns = (nspace *)_ns; 22021e1553eSJérôme Duval 22121e1553eSJérôme Duval TRACE(("fs_unmount - ENTER\n")); 22221e1553eSJérôme Duval 22321e1553eSJérôme Duval block_cache_delete(ns->fBlockCache, false); 22421e1553eSJérôme Duval close(ns->fdOfSession); 22521e1553eSJérôme Duval result = close(ns->fd); 22621e1553eSJérôme Duval 22721e1553eSJérôme Duval free(ns); 22821e1553eSJérôme Duval 22921e1553eSJérôme Duval TRACE(("fs_unmount - EXIT, result is %s\n", strerror(result))); 23021e1553eSJérôme Duval return result; 23121e1553eSJérôme Duval } 23221e1553eSJérôme Duval 23321e1553eSJérôme Duval 23421e1553eSJérôme Duval static status_t 23521e1553eSJérôme Duval fs_read_fs_stat(void *_ns, struct fs_info *fss) 23621e1553eSJérôme Duval { 23721e1553eSJérôme Duval // Fill in fs_info struct for device. 23821e1553eSJérôme Duval nspace *ns = (nspace *)_ns; 23921e1553eSJérôme Duval int i; 24021e1553eSJérôme Duval 241*5b4cb109SJérôme Duval TRACE(("fs_read_fs_stat - ENTER\n")); 24221e1553eSJérôme Duval 24321e1553eSJérôme Duval // Fill in device id. 24421e1553eSJérôme Duval //fss->dev = ns->fd; 24521e1553eSJérôme Duval 24621e1553eSJérôme Duval // Root vnode ID 24721e1553eSJérôme Duval //fss->root = ISO_ROOTNODE_ID; 24821e1553eSJérôme Duval 24921e1553eSJérôme Duval // File system flags. 25021e1553eSJérôme Duval fss->flags = B_FS_IS_PERSISTENT | B_FS_IS_READONLY; 25121e1553eSJérôme Duval 25221e1553eSJérôme Duval // FS block size. 25321e1553eSJérôme Duval fss->block_size = ns->logicalBlkSize[FS_DATA_FORMAT]; 25421e1553eSJérôme Duval 25521e1553eSJérôme Duval // IO size - specifies buffer size for file copying 25621e1553eSJérôme Duval fss->io_size = 65536; 25721e1553eSJérôme Duval 25821e1553eSJérôme Duval // Total blocks? 25921e1553eSJérôme Duval fss->total_blocks = ns->volSpaceSize[FS_DATA_FORMAT]; 26021e1553eSJérôme Duval 26121e1553eSJérôme Duval // Free blocks = 0, read only 26221e1553eSJérôme Duval fss->free_blocks = 0; 26321e1553eSJérôme Duval 26421e1553eSJérôme Duval // Device name. 26521e1553eSJérôme Duval strncpy(fss->device_name, ns->devicePath, sizeof(fss->device_name)); 26621e1553eSJérôme Duval 26721e1553eSJérôme Duval strncpy(fss->volume_name, ns->volIDString, sizeof(fss->volume_name)); 26821e1553eSJérôme Duval for (i = strlen(fss->volume_name)-1; i >=0 ; i--) 26921e1553eSJérôme Duval if (fss->volume_name[i] != ' ') 27021e1553eSJérôme Duval break; 27121e1553eSJérôme Duval 27221e1553eSJérôme Duval if (i < 0) 27321e1553eSJérôme Duval strcpy(fss->volume_name, "UNKNOWN"); 27421e1553eSJérôme Duval else 27521e1553eSJérôme Duval fss->volume_name[i + 1] = 0; 27621e1553eSJérôme Duval 27721e1553eSJérôme Duval // File system name 27821e1553eSJérôme Duval strcpy(fss->fsh_name, "iso9660"); 27921e1553eSJérôme Duval 280*5b4cb109SJérôme Duval TRACE(("fs_read_fs_stat - EXIT\n")); 28121e1553eSJérôme Duval return 0; 28221e1553eSJérôme Duval } 28321e1553eSJérôme Duval 2843b723f79SJérôme Duval 2853b723f79SJérôme Duval static status_t 2863b723f79SJérôme Duval fs_get_vnode_name(void *ns, void *_node, char *buffer, size_t bufferSize) 2873b723f79SJérôme Duval { 2883b723f79SJérôme Duval vnode *node = (vnode*)_node; 2893b723f79SJérôme Duval 2903b723f79SJérôme Duval strlcpy(buffer, node->fileIDString, bufferSize); 2913b723f79SJérôme Duval return B_OK; 2923b723f79SJérôme Duval } 2933b723f79SJérôme Duval 2943b723f79SJérôme Duval 29521e1553eSJérôme Duval /* fs_walk - the walk function just "walks" through a directory looking for 29621e1553eSJérôme Duval the specified file. When you find it, call get_vnode on its vnid to init 29721e1553eSJérôme Duval it for the kernel. 29821e1553eSJérôme Duval */ 29921e1553eSJérôme Duval static status_t 30021e1553eSJérôme Duval fs_walk(void *_ns, void *base, const char *file, vnode_id *_vnodeID, int *_type) 30121e1553eSJérôme Duval { 30221e1553eSJérôme Duval /* Starting at the base, find file in the subdir, and return path 30321e1553eSJérôme Duval string and vnode id of file. */ 30421e1553eSJérôme Duval nspace *ns = (nspace *)_ns; 30521e1553eSJérôme Duval vnode *baseNode = (vnode*)base; 30621e1553eSJérôme Duval uint32 dataLen = baseNode->dataLen[FS_DATA_FORMAT]; 30721e1553eSJérôme Duval vnode *newNode = NULL; 30821e1553eSJérôme Duval status_t result = ENOENT; 30921e1553eSJérôme Duval bool done = FALSE; 31021e1553eSJérôme Duval uint32 totalRead = 0; 31121e1553eSJérôme Duval off_t block = baseNode->startLBN[FS_DATA_FORMAT]; 31221e1553eSJérôme Duval 31321e1553eSJérôme Duval TRACE(("fs_walk - looking for %s in dir file of length %d\n", file, 31421e1553eSJérôme Duval baseNode->dataLen[FS_DATA_FORMAT])); 31521e1553eSJérôme Duval 31621e1553eSJérôme Duval if (strcmp(file, ".") == 0) { 31721e1553eSJérôme Duval // base directory 31821e1553eSJérôme Duval TRACE(("fs_walk - found \".\" file.\n")); 31921e1553eSJérôme Duval *_vnodeID = baseNode->id; 32021e1553eSJérôme Duval *_type = S_IFDIR; 32121e1553eSJérôme Duval if (get_vnode(ns->id, *_vnodeID, (void **)&newNode) != 0) 32221e1553eSJérôme Duval result = EINVAL; 32321e1553eSJérôme Duval else 32421e1553eSJérôme Duval result = B_NO_ERROR; 32521e1553eSJérôme Duval } else if (strcmp(file, "..") == 0) { 32621e1553eSJérôme Duval // parent directory 32721e1553eSJérôme Duval TRACE(("fs_walk - found \"..\" file.\n")); 32821e1553eSJérôme Duval *_vnodeID = baseNode->parID; 32921e1553eSJérôme Duval *_type = S_IFDIR; 33021e1553eSJérôme Duval if (get_vnode(ns->id, *_vnodeID, (void **)&newNode) != 0) 33121e1553eSJérôme Duval result = EINVAL; 33221e1553eSJérôme Duval else 33321e1553eSJérôme Duval result = B_NO_ERROR; 33421e1553eSJérôme Duval } else { 33521e1553eSJérôme Duval // look up file in the directory 33621e1553eSJérôme Duval char *blockData; 33721e1553eSJérôme Duval 33821e1553eSJérôme Duval while ((totalRead < dataLen) && !done) { 33921e1553eSJérôme Duval off_t cachedBlock = block; 34021e1553eSJérôme Duval 34121e1553eSJérôme Duval blockData = (char *)block_cache_get_etc(ns->fBlockCache, block, 0, ns->logicalBlkSize[FS_DATA_FORMAT]); 34221e1553eSJérôme Duval if (blockData != NULL) { 34321e1553eSJérôme Duval int bytesRead = 0; 34421e1553eSJérôme Duval off_t blockBytesRead = 0; 34521e1553eSJérôme Duval vnode node; 34621e1553eSJérôme Duval int initResult; 34721e1553eSJérôme Duval 34821e1553eSJérôme Duval TRACE(("fs_walk - read buffer from disk at LBN %Ld into buffer 0x%x.\n", 34921e1553eSJérôme Duval block, blockData)); 35021e1553eSJérôme Duval 35121e1553eSJérôme Duval // Move to the next 2-block set if necessary 35221e1553eSJérôme Duval // Don't go over end of buffer, if dir record sits on boundary. 35321e1553eSJérôme Duval 35421e1553eSJérôme Duval node.fileIDString = NULL; 35521e1553eSJérôme Duval node.attr.slName = NULL; 35621e1553eSJérôme Duval 35721e1553eSJérôme Duval while (blockBytesRead < 2*ns->logicalBlkSize[FS_DATA_FORMAT] 35821e1553eSJérôme Duval && totalRead + blockBytesRead < dataLen 35921e1553eSJérôme Duval && blockData[0] != 0 36021e1553eSJérôme Duval && !done) 36121e1553eSJérôme Duval { 36221e1553eSJérôme Duval initResult = InitNode(&node, blockData, &bytesRead, ns->joliet_level); 36321e1553eSJérôme Duval TRACE(("fs_walk - InitNode returned %s, filename %s, %d bytes read\n", strerror(initResult), node.fileIDString, bytesRead)); 36421e1553eSJérôme Duval 36521e1553eSJérôme Duval if (initResult == B_NO_ERROR) { 36621e1553eSJérôme Duval if (strlen(node.fileIDString) == strlen(file) 36721e1553eSJérôme Duval && !strncmp(node.fileIDString, file, strlen(file))) 36821e1553eSJérôme Duval { 36921e1553eSJérôme Duval TRACE(("fs_walk - success, found vnode at block %Ld, pos %Ld\n", block, blockBytesRead)); 37021e1553eSJérôme Duval *_vnodeID = (block << 30) + (blockBytesRead & 0xFFFFFFFF); 37121e1553eSJérôme Duval TRACE(("fs_walk - New vnode id is %Ld\n", *_vnodeID)); 37221e1553eSJérôme Duval 37321e1553eSJérôme Duval if (get_vnode(ns->id, *_vnodeID, (void **)&newNode) != 0) 37421e1553eSJérôme Duval result = EINVAL; 37521e1553eSJérôme Duval else { 37621e1553eSJérôme Duval newNode->parID = baseNode->id; 37721e1553eSJérôme Duval done = TRUE; 37821e1553eSJérôme Duval result = B_NO_ERROR; 37921e1553eSJérôme Duval } 38021e1553eSJérôme Duval } else { 38121e1553eSJérôme Duval if (node.fileIDString != NULL) { 38221e1553eSJérôme Duval free(node.fileIDString); 38321e1553eSJérôme Duval node.fileIDString = NULL; 38421e1553eSJérôme Duval } 38521e1553eSJérôme Duval if (node.attr.slName != NULL) { 38621e1553eSJérôme Duval free(node.attr.slName); 38721e1553eSJérôme Duval node.attr.slName = NULL; 38821e1553eSJérôme Duval } 38921e1553eSJérôme Duval } 39021e1553eSJérôme Duval } else { 39121e1553eSJérôme Duval result = initResult; 39221e1553eSJérôme Duval if (bytesRead == 0) 39321e1553eSJérôme Duval done = TRUE; 39421e1553eSJérôme Duval } 39521e1553eSJérôme Duval blockData += bytesRead; 39621e1553eSJérôme Duval blockBytesRead += bytesRead; 39721e1553eSJérôme Duval 39821e1553eSJérôme Duval TRACE(("fs_walk - Adding %d bytes to blockBytes read (total %Ld/%Ld).\n", 39921e1553eSJérôme Duval bytesRead, blockBytesRead, baseNode->dataLen[FS_DATA_FORMAT])); 40021e1553eSJérôme Duval } 40121e1553eSJérôme Duval totalRead += ns->logicalBlkSize[FS_DATA_FORMAT]; 40221e1553eSJérôme Duval block++; 40321e1553eSJérôme Duval 40421e1553eSJérôme Duval TRACE(("fs_walk - moving to next block %Ld, total read %Ld\n", block, totalRead)); 40521e1553eSJérôme Duval block_cache_put(ns->fBlockCache, cachedBlock); 40621e1553eSJérôme Duval 40721e1553eSJérôme Duval } else 40821e1553eSJérôme Duval done = TRUE; 40921e1553eSJérôme Duval } 41021e1553eSJérôme Duval 4113b723f79SJérôme Duval if (newNode) 41221e1553eSJérôme Duval *_type = newNode->attr.stat[FS_DATA_FORMAT].st_mode; 41321e1553eSJérôme Duval 41421e1553eSJérôme Duval } 41521e1553eSJérôme Duval TRACE(("fs_walk - EXIT, result is %s, vnid is %Lu\n", strerror(result), *_vnodeID)); 41621e1553eSJérôme Duval return result; 41721e1553eSJérôme Duval } 41821e1553eSJérôme Duval 41921e1553eSJérôme Duval 42021e1553eSJérôme Duval static status_t 42121e1553eSJérôme Duval fs_read_vnode(void *_ns, vnode_id vnid, void **node, bool reenter) 42221e1553eSJérôme Duval { 42321e1553eSJérôme Duval uint32 block, pos; 42421e1553eSJérôme Duval nspace *ns = (nspace*)_ns; 42521e1553eSJérôme Duval status_t result = B_NO_ERROR; 42621e1553eSJérôme Duval vnode *newNode = (vnode*)calloc(sizeof(vnode), 1); 42721e1553eSJérôme Duval 42821e1553eSJérôme Duval (void)reenter; 42921e1553eSJérôme Duval 43021e1553eSJérôme Duval pos = (vnid & 0x3FFFFFFF); 43121e1553eSJérôme Duval block = (vnid >> 30); 43221e1553eSJérôme Duval 43321e1553eSJérôme Duval TRACE(("fs_read_vnode - ENTER, block = %ld, pos = %ld, raw = %Lu node 0x%x\n", 43421e1553eSJérôme Duval block, pos, vnid, newNode)); 43521e1553eSJérôme Duval 43621e1553eSJérôme Duval if (newNode != NULL) { 43721e1553eSJérôme Duval if (vnid == ISO_ROOTNODE_ID) { 43821e1553eSJérôme Duval TRACE(("fs_read_vnode - root node requested.\n")); 43921e1553eSJérôme Duval memcpy(newNode, &(ns->rootDirRec), sizeof(vnode)); 44021e1553eSJérôme Duval *node = (void*)newNode; 44121e1553eSJérôme Duval } else { 44221e1553eSJérôme Duval char *blockData = (char *)block_cache_get_etc(ns->fBlockCache, block, 0, ns->logicalBlkSize[FS_DATA_FORMAT]); 44321e1553eSJérôme Duval 44421e1553eSJérôme Duval if (pos > ns->logicalBlkSize[FS_DATA_FORMAT]) { 44521e1553eSJérôme Duval if (blockData != NULL) 44621e1553eSJérôme Duval block_cache_put(ns->fBlockCache, block); 44721e1553eSJérôme Duval 44821e1553eSJérôme Duval result = EINVAL; 44921e1553eSJérôme Duval } else if (blockData != NULL) { 45021e1553eSJérôme Duval result = InitNode(newNode, blockData + pos, NULL, ns->joliet_level); 45121e1553eSJérôme Duval block_cache_put(ns->fBlockCache, block); 45221e1553eSJérôme Duval newNode->id = vnid; 45321e1553eSJérôme Duval 45421e1553eSJérôme Duval TRACE(("fs_read_vnode - init result is %s\n", strerror(result))); 45521e1553eSJérôme Duval *node = (void *)newNode; 45621e1553eSJérôme Duval TRACE(("fs_read_vnode - new file %s, size %ld\n", newNode->fileIDString, newNode->dataLen[FS_DATA_FORMAT])); 45721e1553eSJérôme Duval } 45821e1553eSJérôme Duval } 45921e1553eSJérôme Duval } else 46021e1553eSJérôme Duval result = ENOMEM; 46121e1553eSJérôme Duval 462*5b4cb109SJérôme Duval if (result == B_OK && !(newNode->flags & ISO_ISDIR)) { 463*5b4cb109SJérôme Duval newNode->cache = file_cache_create(ns->id, vnid, newNode->dataLen[FS_DATA_FORMAT], ns->fdOfSession); 464*5b4cb109SJérôme Duval } 465*5b4cb109SJérôme Duval 46621e1553eSJérôme Duval TRACE(("fs_read_vnode - EXIT, result is %s\n", strerror(result))); 46721e1553eSJérôme Duval return result; 46821e1553eSJérôme Duval } 46921e1553eSJérôme Duval 47021e1553eSJérôme Duval 47121e1553eSJérôme Duval static status_t 47221e1553eSJérôme Duval fs_release_vnode(void *ns, void *_node, bool reenter) 47321e1553eSJérôme Duval { 47421e1553eSJérôme Duval status_t result = B_NO_ERROR; 47521e1553eSJérôme Duval vnode *node = (vnode*)_node; 47621e1553eSJérôme Duval 47721e1553eSJérôme Duval (void)ns; 47821e1553eSJérôme Duval (void)reenter; 47921e1553eSJérôme Duval 480*5b4cb109SJérôme Duval TRACE(("fs_release_vnode - ENTER (0x%x)\n", node)); 48121e1553eSJérôme Duval 48221e1553eSJérôme Duval if (node != NULL) { 48321e1553eSJérôme Duval if (node->id != ISO_ROOTNODE_ID) { 48421e1553eSJérôme Duval if (node->fileIDString != NULL) 48521e1553eSJérôme Duval free (node->fileIDString); 48621e1553eSJérôme Duval if (node->attr.slName != NULL) 48721e1553eSJérôme Duval free (node->attr.slName); 488*5b4cb109SJérôme Duval if (node->cache != NULL) 489*5b4cb109SJérôme Duval file_cache_delete(node->cache); 49021e1553eSJérôme Duval 49121e1553eSJérôme Duval free(node); 49221e1553eSJérôme Duval } 49321e1553eSJérôme Duval } 49421e1553eSJérôme Duval 495*5b4cb109SJérôme Duval TRACE(("fs_release_vnode - EXIT\n")); 49621e1553eSJérôme Duval return result; 49721e1553eSJérôme Duval } 49821e1553eSJérôme Duval 49921e1553eSJérôme Duval 50021e1553eSJérôme Duval static status_t 501*5b4cb109SJérôme Duval fs_get_file_map(fs_volume _fs, fs_vnode _node, off_t pos, size_t reqLen, 502*5b4cb109SJérôme Duval struct file_io_vec *vecs, size_t *_count) 503*5b4cb109SJérôme Duval { 504*5b4cb109SJérôme Duval nspace *ns = (nspace *)_fs; // global stuff 505*5b4cb109SJérôme Duval vnode *node = (vnode *)_node; // The read file vnode. 506*5b4cb109SJérôme Duval uint16 blockSize = ns->logicalBlkSize[FS_DATA_FORMAT]; 507*5b4cb109SJérôme Duval uint32 startBlock = node->startLBN[FS_DATA_FORMAT] + (pos / blockSize); 508*5b4cb109SJérôme Duval off_t blockPos = pos % blockSize; 509*5b4cb109SJérôme Duval off_t numBlocks = 0; 510*5b4cb109SJérôme Duval uint32 dataLen = node->dataLen[FS_DATA_FORMAT]; 511*5b4cb109SJérôme Duval size_t endLen = 0; 512*5b4cb109SJérôme Duval size_t startLen = 0; 513*5b4cb109SJérôme Duval size_t index = 0, max = *_count; 514*5b4cb109SJérôme Duval 515*5b4cb109SJérôme Duval TRACE(("fs_get_file_map - ENTER (0x%x)\n", node)); 516*5b4cb109SJérôme Duval 517*5b4cb109SJérôme Duval // Allow an open to work on a dir, but no reads 518*5b4cb109SJérôme Duval if (node->flags & ISO_ISDIR) 519*5b4cb109SJérôme Duval return EISDIR; 520*5b4cb109SJérôme Duval 521*5b4cb109SJérôme Duval if (pos < 0) 522*5b4cb109SJérôme Duval pos = 0; 523*5b4cb109SJérôme Duval *_count = 0; 524*5b4cb109SJérôme Duval 525*5b4cb109SJérôme Duval // If passed-in requested length is bigger than file size, change it to 526*5b4cb109SJérôme Duval // file size. 527*5b4cb109SJérôme Duval if (reqLen + pos > dataLen) 528*5b4cb109SJérôme Duval reqLen = dataLen - pos; 529*5b4cb109SJérôme Duval 530*5b4cb109SJérôme Duval // Compute the length of the partial start-block read, if any. 531*5b4cb109SJérôme Duval if (reqLen + blockPos <= blockSize) 532*5b4cb109SJérôme Duval startLen = reqLen; 533*5b4cb109SJérôme Duval else if (blockPos > 0) 534*5b4cb109SJérôme Duval startLen = blockSize - blockPos; 535*5b4cb109SJérôme Duval 536*5b4cb109SJérôme Duval if (blockPos == 0 && reqLen >= blockSize) { 537*5b4cb109SJérôme Duval TRACE(("Setting startLen to 0\n")); 538*5b4cb109SJérôme Duval startLen = 0; 539*5b4cb109SJérôme Duval } 540*5b4cb109SJérôme Duval 541*5b4cb109SJérôme Duval // Compute the length of the partial end-block read, if any. 542*5b4cb109SJérôme Duval if (reqLen + blockPos > blockSize) 543*5b4cb109SJérôme Duval endLen = (reqLen + blockPos) % blockSize; 544*5b4cb109SJérôme Duval 545*5b4cb109SJérôme Duval // Compute the number of middle blocks to read. 546*5b4cb109SJérôme Duval numBlocks = ((reqLen - endLen - startLen) / blockSize); 547*5b4cb109SJérôme Duval 548*5b4cb109SJérôme Duval if (pos >= dataLen) { 549*5b4cb109SJérôme Duval // If pos >= file length, return 550*5b4cb109SJérôme Duval return B_OK; 551*5b4cb109SJérôme Duval } 552*5b4cb109SJérôme Duval 553*5b4cb109SJérôme Duval // Read in the first, potentially partial, block. 554*5b4cb109SJérôme Duval if (startLen > 0) { 555*5b4cb109SJérôme Duval vecs[index].offset = startBlock * blockSize + blockPos; 556*5b4cb109SJérôme Duval vecs[index].length = startLen; 557*5b4cb109SJérôme Duval startBlock++; 558*5b4cb109SJérôme Duval index++; 559*5b4cb109SJérôme Duval if (index >= max) { 560*5b4cb109SJérôme Duval // we're out of file_io_vecs; let's bail out 561*5b4cb109SJérôme Duval *_count = index; 562*5b4cb109SJérôme Duval return B_BUFFER_OVERFLOW; 563*5b4cb109SJérôme Duval } 564*5b4cb109SJérôme Duval } 565*5b4cb109SJérôme Duval 566*5b4cb109SJérôme Duval // Read in the middle blocks. 567*5b4cb109SJérôme Duval if (numBlocks > 0) { 568*5b4cb109SJérôme Duval for (int32 i=startBlock; i<startBlock+numBlocks; i++) { 569*5b4cb109SJérôme Duval vecs[index].offset = i * blockSize; 570*5b4cb109SJérôme Duval vecs[index].length = blockSize; 571*5b4cb109SJérôme Duval index++; 572*5b4cb109SJérôme Duval if (index >= max) { 573*5b4cb109SJérôme Duval // we're out of file_io_vecs; let's bail out 574*5b4cb109SJérôme Duval *_count = index; 575*5b4cb109SJérôme Duval return B_BUFFER_OVERFLOW; 576*5b4cb109SJérôme Duval } 577*5b4cb109SJérôme Duval } 578*5b4cb109SJérôme Duval } 579*5b4cb109SJérôme Duval 580*5b4cb109SJérôme Duval // Read in the last partial block. 581*5b4cb109SJérôme Duval if (endLen > 0) { 582*5b4cb109SJérôme Duval off_t endBlock = startBlock + numBlocks; 583*5b4cb109SJérôme Duval vecs[index].offset = endBlock * blockSize; 584*5b4cb109SJérôme Duval vecs[index].length = endLen; 585*5b4cb109SJérôme Duval index++; 586*5b4cb109SJérôme Duval } 587*5b4cb109SJérôme Duval 588*5b4cb109SJérôme Duval *_count = index; 589*5b4cb109SJérôme Duval 590*5b4cb109SJérôme Duval TRACE(("fs_get_file_map - EXIT\n")); 591*5b4cb109SJérôme Duval return B_OK; 592*5b4cb109SJérôme Duval } 593*5b4cb109SJérôme Duval 594*5b4cb109SJérôme Duval 595*5b4cb109SJérôme Duval static status_t 59621e1553eSJérôme Duval fs_read_stat(void *_ns, void *_node, struct stat *st) 59721e1553eSJérôme Duval { 59821e1553eSJérôme Duval nspace *ns = (nspace*)_ns; 59921e1553eSJérôme Duval vnode *node = (vnode*)_node; 6003b723f79SJérôme Duval status_t result = B_NO_ERROR; 60121e1553eSJérôme Duval time_t time; 60221e1553eSJérôme Duval 6033b723f79SJérôme Duval TRACE(("fs_read_stat - ENTER\n")); 60421e1553eSJérôme Duval 60521e1553eSJérôme Duval st->st_dev = ns->id; 60621e1553eSJérôme Duval st->st_ino = node->id; 60721e1553eSJérôme Duval st->st_nlink = node->attr.stat[FS_DATA_FORMAT].st_nlink; 60821e1553eSJérôme Duval st->st_uid = node->attr.stat[FS_DATA_FORMAT].st_uid; 60921e1553eSJérôme Duval st->st_gid = node->attr.stat[FS_DATA_FORMAT].st_gid; 61021e1553eSJérôme Duval st->st_blksize = 65536; 61121e1553eSJérôme Duval st->st_mode = node->attr.stat[FS_DATA_FORMAT].st_mode; 61221e1553eSJérôme Duval 61321e1553eSJérôme Duval // Same for file/dir in ISO9660 61421e1553eSJérôme Duval st->st_size = node->dataLen[FS_DATA_FORMAT]; 61521e1553eSJérôme Duval if (ConvertRecDate(&(node->recordDate), &time) == B_NO_ERROR) 61621e1553eSJérôme Duval st->st_ctime = st->st_mtime = st->st_atime = time; 61721e1553eSJérôme Duval 6183b723f79SJérôme Duval TRACE(("fs_read_stat - EXIT, result is %s\n", strerror(result))); 61921e1553eSJérôme Duval 62021e1553eSJérôme Duval return result; 62121e1553eSJérôme Duval } 62221e1553eSJérôme Duval 62321e1553eSJérôme Duval 62421e1553eSJérôme Duval static status_t 62521e1553eSJérôme Duval fs_open(void *_ns, void *_node, int omode, void **cookie) 62621e1553eSJérôme Duval { 62721e1553eSJérôme Duval status_t result = B_NO_ERROR; 62821e1553eSJérôme Duval 62921e1553eSJérôme Duval (void)_ns; 63021e1553eSJérôme Duval (void)cookie; 63121e1553eSJérôme Duval 63221e1553eSJérôme Duval // Do not allow any of the write-like open modes to get by 63321e1553eSJérôme Duval if ((omode == O_WRONLY) || (omode == O_RDWR)) 63421e1553eSJérôme Duval result = EROFS; 63521e1553eSJérôme Duval else if((omode & O_TRUNC) || (omode & O_CREAT)) 63621e1553eSJérôme Duval result = EROFS; 63721e1553eSJérôme Duval 63821e1553eSJérôme Duval return result; 63921e1553eSJérôme Duval } 64021e1553eSJérôme Duval 64121e1553eSJérôme Duval 64221e1553eSJérôme Duval static status_t 64321e1553eSJérôme Duval fs_read(void *_ns, void *_node, void *cookie, off_t pos, void *buf, size_t *len) 64421e1553eSJérôme Duval { 645*5b4cb109SJérôme Duval #if 0 64621e1553eSJérôme Duval nspace *ns = (nspace *)_ns; // global stuff 64721e1553eSJérôme Duval vnode *node = (vnode *)_node; // The read file vnode. 64821e1553eSJérôme Duval uint16 blockSize = ns->logicalBlkSize[FS_DATA_FORMAT]; 64921e1553eSJérôme Duval uint32 startBlock = node->startLBN[FS_DATA_FORMAT] + (pos / blockSize); 65021e1553eSJérôme Duval off_t blockPos = pos % blockSize; 65121e1553eSJérôme Duval off_t numBlocks = 0; 65221e1553eSJérôme Duval uint32 dataLen = node->dataLen[FS_DATA_FORMAT]; 65321e1553eSJérôme Duval status_t result = B_NO_ERROR; 65421e1553eSJérôme Duval size_t endLen = 0; 65521e1553eSJérôme Duval size_t reqLen = *len; 65621e1553eSJérôme Duval size_t startLen = 0; 65721e1553eSJérôme Duval 65821e1553eSJérôme Duval (void)cookie; 65921e1553eSJérôme Duval 66021e1553eSJérôme Duval // Allow an open to work on a dir, but no reads 66121e1553eSJérôme Duval if (node->flags & ISO_ISDIR) 66221e1553eSJérôme Duval return EISDIR; 66321e1553eSJérôme Duval 66421e1553eSJérôme Duval if (pos < 0) 66521e1553eSJérôme Duval pos = 0; 66621e1553eSJérôme Duval *len = 0; 66721e1553eSJérôme Duval 66821e1553eSJérôme Duval // If passed-in requested length is bigger than file size, change it to 66921e1553eSJérôme Duval // file size. 67021e1553eSJérôme Duval if (reqLen + pos > dataLen) 67121e1553eSJérôme Duval reqLen = dataLen - pos; 67221e1553eSJérôme Duval 67321e1553eSJérôme Duval // Compute the length of the partial start-block read, if any. 67421e1553eSJérôme Duval 67521e1553eSJérôme Duval if (reqLen + blockPos <= blockSize) 67621e1553eSJérôme Duval startLen = reqLen; 67721e1553eSJérôme Duval else if (blockPos > 0) 67821e1553eSJérôme Duval startLen = blockSize - blockPos; 67921e1553eSJérôme Duval 68021e1553eSJérôme Duval if (blockPos == 0 && reqLen >= blockSize) { 68121e1553eSJérôme Duval TRACE(("Setting startLen to 0, even block read\n")); 68221e1553eSJérôme Duval startLen = 0; 68321e1553eSJérôme Duval } 68421e1553eSJérôme Duval 68521e1553eSJérôme Duval // Compute the length of the partial end-block read, if any. 68621e1553eSJérôme Duval if (reqLen + blockPos > blockSize) 68721e1553eSJérôme Duval endLen = (reqLen + blockPos) % blockSize; 68821e1553eSJérôme Duval 68921e1553eSJérôme Duval // Compute the number of middle blocks to read. 69021e1553eSJérôme Duval numBlocks = ((reqLen - endLen - startLen) / blockSize); 69121e1553eSJérôme Duval 69221e1553eSJérôme Duval //dprintf("fs_read - ENTER, pos is %Ld, len is %lu\n", pos, reqLen); 69321e1553eSJérôme Duval //dprintf("fs_read - filename is %s\n", node->fileIDString); 69421e1553eSJérôme Duval //dprintf("fs_read - total file length is %lu\n", dataLen); 69521e1553eSJérôme Duval //dprintf("fs_read - start block of file is %lu\n", node->startLBN[FS_DATA_FORMAT]); 69621e1553eSJérôme Duval //dprintf("fs_read - block pos is %Lu\n", blockPos); 69721e1553eSJérôme Duval //dprintf("fs_read - read block will be %lu\n", startBlock); 69821e1553eSJérôme Duval //dprintf("fs_read - startLen is %lu\n", startLen); 69921e1553eSJérôme Duval //dprintf("fs_read - endLen is %lu\n", endLen); 70021e1553eSJérôme Duval //dprintf("fs_read - num blocks to read is %Ld\n", numBlocks); 70121e1553eSJérôme Duval 70221e1553eSJérôme Duval if (pos >= dataLen) { 70321e1553eSJérôme Duval // If pos >= file length, return length of 0. 70421e1553eSJérôme Duval *len = 0; 70521e1553eSJérôme Duval return B_OK; 70621e1553eSJérôme Duval } 70721e1553eSJérôme Duval 70821e1553eSJérôme Duval // Read in the first, potentially partial, block. 70921e1553eSJérôme Duval if (startLen > 0) { 71021e1553eSJérôme Duval off_t cachedBlock = startBlock; 71121e1553eSJérôme Duval char *blockData = (char *)block_cache_get_etc(ns->fBlockCache, startBlock, 0, blockSize); 71221e1553eSJérôme Duval if (blockData != NULL) { 71321e1553eSJérôme Duval //dprintf("fs_read - copying first block, len is %d.\n", startLen); 71421e1553eSJérôme Duval memcpy(buf, blockData+blockPos, startLen); 71521e1553eSJérôme Duval *len += startLen; 71621e1553eSJérôme Duval block_cache_put(ns->fBlockCache, cachedBlock); 71721e1553eSJérôme Duval startBlock++; 7183b723f79SJérôme Duval } else 7193b723f79SJérôme Duval result = EIO; 72021e1553eSJérôme Duval } 72121e1553eSJérôme Duval 72221e1553eSJérôme Duval // Read in the middle blocks. 72321e1553eSJérôme Duval if (numBlocks > 0 && result == B_NO_ERROR) { 72421e1553eSJérôme Duval TRACE(("fs_read - getting middle blocks\n")); 7253b723f79SJérôme Duval char *endBuf = ((char *)buf) + startLen; 72621e1553eSJérôme Duval for (int32 i=startBlock; i<startBlock+numBlocks; i++) { 72721e1553eSJérôme Duval char *blockData = (char *)block_cache_get_etc(ns->fBlockCache, i, 0, blockSize); 7283b723f79SJérôme Duval memcpy(endBuf, blockData, blockSize); 72921e1553eSJérôme Duval *len += blockSize; 7303b723f79SJérôme Duval endBuf += blockSize; 73121e1553eSJérôme Duval block_cache_put(ns->fBlockCache, i); 73221e1553eSJérôme Duval } 73321e1553eSJérôme Duval } 73421e1553eSJérôme Duval 73521e1553eSJérôme Duval // Read in the last partial block. 73621e1553eSJérôme Duval if (result == B_NO_ERROR && endLen > 0) { 73721e1553eSJérôme Duval off_t endBlock = startBlock + numBlocks; 73821e1553eSJérôme Duval char *endBlockData = (char*)block_cache_get_etc(ns->fBlockCache, endBlock, 0, blockSize); 73921e1553eSJérôme Duval if (endBlockData != NULL) { 74021e1553eSJérôme Duval char *endBuf = ((char *)buf) + (reqLen - endLen); 74121e1553eSJérôme Duval 74221e1553eSJérôme Duval memcpy(endBuf, endBlockData, endLen); 74321e1553eSJérôme Duval block_cache_put(ns->fBlockCache, endBlock); 74421e1553eSJérôme Duval *len += endLen; 74521e1553eSJérôme Duval } else 74621e1553eSJérôme Duval result = EIO; 74721e1553eSJérôme Duval } 74821e1553eSJérôme Duval 74921e1553eSJérôme Duval TRACE(("fs_read - EXIT, result is %s\n", strerror(result))); 75021e1553eSJérôme Duval return result; 751*5b4cb109SJérôme Duval #else 752*5b4cb109SJérôme Duval vnode *node = (vnode *)_node; // The read file vnode. 753*5b4cb109SJérôme Duval uint32 dataLen = node->dataLen[FS_DATA_FORMAT]; 754*5b4cb109SJérôme Duval 755*5b4cb109SJérôme Duval // set/check boundaries for pos/length 756*5b4cb109SJérôme Duval if (pos < 0) { 757*5b4cb109SJérôme Duval return B_BAD_VALUE; 758*5b4cb109SJérôme Duval } 759*5b4cb109SJérôme Duval if (pos >= dataLen) { 760*5b4cb109SJérôme Duval // If pos >= file length, return length of 0. 761*5b4cb109SJérôme Duval *len = 0; 762*5b4cb109SJérôme Duval return B_OK; 763*5b4cb109SJérôme Duval } 764*5b4cb109SJérôme Duval return file_cache_read(node->cache, pos, buf, len); 765*5b4cb109SJérôme Duval #endif 76621e1553eSJérôme Duval } 76721e1553eSJérôme Duval 76821e1553eSJérôme Duval 76921e1553eSJérôme Duval static status_t 77021e1553eSJérôme Duval fs_close(void *ns, void *node, void *cookie) 77121e1553eSJérôme Duval { 77221e1553eSJérôme Duval (void)ns; 77321e1553eSJérôme Duval (void)node; 77421e1553eSJérôme Duval (void)cookie; 77521e1553eSJérôme Duval 77621e1553eSJérôme Duval //dprintf("fs_close - ENTER\n"); 77721e1553eSJérôme Duval //dprintf("fs_close - EXIT\n"); 77821e1553eSJérôme Duval return B_OK; 77921e1553eSJérôme Duval } 78021e1553eSJérôme Duval 78121e1553eSJérôme Duval static status_t 78221e1553eSJérôme Duval fs_free_cookie(void *ns, void *node, void *cookie) 78321e1553eSJérôme Duval { 78421e1553eSJérôme Duval (void)ns; 78521e1553eSJérôme Duval (void)node; 78621e1553eSJérôme Duval (void)cookie; 78721e1553eSJérôme Duval 78821e1553eSJérôme Duval // We don't allocate file cookies, so we do nothing here. 78921e1553eSJérôme Duval //dprintf("fs_free_cookie - ENTER\n"); 79021e1553eSJérôme Duval //if (cookie != NULL) free (cookie); 79121e1553eSJérôme Duval //dprintf("fs_free_cookie - EXIT\n"); 79221e1553eSJérôme Duval return B_OK; 79321e1553eSJérôme Duval } 79421e1553eSJérôme Duval 79521e1553eSJérôme Duval // fs_access - checks permissions for access. 79621e1553eSJérôme Duval static status_t 79721e1553eSJérôme Duval fs_access(void *ns, void *node, int mode) 79821e1553eSJérôme Duval { 79921e1553eSJérôme Duval (void)ns; 80021e1553eSJérôme Duval (void)node; 80121e1553eSJérôme Duval (void)mode; 80221e1553eSJérôme Duval 80321e1553eSJérôme Duval // ns - global, fs-specific struct for device 80421e1553eSJérôme Duval // node - node to check permissions for 80521e1553eSJérôme Duval // mode - requested permissions on node. 80621e1553eSJérôme Duval //dprintf("fs_access - ENTER\n"); 80721e1553eSJérôme Duval //dprintf("fs_access - EXIT\n"); 80821e1553eSJérôme Duval return B_OK; 80921e1553eSJérôme Duval } 81021e1553eSJérôme Duval 81121e1553eSJérôme Duval static status_t 81221e1553eSJérôme Duval fs_read_link(void *_ns, void *_node, char *buffer, size_t *_bufferSize) 81321e1553eSJérôme Duval { 81421e1553eSJérôme Duval vnode *node = (vnode *)_node; 81521e1553eSJérôme Duval status_t result = EINVAL; 81621e1553eSJérôme Duval 81721e1553eSJérôme Duval (void)_ns; 81821e1553eSJérôme Duval 81921e1553eSJérôme Duval if (S_ISLNK(node->attr.stat[FS_DATA_FORMAT].st_mode)) { 82021e1553eSJérôme Duval size_t length = strlen(node->attr.slName); 82121e1553eSJérôme Duval if (length > *_bufferSize) 8223b723f79SJérôme Duval memcpy(buffer, node->attr.slName, *_bufferSize); 8233b723f79SJérôme Duval else { 82421e1553eSJérôme Duval memcpy(buffer, node->attr.slName, length); 8253b723f79SJérôme Duval *_bufferSize = length; 8263b723f79SJérôme Duval } 82721e1553eSJérôme Duval 82821e1553eSJérôme Duval result = B_NO_ERROR; 82921e1553eSJérôme Duval } 83021e1553eSJérôme Duval 83121e1553eSJérôme Duval return result; 83221e1553eSJérôme Duval } 83321e1553eSJérôme Duval 83421e1553eSJérôme Duval 83521e1553eSJérôme Duval static status_t 83621e1553eSJérôme Duval fs_open_dir(void *_ns, void *_node, void **cookie) 83721e1553eSJérôme Duval { 83821e1553eSJérôme Duval vnode *node = (vnode *)_node; 83921e1553eSJérôme Duval status_t result = B_NO_ERROR; 84021e1553eSJérôme Duval dircookie *dirCookie = (dircookie *)malloc(sizeof(dircookie)); 84121e1553eSJérôme Duval 84221e1553eSJérôme Duval (void)_ns; 84321e1553eSJérôme Duval 844*5b4cb109SJérôme Duval TRACE(("fs_open_dir - ENTER, node is 0x%x\n", _node)); 84521e1553eSJérôme Duval 84621e1553eSJérôme Duval if (!(node->flags & ISO_ISDIR)) 84721e1553eSJérôme Duval result = EMFILE; 84821e1553eSJérôme Duval 84921e1553eSJérôme Duval if (dirCookie != NULL) { 85021e1553eSJérôme Duval dirCookie->startBlock = node->startLBN[FS_DATA_FORMAT]; 85121e1553eSJérôme Duval dirCookie->block = node->startLBN[FS_DATA_FORMAT]; 85221e1553eSJérôme Duval dirCookie->totalSize = node->dataLen[FS_DATA_FORMAT]; 85321e1553eSJérôme Duval dirCookie->pos = 0; 85421e1553eSJérôme Duval dirCookie->id = node->id; 85521e1553eSJérôme Duval *cookie = (void *)dirCookie; 85621e1553eSJérôme Duval } else 85721e1553eSJérôme Duval result = ENOMEM; 85821e1553eSJérôme Duval 859*5b4cb109SJérôme Duval TRACE(("fs_open_dir - EXIT\n")); 86021e1553eSJérôme Duval return result; 86121e1553eSJérôme Duval } 86221e1553eSJérôme Duval 86321e1553eSJérôme Duval 86421e1553eSJérôme Duval static status_t 86521e1553eSJérôme Duval fs_read_dir(void *_ns, void *_node, void *_cookie, struct dirent *buffer, 86621e1553eSJérôme Duval size_t bufferSize, uint32 *num) 86721e1553eSJérôme Duval { 86821e1553eSJérôme Duval status_t result = B_NO_ERROR; 86921e1553eSJérôme Duval nspace *ns = (nspace *)_ns; 87021e1553eSJérôme Duval dircookie *dirCookie = (dircookie *)_cookie; 87121e1553eSJérôme Duval 87221e1553eSJérôme Duval (void)_node; 87321e1553eSJérôme Duval 874*5b4cb109SJérôme Duval TRACE(("fs_read_dir - ENTER\n")); 87521e1553eSJérôme Duval 87621e1553eSJérôme Duval result = ISOReadDirEnt(ns, dirCookie, buffer, bufferSize); 87721e1553eSJérôme Duval 87821e1553eSJérôme Duval // If we succeeded, return 1, the number of dirents we read. 87921e1553eSJérôme Duval if (result == B_NO_ERROR) 88021e1553eSJérôme Duval *num = 1; 88121e1553eSJérôme Duval else 88221e1553eSJérôme Duval *num = 0; 88321e1553eSJérôme Duval 88421e1553eSJérôme Duval // When you get to the end, don't return an error, just return 88521e1553eSJérôme Duval // a zero in *num. 88621e1553eSJérôme Duval 88721e1553eSJérôme Duval if (result == ENOENT) 88821e1553eSJérôme Duval result = B_NO_ERROR; 88921e1553eSJérôme Duval 890*5b4cb109SJérôme Duval TRACE(("fs_read_dir - EXIT, result is %s\n", strerror(result))); 89121e1553eSJérôme Duval return result; 89221e1553eSJérôme Duval } 89321e1553eSJérôme Duval 89421e1553eSJérôme Duval 89521e1553eSJérôme Duval static status_t 89621e1553eSJérôme Duval fs_rewind_dir(void *ns, void *node, void* _cookie) 89721e1553eSJérôme Duval { 89821e1553eSJérôme Duval status_t result = EINVAL; 89921e1553eSJérôme Duval dircookie *cookie = (dircookie*)_cookie; 90021e1553eSJérôme Duval 90121e1553eSJérôme Duval (void)ns; 90221e1553eSJérôme Duval (void)node; 90321e1553eSJérôme Duval 904*5b4cb109SJérôme Duval //dprintf("fs_rewind_dir - ENTER\n"); 90521e1553eSJérôme Duval if (cookie != NULL) { 90621e1553eSJérôme Duval cookie->block = cookie->startBlock; 90721e1553eSJérôme Duval cookie->pos = 0; 90821e1553eSJérôme Duval result = B_NO_ERROR; 90921e1553eSJérôme Duval } 910*5b4cb109SJérôme Duval //dprintf("fs_rewind_dir - EXIT, result is %s\n", strerror(result)); 91121e1553eSJérôme Duval return result; 91221e1553eSJérôme Duval } 91321e1553eSJérôme Duval 91421e1553eSJérôme Duval 91521e1553eSJérôme Duval static status_t 91621e1553eSJérôme Duval fs_close_dir(void *ns, void *node, void *cookie) 91721e1553eSJérôme Duval { 91821e1553eSJérôme Duval (void)ns; 91921e1553eSJérôme Duval (void)node; 92021e1553eSJérôme Duval (void)cookie; 92121e1553eSJérôme Duval 92221e1553eSJérôme Duval // ns - global, fs-specific struct for device 92321e1553eSJérôme Duval // node - directory to close 92421e1553eSJérôme Duval // cookie - current cookie for directory. 925*5b4cb109SJérôme Duval //dprintf("fs_close_dir - ENTER\n"); 926*5b4cb109SJérôme Duval //dprintf("fs_close_dir - EXIT\n"); 92721e1553eSJérôme Duval return B_OK; 92821e1553eSJérôme Duval } 92921e1553eSJérôme Duval 93021e1553eSJérôme Duval 93121e1553eSJérôme Duval static status_t 93221e1553eSJérôme Duval fs_free_dir_cookie(void *ns, void *node, void *cookie) 93321e1553eSJérôme Duval { 93421e1553eSJérôme Duval (void)ns; 93521e1553eSJérôme Duval (void)node; 93621e1553eSJérôme Duval 93721e1553eSJérôme Duval // ns - global, fs-specific struct for device 93821e1553eSJérôme Duval // node - directory related to cookie 93921e1553eSJérôme Duval // cookie - current cookie for directory, to free. 940*5b4cb109SJérôme Duval //dprintf("fs_free_dir_cookie - ENTER\n"); 94121e1553eSJérôme Duval if (cookie != NULL) 94221e1553eSJérôme Duval free(cookie); 94321e1553eSJérôme Duval 944*5b4cb109SJérôme Duval //dprintf("fs_free_dir_cookie - EXIT\n"); 94521e1553eSJérôme Duval return B_OK; 94621e1553eSJérôme Duval } 94721e1553eSJérôme Duval 94821e1553eSJérôme Duval // #pragma mark - 94921e1553eSJérôme Duval 95021e1553eSJérôme Duval 95121e1553eSJérôme Duval static status_t 95221e1553eSJérôme Duval iso_std_ops(int32 op, ...) 95321e1553eSJérôme Duval { 95421e1553eSJérôme Duval switch (op) { 95521e1553eSJérôme Duval case B_MODULE_INIT: 95621e1553eSJérôme Duval return B_OK; 95721e1553eSJérôme Duval case B_MODULE_UNINIT: 95821e1553eSJérôme Duval return B_OK; 95921e1553eSJérôme Duval default: 96021e1553eSJérôme Duval return B_ERROR; 96121e1553eSJérôme Duval } 96221e1553eSJérôme Duval } 96321e1553eSJérôme Duval 96421e1553eSJérôme Duval 96521e1553eSJérôme Duval static file_system_module_info sISO660FileSystem = { 96621e1553eSJérôme Duval { 96721e1553eSJérôme Duval "file_systems/iso9660" B_CURRENT_FS_API_VERSION, 96821e1553eSJérôme Duval 0, 96921e1553eSJérôme Duval iso_std_ops, 97021e1553eSJérôme Duval }, 97121e1553eSJérôme Duval 97221e1553eSJérôme Duval "ISO9660 File System", 97321e1553eSJérôme Duval 97421e1553eSJérôme Duval // scanning 97521e1553eSJérôme Duval fs_identify_partition, 97621e1553eSJérôme Duval fs_scan_partition, 97721e1553eSJérôme Duval fs_free_identify_partition_cookie, 97821e1553eSJérôme Duval NULL, // free_partition_content_cookie() 97921e1553eSJérôme Duval 98021e1553eSJérôme Duval &fs_mount, 98121e1553eSJérôme Duval &fs_unmount, 98221e1553eSJérôme Duval &fs_read_fs_stat, 98321e1553eSJérôme Duval NULL, 98421e1553eSJérôme Duval NULL, 98521e1553eSJérôme Duval 98621e1553eSJérôme Duval /* vnode operations */ 98721e1553eSJérôme Duval &fs_walk, 9883b723f79SJérôme Duval &fs_get_vnode_name, 98921e1553eSJérôme Duval &fs_read_vnode, 99021e1553eSJérôme Duval &fs_release_vnode, 99121e1553eSJérôme Duval NULL, // &fs_remove_vnode() 99221e1553eSJérôme Duval 99321e1553eSJérôme Duval /* VM file access */ 99421e1553eSJérôme Duval NULL, // &fs_can_page 99521e1553eSJérôme Duval NULL, // &fs_read_pages 99621e1553eSJérôme Duval NULL, // &fs_write_pages 99721e1553eSJérôme Duval 998*5b4cb109SJérôme Duval &fs_get_file_map, 99921e1553eSJérôme Duval 100021e1553eSJérôme Duval NULL, // &fs_ioctl 100121e1553eSJérôme Duval NULL, // &fs_set_flags 10023b723f79SJérôme Duval NULL, // &fs_select 10033b723f79SJérôme Duval NULL, // &fs_deselect 100421e1553eSJérôme Duval NULL, // &fs_fsync 100521e1553eSJérôme Duval 100621e1553eSJérôme Duval &fs_read_link, 100721e1553eSJérôme Duval NULL, // write link 100821e1553eSJérôme Duval NULL, // &fs_create_symlink, 100921e1553eSJérôme Duval 101021e1553eSJérôme Duval NULL, // &fs_link, 101121e1553eSJérôme Duval NULL, // &fs_unlink 101221e1553eSJérôme Duval NULL, // &fs_rename 101321e1553eSJérôme Duval 101421e1553eSJérôme Duval &fs_access, 101521e1553eSJérôme Duval &fs_read_stat, 101621e1553eSJérôme Duval NULL, // &fs_write_stat 101721e1553eSJérôme Duval 101821e1553eSJérôme Duval /* file operations */ 101921e1553eSJérôme Duval NULL, // &fs_create 102021e1553eSJérôme Duval &fs_open, 102121e1553eSJérôme Duval &fs_close, 102221e1553eSJérôme Duval &fs_free_cookie, 102321e1553eSJérôme Duval &fs_read, 102421e1553eSJérôme Duval NULL, // &fs_write 102521e1553eSJérôme Duval 102621e1553eSJérôme Duval /* directory operations */ 102721e1553eSJérôme Duval NULL, // &fs_create_dir 102821e1553eSJérôme Duval NULL, // &fs_remove_dir 102921e1553eSJérôme Duval &fs_open_dir, 103021e1553eSJérôme Duval &fs_close_dir, 103121e1553eSJérôme Duval &fs_free_dir_cookie, 103221e1553eSJérôme Duval &fs_read_dir, 103321e1553eSJérôme Duval &fs_rewind_dir, 103421e1553eSJérôme Duval 103521e1553eSJérôme Duval /* attribute directory operations */ 103621e1553eSJérôme Duval NULL, // &fs_open_attr_dir 103721e1553eSJérôme Duval NULL, // &fs_close_attr_dir 103821e1553eSJérôme Duval NULL, // &fs_free_attr_dir_cookie 103921e1553eSJérôme Duval NULL, // &fs_read_attr_dir 104021e1553eSJérôme Duval NULL, // &fs_rewind_attr_dir 104121e1553eSJérôme Duval 104221e1553eSJérôme Duval /* attribute operations */ 104321e1553eSJérôme Duval NULL, // &fs_create_attr 104421e1553eSJérôme Duval NULL, // &fs_open_attr 104521e1553eSJérôme Duval NULL, // &fs_close_attr 104621e1553eSJérôme Duval NULL, // &fs_free_attr_cookie 104721e1553eSJérôme Duval NULL, // &fs_read_attr 104821e1553eSJérôme Duval NULL, // &fs_write_attr 104921e1553eSJérôme Duval 105021e1553eSJérôme Duval NULL, // &fs_read_attr_stat 105121e1553eSJérôme Duval NULL, // &fs_write_attr_stat 105221e1553eSJérôme Duval NULL, // &fs_rename_attr 105321e1553eSJérôme Duval NULL, // &fs_remove_attr 105421e1553eSJérôme Duval 105521e1553eSJérôme Duval /* index directory & index operations */ 105621e1553eSJérôme Duval NULL, // &fs_open_index_dir 105721e1553eSJérôme Duval NULL, // &fs_close_index_dir 105821e1553eSJérôme Duval NULL, // &fs_free_index_dir_cookie 105921e1553eSJérôme Duval NULL, // &fs_read_index_dir 106021e1553eSJérôme Duval NULL, // &fs_rewind_index_dir 106121e1553eSJérôme Duval 106221e1553eSJérôme Duval NULL, // &fs_create_index 106321e1553eSJérôme Duval NULL, // &fs_remove_index 106421e1553eSJérôme Duval NULL, // &fs_stat_index 106521e1553eSJérôme Duval 106621e1553eSJérôme Duval /* query operations */ 106721e1553eSJérôme Duval NULL, // &fs_open_query 106821e1553eSJérôme Duval NULL, // &fs_close_query 106921e1553eSJérôme Duval NULL, // &fs_free_query_cookie 107021e1553eSJérôme Duval NULL, // &fs_read_query 107121e1553eSJérôme Duval NULL, // &fs_rewind_query 107221e1553eSJérôme Duval }; 107321e1553eSJérôme Duval 107421e1553eSJérôme Duval module_info *modules[] = { 107521e1553eSJérôme Duval (module_info *)&sISO660FileSystem, 107621e1553eSJérôme Duval NULL, 107721e1553eSJérôme Duval }; 107821e1553eSJérôme Duval 1079