1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     fslow_IArchive.h
4 
5   Copyright (C)2009 Nintendo Co., Ltd.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Rev: 29386 $
14  *---------------------------------------------------------------------------*/
15 
16 #ifndef NN_FSLOW_FSLOW_ARCHIVEMAPFILESYSTEM_H_
17 #define NN_FSLOW_FSLOW_ARCHIVEMAPFILESYSTEM_H_
18 
19 #include <nn/Result.h>
20 #include <nn/fs/fs_Result.h>
21 #include <nn/util/util_Result.h>
22 
23 #pragma push
24 #pragma diag_suppress 2817
25 // #2817-D: temporary used for conditional class rvalue result (C++ core issue #446 resolution) 対策
26 #include <map>
27 #pragma pop
28 
29 #include <nn/fslow/fslow_IArchive.h>
30 
31 namespace nn { namespace fslow {
32 
33 template <class Self, class TFileSystemTypeInfo, class TArchiveHandleTable, class ArchiveName>
34 class ArchiveMapFileSystem
35 {
36 public:
37     // スレッドセーフティ?
38 
39     typedef typename TFileSystemTypeInfo::Archive Archive;
40     typedef typename TFileSystemTypeInfo::File File;
41     typedef typename TFileSystemTypeInfo::Directory Directory;
42     typedef typename TFileSystemTypeInfo::FileHandle FileHandle;
43     typedef typename TFileSystemTypeInfo::DirectoryHandle DirectoryHandle;
44     typedef typename TFileSystemTypeInfo::Path Path;
45     typedef typename TFileSystemTypeInfo::DirectoryEntry DirectoryEntry;
46     typedef TArchiveHandleTable ArchiveHandleTable;
47     typedef typename ArchiveHandleTable::Handle ArchiveHandle;
48 
49     // Self に CRTP で要求するインターフェイス
50     //     ArchiveHandleTable& GetHandleTable();
51     //     Result RegisterToNameMap(ArchiveName, ArchiveHandle);
52     //     void UnregisterFromNameMap(ArchiveName);
53     //     ArchiveName GetArchiveName(Path);
54     //     Path GetPathString(Path);
55 
56 private:
57 
GetSelf()58     Self& GetSelf() { return static_cast<Self&>(*this); }
GetSelf()59     const Self& GetSelf() const { return static_cast<const Self&>(*this); }
60 
61     typedef typename ArchiveHandleTable::Accessor Accessor;
62 
63 public:
64 
AddArchive(const ArchiveName & name,Archive archive)65     Result AddArchive(const ArchiveName& name, Archive archive)
66     {
67         ArchiveHandle handle = GetSelf().GetHandleTable().Register(archive);
68         if (!handle)
69         {
70             return nn::fs::ResultHandleTableFull();
71         }
72         Result result = GetSelf().RegisterToNameMap(name, handle);
73         if (result.IsFailure())
74         {
75             GetSelf().GetHandleTable().Unregister(handle);
76         }
77         return result;
78     }
79 
RemoveArchive(const ArchiveName & name)80     Result RemoveArchive(const ArchiveName& name)
81     {
82         ArchiveHandle handle;
83         NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle, name));
84         GetSelf().UnregisterFromNameMap(name);
85         GetSelf().GetHandleTable().Unregister(handle);
86         return nn::ResultSuccess();
87     }
88 
OpenFile(FileHandle * pOut,nn::fs::Transaction transaction,Path path,bit32 mode,nn::fs::Attributes attributes)89     Result OpenFile(FileHandle* pOut, nn::fs::Transaction transaction, Path path, bit32 mode, nn::fs::Attributes attributes)
90     {
91         nn::fs::PathMark pathMark;
92         pathMark.rawPathMark = 0;
93         return OpenFile( pOut, transaction, path, pathMark, mode, attributes);
94     }
95 
OpenFile(FileHandle * pOut,nn::fs::Transaction transaction,Path path,nn::fs::PathMark pathMark,bit32 mode,nn::fs::Attributes attributes)96     Result OpenFile(FileHandle* pOut, nn::fs::Transaction transaction, Path path, nn::fs::PathMark pathMark, bit32 mode, nn::fs::Attributes attributes)
97     {
98         ArchiveName name = GetSelf().GetArchiveName(path);
99         if (!name.IsValid())
100         {
101             return nn::fs::ResultInvalidPathFormat();
102         }
103         ArchiveHandle handle;
104         NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle, name));
105         File file;
106         {
107             Accessor acc(GetSelf().GetHandleTable(), handle);
108             if (!acc)
109             {
110                 return nn::fs::ResultArchiveInvalidated();
111             }
112             NN_UTIL_RETURN_IF_FAILED(acc->OpenFile(&file, transaction, GetSelf().GetPathString(Move(path)), pathMark, mode, attributes));
113         }
114         *pOut = FileHandle(handle, file);
115         return nn::ResultSuccess();
116     }
117 
ReadFile(s32 * pOut,const FileHandle & handle,s64 offset,void * buffer,size_t size)118     Result ReadFile(s32* pOut, const FileHandle& handle, s64 offset, void* buffer, size_t size)
119     {
120         Accessor acc(GetSelf().GetHandleTable(), handle.archiveHandle);
121         if (!acc)
122         {
123             return nn::fs::ResultArchiveInvalidated();
124         }
125         return handle.p->ReadBytes(pOut, offset, buffer, size);
126     }
127 
WriteFile(s32 * pOut,const FileHandle & handle,s64 offset,const void * buffer,size_t size)128     Result WriteFile(s32* pOut, const FileHandle& handle, s64 offset, const void* buffer, size_t size)
129     {
130         Accessor acc(GetSelf().GetHandleTable(), handle.archiveHandle);
131         if (!acc)
132         {
133             return nn::fs::ResultArchiveInvalidated();
134         }
135         return handle.p->WriteBytes(pOut, offset, buffer, size, nn::fs::WriteOption(true));
136     }
137 
GetFileSize(s64 * pOut,const FileHandle & handle)138     Result GetFileSize(s64* pOut, const FileHandle& handle)
139     {
140         Accessor acc(GetSelf().GetHandleTable(), handle.archiveHandle);
141         if (!acc)
142         {
143             return nn::fs::ResultArchiveInvalidated();
144         }
145         return handle.p->GetSize(pOut);
146     }
147 
SetFileSize(const FileHandle & handle,s64 size)148     Result SetFileSize(const FileHandle& handle, s64 size)
149     {
150         Accessor acc(GetSelf().GetHandleTable(), handle.archiveHandle);
151         if (!acc)
152         {
153             return nn::fs::ResultArchiveInvalidated();
154         }
155         return handle.p->SetSize(size);
156     }
157 
CloseFile(const FileHandle & handle)158     Result CloseFile(const FileHandle& handle)
159     {
160         Accessor acc(GetSelf().GetHandleTable(), handle.archiveHandle);
161         if (!acc)
162         {
163             return nn::fs::ResultArchiveInvalidated();
164         }
165         Result result = handle.p->Close();
166         acc->FreeFileObject(handle.p);
167         return result;
168     }
169 
OpenDirectory(DirectoryHandle * pOut,Path path)170     Result OpenDirectory(DirectoryHandle* pOut, Path path)
171     {
172         ArchiveName name = GetSelf().GetArchiveName(path);
173         if (!name.IsValid())
174         {
175             return nn::fs::ResultInvalidPathFormat();
176         }
177         ArchiveHandle handle;
178         NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle, name));
179         Directory directory;
180         {
181             Accessor acc(GetSelf().GetHandleTable(), handle);
182             if (!acc)
183             {
184                 return nn::fs::ResultArchiveInvalidated();
185             }
186             NN_UTIL_RETURN_IF_FAILED(acc->OpenDirectory(&directory, GetSelf().GetPathString(Move(path))));
187         }
188         *pOut = DirectoryHandle(handle, directory);
189         return nn::ResultSuccess();
190     }
191 
ReadDirectory(s32 * pNumEntriesOut,const DirectoryHandle & handle,DirectoryEntry entries[],s32 numEntries)192     Result ReadDirectory(s32* pNumEntriesOut, const DirectoryHandle& handle, DirectoryEntry entries[], s32 numEntries)
193     {
194         Accessor acc(GetSelf().GetHandleTable(), handle.archiveHandle);
195         if (!acc)
196         {
197             return nn::fs::ResultArchiveInvalidated();
198         }
199         return handle.p->Read(pNumEntriesOut, entries, numEntries);
200     }
201 
CloseDirectory(const DirectoryHandle & handle)202     Result CloseDirectory(const DirectoryHandle& handle)
203     {
204         Accessor acc(GetSelf().GetHandleTable(), handle.archiveHandle);
205         if (!acc)
206         {
207             return nn::fs::ResultArchiveInvalidated();
208         }
209         Result result = handle.p->Close();
210         acc->FreeDirectoryObject(handle.p);
211         return result;
212     }
213 
DeleteFile(nn::fs::Transaction transaction,Path path)214     Result DeleteFile(nn::fs::Transaction transaction, Path path)
215     {
216         ArchiveName name = GetSelf().GetArchiveName(path);
217         if (!name.IsValid())
218         {
219             return nn::fs::ResultInvalidPathFormat();
220         }
221         ArchiveHandle handle;
222         NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle, name));
223         {
224             Accessor acc(GetSelf().GetHandleTable(), handle);
225             if (!acc)
226             {
227                 return nn::fs::ResultArchiveInvalidated();
228             }
229             NN_UTIL_RETURN_IF_FAILED(acc->DeleteFile(transaction, GetSelf().GetPathString(Move(path))));
230         }
231         return nn::ResultSuccess();
232     }
233 
DeleteDirectory(nn::fs::Transaction transaction,Path path)234     Result DeleteDirectory(nn::fs::Transaction transaction, Path path)
235     {
236         ArchiveName name = GetSelf().GetArchiveName(path);
237         if (!name.IsValid())
238         {
239             return nn::fs::ResultInvalidPathFormat();
240         }
241         ArchiveHandle handle;
242         NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle, name));
243         {
244             Accessor acc(GetSelf().GetHandleTable(), handle);
245             if (!acc)
246             {
247                 return nn::fs::ResultArchiveInvalidated();
248             }
249             NN_UTIL_RETURN_IF_FAILED(acc->DeleteDirectory(transaction, GetSelf().GetPathString(Move(path))));
250         }
251         return nn::ResultSuccess();
252     }
253 
DeleteDirectoryRecursively(nn::fs::Transaction transaction,Path path)254     Result DeleteDirectoryRecursively(nn::fs::Transaction transaction, Path path)
255     {
256         ArchiveName name = GetSelf().GetArchiveName(path);
257         if (!name.IsValid())
258         {
259             return nn::fs::ResultInvalidPathFormat();
260         }
261         ArchiveHandle handle;
262         NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle, name));
263         {
264             Accessor acc(GetSelf().GetHandleTable(), handle);
265             if (!acc)
266             {
267                 return nn::fs::ResultArchiveInvalidated();
268             }
269             NN_UTIL_RETURN_IF_FAILED(acc->DeleteDirectoryRecursively(transaction, GetSelf().GetPathString(Move(path))));
270         }
271         return nn::ResultSuccess();
272     }
273 
CreateFile(nn::fs::Transaction transaction,Path path,nn::fs::Attributes attributes,s64 size)274     Result CreateFile(nn::fs::Transaction transaction, Path path, nn::fs::Attributes attributes, s64 size)
275     {
276         ArchiveName name = GetSelf().GetArchiveName(path);
277         if (!name.IsValid())
278         {
279             return nn::fs::ResultInvalidPathFormat();
280         }
281         ArchiveHandle handle;
282         NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle, name));
283         {
284             Accessor acc(GetSelf().GetHandleTable(), handle);
285             if (!acc)
286             {
287                 return nn::fs::ResultArchiveInvalidated();
288             }
289             NN_UTIL_RETURN_IF_FAILED(acc->CreateFile(transaction, GetSelf().GetPathString(Move(path)), attributes, size));
290         }
291         return nn::ResultSuccess();
292     }
293 
CreateDirectory(nn::fs::Transaction transaction,Path path,nn::fs::Attributes attributes)294     Result CreateDirectory(nn::fs::Transaction transaction, Path path, nn::fs::Attributes attributes)
295     {
296         ArchiveName name = GetSelf().GetArchiveName(path);
297         if (!name.IsValid())
298         {
299             return nn::fs::ResultInvalidPathFormat();
300         }
301         ArchiveHandle handle;
302         NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle, name));
303         {
304             Accessor acc(GetSelf().GetHandleTable(), handle);
305             if (!acc)
306             {
307                 return nn::fs::ResultArchiveInvalidated();
308             }
309             NN_UTIL_RETURN_IF_FAILED(acc->CreateDirectory(transaction, GetSelf().GetPathString(Move(path)), attributes));
310         }
311         return nn::ResultSuccess();
312     }
313 
RenameFile(nn::fs::Transaction transaction,Path oldPath,Path newPath)314     Result RenameFile(nn::fs::Transaction transaction, Path oldPath, Path newPath)
315     {
316         ArchiveHandle handle1, handle2;
317         {
318             ArchiveName name = GetSelf().GetArchiveName(oldPath);
319             if (!name.IsValid())
320             {
321                 return nn::fs::ResultInvalidPathFormat();
322             }
323             NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle1, name));
324         }
325         {
326             ArchiveName name = GetSelf().GetArchiveName(newPath);
327             if (!name.IsValid())
328             {
329                 return nn::fs::ResultInvalidPathFormat();
330             }
331             NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle2, name));
332         }
333         if (handle1 != handle2)
334         {
335             return nn::fs::ResultUnsupportedOperation();
336         }
337         {
338             Accessor acc(GetSelf().GetHandleTable(), handle1);
339             if (!acc)
340             {
341                 return nn::fs::ResultArchiveInvalidated();
342             }
343             NN_UTIL_RETURN_IF_FAILED(acc->RenameFile(transaction, GetSelf().GetPathString(Move(oldPath)), GetSelf().GetPathString(Move(newPath))));
344         }
345         return nn::ResultSuccess();
346     }
347 
RenameDirectory(nn::fs::Transaction transaction,Path oldPath,Path newPath)348     Result RenameDirectory(nn::fs::Transaction transaction, Path oldPath, Path newPath)
349     {
350         ArchiveHandle handle1, handle2;
351         {
352             ArchiveName name = GetSelf().GetArchiveName(oldPath);
353             if (!name.IsValid())
354             {
355                 return nn::fs::ResultInvalidPathFormat();
356             }
357             NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle1, name));
358         }
359         {
360             ArchiveName name = GetSelf().GetArchiveName(newPath);
361             if (!name.IsValid())
362             {
363                 return nn::fs::ResultInvalidPathFormat();
364             }
365             NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle2, name));
366         }
367         if (handle1 != handle2)
368         {
369             return nn::fs::ResultUnsupportedOperation();
370         }
371         {
372             Accessor acc(GetSelf().GetHandleTable(), handle1);
373             if (!acc)
374             {
375                 return nn::fs::ResultArchiveInvalidated();
376             }
377             NN_UTIL_RETURN_IF_FAILED(acc->RenameDirectory(transaction, GetSelf().GetPathString(Move(oldPath)), GetSelf().GetPathString(Move(newPath))));
378         }
379         return nn::ResultSuccess();
380     }
381 
GetPathMark(nn::fs::PathMark * pathMark,Path path)382     Result GetPathMark( nn::fs::PathMark* pathMark, Path path)
383     {
384         ArchiveName name = GetSelf().GetArchiveName(path);
385         if (!name.IsValid())
386         {
387             return nn::fs::ResultInvalidPathFormat();
388         }
389         ArchiveHandle handle;
390         NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle, name));
391         {
392             Accessor acc(GetSelf().GetHandleTable(), handle);
393             if (!acc)
394             {
395                 return nn::fs::ResultArchiveInvalidated();
396             }
397             NN_UTIL_RETURN_IF_FAILED(acc->GetPathMark( pathMark, GetSelf().GetPathString(Move(path))));
398         }
399         return nn::ResultSuccess();
400     }
401 
HasFile(bool * pOut,Path path)402     Result HasFile(bool* pOut, Path path)
403     {
404         FileHandle* p;
405         Result result = OpenFile(p, nn::fs::Transaction(), path, nn::fs::OPEN_MODE_READ, nn::fs::Attributes());
406         if (result.IsFailure())
407         {
408             if (result <= nn::fs::ResultNotFound())
409             {
410                 *pOut = false;
411                 return ResultSuccess();
412             }
413             else
414             {
415                 return result;
416             }
417         }
418         p->p->Close();
419         CloseFile(*p);
420         *pOut = true;
421         return ResultSuccess();
422     }// TORIAEZU
423 
HasDirectory(bool * pOut,Path path)424     Result HasDirectory(bool* pOut, Path path)
425     {
426         DirectoryHandle* p;
427         Result result = OpenDirectory(p, path);
428         if (result.IsFailure())
429         {
430             if (result <= nn::fs::ResultNotFound())
431             {
432                 *pOut = false;
433                 return ResultSuccess();
434             }
435             else
436             {
437                 return result;
438             }
439         }
440         p->p->Close();
441         CloseDirectory(*p);
442         *pOut = true;
443         return ResultSuccess();
444     }// TORIAEZU
445 };
446 
447 }}
448 
449 #endif
450