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