root / Whitix / branches / hybrid / fs / isofs / super.c

Revision 523, 5.4 kB (checked in by mwhitworth, 6 months ago)

Convert code to use new APIs.

Line 
1/*  This file is part of Whitix.
2 *
3 *  Whitix is free software; you can redistribute it and/or modify
4 *  it under the terms of the GNU General Public License as published by
5 *  the Free Software Foundation; either version 2 of the License, or
6 *  (at your option) any later version.
7 *
8 *  Whitix is distributed in the hope that it will be useful,
9 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 *  GNU General Public License for more details.
12 *
13 *  You should have received a copy of the GNU General Public License
14 *  along with Whitix; if not, write to the Free Software
15 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
16 *
17 */
18
19#include <console.h>
20#include <error.h>
21#include <typedefs.h>
22#include <fs/vfs.h>
23#include <malloc.h>
24#include <init.h>
25
26#include "isofs.h"
27
28static inline void IsoTranslateDirEnt(struct VNode* vNode,struct IsoDirEntry* dirEntry)
29{
30        vNode->mode=((dirEntry->flags & 2) ? VFS_ATTR_DIR : VFS_ATTR_FILE) | VFS_ATTR_READ;
31
32        if (dirEntry->flags & 0x80)
33        {
34                KePrint("dirEntry->flags & 0x80!\n");
35                cli(); hlt();
36        }else
37                vNode->size=dirEntry->length.native;
38}
39
40int IsoReadVNode(struct VNode* vNode)
41{
42        struct Buffer* buffer;
43        DWORD offset=ISO_VNUM_OFFSET(vNode->id);
44        struct IsoDirEntry* dirEntry, *tmpDirEntry=NULL;
45        struct IsoVNodePriv* isoPriv;
46        struct IsoSbPriv* sbPriv=IsoGetSbPriv(vNode->superBlock);
47        int err=0;
48
49        buffer=BlockRead(vNode->superBlock->sDevice,ISO_VNUM_SECTOR(vNode->id));
50
51        if (!buffer)
52        {
53                KePrint("IsoReadVNode: failed to read buffer\n");
54                return -EIO;
55        }
56
57        dirEntry=(struct IsoDirEntry*)(buffer->data+offset);
58
59        /* Does the directory entry cross a sector boundary? If so,
60         * read in the next sector and piece the entry together. */
61        if (offset+dirEntry->entryLength > sbPriv->sectorSize)
62        {
63                int firstFrag = sbPriv->sectorSize-offset;
64                tmpDirEntry=(struct IsoDirEntry*)malloc(sizeof(struct IsoDirEntry));
65                if (!tmpDirEntry)
66                {
67                        err=-ENOMEM;
68                        goto out;
69                }
70                       
71                memcpy(tmpDirEntry, buffer->data+offset, firstFrag);
72                BlockFree(buffer);
73               
74                buffer=BlockRead(vNode->superBlock->sDevice, ISO_VNUM_SECTOR(vNode->id)+1);
75                if (!buffer)
76                {
77                        err=-EIO;
78                        goto out;
79                }
80               
81                memcpy((char*)(tmpDirEntry+firstFrag), buffer->data, tmpDirEntry->entryLength - firstFrag);
82                dirEntry=tmpDirEntry;
83        }
84
85        IsoTranslateDirEnt(vNode,dirEntry);
86
87        vNode->extraInfo=(struct IsoVNodePriv*)malloc(sizeof(struct IsoVNodePriv));
88
89        if (!vNode->extraInfo)
90        {
91                err=-ENOMEM;
92                goto out;
93        }
94
95        isoPriv=IsoGetPriv(vNode);
96        isoPriv->firstSector=dirEntry->firstSector.native+dirEntry->extAddrLength;
97
98        vNode->vNodeOps=&isoVNodeOps;
99        vNode->fileOps=&isoFileOps;
100
101out:
102        if (tmpDirEntry)
103                free(tmpDirEntry);
104
105        BlockFree(buffer);
106        return err;
107}
108
109/* TODO: Get the multisession information */
110
111DWORD IsoGetVolStart(struct VfsSuperBlock* superBlock)
112{
113/*
114        int ret;
115        struct CdRomMultiSession msInfo;
116
117        ret=BlockIoCtl(superBlock->dev,CDROM_MULTISESSION,(void*)&msInfo);
118*/
119        return 0;
120}
121
122/* ISO volume descriptor types */
123
124#define ISO_VD_PRI      0x01
125#define ISO_VD_END      0xFF
126
127#define ISO_VD_IDS      "CD001"
128
129struct SuperBlockOps isoSbOps=
130{
131        .readVNode = IsoReadVNode,
132        .writeVNode = NULL,
133};
134
135struct VfsSuperBlock* IsoReadSuper(struct StorageDevice* dev,int flags,char* data)
136{
137        struct VfsSuperBlock* retVal;
138        struct Buffer* buff,*priBuff=NULL;
139        struct IsoVolumeDesc* volDesc;
140        struct IsoPrimaryDesc* priDesc=NULL;
141        struct IsoDirEntry* rootEntry;
142        struct IsoSbPriv* sbPriv;
143        int currBlock;
144        DWORD volStart;
145
146        if (!dev || BlockSetSize(dev,2048))
147                return NULL;
148
149        retVal=VfsAllocSuper(dev,flags);
150
151        if (!retVal)
152                return NULL;
153
154        retVal->sbOps=&isoSbOps;
155
156        volStart=IsoGetVolStart(retVal);
157
158        for (currBlock=volStart+16; currBlock<volStart+100; currBlock++)
159        {
160                buff=BlockRead(dev,currBlock);
161                if (!buff)
162                        goto freeSuper;
163
164                volDesc=(struct IsoVolumeDesc*)buff->data;
165
166                if (!strncmp((char*)volDesc->id,ISO_VD_IDS,5))
167                {
168                        if (volDesc->type == ISO_VD_END)
169                                break;
170
171                        if (volDesc->type == ISO_VD_PRI)
172                        {
173                                priDesc=(struct IsoPrimaryDesc*)volDesc;
174                                priBuff=buff;
175                                buff=NULL; /* So it isn't freed */
176                        }
177                }
178
179                if (buff)
180                        BlockFree(buff);
181        }
182
183        if (!priDesc)
184                goto freeSuper;
185
186        rootEntry=&priDesc->root.dirEntry;
187
188        retVal->privData=malloc(sizeof(struct IsoSbPriv));
189        sbPriv=IsoGetSbPriv(retVal);
190        sbPriv->sectorSize=priDesc->sectorSize.native;
191       
192        /* Is the sector size less than the hardware block size? If so, error out. */
193        if (sbPriv->sectorSize < dev->blockSize)
194                goto freeSuper;
195               
196        BlockSetSize(dev, sbPriv->sectorSize);
197
198        if (sbPriv->sectorSize != 512 && sbPriv->sectorSize != 1024 && sbPriv->sectorSize != 2048)
199                /* Not a valid size, so pretend we never read it. */
200                goto freeSuper;
201
202        retVal->mount=VNodeGet(retVal,ISO_TO_VNUM(rootEntry->firstSector.native,0));
203        if (!retVal->mount)
204                goto freeSuper;
205
206        /* CDFS is always a read-only filesystem */
207        retVal->flags|=SB_RDONLY;
208
209freeBlock:
210        if (priBuff)
211                BlockFree(priBuff);
212        return retVal;
213
214        /* privData is freed in VfsFreeSuper */
215freeSuper:
216        VfsFreeSuper(retVal);
217        retVal=NULL;
218        goto freeBlock;
219}
220
221static struct FileSystem isoFileSystem={
222        .name="CDFS",
223        .readSuper=IsoReadSuper,
224};
225
226int IsoFsInit()
227{
228        return VfsRegisterFileSystem(&isoFileSystem);
229}
230
231void IsoFsExit()
232{
233        VfsDeregisterFileSystem(&isoFileSystem);
234}
235
236FsInit(IsoFsInit);
Note: See TracBrowser for help on using the browser.