xref: /haiku/src/add-ons/kernel/file_systems/iso9660/kernel_interface.cpp (revision 425ac1b60a56f4df7a0e88bd784545c0ec4fa01f)
121e1553eSJérôme Duval /*
2245aecdaSAxel Dörfler  * Copyright 1999, Be Incorporated.   All Rights Reserved.
3245aecdaSAxel Dörfler  * This file may be used under the terms of the Be Sample Code License.
4245aecdaSAxel Dörfler  *
5245aecdaSAxel Dörfler  * Copyright 2001, pinc Software.  All Rights Reserved.
6245aecdaSAxel Dörfler  *
7245aecdaSAxel Dörfler  * iso9960/multi-session, 1.0.0
821e1553eSJérôme Duval  */
921e1553eSJérôme Duval 
10245aecdaSAxel Dörfler 
11e1b7c1c7SKyle Ambroff-Kao #include <algorithm>
1221e1553eSJérôme Duval #include <ctype.h>
13f47bff08SAxel Dörfler 
14f47bff08SAxel Dörfler #ifndef FS_SHELL
1521e1553eSJérôme Duval #	include <dirent.h>
165b2c5d03SAxel Dörfler #	include <errno.h>
175b2c5d03SAxel Dörfler #	include <fcntl.h>
185b2c5d03SAxel Dörfler #	include <stdio.h>
195b2c5d03SAxel Dörfler #	include <stdlib.h>
205b2c5d03SAxel Dörfler #	include <string.h>
2121e1553eSJérôme Duval #	include <sys/stat.h>
2221e1553eSJérôme Duval #	include <time.h>
235b2c5d03SAxel Dörfler #	include <unistd.h>
2421e1553eSJérôme Duval 
2521e1553eSJérôme Duval #	include <KernelExport.h>
2621e1553eSJérôme Duval #	include <NodeMonitor.h>
2721e1553eSJérôme Duval #	include <fs_interface.h>
2821e1553eSJérôme Duval #	include <fs_cache.h>
2921e1553eSJérôme Duval 
3021e1553eSJérôme Duval #	include <fs_attr.h>
3121e1553eSJérôme Duval #	include <fs_info.h>
3221e1553eSJérôme Duval #	include <fs_index.h>
3321e1553eSJérôme Duval #	include <fs_query.h>
3421e1553eSJérôme Duval #	include <fs_volume.h>
3521e1553eSJérôme Duval 
3621e1553eSJérôme Duval #	include <util/kernel_cpp.h>
3738fa917cSAugustin Cavalier 
3838fa917cSAugustin Cavalier // TODO: temporary solution as long as there is no public I/O requests API
3938fa917cSAugustin Cavalier #	include <io_requests.h>
40f47bff08SAxel Dörfler #endif
4121e1553eSJérôme Duval 
42dc9a52b9SAxel Dörfler #include "iso9660.h"
435b2c5d03SAxel Dörfler #include "iso9660_identify.h"
445b2c5d03SAxel Dörfler 
455b2c5d03SAxel Dörfler 
465b2c5d03SAxel Dörfler //#define TRACE_ISO9660
475b2c5d03SAxel Dörfler #ifdef TRACE_ISO9660
4821e1553eSJérôme Duval #	define TRACE(x) dprintf x
4921e1553eSJérôme Duval #else
5021e1553eSJérôme Duval #	define TRACE(x) ;
5121e1553eSJérôme Duval #endif
5221e1553eSJérôme Duval 
5321e1553eSJérôme Duval 
5421e1553eSJérôme Duval struct identify_cookie {
5521e1553eSJérôme Duval 	iso9660_info info;
5621e1553eSJérôme Duval };
5721e1553eSJérôme Duval 
580eaadd30SMichael Lotz extern fs_volume_ops gISO9660VolumeOps;
590eaadd30SMichael Lotz extern fs_vnode_ops gISO9660VnodeOps;
600eaadd30SMichael Lotz 
6121e1553eSJérôme Duval 
6241b19806SAxel Dörfler //!	fs_io() callback hook
6341b19806SAxel Dörfler static status_t
iterative_io_get_vecs_hook(void * cookie,io_request * request,off_t offset,size_t size,struct file_io_vec * vecs,size_t * _count)6441b19806SAxel Dörfler iterative_io_get_vecs_hook(void* cookie, io_request* request, off_t offset,
6541b19806SAxel Dörfler 	size_t size, struct file_io_vec* vecs, size_t* _count)
6641b19806SAxel Dörfler {
6741b19806SAxel Dörfler 	iso9660_inode* node = (iso9660_inode*)cookie;
6841b19806SAxel Dörfler 
696ea60bcdSAxel Dörfler 	vecs->offset = offset + ((off_t)node->startLBN[FS_DATA_FORMAT]
706ea60bcdSAxel Dörfler 		* (off_t)node->volume->logicalBlkSize[FS_DATA_FORMAT]);
7141b19806SAxel Dörfler 	vecs->length = size;
7241b19806SAxel Dörfler 
7341b19806SAxel Dörfler 	*_count = 1;
7441b19806SAxel Dörfler 
7541b19806SAxel Dörfler 	return B_OK;
7641b19806SAxel Dörfler }
7741b19806SAxel Dörfler 
7841b19806SAxel Dörfler 
7941b19806SAxel Dörfler //!	fs_io() callback hook
8041b19806SAxel Dörfler static status_t
iterative_io_finished_hook(void * cookie,io_request * request,status_t status,bool partialTransfer,size_t bytesTransferred)8141b19806SAxel Dörfler iterative_io_finished_hook(void* cookie, io_request* request, status_t status,
8241b19806SAxel Dörfler 	bool partialTransfer, size_t bytesTransferred)
8341b19806SAxel Dörfler {
8441b19806SAxel Dörfler 	// nothing to do here...
8541b19806SAxel Dörfler 	return B_OK;
8641b19806SAxel Dörfler }
8741b19806SAxel Dörfler 
8841b19806SAxel Dörfler 
895b2c5d03SAxel Dörfler //	#pragma mark - Scanning
905b2c5d03SAxel Dörfler 
915b2c5d03SAxel Dörfler 
9221e1553eSJérôme Duval static float
fs_identify_partition(int fd,partition_data * partition,void ** _cookie)9321e1553eSJérôme Duval fs_identify_partition(int fd, partition_data* partition, void** _cookie)
9421e1553eSJérôme Duval {
955b2c5d03SAxel Dörfler 	iso9660_info* info = new iso9660_info;
9621e1553eSJérôme Duval 
975b2c5d03SAxel Dörfler 	status_t status = iso9660_fs_identify(fd, info);
985b2c5d03SAxel Dörfler 	if (status != B_OK) {
995b2c5d03SAxel Dörfler 		delete info;
1005b2c5d03SAxel Dörfler 		return -1;
1015b2c5d03SAxel Dörfler 	}
10221e1553eSJérôme Duval 
1035b2c5d03SAxel Dörfler 	*_cookie = info;
1045b2c5d03SAxel Dörfler 	return 0.6f;
10521e1553eSJérôme Duval }
10621e1553eSJérôme Duval 
10721e1553eSJérôme Duval 
10821e1553eSJérôme Duval static status_t
fs_scan_partition(int fd,partition_data * partition,void * _cookie)10921e1553eSJérôme Duval fs_scan_partition(int fd, partition_data* partition, void* _cookie)
11021e1553eSJérôme Duval {
1115b2c5d03SAxel Dörfler 	iso9660_info* info = (iso9660_info*)_cookie;
11221e1553eSJérôme Duval 
11321e1553eSJérôme Duval 	partition->status = B_PARTITION_VALID;
11421e1553eSJérôme Duval 	partition->flags |= B_PARTITION_FILE_SYSTEM | B_PARTITION_READ_ONLY ;
11521e1553eSJérôme Duval 	partition->block_size = ISO_PVD_SIZE;
1165b2c5d03SAxel Dörfler 	partition->content_size = ISO_PVD_SIZE * info->max_blocks;
1175b2c5d03SAxel Dörfler 	partition->content_name = strdup(info->PreferredName());
1185b2c5d03SAxel Dörfler 
11921e1553eSJérôme Duval 	if (partition->content_name == NULL)
12021e1553eSJérôme Duval 		return B_NO_MEMORY;
12121e1553eSJérôme Duval 
12221e1553eSJérôme Duval 	return B_OK;
12321e1553eSJérôme Duval }
12421e1553eSJérôme Duval 
12521e1553eSJérôme Duval 
12621e1553eSJérôme Duval static void
fs_free_identify_partition_cookie(partition_data * partition,void * _cookie)12721e1553eSJérôme Duval fs_free_identify_partition_cookie(partition_data* partition, void* _cookie)
12821e1553eSJérôme Duval {
1295b2c5d03SAxel Dörfler 	delete (iso9660_info*)_cookie;
13021e1553eSJérôme Duval }
13121e1553eSJérôme Duval 
13221e1553eSJérôme Duval 
133ff99132eSAxel Dörfler //	#pragma mark - FS hooks
134ff99132eSAxel Dörfler 
135ff99132eSAxel Dörfler 
13621e1553eSJérôme Duval static status_t
fs_mount(fs_volume * _volume,const char * device,uint32 flags,const char * args,ino_t * _rootID)1370eaadd30SMichael Lotz fs_mount(fs_volume* _volume, const char* device, uint32 flags,
1380eaadd30SMichael Lotz 	const char* args, ino_t* _rootID)
13921e1553eSJérôme Duval {
1405b2c5d03SAxel Dörfler 	bool allowJoliet = true;
141eb097431SAxel Dörfler 	iso9660_volume* volume;
14221e1553eSJérôme Duval 
14321e1553eSJérôme Duval 	// Check for a 'nojoliet' parm
14421e1553eSJérôme Duval 	// all we check for is the existance of 'nojoliet' in the parms.
14521e1553eSJérôme Duval 	if (args != NULL) {
14621e1553eSJérôme Duval 		uint32 i;
14721e1553eSJérôme Duval 		char* spot;
14821e1553eSJérôme Duval 		char* buf = strdup(args);
14921e1553eSJérôme Duval 
15021e1553eSJérôme Duval 		uint32 len = strlen(buf);
15121e1553eSJérôme Duval 		// lower case the parms data
15221e1553eSJérôme Duval 		for (i = 0; i < len + 1; i++)
15321e1553eSJérôme Duval 			buf[i] = tolower(buf[i]);
15421e1553eSJérôme Duval 
15521e1553eSJérôme Duval 		// look for nojoliet
15621e1553eSJérôme Duval 		spot = strstr(buf, "nojoliet");
15721e1553eSJérôme Duval 		if (spot != NULL)
1585b2c5d03SAxel Dörfler 			allowJoliet = false;
15921e1553eSJérôme Duval 
16021e1553eSJérôme Duval 		free(buf);
16121e1553eSJérôme Duval 	}
16221e1553eSJérôme Duval 
16321e1553eSJérôme Duval 	// Try and mount volume as an ISO volume.
164ff99132eSAxel Dörfler 	status_t result = ISOMount(device, O_RDONLY, &volume, allowJoliet);
165ff99132eSAxel Dörfler 	if (result == B_OK) {
16621e1553eSJérôme Duval 		*_rootID = ISO_ROOTNODE_ID;
16721e1553eSJérôme Duval 
1680eaadd30SMichael Lotz 		_volume->private_volume = volume;
1690eaadd30SMichael Lotz 		_volume->ops = &gISO9660VolumeOps;
1700eaadd30SMichael Lotz 		volume->volume = _volume;
1710eaadd30SMichael Lotz 		volume->id = _volume->id;
17221e1553eSJérôme Duval 
1730eaadd30SMichael Lotz 		result = publish_vnode(_volume, *_rootID, &volume->rootDirRec,
174a26c2439SMichael Lotz 			&gISO9660VnodeOps,
175a26c2439SMichael Lotz 			volume->rootDirRec.attr.stat[FS_DATA_FORMAT].st_mode, 0);
176ff99132eSAxel Dörfler 		if (result != B_OK) {
177ff99132eSAxel Dörfler 			block_cache_delete(volume->fBlockCache, false);
178ff99132eSAxel Dörfler 			free(volume);
179ff99132eSAxel Dörfler 			result = B_ERROR;
180ff99132eSAxel Dörfler 		}
18121e1553eSJérôme Duval 	}
18221e1553eSJérôme Duval 	return result;
18321e1553eSJérôme Duval }
18421e1553eSJérôme Duval 
18521e1553eSJérôme Duval 
18621e1553eSJérôme Duval static status_t
fs_unmount(fs_volume * _volume)187f0c050f6SAxel Dörfler fs_unmount(fs_volume* _volume)
18821e1553eSJérôme Duval {
18921e1553eSJérôme Duval 	status_t result = B_NO_ERROR;
190f0c050f6SAxel Dörfler 	iso9660_volume* volume = (iso9660_volume*)_volume->private_volume;
19121e1553eSJérôme Duval 
19221e1553eSJérôme Duval 	TRACE(("fs_unmount - ENTER\n"));
19321e1553eSJérôme Duval 
1949d254f45SJérôme Duval 	// Unlike in BeOS, we need to put the reference to our root node ourselves
195f0c050f6SAxel Dörfler 	put_vnode(_volume, ISO_ROOTNODE_ID);
1969d254f45SJérôme Duval 
197f0c050f6SAxel Dörfler 	block_cache_delete(volume->fBlockCache, false);
198f0c050f6SAxel Dörfler 	close(volume->fdOfSession);
199f0c050f6SAxel Dörfler 	result = close(volume->fd);
20021e1553eSJérôme Duval 
201f0c050f6SAxel Dörfler 	free(volume);
20221e1553eSJérôme Duval 
20321e1553eSJérôme Duval 	TRACE(("fs_unmount - EXIT, result is %s\n", strerror(result)));
20421e1553eSJérôme Duval 	return result;
20521e1553eSJérôme Duval }
20621e1553eSJérôme Duval 
20721e1553eSJérôme Duval 
20821e1553eSJérôme Duval static status_t
fs_read_fs_stat(fs_volume * _volume,struct fs_info * info)209f0c050f6SAxel Dörfler fs_read_fs_stat(fs_volume* _volume, struct fs_info* info)
21021e1553eSJérôme Duval {
211f0c050f6SAxel Dörfler 	iso9660_volume* volume = (iso9660_volume*)_volume->private_volume;
212f0c050f6SAxel Dörfler 
213f0c050f6SAxel Dörfler 	info->flags = B_FS_IS_PERSISTENT | B_FS_IS_READONLY;
214f0c050f6SAxel Dörfler 	info->block_size = volume->logicalBlkSize[FS_DATA_FORMAT];
215f0c050f6SAxel Dörfler 	info->io_size = 65536;
216f0c050f6SAxel Dörfler 	info->total_blocks = volume->volSpaceSize[FS_DATA_FORMAT];
217f0c050f6SAxel Dörfler 	info->free_blocks = 0;
218f0c050f6SAxel Dörfler 
219f0c050f6SAxel Dörfler 	strlcpy(info->device_name, volume->devicePath, sizeof(info->device_name));
220f0c050f6SAxel Dörfler 	strlcpy(info->volume_name, volume->volIDString, sizeof(info->volume_name));
221f0c050f6SAxel Dörfler 
222f0c050f6SAxel Dörfler 	// strip trailing spaces
22321e1553eSJérôme Duval 	int i;
224f0c050f6SAxel Dörfler 	for (i = strlen(info->volume_name) - 1; i >=0 ; i--) {
225f0c050f6SAxel Dörfler 		if (info->volume_name[i] != ' ')
22621e1553eSJérôme Duval 			break;
227ff99132eSAxel Dörfler 	}
22821e1553eSJérôme Duval 
22921e1553eSJérôme Duval 	if (i < 0)
230f0c050f6SAxel Dörfler 		strcpy(info->volume_name, "UNKNOWN");
23121e1553eSJérôme Duval 	else
232f0c050f6SAxel Dörfler 		info->volume_name[i + 1] = 0;
23321e1553eSJérôme Duval 
234f0c050f6SAxel Dörfler 	strcpy(info->fsh_name, "iso9660");
235ff99132eSAxel Dörfler 	return B_OK;
23621e1553eSJérôme Duval }
23721e1553eSJérôme Duval 
2383b723f79SJérôme Duval 
2393b723f79SJérôme Duval static status_t
fs_get_vnode_name(fs_volume * _volume,fs_vnode * _node,char * buffer,size_t bufferSize)240f0c050f6SAxel Dörfler fs_get_vnode_name(fs_volume* _volume, fs_vnode* _node, char* buffer,
241f0c050f6SAxel Dörfler 	size_t bufferSize)
2423b723f79SJérôme Duval {
243eb097431SAxel Dörfler 	iso9660_inode* node = (iso9660_inode*)_node->private_node;
2443b723f79SJérôme Duval 
245eb097431SAxel Dörfler 	strlcpy(buffer, node->name, bufferSize);
2463b723f79SJérôme Duval 	return B_OK;
2473b723f79SJérôme Duval }
2483b723f79SJérôme Duval 
2493b723f79SJérôme Duval 
25021e1553eSJérôme Duval static status_t
fs_walk(fs_volume * _volume,fs_vnode * _base,const char * file,ino_t * _vnodeID)251f0c050f6SAxel Dörfler fs_walk(fs_volume* _volume, fs_vnode* _base, const char* file, ino_t* _vnodeID)
25221e1553eSJérôme Duval {
253f0c050f6SAxel Dörfler 	iso9660_volume* volume = (iso9660_volume*)_volume->private_volume;
254eb097431SAxel Dörfler 	iso9660_inode* baseNode = (iso9660_inode*)_base->private_node;
255eb097431SAxel Dörfler 	iso9660_inode* newNode = NULL;
25621e1553eSJérôme Duval 
25799d1bfb5SAxel Dörfler 	TRACE(("fs_walk - looking for %s in dir file of length %d\n", file,
25899d1bfb5SAxel Dörfler 		(int)baseNode->dataLen[FS_DATA_FORMAT]));
25921e1553eSJérôme Duval 
26021e1553eSJérôme Duval 	if (strcmp(file, ".") == 0)  {
26121e1553eSJérôme Duval 		// base directory
26221e1553eSJérôme Duval 		TRACE(("fs_walk - found \".\" file.\n"));
26321e1553eSJérôme Duval 		*_vnodeID = baseNode->id;
264f0c050f6SAxel Dörfler 		return get_vnode(_volume, *_vnodeID, NULL);
26521e1553eSJérôme Duval 	} else if (strcmp(file, "..") == 0) {
26621e1553eSJérôme Duval 		// parent directory
26721e1553eSJérôme Duval 		TRACE(("fs_walk - found \"..\" file.\n"));
26821e1553eSJérôme Duval 		*_vnodeID = baseNode->parID;
269f0c050f6SAxel Dörfler 		return get_vnode(_volume, *_vnodeID, NULL);
270ff99132eSAxel Dörfler 	}
271ff99132eSAxel Dörfler 
27221e1553eSJérôme Duval 	// look up file in the directory
273ff99132eSAxel Dörfler 	uint32 dataLength = baseNode->dataLen[FS_DATA_FORMAT];
274ff99132eSAxel Dörfler 	status_t result = ENOENT;
275eb097431SAxel Dörfler 	size_t totalRead = 0;
276ff99132eSAxel Dörfler 	off_t block = baseNode->startLBN[FS_DATA_FORMAT];
277ff99132eSAxel Dörfler 	bool done = false;
27821e1553eSJérôme Duval 
279ff99132eSAxel Dörfler 	while (totalRead < dataLength && !done) {
28021e1553eSJérôme Duval 		off_t cachedBlock = block;
281f0c050f6SAxel Dörfler 		char* blockData = (char*)block_cache_get(volume->fBlockCache, block);
2822a64cb11SAxel Dörfler 		if (blockData == NULL)
2832a64cb11SAxel Dörfler 			break;
2842a64cb11SAxel Dörfler 
285eb097431SAxel Dörfler 		size_t bytesRead = 0;
28621e1553eSJérôme Duval 		off_t blockBytesRead = 0;
287eb097431SAxel Dörfler 		iso9660_inode node;
28821e1553eSJérôme Duval 		int initResult;
28921e1553eSJérôme Duval 
290*425ac1b6SAlexander von Gluck IV 		TRACE(("fs_walk - read buffer from disk at LBN %lld into buffer "
291eb097431SAxel Dörfler 			"%p.\n", block, blockData));
29221e1553eSJérôme Duval 
2932a64cb11SAxel Dörfler 		// Move to the next block if necessary
29421e1553eSJérôme Duval 		// Don't go over end of buffer, if dir record sits on boundary.
29521e1553eSJérôme Duval 
296f0c050f6SAxel Dörfler 		while (blockBytesRead < volume->logicalBlkSize[FS_DATA_FORMAT]
297ff99132eSAxel Dörfler 			&& totalRead + blockBytesRead < dataLength
29821e1553eSJérôme Duval 			&& blockData[0] != 0
299ff99132eSAxel Dörfler 			&& !done) {
300f0c050f6SAxel Dörfler 			initResult = InitNode(volume, &node, blockData, &bytesRead);
30199d1bfb5SAxel Dörfler 			TRACE(("fs_walk - InitNode returned %s, filename %s, %u bytes "
30299d1bfb5SAxel Dörfler 				"read\n", strerror(initResult), node.name, (unsigned)bytesRead));
30321e1553eSJérôme Duval 
304ff99132eSAxel Dörfler 			if (initResult == B_OK) {
30599d1bfb5SAxel Dörfler 				if ((node.flags & ISO_IS_ASSOCIATED_FILE) == 0
30699d1bfb5SAxel Dörfler 					&& !strcmp(node.name, file)) {
307*425ac1b6SAlexander von Gluck IV 					TRACE(("fs_walk - success, found vnode at block %lld, pos "
308*425ac1b6SAlexander von Gluck IV 						"%lld\n", block, blockBytesRead));
3092a64cb11SAxel Dörfler 
3102a64cb11SAxel Dörfler 					*_vnodeID = (block << 30) + (blockBytesRead & 0xffffffff);
311*425ac1b6SAlexander von Gluck IV 					TRACE(("fs_walk - New vnode id is %lld\n", *_vnodeID));
31221e1553eSJérôme Duval 
313f0c050f6SAxel Dörfler 					result = get_vnode(_volume, *_vnodeID, (void**)&newNode);
314ff99132eSAxel Dörfler 					if (result == B_OK) {
31521e1553eSJérôme Duval 						newNode->parID = baseNode->id;
316ff99132eSAxel Dörfler 						done = true;
31721e1553eSJérôme Duval 					}
31821e1553eSJérôme Duval 				} else {
319eb097431SAxel Dörfler 					free(node.name);
32021e1553eSJérôme Duval 					free(node.attr.slName);
32121e1553eSJérôme Duval 				}
32221e1553eSJérôme Duval 			} else {
32321e1553eSJérôme Duval 				result = initResult;
32421e1553eSJérôme Duval 				if (bytesRead == 0)
325f47bff08SAxel Dörfler 					done = true;
32621e1553eSJérôme Duval 			}
32721e1553eSJérôme Duval 			blockData += bytesRead;
32821e1553eSJérôme Duval 			blockBytesRead += bytesRead;
32921e1553eSJérôme Duval 
33099d1bfb5SAxel Dörfler 			TRACE(("fs_walk - Adding %u bytes to blockBytes read (total "
331*425ac1b6SAlexander von Gluck IV 				"%lld/%u).\n", (unsigned)bytesRead, blockBytesRead,
33299d1bfb5SAxel Dörfler 				(unsigned)baseNode->dataLen[FS_DATA_FORMAT]));
33321e1553eSJérôme Duval 		}
334f0c050f6SAxel Dörfler 		totalRead += volume->logicalBlkSize[FS_DATA_FORMAT];
33521e1553eSJérôme Duval 		block++;
33621e1553eSJérôme Duval 
337*425ac1b6SAlexander von Gluck IV 		TRACE(("fs_walk - moving to next block %lld, total read %u\n",
33899d1bfb5SAxel Dörfler 			block, (unsigned)totalRead));
339f0c050f6SAxel Dörfler 		block_cache_put(volume->fBlockCache, cachedBlock);
34021e1553eSJérôme Duval 	}
34121e1553eSJérôme Duval 
342ff99132eSAxel Dörfler 	TRACE(("fs_walk - EXIT, result is %s, vnid is %Lu\n",
343ff99132eSAxel Dörfler 		strerror(result), *_vnodeID));
34421e1553eSJérôme Duval 	return result;
34521e1553eSJérôme Duval }
34621e1553eSJérôme Duval 
34721e1553eSJérôme Duval 
34821e1553eSJérôme Duval static status_t
fs_read_vnode(fs_volume * _volume,ino_t vnodeID,fs_vnode * _node,int * _type,uint32 * _flags,bool reenter)349f0c050f6SAxel Dörfler fs_read_vnode(fs_volume* _volume, ino_t vnodeID, fs_vnode* _node,
3500eaadd30SMichael Lotz 	int* _type, uint32* _flags, bool reenter)
35121e1553eSJérôme Duval {
352f0c050f6SAxel Dörfler 	iso9660_volume* volume = (iso9660_volume*)_volume->private_volume;
353ff99132eSAxel Dörfler 
354eb097431SAxel Dörfler 	iso9660_inode* newNode = (iso9660_inode*)calloc(sizeof(iso9660_inode), 1);
355ff99132eSAxel Dörfler 	if (newNode == NULL)
356ff99132eSAxel Dörfler 		return B_NO_MEMORY;
35721e1553eSJérôme Duval 
358ff99132eSAxel Dörfler 	uint32 pos = vnodeID & 0x3fffffff;
359ff99132eSAxel Dörfler 	uint32 block = vnodeID >> 30;
36021e1553eSJérôme Duval 
36199d1bfb5SAxel Dörfler 	TRACE(("fs_read_vnode - block = %u, pos = %u, raw = %Lu node %p\n",
36299d1bfb5SAxel Dörfler 		(unsigned)block, (unsigned) pos, vnodeID, newNode));
36321e1553eSJérôme Duval 
364f0c050f6SAxel Dörfler 	if (pos > volume->logicalBlkSize[FS_DATA_FORMAT]) {
365d02cde30SMichael Lotz 		free(newNode);
366ff99132eSAxel Dörfler 		return B_BAD_VALUE;
367d02cde30SMichael Lotz 	}
36821e1553eSJérôme Duval 
369f0c050f6SAxel Dörfler 	char* data = (char*)block_cache_get(volume->fBlockCache, block);
370ff99132eSAxel Dörfler 	if (data == NULL) {
371ff99132eSAxel Dörfler 		free(newNode);
372ff99132eSAxel Dörfler 		return B_IO_ERROR;
373ff99132eSAxel Dörfler 	}
37421e1553eSJérôme Duval 
375f0c050f6SAxel Dörfler 	status_t result = InitNode(volume, newNode, data + pos, NULL);
376f0c050f6SAxel Dörfler 	block_cache_put(volume->fBlockCache, block);
37721e1553eSJérôme Duval 
378ff99132eSAxel Dörfler 	if (result < B_OK) {
379ff99132eSAxel Dörfler 		free(newNode);
380ff99132eSAxel Dörfler 		return result;
38121e1553eSJérôme Duval 	}
38221e1553eSJérôme Duval 
38341b19806SAxel Dörfler 	newNode->volume = volume;
384ff99132eSAxel Dörfler 	newNode->id = vnodeID;
38541b19806SAxel Dörfler 
3860eaadd30SMichael Lotz 	_node->private_node = newNode;
3870eaadd30SMichael Lotz 	_node->ops = &gISO9660VnodeOps;
38899d1bfb5SAxel Dörfler 	*_type = newNode->attr.stat[FS_DATA_FORMAT].st_mode
38999d1bfb5SAxel Dörfler 		& ~(S_IWUSR | S_IWGRP | S_IWOTH);
390a26c2439SMichael Lotz 	*_flags = 0;
391ff99132eSAxel Dörfler 
39247a214deSAxel Dörfler 	if ((newNode->flags & ISO_IS_DIR) == 0) {
393f0c050f6SAxel Dörfler 		newNode->cache = file_cache_create(volume->id, vnodeID,
3943d268edaSAxel Dörfler 			newNode->dataLen[FS_DATA_FORMAT]);
3955b4cb109SJérôme Duval 	}
3965b4cb109SJérôme Duval 
397ff99132eSAxel Dörfler 	return B_OK;
39821e1553eSJérôme Duval }
39921e1553eSJérôme Duval 
40021e1553eSJérôme Duval 
40121e1553eSJérôme Duval static status_t
fs_release_vnode(fs_volume *,fs_vnode * _node,bool)402eb097431SAxel Dörfler fs_release_vnode(fs_volume* /*_volume*/, fs_vnode* _node, bool /*reenter*/)
40321e1553eSJérôme Duval {
404eb097431SAxel Dörfler 	iso9660_inode* node = (iso9660_inode*)_node->private_node;
40521e1553eSJérôme Duval 
406eb097431SAxel Dörfler 	TRACE(("fs_release_vnode - ENTER (%p)\n", node));
40721e1553eSJérôme Duval 
40821e1553eSJérôme Duval 	if (node->id != ISO_ROOTNODE_ID) {
409eb097431SAxel Dörfler 		free(node->name);
41021e1553eSJérôme Duval 		free(node->attr.slName);
411eb097431SAxel Dörfler 
4125b4cb109SJérôme Duval 		if (node->cache != NULL)
4135b4cb109SJérôme Duval 			file_cache_delete(node->cache);
41421e1553eSJérôme Duval 
41521e1553eSJérôme Duval 		free(node);
41621e1553eSJérôme Duval 	}
41721e1553eSJérôme Duval 
4185b4cb109SJérôme Duval 	TRACE(("fs_release_vnode - EXIT\n"));
419eb097431SAxel Dörfler 	return B_OK;
42021e1553eSJérôme Duval }
42121e1553eSJérôme Duval 
42221e1553eSJérôme Duval 
42321e1553eSJérôme Duval static status_t
fs_read_pages(fs_volume * _volume,fs_vnode * _node,void * _cookie,off_t pos,const iovec * vecs,size_t count,size_t * _numBytes)424f0c050f6SAxel Dörfler fs_read_pages(fs_volume* _volume, fs_vnode* _node, void*  _cookie, off_t pos,
425e6bd90c5SIngo Weinhold 	const iovec* vecs, size_t count, size_t* _numBytes)
4265b4cb109SJérôme Duval {
427f0c050f6SAxel Dörfler 	iso9660_volume* volume = (iso9660_volume*)_volume->private_volume;
428eb097431SAxel Dörfler 	iso9660_inode* node = (iso9660_inode*)_node->private_node;
4295b4cb109SJérôme Duval 
430ff99132eSAxel Dörfler 	uint32 fileSize = node->dataLen[FS_DATA_FORMAT];
431ff99132eSAxel Dörfler 	size_t bytesLeft = *_numBytes;
4325b4cb109SJérôme Duval 
433ff99132eSAxel Dörfler 	if (pos >= fileSize) {
434ff99132eSAxel Dörfler 		*_numBytes = 0;
4355b4cb109SJérôme Duval 		return B_OK;
4365b4cb109SJérôme Duval 	}
437ff99132eSAxel Dörfler 	if (pos + bytesLeft > fileSize) {
438ff99132eSAxel Dörfler 		bytesLeft = fileSize - pos;
439ff99132eSAxel Dörfler 		*_numBytes = bytesLeft;
4405b4cb109SJérôme Duval 	}
4415b4cb109SJérôme Duval 
442ff99132eSAxel Dörfler 	file_io_vec fileVec;
4436ea60bcdSAxel Dörfler 	fileVec.offset = pos + ((off_t)node->startLBN[FS_DATA_FORMAT]
4446ea60bcdSAxel Dörfler 		* (off_t)volume->logicalBlkSize[FS_DATA_FORMAT]);
445ff99132eSAxel Dörfler 	fileVec.length = bytesLeft;
4465b4cb109SJérôme Duval 
447ff99132eSAxel Dörfler 	uint32 vecIndex = 0;
448ff99132eSAxel Dörfler 	size_t vecOffset = 0;
449f0c050f6SAxel Dörfler 	return read_file_io_vec_pages(volume->fd, &fileVec, 1, vecs, count,
450ff99132eSAxel Dörfler 		&vecIndex, &vecOffset, &bytesLeft);
4515b4cb109SJérôme Duval }
4525b4cb109SJérôme Duval 
4535b4cb109SJérôme Duval 
4545b4cb109SJérôme Duval static status_t
fs_io(fs_volume * _volume,fs_vnode * _node,void * _cookie,io_request * request)45541b19806SAxel Dörfler fs_io(fs_volume* _volume, fs_vnode* _node, void* _cookie, io_request* request)
45641b19806SAxel Dörfler {
45741b19806SAxel Dörfler 	iso9660_volume* volume = (iso9660_volume*)_volume->private_volume;
45841b19806SAxel Dörfler 	iso9660_inode* node = (iso9660_inode*)_node->private_node;
45941b19806SAxel Dörfler 
46038fa917cSAugustin Cavalier #ifndef FS_SHELL
461533cba7eSAxel Dörfler 	if (io_request_is_write(request)) {
462533cba7eSAxel Dörfler 		notify_io_request(request, B_READ_ONLY_DEVICE);
46341b19806SAxel Dörfler 		return B_READ_ONLY_DEVICE;
464533cba7eSAxel Dörfler 	}
46538fa917cSAugustin Cavalier #endif
46641b19806SAxel Dörfler 
467533cba7eSAxel Dörfler 	if ((node->flags & ISO_IS_DIR) != 0) {
46838fa917cSAugustin Cavalier #ifndef FS_SHELL
469533cba7eSAxel Dörfler 		notify_io_request(request, B_IS_A_DIRECTORY);
47038fa917cSAugustin Cavalier #endif
471533cba7eSAxel Dörfler 		return B_IS_A_DIRECTORY;
472533cba7eSAxel Dörfler 	}
47341b19806SAxel Dörfler 
47441b19806SAxel Dörfler 	return do_iterative_fd_io(volume->fd, request, iterative_io_get_vecs_hook,
47541b19806SAxel Dörfler 		iterative_io_finished_hook, node);
47641b19806SAxel Dörfler }
47741b19806SAxel Dörfler 
47841b19806SAxel Dörfler 
47941b19806SAxel Dörfler static status_t
fs_read_stat(fs_volume * _volume,fs_vnode * _node,struct stat * st)480f0c050f6SAxel Dörfler fs_read_stat(fs_volume* _volume, fs_vnode* _node, struct stat* st)
48121e1553eSJérôme Duval {
482f0c050f6SAxel Dörfler 	iso9660_volume* volume = (iso9660_volume*)_volume->private_volume;
483eb097431SAxel Dörfler 	iso9660_inode* node = (iso9660_inode*)_node->private_node;
4843b723f79SJérôme Duval 	status_t result = B_NO_ERROR;
48521e1553eSJérôme Duval 	time_t time;
48621e1553eSJérôme Duval 
4873b723f79SJérôme Duval 	TRACE(("fs_read_stat - ENTER\n"));
48821e1553eSJérôme Duval 
489f0c050f6SAxel Dörfler 	st->st_dev = volume->id;
49021e1553eSJérôme Duval 	st->st_ino = node->id;
49121e1553eSJérôme Duval 	st->st_nlink = node->attr.stat[FS_DATA_FORMAT].st_nlink;
49221e1553eSJérôme Duval 	st->st_uid = node->attr.stat[FS_DATA_FORMAT].st_uid;
49321e1553eSJérôme Duval 	st->st_gid = node->attr.stat[FS_DATA_FORMAT].st_gid;
49421e1553eSJérôme Duval 	st->st_blksize = 65536;
49521e1553eSJérôme Duval 	st->st_mode = node->attr.stat[FS_DATA_FORMAT].st_mode;
49621e1553eSJérôme Duval 
49721e1553eSJérôme Duval 	// Same for file/dir in ISO9660
49821e1553eSJérôme Duval 	st->st_size = node->dataLen[FS_DATA_FORMAT];
4992c348abbSAxel Dörfler 	st->st_blocks = (st->st_size + 511) / 512;
500c3e68d8dSJerome Duval 	if (ConvertRecDate(&(node->recordDate), &time) == B_NO_ERROR) {
501c3e68d8dSJerome Duval 		st->st_ctim.tv_sec = st->st_mtim.tv_sec = st->st_atim.tv_sec = time;
502c3e68d8dSJerome Duval 		st->st_ctim.tv_nsec = st->st_mtim.tv_nsec = st->st_atim.tv_nsec = 0;
503c3e68d8dSJerome Duval 	}
50421e1553eSJérôme Duval 
5053b723f79SJérôme Duval 	TRACE(("fs_read_stat - EXIT, result is %s\n", strerror(result)));
50621e1553eSJérôme Duval 
50721e1553eSJérôme Duval 	return result;
50821e1553eSJérôme Duval }
50921e1553eSJérôme Duval 
51021e1553eSJérôme Duval 
51121e1553eSJérôme Duval static status_t
fs_open(fs_volume *,fs_vnode * _node,int openMode,void **)512f0c050f6SAxel Dörfler fs_open(fs_volume* /*_volume*/, fs_vnode* _node, int openMode, void** /*cookie*/)
51321e1553eSJérôme Duval {
51421e1553eSJérôme Duval 	// Do not allow any of the write-like open modes to get by
515f0c050f6SAxel Dörfler 	if ((openMode & O_RWMASK) == O_WRONLY || (openMode & O_RWMASK) == O_RDWR
516f0c050f6SAxel Dörfler 		|| (openMode & O_TRUNC) != 0 || (openMode & O_CREAT) != 0)
517f0c050f6SAxel Dörfler 		return EROFS;
51821e1553eSJérôme Duval 
519f0c050f6SAxel Dörfler 	return B_OK;
52021e1553eSJérôme Duval }
52121e1553eSJérôme Duval 
52221e1553eSJérôme Duval 
52321e1553eSJérôme Duval static status_t
fs_read(fs_volume * _volume,fs_vnode * _node,void * cookie,off_t pos,void * buffer,size_t * _length)524f0c050f6SAxel Dörfler fs_read(fs_volume* _volume, fs_vnode* _node, void* cookie, off_t pos,
525f0c050f6SAxel Dörfler 	void* buffer, size_t* _length)
52621e1553eSJérôme Duval {
527eb097431SAxel Dörfler 	iso9660_inode* node = (iso9660_inode*)_node->private_node;
52821e1553eSJérôme Duval 
52947a214deSAxel Dörfler 	if ((node->flags & ISO_IS_DIR) != 0)
53021e1553eSJérôme Duval 		return EISDIR;
53121e1553eSJérôme Duval 
532ff99132eSAxel Dörfler 	return file_cache_read(node->cache, NULL, pos, buffer, _length);
53321e1553eSJérôme Duval }
53421e1553eSJérôme Duval 
53521e1553eSJérôme Duval 
53621e1553eSJérôme Duval static status_t
fs_close(fs_volume *,fs_vnode *,void *)537f0c050f6SAxel Dörfler fs_close(fs_volume* /*_volume*/, fs_vnode* /*_node*/, void* /*cookie*/)
53821e1553eSJérôme Duval {
53921e1553eSJérôme Duval 	return B_OK;
54021e1553eSJérôme Duval }
54121e1553eSJérôme Duval 
542ff99132eSAxel Dörfler 
54321e1553eSJérôme Duval static status_t
fs_free_cookie(fs_volume *,fs_vnode *,void *)544f0c050f6SAxel Dörfler fs_free_cookie(fs_volume* /*_volume*/, fs_vnode* /*_node*/, void* /*cookie*/)
54521e1553eSJérôme Duval {
54621e1553eSJérôme Duval 	return B_OK;
54721e1553eSJérôme Duval }
54821e1553eSJérôme Duval 
549ff99132eSAxel Dörfler 
55021e1553eSJérôme Duval static status_t
fs_access(fs_volume *,fs_vnode *,int)551f0c050f6SAxel Dörfler fs_access(fs_volume* /*_volume*/, fs_vnode* /*_node*/, int /*mode*/)
55221e1553eSJérôme Duval {
55321e1553eSJérôme Duval 	return B_OK;
55421e1553eSJérôme Duval }
55521e1553eSJérôme Duval 
556ff99132eSAxel Dörfler 
55721e1553eSJérôme Duval static status_t
fs_read_link(fs_volume * _volume,fs_vnode * _node,char * buffer,size_t * _bufferSize)558f0c050f6SAxel Dörfler fs_read_link(fs_volume* _volume, fs_vnode* _node, char* buffer,
559f0c050f6SAxel Dörfler 	size_t* _bufferSize)
56021e1553eSJérôme Duval {
561eb097431SAxel Dörfler 	iso9660_inode* node = (iso9660_inode*)_node->private_node;
56221e1553eSJérôme Duval 
563ff99132eSAxel Dörfler 	if (!S_ISLNK(node->attr.stat[FS_DATA_FORMAT].st_mode))
564ff99132eSAxel Dörfler 		return B_BAD_VALUE;
56521e1553eSJérôme Duval 
56621e1553eSJérôme Duval 	size_t length = strlen(node->attr.slName);
56721e1553eSJérôme Duval 
568e1b7c1c7SKyle Ambroff-Kao 	size_t bytesToCopy = std::min(length, *_bufferSize);
569e1b7c1c7SKyle Ambroff-Kao 
570e1b7c1c7SKyle Ambroff-Kao 	*_bufferSize = length;
571e1b7c1c7SKyle Ambroff-Kao 
572f9b218aaSJérôme Duval 	memcpy(buffer, node->attr.slName, bytesToCopy);
573f9b218aaSJérôme Duval 	return B_OK;
57421e1553eSJérôme Duval }
57521e1553eSJérôme Duval 
57621e1553eSJérôme Duval 
57721e1553eSJérôme Duval static status_t
fs_open_dir(fs_volume *,fs_vnode * _node,void ** _cookie)578eb097431SAxel Dörfler fs_open_dir(fs_volume* /*_volume*/, fs_vnode* _node, void** _cookie)
57921e1553eSJérôme Duval {
580eb097431SAxel Dörfler 	iso9660_inode* node = (iso9660_inode*)_node->private_node;
58121e1553eSJérôme Duval 
582eb097431SAxel Dörfler 	TRACE(("fs_open_dir - node is %p\n", node));
58321e1553eSJérôme Duval 
58447a214deSAxel Dörfler 	if ((node->flags & ISO_IS_DIR) == 0)
585ff99132eSAxel Dörfler 		return B_NOT_A_DIRECTORY;
58621e1553eSJérôme Duval 
587ff99132eSAxel Dörfler 	dircookie* dirCookie = (dircookie*)malloc(sizeof(dircookie));
588ff99132eSAxel Dörfler 	if (dirCookie == NULL)
589ff99132eSAxel Dörfler 		return B_NO_MEMORY;
590ff99132eSAxel Dörfler 
59121e1553eSJérôme Duval 	dirCookie->startBlock = node->startLBN[FS_DATA_FORMAT];
59221e1553eSJérôme Duval 	dirCookie->block = node->startLBN[FS_DATA_FORMAT];
59321e1553eSJérôme Duval 	dirCookie->totalSize = node->dataLen[FS_DATA_FORMAT];
59421e1553eSJérôme Duval 	dirCookie->pos = 0;
59521e1553eSJérôme Duval 	dirCookie->id = node->id;
596eb097431SAxel Dörfler 	*_cookie = (void*)dirCookie;
59721e1553eSJérôme Duval 
598ff99132eSAxel Dörfler 	return B_OK;
59921e1553eSJérôme Duval }
60021e1553eSJérôme Duval 
60121e1553eSJérôme Duval 
60221e1553eSJérôme Duval static status_t
fs_read_dir(fs_volume * _volume,fs_vnode * _node,void * _cookie,struct dirent * buffer,size_t bufferSize,uint32 * num)603f0c050f6SAxel Dörfler fs_read_dir(fs_volume* _volume, fs_vnode* _node, void* _cookie,
60444d0dbc8SAxel Dörfler 	struct dirent* buffer, size_t bufferSize, uint32* num)
60521e1553eSJérôme Duval {
606f0c050f6SAxel Dörfler 	iso9660_volume* volume = (iso9660_volume*)_volume->private_volume;
60721e1553eSJérôme Duval 	dircookie* dirCookie = (dircookie*)_cookie;
60821e1553eSJérôme Duval 
6095b4cb109SJérôme Duval 	TRACE(("fs_read_dir - ENTER\n"));
61021e1553eSJérôme Duval 
611f0c050f6SAxel Dörfler 	status_t result = ISOReadDirEnt(volume, dirCookie, buffer, bufferSize);
61221e1553eSJérôme Duval 
61321e1553eSJérôme Duval 	// If we succeeded, return 1, the number of dirents we read.
614ff99132eSAxel Dörfler 	if (result == B_OK)
61521e1553eSJérôme Duval 		*num = 1;
61621e1553eSJérôme Duval 	else
61721e1553eSJérôme Duval 		*num = 0;
61821e1553eSJérôme Duval 
61921e1553eSJérôme Duval 	// When you get to the end, don't return an error, just return
62021e1553eSJérôme Duval 	// a zero in *num.
62121e1553eSJérôme Duval 
622eb097431SAxel Dörfler 	if (result == B_ENTRY_NOT_FOUND)
623ff99132eSAxel Dörfler 		result = B_OK;
62421e1553eSJérôme Duval 
6255b4cb109SJérôme Duval 	TRACE(("fs_read_dir - EXIT, result is %s\n", strerror(result)));
62621e1553eSJérôme Duval 	return result;
62721e1553eSJérôme Duval }
62821e1553eSJérôme Duval 
62921e1553eSJérôme Duval 
63021e1553eSJérôme Duval static status_t
fs_rewind_dir(fs_volume * _volume,fs_vnode * _node,void * _cookie)631f0c050f6SAxel Dörfler fs_rewind_dir(fs_volume* _volume, fs_vnode* _node, void* _cookie)
63221e1553eSJérôme Duval {
63321e1553eSJérôme Duval 	dircookie* cookie = (dircookie*)_cookie;
63421e1553eSJérôme Duval 
63521e1553eSJérôme Duval 	cookie->block = cookie->startBlock;
63621e1553eSJérôme Duval 	cookie->pos = 0;
637ff99132eSAxel Dörfler 	return B_OK;
63821e1553eSJérôme Duval }
63921e1553eSJérôme Duval 
64021e1553eSJérôme Duval 
64121e1553eSJérôme Duval static status_t
fs_close_dir(fs_volume * _volume,fs_vnode * _node,void * cookie)642f0c050f6SAxel Dörfler fs_close_dir(fs_volume* _volume, fs_vnode* _node, void* cookie)
64321e1553eSJérôme Duval {
64421e1553eSJérôme Duval 	return B_OK;
64521e1553eSJérôme Duval }
64621e1553eSJérôme Duval 
64721e1553eSJérôme Duval 
64821e1553eSJérôme Duval static status_t
fs_free_dir_cookie(fs_volume * _volume,fs_vnode * _node,void * cookie)649f0c050f6SAxel Dörfler fs_free_dir_cookie(fs_volume* _volume, fs_vnode* _node, void* cookie)
65021e1553eSJérôme Duval {
65121e1553eSJérôme Duval 	free(cookie);
65221e1553eSJérôme Duval 	return B_OK;
65321e1553eSJérôme Duval }
65421e1553eSJérôme Duval 
655ff99132eSAxel Dörfler 
65621e1553eSJérôme Duval //	#pragma mark -
65721e1553eSJérôme Duval 
65821e1553eSJérôme Duval 
65921e1553eSJérôme Duval static status_t
iso_std_ops(int32 op,...)66021e1553eSJérôme Duval iso_std_ops(int32 op, ...)
66121e1553eSJérôme Duval {
66221e1553eSJérôme Duval 	switch (op) {
66321e1553eSJérôme Duval 		case B_MODULE_INIT:
66421e1553eSJérôme Duval 		case B_MODULE_UNINIT:
66521e1553eSJérôme Duval 			return B_OK;
66621e1553eSJérôme Duval 		default:
66721e1553eSJérôme Duval 			return B_ERROR;
66821e1553eSJérôme Duval 	}
66921e1553eSJérôme Duval }
67021e1553eSJérôme Duval 
67121e1553eSJérôme Duval 
6720eaadd30SMichael Lotz fs_volume_ops gISO9660VolumeOps = {
6730eaadd30SMichael Lotz 	&fs_unmount,
6740eaadd30SMichael Lotz 	&fs_read_fs_stat,
6750eaadd30SMichael Lotz 	NULL,
6760eaadd30SMichael Lotz 	NULL,
6770eaadd30SMichael Lotz 	&fs_read_vnode,
6780eaadd30SMichael Lotz 
6790eaadd30SMichael Lotz 	/* index and index directory ops */
6800eaadd30SMichael Lotz 	NULL,
6810eaadd30SMichael Lotz 	NULL,
6820eaadd30SMichael Lotz 	NULL,
6830eaadd30SMichael Lotz 	NULL,
6840eaadd30SMichael Lotz 	NULL,
6850eaadd30SMichael Lotz 	NULL,
6860eaadd30SMichael Lotz 	NULL,
6870eaadd30SMichael Lotz 	NULL,
6880eaadd30SMichael Lotz 
6890eaadd30SMichael Lotz 	/* query ops */
6900eaadd30SMichael Lotz 	NULL,
6910eaadd30SMichael Lotz 	NULL,
6920eaadd30SMichael Lotz 	NULL,
6930eaadd30SMichael Lotz 	NULL,
6940eaadd30SMichael Lotz 	NULL,
6950eaadd30SMichael Lotz 
6960eaadd30SMichael Lotz 	/* FS layer ops */
6970eaadd30SMichael Lotz 	NULL,
6980eaadd30SMichael Lotz 	NULL,
6990eaadd30SMichael Lotz };
7000eaadd30SMichael Lotz 
7010eaadd30SMichael Lotz fs_vnode_ops gISO9660VnodeOps = {
7020eaadd30SMichael Lotz 	&fs_walk,
7030eaadd30SMichael Lotz 	&fs_get_vnode_name,
7040eaadd30SMichael Lotz 	&fs_release_vnode,
7050eaadd30SMichael Lotz 	NULL,
7060eaadd30SMichael Lotz 
7070eaadd30SMichael Lotz 	/* vm-related ops */
7080eaadd30SMichael Lotz 	NULL,
7090eaadd30SMichael Lotz 	&fs_read_pages,
7100eaadd30SMichael Lotz 	NULL,
7110eaadd30SMichael Lotz 
71241b19806SAxel Dörfler 	&fs_io,
713ec598fe4SIngo Weinhold 	NULL,	// cancel_io()
714ec598fe4SIngo Weinhold 
7150eaadd30SMichael Lotz 	/* cache file access */
7160eaadd30SMichael Lotz 	NULL,
7170eaadd30SMichael Lotz 
7180eaadd30SMichael Lotz 	/* common */
7190eaadd30SMichael Lotz 	NULL,
7200eaadd30SMichael Lotz 	NULL,
7210eaadd30SMichael Lotz 	NULL,
7220eaadd30SMichael Lotz 	NULL,
7230eaadd30SMichael Lotz 	NULL,
7240eaadd30SMichael Lotz 	&fs_read_link,
7250eaadd30SMichael Lotz 	NULL,
7260eaadd30SMichael Lotz 	NULL,
7270eaadd30SMichael Lotz 	NULL,
7280eaadd30SMichael Lotz 	NULL,
7290eaadd30SMichael Lotz 	&fs_access,
7300eaadd30SMichael Lotz 	&fs_read_stat,
7310eaadd30SMichael Lotz 	NULL,
732d63f4274SJérôme Duval 	NULL,
7330eaadd30SMichael Lotz 
7340eaadd30SMichael Lotz 	/* file */
7350eaadd30SMichael Lotz 	NULL,
7360eaadd30SMichael Lotz 	&fs_open,
7370eaadd30SMichael Lotz 	&fs_close,
7380eaadd30SMichael Lotz 	&fs_free_cookie,
7390eaadd30SMichael Lotz 	&fs_read,
7400eaadd30SMichael Lotz 	NULL,
7410eaadd30SMichael Lotz 
7420eaadd30SMichael Lotz 	/* dir */
7430eaadd30SMichael Lotz 	NULL,
7440eaadd30SMichael Lotz 	NULL,
7450eaadd30SMichael Lotz 	&fs_open_dir,
7460eaadd30SMichael Lotz 	&fs_close_dir,
7470eaadd30SMichael Lotz 	&fs_free_dir_cookie,
7480eaadd30SMichael Lotz 	&fs_read_dir,
7490eaadd30SMichael Lotz 	&fs_rewind_dir,
7500eaadd30SMichael Lotz 
7510eaadd30SMichael Lotz 	/* attribute directory ops */
7520eaadd30SMichael Lotz 	NULL,
7530eaadd30SMichael Lotz 	NULL,
7540eaadd30SMichael Lotz 	NULL,
7550eaadd30SMichael Lotz 	NULL,
7560eaadd30SMichael Lotz 	NULL,
7570eaadd30SMichael Lotz 
7580eaadd30SMichael Lotz 	/* attribute ops */
7590eaadd30SMichael Lotz 	NULL,
7600eaadd30SMichael Lotz 	NULL,
7610eaadd30SMichael Lotz 	NULL,
7620eaadd30SMichael Lotz 	NULL,
7630eaadd30SMichael Lotz 	NULL,
7640eaadd30SMichael Lotz 	NULL,
7650eaadd30SMichael Lotz 	NULL,
7660eaadd30SMichael Lotz 	NULL,
7670eaadd30SMichael Lotz 	NULL,
7680eaadd30SMichael Lotz 	NULL,
7690eaadd30SMichael Lotz 
7700eaadd30SMichael Lotz 	/* node and FS layer support */
7710eaadd30SMichael Lotz 	NULL,
7720eaadd30SMichael Lotz 	NULL,
7730eaadd30SMichael Lotz };
7740eaadd30SMichael Lotz 
77521e1553eSJérôme Duval static file_system_module_info sISO660FileSystem = {
77621e1553eSJérôme Duval 	{
77721e1553eSJérôme Duval 		"file_systems/iso9660" B_CURRENT_FS_API_VERSION,
77821e1553eSJérôme Duval 		0,
77921e1553eSJérôme Duval 		iso_std_ops,
78021e1553eSJérôme Duval 	},
78121e1553eSJérôme Duval 
7821da9f5ceSAxel Dörfler 	"iso9660",					// short_name
7831da9f5ceSAxel Dörfler 	"ISO9660 File System",		// pretty_name
78476a8ec23SIngo Weinhold 	0,							// DDM flags
78521e1553eSJérôme Duval 
78621e1553eSJérôme Duval 	// scanning
78721e1553eSJérôme Duval 	fs_identify_partition,
78821e1553eSJérôme Duval 	fs_scan_partition,
78921e1553eSJérôme Duval 	fs_free_identify_partition_cookie,
79021e1553eSJérôme Duval 	NULL,	// free_partition_content_cookie()
79121e1553eSJérôme Duval 
79221e1553eSJérôme Duval 	&fs_mount,
7930eaadd30SMichael Lotz 
7940eaadd30SMichael Lotz 	/* capability querying */
7950eaadd30SMichael Lotz 	NULL,
7960eaadd30SMichael Lotz 	NULL,
7970eaadd30SMichael Lotz 	NULL,
7980eaadd30SMichael Lotz 	NULL,
79921e1553eSJérôme Duval 	NULL,
80021e1553eSJérôme Duval 	NULL,
80121e1553eSJérôme Duval 
8020eaadd30SMichael Lotz 	/* shadow partition modifications */
8030eaadd30SMichael Lotz 	NULL,
80421e1553eSJérôme Duval 
8050eaadd30SMichael Lotz 	/* writing */
8060eaadd30SMichael Lotz 	NULL,
8070eaadd30SMichael Lotz 	NULL,
8080eaadd30SMichael Lotz 	NULL,
8090eaadd30SMichael Lotz 	NULL,
8100eaadd30SMichael Lotz 	NULL,
8110eaadd30SMichael Lotz 	NULL,
8120eaadd30SMichael Lotz 	NULL,
81321e1553eSJérôme Duval };
81421e1553eSJérôme Duval 
81521e1553eSJérôme Duval module_info* modules[] = {
81621e1553eSJérôme Duval 	(module_info*)&sISO660FileSystem,
81721e1553eSJérôme Duval 	NULL,
81821e1553eSJérôme Duval };
81921e1553eSJérôme Duval 
820