OSDN Git Service

db205cdc9f67595d8283ff2677acfbd094328875
[hos/hos-v4a.git] / aplfw / driver / volume / fat / fatvol_open.c
1 /** 
2  *  Hyper Operating System  Application Framework
3  *
4  * @file  fatvol.c
5  * @brief %jp{FATボリューム用デバイスドライバ}
6  *
7  * Copyright (C) 2006-2007 by Project HOS
8  * http://sourceforge.jp/projects/hos/
9  */
10
11
12 #include <string.h>
13 #include "fatvol_local.h"
14
15
16 HANDLE FatVol_Open(C_DRVOBJ *pDrvObj, const char *pszPath, int iMode)
17 {
18         C_FATVOL                        *self;
19         FATVOL_UINT                     uiCluster;
20         HANDLE                          hFile;
21         char                            szEntryName[8+1+3+1];
22         int                             iEntryNameLen;
23         char                            szName[8+1+3+1];
24         int                             iNameLen;
25         unsigned char           ubAttr;
26         FILE_POS                        FileSize;
27         T_FATVOL_CLUSTERBUF *pClusterBuf;
28         unsigned char           *pubBuf;
29         FATVOL_UINT                     uiDirCluster;   
30         FATVOL_UINT                     uiDirEntryPos;
31         int                                     iEntryHit;
32         int                             i;
33         
34         /* upper cast */
35         self = (C_FATVOL *)pDrvObj;
36         
37         
38         /* クリティカルセクションに入る */
39         SysMtx_Lock(self->hMtx);
40         
41         /* ルートディレクトリを設定 */
42         uiDirCluster  = self->RootDirCluster;
43         uiDirEntryPos = 0;
44         if ( (pClusterBuf = FatVol_GetClusterBuf(self, uiDirCluster, 1)) == NULL )
45         {
46                 SysMtx_Unlock(self->hMtx);
47                 return HANDLE_NULL;
48         }
49         
50         /* パス探索 */
51         for ( ; ; )
52         {
53                 /* 名前の部分を切り出し */
54                 for ( iNameLen = 0; iNameLen < sizeof(szName) && *pszPath != '\0'; pszPath++, iNameLen++ )
55                 {
56                         /* パス区切りなら抜ける */
57                         if ( *pszPath == '/' )
58                         {
59                                 pszPath++;
60                                 break;
61                         }
62                         szName[iNameLen] = *pszPath;
63                         
64                         /* 大文字に変換 */
65                         if ( szName[iNameLen] >= 'a' && szName[iNameLen] <= 'z' )
66                         {
67                                 szName[iNameLen] -= ('a' - 'A');
68                         }
69                 }
70                 szName[iNameLen] = '\0';
71                 
72                                 
73                 /* ディレクトリ自身を指す場合 */
74                 if ( iNameLen == 0 )
75                 {
76                         /* ディレクトリを閉じる */
77                         FatVol_RelClusterBuf(self, pClusterBuf, 0);
78
79                         /* ディレクトリ指定があれば開く */
80                         if ( iMode & FILE_OPEN_DIR )
81                         {
82                                 if ( (hFile = FatVol_FileCreate(self, uiDirCluster, FATVOL_CLUSTER_ENDMARKER, 0, 0, iMode)) != HANDLE_NULL )
83                                 {
84                                         self->iOpenCount++;
85                                         SysMtx_Unlock(self->hMtx);
86                                         return hFile;
87                                 }
88                         }
89                         
90                         /* エラー終了 */
91                         SysMtx_Unlock(self->hMtx);
92                         return HANDLE_NULL;                             
93                 }
94                 
95                 
96                 /* ディレクトリエントリを検索 */
97                 iEntryHit = 0;
98                 for ( ; ; )
99                 {
100                         /* ディレクトリエントリ位置 */
101                         pubBuf = &pClusterBuf->pubBuf[uiDirEntryPos];
102                 
103                         /* 0なら打ち切り */
104                         if ( pubBuf[0] == 0x00 )
105                         {
106                                 break;
107                         }
108                         
109                         /* 名前部分取り出し */
110                         iEntryNameLen = 0;
111                         for ( i = 0; i < 8; i++ )
112                         {
113                                 if ( pubBuf[0+i] == ' ' || pubBuf[0+i] == '\0' )
114                                 {
115                                         break;
116                                 }
117                                 szEntryName[iEntryNameLen++] = (char)pubBuf[0+i];
118                         }
119                         szEntryName[iEntryNameLen++] = '.';
120                         for ( i = 0; i < 3; i++ )
121                         {
122                                 if ( pubBuf[8+i] == ' ' || pubBuf[8+i] == '\0' )
123                                 {
124                                         break;
125                                 }
126                                 szEntryName[iEntryNameLen++] = (char)pubBuf[8+i];
127                         }
128                         szEntryName[iEntryNameLen] = '\0';
129                         if ( iEntryNameLen > 2 && szEntryName[iEntryNameLen-1] == '.' )
130                         {
131                                 szEntryName[--iEntryNameLen] = '\0';
132                         }
133                         
134                         /* 名前比較 */
135                         if ( strcmp(szEntryName, szName) == 0 )
136                         {
137                                 iEntryHit = 1;
138                                 break;
139                         }
140                         
141                         /* シーク */
142                         uiDirEntryPos += 32;
143                         if ( uiDirEntryPos >= self->BytesPerCluster )
144                         {
145                                 FatVol_RelClusterBuf(self, pClusterBuf, 0);
146                                 uiDirCluster = FatVol_GetNextCluster(self, uiDirCluster);
147                                 if ( uiDirCluster == FATVOL_CLUSTER_ENDMARKER
148                                         || (pClusterBuf = FatVol_GetClusterBuf(self, uiDirCluster, 1)) == NULL )
149                                 {
150                                         SysMtx_Unlock(self->hMtx);
151                                         return HANDLE_NULL;
152                                 }
153                                 uiDirEntryPos = 0;
154                         }
155                 }
156                 
157                 /* 見つからなければエラー */
158                 if ( !iEntryHit )
159                 {
160                         FatVol_RelClusterBuf(self, pClusterBuf, 0);
161                         SysMtx_Unlock(self->hMtx);
162                         return HANDLE_NULL;
163                 }
164                 
165                 /* 開始クラスタ取得 */
166                 uiCluster = pubBuf[26] + (pubBuf[27] << 8);
167                 if ( self->iFatType == FATVOL_TYPE_FAT32 )
168                 {
169                         uiCluster += (pubBuf[20] << 16) + (pubBuf[21] << 24);
170                 }
171
172                 /* 属性取得 */ 
173                 ubAttr = pubBuf[11];
174                 
175                 /* サイズ取得 */
176                 FileSize = pubBuf[28] + (pubBuf[29] << 8) + (pubBuf[30] << 16) + (pubBuf[31] << 24);
177
178                 /* 親ディレクトリを閉じる */
179                 FatVol_RelClusterBuf(self, pClusterBuf, 0);
180
181                 
182                 /* パス部分の解析が終わっていればここで抜ける */
183                 if ( *pszPath == '\0' )
184                 {
185                         break;
186                 }
187                 
188                 /* サブディレクトリでなければエラー */
189                 if ( !(ubAttr & 0x10) )
190                 {
191                         SysMtx_Unlock(self->hMtx);
192                         return HANDLE_NULL;
193                 }
194                 
195                 /* サブディレクトリを開く */
196                 uiDirCluster = uiCluster;
197                 uiDirEntryPos = 0;
198                 if ( (pClusterBuf = FatVol_GetClusterBuf(self, uiDirCluster, 1)) == NULL )
199                 {
200                         SysMtx_Unlock(self->hMtx);
201                         return HANDLE_NULL;
202                 }
203         }
204         
205         /* モードチェック */
206         if ( iMode & FILE_OPEN_DIR )
207         {
208                 SysMtx_Unlock(self->hMtx);
209                 return HANDLE_NULL;             
210         }
211         
212         /* ファイルディスクリプタを作成 */
213         hFile = FatVol_FileCreate(self, uiCluster, uiDirCluster, uiDirEntryPos, FileSize, iMode);
214         if ( hFile != HANDLE_NULL )
215         {
216                 self->iOpenCount++;
217         }
218         
219         /* クリティカルセクションを出る */
220         SysMtx_Unlock(self->hMtx);
221         
222         return hFile;
223 }
224
225