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 <malloc.h> 2221e1553eSJérôme Duval 2321e1553eSJérôme Duval #include <KernelExport.h> 2421e1553eSJérôme Duval #include <NodeMonitor.h> 2521e1553eSJérôme Duval #include <fs_interface.h> 2621e1553eSJérôme Duval #include <fs_cache.h> 2721e1553eSJérôme Duval 2821e1553eSJérôme Duval #include <fs_attr.h> 2921e1553eSJérôme Duval #include <fs_info.h> 3021e1553eSJérôme Duval #include <fs_index.h> 3121e1553eSJérôme Duval #include <fs_query.h> 3221e1553eSJérôme Duval #include <fs_volume.h> 3321e1553eSJérôme Duval 3421e1553eSJérôme Duval #include <util/kernel_cpp.h> 3521e1553eSJérôme Duval 3644d56753SJérôme Duval #include "lock.h" 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); 605b4cb109SJérôme Duval static status_t fs_get_file_map(fs_volume _fs, fs_vnode _node, off_t offset, size_t size, 615b4cb109SJé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 223*9d254f45SJérôme Duval // Unlike in BeOS, we need to put the reference to our root node ourselves 224*9d254f45SJérôme Duval put_vnode(ns->id, ISO_ROOTNODE_ID); 225*9d254f45SJérôme Duval 22621e1553eSJérôme Duval block_cache_delete(ns->fBlockCache, false); 22721e1553eSJérôme Duval close(ns->fdOfSession); 22821e1553eSJérôme Duval result = close(ns->fd); 22921e1553eSJérôme Duval 23021e1553eSJérôme Duval free(ns); 23121e1553eSJérôme Duval 23221e1553eSJérôme Duval TRACE(("fs_unmount - EXIT, result is %s\n", strerror(result))); 23321e1553eSJérôme Duval return result; 23421e1553eSJérôme Duval } 23521e1553eSJérôme Duval 23621e1553eSJérôme Duval 23721e1553eSJérôme Duval static status_t 23821e1553eSJérôme Duval fs_read_fs_stat(void *_ns, struct fs_info *fss) 23921e1553eSJérôme Duval { 24021e1553eSJérôme Duval // Fill in fs_info struct for device. 24121e1553eSJérôme Duval nspace *ns = (nspace *)_ns; 24221e1553eSJérôme Duval int i; 24321e1553eSJérôme Duval 2445b4cb109SJérôme Duval TRACE(("fs_read_fs_stat - ENTER\n")); 24521e1553eSJérôme Duval 24621e1553eSJérôme Duval // Fill in device id. 24721e1553eSJérôme Duval //fss->dev = ns->fd; 24821e1553eSJérôme Duval 24921e1553eSJérôme Duval // Root vnode ID 25021e1553eSJérôme Duval //fss->root = ISO_ROOTNODE_ID; 25121e1553eSJérôme Duval 25221e1553eSJérôme Duval // File system flags. 25321e1553eSJérôme Duval fss->flags = B_FS_IS_PERSISTENT | B_FS_IS_READONLY; 25421e1553eSJérôme Duval 25521e1553eSJérôme Duval // FS block size. 25621e1553eSJérôme Duval fss->block_size = ns->logicalBlkSize[FS_DATA_FORMAT]; 25721e1553eSJérôme Duval 25821e1553eSJérôme Duval // IO size - specifies buffer size for file copying 25921e1553eSJérôme Duval fss->io_size = 65536; 26021e1553eSJérôme Duval 26121e1553eSJérôme Duval // Total blocks? 26221e1553eSJérôme Duval fss->total_blocks = ns->volSpaceSize[FS_DATA_FORMAT]; 26321e1553eSJérôme Duval 26421e1553eSJérôme Duval // Free blocks = 0, read only 26521e1553eSJérôme Duval fss->free_blocks = 0; 26621e1553eSJérôme Duval 26721e1553eSJérôme Duval // Device name. 26821e1553eSJérôme Duval strncpy(fss->device_name, ns->devicePath, sizeof(fss->device_name)); 26921e1553eSJérôme Duval 27021e1553eSJérôme Duval strncpy(fss->volume_name, ns->volIDString, sizeof(fss->volume_name)); 27121e1553eSJérôme Duval for (i = strlen(fss->volume_name)-1; i >=0 ; i--) 27221e1553eSJérôme Duval if (fss->volume_name[i] != ' ') 27321e1553eSJérôme Duval break; 27421e1553eSJérôme Duval 27521e1553eSJérôme Duval if (i < 0) 27621e1553eSJérôme Duval strcpy(fss->volume_name, "UNKNOWN"); 27721e1553eSJérôme Duval else 27821e1553eSJérôme Duval fss->volume_name[i + 1] = 0; 27921e1553eSJérôme Duval 28021e1553eSJérôme Duval // File system name 28121e1553eSJérôme Duval strcpy(fss->fsh_name, "iso9660"); 28221e1553eSJérôme Duval 2835b4cb109SJérôme Duval TRACE(("fs_read_fs_stat - EXIT\n")); 28421e1553eSJérôme Duval return 0; 28521e1553eSJérôme Duval } 28621e1553eSJérôme Duval 2873b723f79SJérôme Duval 2883b723f79SJérôme Duval static status_t 2893b723f79SJérôme Duval fs_get_vnode_name(void *ns, void *_node, char *buffer, size_t bufferSize) 2903b723f79SJérôme Duval { 2913b723f79SJérôme Duval vnode *node = (vnode*)_node; 2923b723f79SJérôme Duval 2933b723f79SJérôme Duval strlcpy(buffer, node->fileIDString, bufferSize); 2943b723f79SJérôme Duval return B_OK; 2953b723f79SJérôme Duval } 2963b723f79SJérôme Duval 2973b723f79SJérôme Duval 29821e1553eSJérôme Duval /* fs_walk - the walk function just "walks" through a directory looking for 29921e1553eSJérôme Duval the specified file. When you find it, call get_vnode on its vnid to init 30021e1553eSJérôme Duval it for the kernel. 30121e1553eSJérôme Duval */ 30221e1553eSJérôme Duval static status_t 30321e1553eSJérôme Duval fs_walk(void *_ns, void *base, const char *file, vnode_id *_vnodeID, int *_type) 30421e1553eSJérôme Duval { 30521e1553eSJérôme Duval /* Starting at the base, find file in the subdir, and return path 30621e1553eSJérôme Duval string and vnode id of file. */ 30721e1553eSJérôme Duval nspace *ns = (nspace *)_ns; 30821e1553eSJérôme Duval vnode *baseNode = (vnode*)base; 30921e1553eSJérôme Duval uint32 dataLen = baseNode->dataLen[FS_DATA_FORMAT]; 31021e1553eSJérôme Duval vnode *newNode = NULL; 31121e1553eSJérôme Duval status_t result = ENOENT; 31221e1553eSJérôme Duval bool done = FALSE; 31321e1553eSJérôme Duval uint32 totalRead = 0; 31421e1553eSJérôme Duval off_t block = baseNode->startLBN[FS_DATA_FORMAT]; 31521e1553eSJérôme Duval 31621e1553eSJérôme Duval TRACE(("fs_walk - looking for %s in dir file of length %d\n", file, 31721e1553eSJérôme Duval baseNode->dataLen[FS_DATA_FORMAT])); 31821e1553eSJérôme Duval 31921e1553eSJérôme Duval if (strcmp(file, ".") == 0) { 32021e1553eSJérôme Duval // base directory 32121e1553eSJérôme Duval TRACE(("fs_walk - found \".\" file.\n")); 32221e1553eSJérôme Duval *_vnodeID = baseNode->id; 32321e1553eSJérôme Duval *_type = S_IFDIR; 32421e1553eSJérôme Duval if (get_vnode(ns->id, *_vnodeID, (void **)&newNode) != 0) 32521e1553eSJérôme Duval result = EINVAL; 32621e1553eSJérôme Duval else 32721e1553eSJérôme Duval result = B_NO_ERROR; 32821e1553eSJérôme Duval } else if (strcmp(file, "..") == 0) { 32921e1553eSJérôme Duval // parent directory 33021e1553eSJérôme Duval TRACE(("fs_walk - found \"..\" file.\n")); 33121e1553eSJérôme Duval *_vnodeID = baseNode->parID; 33221e1553eSJérôme Duval *_type = S_IFDIR; 33321e1553eSJérôme Duval if (get_vnode(ns->id, *_vnodeID, (void **)&newNode) != 0) 33421e1553eSJérôme Duval result = EINVAL; 33521e1553eSJérôme Duval else 33621e1553eSJérôme Duval result = B_NO_ERROR; 33721e1553eSJérôme Duval } else { 33821e1553eSJérôme Duval // look up file in the directory 33921e1553eSJérôme Duval char *blockData; 34021e1553eSJérôme Duval 34121e1553eSJérôme Duval while ((totalRead < dataLen) && !done) { 34221e1553eSJérôme Duval off_t cachedBlock = block; 34321e1553eSJérôme Duval 34421e1553eSJérôme Duval blockData = (char *)block_cache_get_etc(ns->fBlockCache, block, 0, ns->logicalBlkSize[FS_DATA_FORMAT]); 34521e1553eSJérôme Duval if (blockData != NULL) { 34621e1553eSJérôme Duval int bytesRead = 0; 34721e1553eSJérôme Duval off_t blockBytesRead = 0; 34821e1553eSJérôme Duval vnode node; 34921e1553eSJérôme Duval int initResult; 35021e1553eSJérôme Duval 35121e1553eSJérôme Duval TRACE(("fs_walk - read buffer from disk at LBN %Ld into buffer 0x%x.\n", 35221e1553eSJérôme Duval block, blockData)); 35321e1553eSJérôme Duval 35421e1553eSJérôme Duval // Move to the next 2-block set if necessary 35521e1553eSJérôme Duval // Don't go over end of buffer, if dir record sits on boundary. 35621e1553eSJérôme Duval 35721e1553eSJérôme Duval node.fileIDString = NULL; 35821e1553eSJérôme Duval node.attr.slName = NULL; 35921e1553eSJérôme Duval 36021e1553eSJérôme Duval while (blockBytesRead < 2*ns->logicalBlkSize[FS_DATA_FORMAT] 36121e1553eSJérôme Duval && totalRead + blockBytesRead < dataLen 36221e1553eSJérôme Duval && blockData[0] != 0 36321e1553eSJérôme Duval && !done) 36421e1553eSJérôme Duval { 36521e1553eSJérôme Duval initResult = InitNode(&node, blockData, &bytesRead, ns->joliet_level); 36621e1553eSJérôme Duval TRACE(("fs_walk - InitNode returned %s, filename %s, %d bytes read\n", strerror(initResult), node.fileIDString, bytesRead)); 36721e1553eSJérôme Duval 36821e1553eSJérôme Duval if (initResult == B_NO_ERROR) { 36921e1553eSJérôme Duval if (strlen(node.fileIDString) == strlen(file) 37021e1553eSJérôme Duval && !strncmp(node.fileIDString, file, strlen(file))) 37121e1553eSJérôme Duval { 37221e1553eSJérôme Duval TRACE(("fs_walk - success, found vnode at block %Ld, pos %Ld\n", block, blockBytesRead)); 37321e1553eSJérôme Duval *_vnodeID = (block << 30) + (blockBytesRead & 0xFFFFFFFF); 37421e1553eSJérôme Duval TRACE(("fs_walk - New vnode id is %Ld\n", *_vnodeID)); 37521e1553eSJérôme Duval 37621e1553eSJérôme Duval if (get_vnode(ns->id, *_vnodeID, (void **)&newNode) != 0) 37721e1553eSJérôme Duval result = EINVAL; 37821e1553eSJérôme Duval else { 37921e1553eSJérôme Duval newNode->parID = baseNode->id; 38021e1553eSJérôme Duval done = TRUE; 38121e1553eSJérôme Duval result = B_NO_ERROR; 38221e1553eSJérôme Duval } 38321e1553eSJérôme Duval } else { 38421e1553eSJérôme Duval if (node.fileIDString != NULL) { 38521e1553eSJérôme Duval free(node.fileIDString); 38621e1553eSJérôme Duval node.fileIDString = NULL; 38721e1553eSJérôme Duval } 38821e1553eSJérôme Duval if (node.attr.slName != NULL) { 38921e1553eSJérôme Duval free(node.attr.slName); 39021e1553eSJérôme Duval node.attr.slName = NULL; 39121e1553eSJérôme Duval } 39221e1553eSJérôme Duval } 39321e1553eSJérôme Duval } else { 39421e1553eSJérôme Duval result = initResult; 39521e1553eSJérôme Duval if (bytesRead == 0) 39621e1553eSJérôme Duval done = TRUE; 39721e1553eSJérôme Duval } 39821e1553eSJérôme Duval blockData += bytesRead; 39921e1553eSJérôme Duval blockBytesRead += bytesRead; 40021e1553eSJérôme Duval 40121e1553eSJérôme Duval TRACE(("fs_walk - Adding %d bytes to blockBytes read (total %Ld/%Ld).\n", 40221e1553eSJérôme Duval bytesRead, blockBytesRead, baseNode->dataLen[FS_DATA_FORMAT])); 40321e1553eSJérôme Duval } 40421e1553eSJérôme Duval totalRead += ns->logicalBlkSize[FS_DATA_FORMAT]; 40521e1553eSJérôme Duval block++; 40621e1553eSJérôme Duval 40721e1553eSJérôme Duval TRACE(("fs_walk - moving to next block %Ld, total read %Ld\n", block, totalRead)); 40821e1553eSJérôme Duval block_cache_put(ns->fBlockCache, cachedBlock); 40921e1553eSJérôme Duval 41021e1553eSJérôme Duval } else 41121e1553eSJérôme Duval done = TRUE; 41221e1553eSJérôme Duval } 41321e1553eSJérôme Duval 4143b723f79SJérôme Duval if (newNode) 41521e1553eSJérôme Duval *_type = newNode->attr.stat[FS_DATA_FORMAT].st_mode; 41621e1553eSJérôme Duval 41721e1553eSJérôme Duval } 41821e1553eSJérôme Duval TRACE(("fs_walk - EXIT, result is %s, vnid is %Lu\n", strerror(result), *_vnodeID)); 41921e1553eSJérôme Duval return result; 42021e1553eSJérôme Duval } 42121e1553eSJérôme Duval 42221e1553eSJérôme Duval 42321e1553eSJérôme Duval static status_t 42421e1553eSJérôme Duval fs_read_vnode(void *_ns, vnode_id vnid, void **node, bool reenter) 42521e1553eSJérôme Duval { 42621e1553eSJérôme Duval uint32 block, pos; 42721e1553eSJérôme Duval nspace *ns = (nspace*)_ns; 42821e1553eSJérôme Duval status_t result = B_NO_ERROR; 42921e1553eSJérôme Duval vnode *newNode = (vnode*)calloc(sizeof(vnode), 1); 43021e1553eSJérôme Duval 43121e1553eSJérôme Duval (void)reenter; 43221e1553eSJérôme Duval 43321e1553eSJérôme Duval pos = (vnid & 0x3FFFFFFF); 43421e1553eSJérôme Duval block = (vnid >> 30); 43521e1553eSJérôme Duval 43621e1553eSJérôme Duval TRACE(("fs_read_vnode - ENTER, block = %ld, pos = %ld, raw = %Lu node 0x%x\n", 43721e1553eSJérôme Duval block, pos, vnid, newNode)); 43821e1553eSJérôme Duval 43921e1553eSJérôme Duval if (newNode != NULL) { 44021e1553eSJérôme Duval if (vnid == ISO_ROOTNODE_ID) { 44121e1553eSJérôme Duval TRACE(("fs_read_vnode - root node requested.\n")); 44221e1553eSJérôme Duval memcpy(newNode, &(ns->rootDirRec), sizeof(vnode)); 44321e1553eSJérôme Duval *node = (void*)newNode; 44421e1553eSJérôme Duval } else { 44521e1553eSJérôme Duval char *blockData = (char *)block_cache_get_etc(ns->fBlockCache, block, 0, ns->logicalBlkSize[FS_DATA_FORMAT]); 44621e1553eSJérôme Duval 44721e1553eSJérôme Duval if (pos > ns->logicalBlkSize[FS_DATA_FORMAT]) { 44821e1553eSJérôme Duval if (blockData != NULL) 44921e1553eSJérôme Duval block_cache_put(ns->fBlockCache, block); 45021e1553eSJérôme Duval 45121e1553eSJérôme Duval result = EINVAL; 45221e1553eSJérôme Duval } else if (blockData != NULL) { 45321e1553eSJérôme Duval result = InitNode(newNode, blockData + pos, NULL, ns->joliet_level); 45421e1553eSJérôme Duval block_cache_put(ns->fBlockCache, block); 45521e1553eSJérôme Duval newNode->id = vnid; 45621e1553eSJérôme Duval 45721e1553eSJérôme Duval TRACE(("fs_read_vnode - init result is %s\n", strerror(result))); 45821e1553eSJérôme Duval *node = (void *)newNode; 45921e1553eSJérôme Duval TRACE(("fs_read_vnode - new file %s, size %ld\n", newNode->fileIDString, newNode->dataLen[FS_DATA_FORMAT])); 46021e1553eSJérôme Duval } 46121e1553eSJérôme Duval } 46221e1553eSJérôme Duval } else 46321e1553eSJérôme Duval result = ENOMEM; 46421e1553eSJérôme Duval 4655b4cb109SJérôme Duval if (result == B_OK && !(newNode->flags & ISO_ISDIR)) { 4665b4cb109SJérôme Duval newNode->cache = file_cache_create(ns->id, vnid, newNode->dataLen[FS_DATA_FORMAT], ns->fdOfSession); 4675b4cb109SJérôme Duval } 4685b4cb109SJérôme Duval 46921e1553eSJérôme Duval TRACE(("fs_read_vnode - EXIT, result is %s\n", strerror(result))); 47021e1553eSJérôme Duval return result; 47121e1553eSJérôme Duval } 47221e1553eSJérôme Duval 47321e1553eSJérôme Duval 47421e1553eSJérôme Duval static status_t 47521e1553eSJérôme Duval fs_release_vnode(void *ns, void *_node, bool reenter) 47621e1553eSJérôme Duval { 47721e1553eSJérôme Duval status_t result = B_NO_ERROR; 47821e1553eSJérôme Duval vnode *node = (vnode*)_node; 47921e1553eSJérôme Duval 48021e1553eSJérôme Duval (void)ns; 48121e1553eSJérôme Duval (void)reenter; 48221e1553eSJérôme Duval 4835b4cb109SJérôme Duval TRACE(("fs_release_vnode - ENTER (0x%x)\n", node)); 48421e1553eSJérôme Duval 48521e1553eSJérôme Duval if (node != NULL) { 48621e1553eSJérôme Duval if (node->id != ISO_ROOTNODE_ID) { 48721e1553eSJérôme Duval if (node->fileIDString != NULL) 48821e1553eSJérôme Duval free (node->fileIDString); 48921e1553eSJérôme Duval if (node->attr.slName != NULL) 49021e1553eSJérôme Duval free (node->attr.slName); 4915b4cb109SJérôme Duval if (node->cache != NULL) 4925b4cb109SJérôme Duval file_cache_delete(node->cache); 49321e1553eSJérôme Duval 49421e1553eSJérôme Duval free(node); 49521e1553eSJérôme Duval } 49621e1553eSJérôme Duval } 49721e1553eSJérôme Duval 4985b4cb109SJérôme Duval TRACE(("fs_release_vnode - EXIT\n")); 49921e1553eSJérôme Duval return result; 50021e1553eSJérôme Duval } 50121e1553eSJérôme Duval 50221e1553eSJérôme Duval 50321e1553eSJérôme Duval static status_t 5045b4cb109SJérôme Duval fs_get_file_map(fs_volume _fs, fs_vnode _node, off_t pos, size_t reqLen, 5055b4cb109SJérôme Duval struct file_io_vec *vecs, size_t *_count) 5065b4cb109SJérôme Duval { 5075b4cb109SJérôme Duval nspace *ns = (nspace *)_fs; // global stuff 5085b4cb109SJérôme Duval vnode *node = (vnode *)_node; // The read file vnode. 5095b4cb109SJérôme Duval uint16 blockSize = ns->logicalBlkSize[FS_DATA_FORMAT]; 5105b4cb109SJérôme Duval uint32 startBlock = node->startLBN[FS_DATA_FORMAT] + (pos / blockSize); 5115b4cb109SJérôme Duval off_t blockPos = pos % blockSize; 5125b4cb109SJérôme Duval off_t numBlocks = 0; 5135b4cb109SJérôme Duval uint32 dataLen = node->dataLen[FS_DATA_FORMAT]; 5145b4cb109SJérôme Duval size_t endLen = 0; 5155b4cb109SJérôme Duval size_t startLen = 0; 5165b4cb109SJérôme Duval size_t index = 0, max = *_count; 5175b4cb109SJérôme Duval 5185b4cb109SJérôme Duval TRACE(("fs_get_file_map - ENTER (0x%x)\n", node)); 5195b4cb109SJérôme Duval 5205b4cb109SJérôme Duval // Allow an open to work on a dir, but no reads 5215b4cb109SJérôme Duval if (node->flags & ISO_ISDIR) 5225b4cb109SJérôme Duval return EISDIR; 5235b4cb109SJérôme Duval 5245b4cb109SJérôme Duval if (pos < 0) 5255b4cb109SJérôme Duval pos = 0; 5265b4cb109SJérôme Duval *_count = 0; 5275b4cb109SJérôme Duval 5285b4cb109SJérôme Duval // If passed-in requested length is bigger than file size, change it to 5295b4cb109SJérôme Duval // file size. 5305b4cb109SJérôme Duval if (reqLen + pos > dataLen) 5315b4cb109SJérôme Duval reqLen = dataLen - pos; 5325b4cb109SJérôme Duval 5335b4cb109SJérôme Duval // Compute the length of the partial start-block read, if any. 5345b4cb109SJérôme Duval if (reqLen + blockPos <= blockSize) 5355b4cb109SJérôme Duval startLen = reqLen; 5365b4cb109SJérôme Duval else if (blockPos > 0) 5375b4cb109SJérôme Duval startLen = blockSize - blockPos; 5385b4cb109SJérôme Duval 5395b4cb109SJérôme Duval if (blockPos == 0 && reqLen >= blockSize) { 5405b4cb109SJérôme Duval TRACE(("Setting startLen to 0\n")); 5415b4cb109SJérôme Duval startLen = 0; 5425b4cb109SJérôme Duval } 5435b4cb109SJérôme Duval 5445b4cb109SJérôme Duval // Compute the length of the partial end-block read, if any. 5455b4cb109SJérôme Duval if (reqLen + blockPos > blockSize) 5465b4cb109SJérôme Duval endLen = (reqLen + blockPos) % blockSize; 5475b4cb109SJérôme Duval 5485b4cb109SJérôme Duval // Compute the number of middle blocks to read. 5495b4cb109SJérôme Duval numBlocks = ((reqLen - endLen - startLen) / blockSize); 5505b4cb109SJérôme Duval 5515b4cb109SJérôme Duval if (pos >= dataLen) { 5525b4cb109SJérôme Duval // If pos >= file length, return 5535b4cb109SJérôme Duval return B_OK; 5545b4cb109SJérôme Duval } 5555b4cb109SJérôme Duval 5565b4cb109SJérôme Duval // Read in the first, potentially partial, block. 5575b4cb109SJérôme Duval if (startLen > 0) { 5585b4cb109SJérôme Duval vecs[index].offset = startBlock * blockSize + blockPos; 5595b4cb109SJérôme Duval vecs[index].length = startLen; 5605b4cb109SJérôme Duval startBlock++; 5615b4cb109SJérôme Duval index++; 5625b4cb109SJérôme Duval if (index >= max) { 5635b4cb109SJérôme Duval // we're out of file_io_vecs; let's bail out 5645b4cb109SJérôme Duval *_count = index; 5655b4cb109SJérôme Duval return B_BUFFER_OVERFLOW; 5665b4cb109SJérôme Duval } 5675b4cb109SJérôme Duval } 5685b4cb109SJérôme Duval 5695b4cb109SJérôme Duval // Read in the middle blocks. 5705b4cb109SJérôme Duval if (numBlocks > 0) { 5715b4cb109SJérôme Duval for (int32 i=startBlock; i<startBlock+numBlocks; i++) { 5725b4cb109SJérôme Duval vecs[index].offset = i * blockSize; 5735b4cb109SJérôme Duval vecs[index].length = blockSize; 5745b4cb109SJérôme Duval index++; 5755b4cb109SJérôme Duval if (index >= max) { 5765b4cb109SJérôme Duval // we're out of file_io_vecs; let's bail out 5775b4cb109SJérôme Duval *_count = index; 5785b4cb109SJérôme Duval return B_BUFFER_OVERFLOW; 5795b4cb109SJérôme Duval } 5805b4cb109SJérôme Duval } 5815b4cb109SJérôme Duval } 5825b4cb109SJérôme Duval 5835b4cb109SJérôme Duval // Read in the last partial block. 5845b4cb109SJérôme Duval if (endLen > 0) { 5855b4cb109SJérôme Duval off_t endBlock = startBlock + numBlocks; 5865b4cb109SJérôme Duval vecs[index].offset = endBlock * blockSize; 5875b4cb109SJérôme Duval vecs[index].length = endLen; 5885b4cb109SJérôme Duval index++; 5895b4cb109SJérôme Duval } 5905b4cb109SJérôme Duval 5915b4cb109SJérôme Duval *_count = index; 5925b4cb109SJérôme Duval 5935b4cb109SJérôme Duval TRACE(("fs_get_file_map - EXIT\n")); 5945b4cb109SJérôme Duval return B_OK; 5955b4cb109SJérôme Duval } 5965b4cb109SJérôme Duval 5975b4cb109SJérôme Duval 5985b4cb109SJérôme Duval static status_t 59921e1553eSJérôme Duval fs_read_stat(void *_ns, void *_node, struct stat *st) 60021e1553eSJérôme Duval { 60121e1553eSJérôme Duval nspace *ns = (nspace*)_ns; 60221e1553eSJérôme Duval vnode *node = (vnode*)_node; 6033b723f79SJérôme Duval status_t result = B_NO_ERROR; 60421e1553eSJérôme Duval time_t time; 60521e1553eSJérôme Duval 6063b723f79SJérôme Duval TRACE(("fs_read_stat - ENTER\n")); 60721e1553eSJérôme Duval 60821e1553eSJérôme Duval st->st_dev = ns->id; 60921e1553eSJérôme Duval st->st_ino = node->id; 61021e1553eSJérôme Duval st->st_nlink = node->attr.stat[FS_DATA_FORMAT].st_nlink; 61121e1553eSJérôme Duval st->st_uid = node->attr.stat[FS_DATA_FORMAT].st_uid; 61221e1553eSJérôme Duval st->st_gid = node->attr.stat[FS_DATA_FORMAT].st_gid; 61321e1553eSJérôme Duval st->st_blksize = 65536; 61421e1553eSJérôme Duval st->st_mode = node->attr.stat[FS_DATA_FORMAT].st_mode; 61521e1553eSJérôme Duval 61621e1553eSJérôme Duval // Same for file/dir in ISO9660 61721e1553eSJérôme Duval st->st_size = node->dataLen[FS_DATA_FORMAT]; 61821e1553eSJérôme Duval if (ConvertRecDate(&(node->recordDate), &time) == B_NO_ERROR) 61921e1553eSJérôme Duval st->st_ctime = st->st_mtime = st->st_atime = time; 62021e1553eSJérôme Duval 6213b723f79SJérôme Duval TRACE(("fs_read_stat - EXIT, result is %s\n", strerror(result))); 62221e1553eSJérôme Duval 62321e1553eSJérôme Duval return result; 62421e1553eSJérôme Duval } 62521e1553eSJérôme Duval 62621e1553eSJérôme Duval 62721e1553eSJérôme Duval static status_t 62821e1553eSJérôme Duval fs_open(void *_ns, void *_node, int omode, void **cookie) 62921e1553eSJérôme Duval { 63021e1553eSJérôme Duval status_t result = B_NO_ERROR; 63121e1553eSJérôme Duval 63221e1553eSJérôme Duval (void)_ns; 63321e1553eSJérôme Duval (void)cookie; 63421e1553eSJérôme Duval 63521e1553eSJérôme Duval // Do not allow any of the write-like open modes to get by 63621e1553eSJérôme Duval if ((omode == O_WRONLY) || (omode == O_RDWR)) 63721e1553eSJérôme Duval result = EROFS; 63821e1553eSJérôme Duval else if((omode & O_TRUNC) || (omode & O_CREAT)) 63921e1553eSJérôme Duval result = EROFS; 64021e1553eSJérôme Duval 64121e1553eSJérôme Duval return result; 64221e1553eSJérôme Duval } 64321e1553eSJérôme Duval 64421e1553eSJérôme Duval 64521e1553eSJérôme Duval static status_t 64621e1553eSJérôme Duval fs_read(void *_ns, void *_node, void *cookie, off_t pos, void *buf, size_t *len) 64721e1553eSJérôme Duval { 6485b4cb109SJérôme Duval #if 0 64921e1553eSJérôme Duval nspace *ns = (nspace *)_ns; // global stuff 65021e1553eSJérôme Duval vnode *node = (vnode *)_node; // The read file vnode. 65121e1553eSJérôme Duval uint16 blockSize = ns->logicalBlkSize[FS_DATA_FORMAT]; 65221e1553eSJérôme Duval uint32 startBlock = node->startLBN[FS_DATA_FORMAT] + (pos / blockSize); 65321e1553eSJérôme Duval off_t blockPos = pos % blockSize; 65421e1553eSJérôme Duval off_t numBlocks = 0; 65521e1553eSJérôme Duval uint32 dataLen = node->dataLen[FS_DATA_FORMAT]; 65621e1553eSJérôme Duval status_t result = B_NO_ERROR; 65721e1553eSJérôme Duval size_t endLen = 0; 65821e1553eSJérôme Duval size_t reqLen = *len; 65921e1553eSJérôme Duval size_t startLen = 0; 66021e1553eSJérôme Duval 66121e1553eSJérôme Duval (void)cookie; 66221e1553eSJérôme Duval 66321e1553eSJérôme Duval // Allow an open to work on a dir, but no reads 66421e1553eSJérôme Duval if (node->flags & ISO_ISDIR) 66521e1553eSJérôme Duval return EISDIR; 66621e1553eSJérôme Duval 66721e1553eSJérôme Duval if (pos < 0) 66821e1553eSJérôme Duval pos = 0; 66921e1553eSJérôme Duval *len = 0; 67021e1553eSJérôme Duval 67121e1553eSJérôme Duval // If passed-in requested length is bigger than file size, change it to 67221e1553eSJérôme Duval // file size. 67321e1553eSJérôme Duval if (reqLen + pos > dataLen) 67421e1553eSJérôme Duval reqLen = dataLen - pos; 67521e1553eSJérôme Duval 67621e1553eSJérôme Duval // Compute the length of the partial start-block read, if any. 67721e1553eSJérôme Duval 67821e1553eSJérôme Duval if (reqLen + blockPos <= blockSize) 67921e1553eSJérôme Duval startLen = reqLen; 68021e1553eSJérôme Duval else if (blockPos > 0) 68121e1553eSJérôme Duval startLen = blockSize - blockPos; 68221e1553eSJérôme Duval 68321e1553eSJérôme Duval if (blockPos == 0 && reqLen >= blockSize) { 68421e1553eSJérôme Duval TRACE(("Setting startLen to 0, even block read\n")); 68521e1553eSJérôme Duval startLen = 0; 68621e1553eSJérôme Duval } 68721e1553eSJérôme Duval 68821e1553eSJérôme Duval // Compute the length of the partial end-block read, if any. 68921e1553eSJérôme Duval if (reqLen + blockPos > blockSize) 69021e1553eSJérôme Duval endLen = (reqLen + blockPos) % blockSize; 69121e1553eSJérôme Duval 69221e1553eSJérôme Duval // Compute the number of middle blocks to read. 69321e1553eSJérôme Duval numBlocks = ((reqLen - endLen - startLen) / blockSize); 69421e1553eSJérôme Duval 69521e1553eSJérôme Duval //dprintf("fs_read - ENTER, pos is %Ld, len is %lu\n", pos, reqLen); 69621e1553eSJérôme Duval //dprintf("fs_read - filename is %s\n", node->fileIDString); 69721e1553eSJérôme Duval //dprintf("fs_read - total file length is %lu\n", dataLen); 69821e1553eSJérôme Duval //dprintf("fs_read - start block of file is %lu\n", node->startLBN[FS_DATA_FORMAT]); 69921e1553eSJérôme Duval //dprintf("fs_read - block pos is %Lu\n", blockPos); 70021e1553eSJérôme Duval //dprintf("fs_read - read block will be %lu\n", startBlock); 70121e1553eSJérôme Duval //dprintf("fs_read - startLen is %lu\n", startLen); 70221e1553eSJérôme Duval //dprintf("fs_read - endLen is %lu\n", endLen); 70321e1553eSJérôme Duval //dprintf("fs_read - num blocks to read is %Ld\n", numBlocks); 70421e1553eSJérôme Duval 70521e1553eSJérôme Duval if (pos >= dataLen) { 70621e1553eSJérôme Duval // If pos >= file length, return length of 0. 70721e1553eSJérôme Duval *len = 0; 70821e1553eSJérôme Duval return B_OK; 70921e1553eSJérôme Duval } 71021e1553eSJérôme Duval 71121e1553eSJérôme Duval // Read in the first, potentially partial, block. 71221e1553eSJérôme Duval if (startLen > 0) { 71321e1553eSJérôme Duval off_t cachedBlock = startBlock; 71421e1553eSJérôme Duval char *blockData = (char *)block_cache_get_etc(ns->fBlockCache, startBlock, 0, blockSize); 71521e1553eSJérôme Duval if (blockData != NULL) { 71621e1553eSJérôme Duval //dprintf("fs_read - copying first block, len is %d.\n", startLen); 71721e1553eSJérôme Duval memcpy(buf, blockData+blockPos, startLen); 71821e1553eSJérôme Duval *len += startLen; 71921e1553eSJérôme Duval block_cache_put(ns->fBlockCache, cachedBlock); 72021e1553eSJérôme Duval startBlock++; 7213b723f79SJérôme Duval } else 7223b723f79SJérôme Duval result = EIO; 72321e1553eSJérôme Duval } 72421e1553eSJérôme Duval 72521e1553eSJérôme Duval // Read in the middle blocks. 72621e1553eSJérôme Duval if (numBlocks > 0 && result == B_NO_ERROR) { 72721e1553eSJérôme Duval TRACE(("fs_read - getting middle blocks\n")); 7283b723f79SJérôme Duval char *endBuf = ((char *)buf) + startLen; 72921e1553eSJérôme Duval for (int32 i=startBlock; i<startBlock+numBlocks; i++) { 73021e1553eSJérôme Duval char *blockData = (char *)block_cache_get_etc(ns->fBlockCache, i, 0, blockSize); 7313b723f79SJérôme Duval memcpy(endBuf, blockData, blockSize); 73221e1553eSJérôme Duval *len += blockSize; 7333b723f79SJérôme Duval endBuf += blockSize; 73421e1553eSJérôme Duval block_cache_put(ns->fBlockCache, i); 73521e1553eSJérôme Duval } 73621e1553eSJérôme Duval } 73721e1553eSJérôme Duval 73821e1553eSJérôme Duval // Read in the last partial block. 73921e1553eSJérôme Duval if (result == B_NO_ERROR && endLen > 0) { 74021e1553eSJérôme Duval off_t endBlock = startBlock + numBlocks; 74121e1553eSJérôme Duval char *endBlockData = (char*)block_cache_get_etc(ns->fBlockCache, endBlock, 0, blockSize); 74221e1553eSJérôme Duval if (endBlockData != NULL) { 74321e1553eSJérôme Duval char *endBuf = ((char *)buf) + (reqLen - endLen); 74421e1553eSJérôme Duval 74521e1553eSJérôme Duval memcpy(endBuf, endBlockData, endLen); 74621e1553eSJérôme Duval block_cache_put(ns->fBlockCache, endBlock); 74721e1553eSJérôme Duval *len += endLen; 74821e1553eSJérôme Duval } else 74921e1553eSJérôme Duval result = EIO; 75021e1553eSJérôme Duval } 75121e1553eSJérôme Duval 75221e1553eSJérôme Duval TRACE(("fs_read - EXIT, result is %s\n", strerror(result))); 75321e1553eSJérôme Duval return result; 7545b4cb109SJérôme Duval #else 7555b4cb109SJérôme Duval vnode *node = (vnode *)_node; // The read file vnode. 7565b4cb109SJérôme Duval uint32 dataLen = node->dataLen[FS_DATA_FORMAT]; 7575b4cb109SJérôme Duval 7585b4cb109SJérôme Duval // set/check boundaries for pos/length 7595b4cb109SJérôme Duval if (pos < 0) { 7605b4cb109SJérôme Duval return B_BAD_VALUE; 7615b4cb109SJérôme Duval } 7625b4cb109SJérôme Duval if (pos >= dataLen) { 7635b4cb109SJérôme Duval // If pos >= file length, return length of 0. 7645b4cb109SJérôme Duval *len = 0; 7655b4cb109SJérôme Duval return B_OK; 7665b4cb109SJérôme Duval } 7675b4cb109SJérôme Duval return file_cache_read(node->cache, pos, buf, len); 7685b4cb109SJérôme Duval #endif 76921e1553eSJérôme Duval } 77021e1553eSJérôme Duval 77121e1553eSJérôme Duval 77221e1553eSJérôme Duval static status_t 77321e1553eSJérôme Duval fs_close(void *ns, void *node, void *cookie) 77421e1553eSJérôme Duval { 77521e1553eSJérôme Duval (void)ns; 77621e1553eSJérôme Duval (void)node; 77721e1553eSJérôme Duval (void)cookie; 77821e1553eSJérôme Duval 77921e1553eSJérôme Duval //dprintf("fs_close - ENTER\n"); 78021e1553eSJérôme Duval //dprintf("fs_close - EXIT\n"); 78121e1553eSJérôme Duval return B_OK; 78221e1553eSJérôme Duval } 78321e1553eSJérôme Duval 78421e1553eSJérôme Duval static status_t 78521e1553eSJérôme Duval fs_free_cookie(void *ns, void *node, void *cookie) 78621e1553eSJérôme Duval { 78721e1553eSJérôme Duval (void)ns; 78821e1553eSJérôme Duval (void)node; 78921e1553eSJérôme Duval (void)cookie; 79021e1553eSJérôme Duval 79121e1553eSJérôme Duval // We don't allocate file cookies, so we do nothing here. 79221e1553eSJérôme Duval //dprintf("fs_free_cookie - ENTER\n"); 79321e1553eSJérôme Duval //if (cookie != NULL) free (cookie); 79421e1553eSJérôme Duval //dprintf("fs_free_cookie - EXIT\n"); 79521e1553eSJérôme Duval return B_OK; 79621e1553eSJérôme Duval } 79721e1553eSJérôme Duval 79821e1553eSJérôme Duval // fs_access - checks permissions for access. 79921e1553eSJérôme Duval static status_t 80021e1553eSJérôme Duval fs_access(void *ns, void *node, int mode) 80121e1553eSJérôme Duval { 80221e1553eSJérôme Duval (void)ns; 80321e1553eSJérôme Duval (void)node; 80421e1553eSJérôme Duval (void)mode; 80521e1553eSJérôme Duval 80621e1553eSJérôme Duval // ns - global, fs-specific struct for device 80721e1553eSJérôme Duval // node - node to check permissions for 80821e1553eSJérôme Duval // mode - requested permissions on node. 80921e1553eSJérôme Duval //dprintf("fs_access - ENTER\n"); 81021e1553eSJérôme Duval //dprintf("fs_access - EXIT\n"); 81121e1553eSJérôme Duval return B_OK; 81221e1553eSJérôme Duval } 81321e1553eSJérôme Duval 81421e1553eSJérôme Duval static status_t 81521e1553eSJérôme Duval fs_read_link(void *_ns, void *_node, char *buffer, size_t *_bufferSize) 81621e1553eSJérôme Duval { 81721e1553eSJérôme Duval vnode *node = (vnode *)_node; 81821e1553eSJérôme Duval status_t result = EINVAL; 81921e1553eSJérôme Duval 82021e1553eSJérôme Duval (void)_ns; 82121e1553eSJérôme Duval 82221e1553eSJérôme Duval if (S_ISLNK(node->attr.stat[FS_DATA_FORMAT].st_mode)) { 82321e1553eSJérôme Duval size_t length = strlen(node->attr.slName); 82421e1553eSJérôme Duval if (length > *_bufferSize) 8253b723f79SJérôme Duval memcpy(buffer, node->attr.slName, *_bufferSize); 8263b723f79SJérôme Duval else { 82721e1553eSJérôme Duval memcpy(buffer, node->attr.slName, length); 8283b723f79SJérôme Duval *_bufferSize = length; 8293b723f79SJérôme Duval } 83021e1553eSJérôme Duval 83121e1553eSJérôme Duval result = B_NO_ERROR; 83221e1553eSJérôme Duval } 83321e1553eSJérôme Duval 83421e1553eSJérôme Duval return result; 83521e1553eSJérôme Duval } 83621e1553eSJérôme Duval 83721e1553eSJérôme Duval 83821e1553eSJérôme Duval static status_t 83921e1553eSJérôme Duval fs_open_dir(void *_ns, void *_node, void **cookie) 84021e1553eSJérôme Duval { 84121e1553eSJérôme Duval vnode *node = (vnode *)_node; 84221e1553eSJérôme Duval status_t result = B_NO_ERROR; 84321e1553eSJérôme Duval dircookie *dirCookie = (dircookie *)malloc(sizeof(dircookie)); 84421e1553eSJérôme Duval 84521e1553eSJérôme Duval (void)_ns; 84621e1553eSJérôme Duval 8475b4cb109SJérôme Duval TRACE(("fs_open_dir - ENTER, node is 0x%x\n", _node)); 84821e1553eSJérôme Duval 84921e1553eSJérôme Duval if (!(node->flags & ISO_ISDIR)) 85021e1553eSJérôme Duval result = EMFILE; 85121e1553eSJérôme Duval 85221e1553eSJérôme Duval if (dirCookie != NULL) { 85321e1553eSJérôme Duval dirCookie->startBlock = node->startLBN[FS_DATA_FORMAT]; 85421e1553eSJérôme Duval dirCookie->block = node->startLBN[FS_DATA_FORMAT]; 85521e1553eSJérôme Duval dirCookie->totalSize = node->dataLen[FS_DATA_FORMAT]; 85621e1553eSJérôme Duval dirCookie->pos = 0; 85721e1553eSJérôme Duval dirCookie->id = node->id; 85821e1553eSJérôme Duval *cookie = (void *)dirCookie; 85921e1553eSJérôme Duval } else 86021e1553eSJérôme Duval result = ENOMEM; 86121e1553eSJérôme Duval 8625b4cb109SJérôme Duval TRACE(("fs_open_dir - EXIT\n")); 86321e1553eSJérôme Duval return result; 86421e1553eSJérôme Duval } 86521e1553eSJérôme Duval 86621e1553eSJérôme Duval 86721e1553eSJérôme Duval static status_t 86821e1553eSJérôme Duval fs_read_dir(void *_ns, void *_node, void *_cookie, struct dirent *buffer, 86921e1553eSJérôme Duval size_t bufferSize, uint32 *num) 87021e1553eSJérôme Duval { 87121e1553eSJérôme Duval status_t result = B_NO_ERROR; 87221e1553eSJérôme Duval nspace *ns = (nspace *)_ns; 87321e1553eSJérôme Duval dircookie *dirCookie = (dircookie *)_cookie; 87421e1553eSJérôme Duval 87521e1553eSJérôme Duval (void)_node; 87621e1553eSJérôme Duval 8775b4cb109SJérôme Duval TRACE(("fs_read_dir - ENTER\n")); 87821e1553eSJérôme Duval 87921e1553eSJérôme Duval result = ISOReadDirEnt(ns, dirCookie, buffer, bufferSize); 88021e1553eSJérôme Duval 88121e1553eSJérôme Duval // If we succeeded, return 1, the number of dirents we read. 88221e1553eSJérôme Duval if (result == B_NO_ERROR) 88321e1553eSJérôme Duval *num = 1; 88421e1553eSJérôme Duval else 88521e1553eSJérôme Duval *num = 0; 88621e1553eSJérôme Duval 88721e1553eSJérôme Duval // When you get to the end, don't return an error, just return 88821e1553eSJérôme Duval // a zero in *num. 88921e1553eSJérôme Duval 89021e1553eSJérôme Duval if (result == ENOENT) 89121e1553eSJérôme Duval result = B_NO_ERROR; 89221e1553eSJérôme Duval 8935b4cb109SJérôme Duval TRACE(("fs_read_dir - EXIT, result is %s\n", strerror(result))); 89421e1553eSJérôme Duval return result; 89521e1553eSJérôme Duval } 89621e1553eSJérôme Duval 89721e1553eSJérôme Duval 89821e1553eSJérôme Duval static status_t 89921e1553eSJérôme Duval fs_rewind_dir(void *ns, void *node, void* _cookie) 90021e1553eSJérôme Duval { 90121e1553eSJérôme Duval status_t result = EINVAL; 90221e1553eSJérôme Duval dircookie *cookie = (dircookie*)_cookie; 90321e1553eSJérôme Duval 90421e1553eSJérôme Duval (void)ns; 90521e1553eSJérôme Duval (void)node; 90621e1553eSJérôme Duval 9075b4cb109SJérôme Duval //dprintf("fs_rewind_dir - ENTER\n"); 90821e1553eSJérôme Duval if (cookie != NULL) { 90921e1553eSJérôme Duval cookie->block = cookie->startBlock; 91021e1553eSJérôme Duval cookie->pos = 0; 91121e1553eSJérôme Duval result = B_NO_ERROR; 91221e1553eSJérôme Duval } 9135b4cb109SJérôme Duval //dprintf("fs_rewind_dir - EXIT, result is %s\n", strerror(result)); 91421e1553eSJérôme Duval return result; 91521e1553eSJérôme Duval } 91621e1553eSJérôme Duval 91721e1553eSJérôme Duval 91821e1553eSJérôme Duval static status_t 91921e1553eSJérôme Duval fs_close_dir(void *ns, void *node, void *cookie) 92021e1553eSJérôme Duval { 92121e1553eSJérôme Duval (void)ns; 92221e1553eSJérôme Duval (void)node; 92321e1553eSJérôme Duval (void)cookie; 92421e1553eSJérôme Duval 92521e1553eSJérôme Duval // ns - global, fs-specific struct for device 92621e1553eSJérôme Duval // node - directory to close 92721e1553eSJérôme Duval // cookie - current cookie for directory. 9285b4cb109SJérôme Duval //dprintf("fs_close_dir - ENTER\n"); 9295b4cb109SJérôme Duval //dprintf("fs_close_dir - EXIT\n"); 93021e1553eSJérôme Duval return B_OK; 93121e1553eSJérôme Duval } 93221e1553eSJérôme Duval 93321e1553eSJérôme Duval 93421e1553eSJérôme Duval static status_t 93521e1553eSJérôme Duval fs_free_dir_cookie(void *ns, void *node, void *cookie) 93621e1553eSJérôme Duval { 93721e1553eSJérôme Duval (void)ns; 93821e1553eSJérôme Duval (void)node; 93921e1553eSJérôme Duval 94021e1553eSJérôme Duval // ns - global, fs-specific struct for device 94121e1553eSJérôme Duval // node - directory related to cookie 94221e1553eSJérôme Duval // cookie - current cookie for directory, to free. 9435b4cb109SJérôme Duval //dprintf("fs_free_dir_cookie - ENTER\n"); 94421e1553eSJérôme Duval if (cookie != NULL) 94521e1553eSJérôme Duval free(cookie); 94621e1553eSJérôme Duval 9475b4cb109SJérôme Duval //dprintf("fs_free_dir_cookie - EXIT\n"); 94821e1553eSJérôme Duval return B_OK; 94921e1553eSJérôme Duval } 95021e1553eSJérôme Duval 95121e1553eSJérôme Duval // #pragma mark - 95221e1553eSJérôme Duval 95321e1553eSJérôme Duval 95421e1553eSJérôme Duval static status_t 95521e1553eSJérôme Duval iso_std_ops(int32 op, ...) 95621e1553eSJérôme Duval { 95721e1553eSJérôme Duval switch (op) { 95821e1553eSJérôme Duval case B_MODULE_INIT: 95921e1553eSJérôme Duval return B_OK; 96021e1553eSJérôme Duval case B_MODULE_UNINIT: 96121e1553eSJérôme Duval return B_OK; 96221e1553eSJérôme Duval default: 96321e1553eSJérôme Duval return B_ERROR; 96421e1553eSJérôme Duval } 96521e1553eSJérôme Duval } 96621e1553eSJérôme Duval 96721e1553eSJérôme Duval 96821e1553eSJérôme Duval static file_system_module_info sISO660FileSystem = { 96921e1553eSJérôme Duval { 97021e1553eSJérôme Duval "file_systems/iso9660" B_CURRENT_FS_API_VERSION, 97121e1553eSJérôme Duval 0, 97221e1553eSJérôme Duval iso_std_ops, 97321e1553eSJérôme Duval }, 97421e1553eSJérôme Duval 97521e1553eSJérôme Duval "ISO9660 File System", 97621e1553eSJérôme Duval 97721e1553eSJérôme Duval // scanning 97821e1553eSJérôme Duval fs_identify_partition, 97921e1553eSJérôme Duval fs_scan_partition, 98021e1553eSJérôme Duval fs_free_identify_partition_cookie, 98121e1553eSJérôme Duval NULL, // free_partition_content_cookie() 98221e1553eSJérôme Duval 98321e1553eSJérôme Duval &fs_mount, 98421e1553eSJérôme Duval &fs_unmount, 98521e1553eSJérôme Duval &fs_read_fs_stat, 98621e1553eSJérôme Duval NULL, 98721e1553eSJérôme Duval NULL, 98821e1553eSJérôme Duval 98921e1553eSJérôme Duval /* vnode operations */ 99021e1553eSJérôme Duval &fs_walk, 9913b723f79SJérôme Duval &fs_get_vnode_name, 99221e1553eSJérôme Duval &fs_read_vnode, 99321e1553eSJérôme Duval &fs_release_vnode, 99421e1553eSJérôme Duval NULL, // &fs_remove_vnode() 99521e1553eSJérôme Duval 99621e1553eSJérôme Duval /* VM file access */ 99721e1553eSJérôme Duval NULL, // &fs_can_page 99821e1553eSJérôme Duval NULL, // &fs_read_pages 99921e1553eSJérôme Duval NULL, // &fs_write_pages 100021e1553eSJérôme Duval 10015b4cb109SJérôme Duval &fs_get_file_map, 100221e1553eSJérôme Duval 100321e1553eSJérôme Duval NULL, // &fs_ioctl 100421e1553eSJérôme Duval NULL, // &fs_set_flags 10053b723f79SJérôme Duval NULL, // &fs_select 10063b723f79SJérôme Duval NULL, // &fs_deselect 100721e1553eSJérôme Duval NULL, // &fs_fsync 100821e1553eSJérôme Duval 100921e1553eSJérôme Duval &fs_read_link, 101021e1553eSJérôme Duval NULL, // write link 101121e1553eSJérôme Duval NULL, // &fs_create_symlink, 101221e1553eSJérôme Duval 101321e1553eSJérôme Duval NULL, // &fs_link, 101421e1553eSJérôme Duval NULL, // &fs_unlink 101521e1553eSJérôme Duval NULL, // &fs_rename 101621e1553eSJérôme Duval 101721e1553eSJérôme Duval &fs_access, 101821e1553eSJérôme Duval &fs_read_stat, 101921e1553eSJérôme Duval NULL, // &fs_write_stat 102021e1553eSJérôme Duval 102121e1553eSJérôme Duval /* file operations */ 102221e1553eSJérôme Duval NULL, // &fs_create 102321e1553eSJérôme Duval &fs_open, 102421e1553eSJérôme Duval &fs_close, 102521e1553eSJérôme Duval &fs_free_cookie, 102621e1553eSJérôme Duval &fs_read, 102721e1553eSJérôme Duval NULL, // &fs_write 102821e1553eSJérôme Duval 102921e1553eSJérôme Duval /* directory operations */ 103021e1553eSJérôme Duval NULL, // &fs_create_dir 103121e1553eSJérôme Duval NULL, // &fs_remove_dir 103221e1553eSJérôme Duval &fs_open_dir, 103321e1553eSJérôme Duval &fs_close_dir, 103421e1553eSJérôme Duval &fs_free_dir_cookie, 103521e1553eSJérôme Duval &fs_read_dir, 103621e1553eSJérôme Duval &fs_rewind_dir, 103721e1553eSJérôme Duval 103821e1553eSJérôme Duval /* attribute directory operations */ 103921e1553eSJérôme Duval NULL, // &fs_open_attr_dir 104021e1553eSJérôme Duval NULL, // &fs_close_attr_dir 104121e1553eSJérôme Duval NULL, // &fs_free_attr_dir_cookie 104221e1553eSJérôme Duval NULL, // &fs_read_attr_dir 104321e1553eSJérôme Duval NULL, // &fs_rewind_attr_dir 104421e1553eSJérôme Duval 104521e1553eSJérôme Duval /* attribute operations */ 104621e1553eSJérôme Duval NULL, // &fs_create_attr 104721e1553eSJérôme Duval NULL, // &fs_open_attr 104821e1553eSJérôme Duval NULL, // &fs_close_attr 104921e1553eSJérôme Duval NULL, // &fs_free_attr_cookie 105021e1553eSJérôme Duval NULL, // &fs_read_attr 105121e1553eSJérôme Duval NULL, // &fs_write_attr 105221e1553eSJérôme Duval 105321e1553eSJérôme Duval NULL, // &fs_read_attr_stat 105421e1553eSJérôme Duval NULL, // &fs_write_attr_stat 105521e1553eSJérôme Duval NULL, // &fs_rename_attr 105621e1553eSJérôme Duval NULL, // &fs_remove_attr 105721e1553eSJérôme Duval 105821e1553eSJérôme Duval /* index directory & index operations */ 105921e1553eSJérôme Duval NULL, // &fs_open_index_dir 106021e1553eSJérôme Duval NULL, // &fs_close_index_dir 106121e1553eSJérôme Duval NULL, // &fs_free_index_dir_cookie 106221e1553eSJérôme Duval NULL, // &fs_read_index_dir 106321e1553eSJérôme Duval NULL, // &fs_rewind_index_dir 106421e1553eSJérôme Duval 106521e1553eSJérôme Duval NULL, // &fs_create_index 106621e1553eSJérôme Duval NULL, // &fs_remove_index 106721e1553eSJérôme Duval NULL, // &fs_stat_index 106821e1553eSJérôme Duval 106921e1553eSJérôme Duval /* query operations */ 107021e1553eSJérôme Duval NULL, // &fs_open_query 107121e1553eSJérôme Duval NULL, // &fs_close_query 107221e1553eSJérôme Duval NULL, // &fs_free_query_cookie 107321e1553eSJérôme Duval NULL, // &fs_read_query 107421e1553eSJérôme Duval NULL, // &fs_rewind_query 107521e1553eSJérôme Duval }; 107621e1553eSJérôme Duval 107721e1553eSJérôme Duval module_info *modules[] = { 107821e1553eSJérôme Duval (module_info *)&sISO660FileSystem, 107921e1553eSJérôme Duval NULL, 108021e1553eSJérôme Duval }; 108121e1553eSJérôme Duval 1082