• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*---------------------------------------------------------------------------*
2  *  PANSIFileSystemImpl.c  *
3  *                                                                           *
4  *  Copyright 2007, 2008 Nuance Communciations, Inc.                               *
5  *                                                                           *
6  *  Licensed under the Apache License, Version 2.0 (the 'License');          *
7  *  you may not use this file except in compliance with the License.         *
8  *                                                                           *
9  *  You may obtain a copy of the License at                                  *
10  *      http://www.apache.org/licenses/LICENSE-2.0                           *
11  *                                                                           *
12  *  Unless required by applicable law or agreed to in writing, software      *
13  *  distributed under the License is distributed on an 'AS IS' BASIS,        *
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
15  *  See the License for the specific language governing permissions and      *
16  *  limitations under the License.                                           *
17  *                                                                           *
18  *---------------------------------------------------------------------------*/
19 
20 
21 #include "LCHAR.h"
22 #include "PFileSystemImpl.h"
23 #include "PANSIFileSystemImpl.h"
24 #include "PANSIFileImpl.h"
25 #include "plog.h"
26 #include "pmemory.h"
27 
28 //extern PFileSystem* PANSIFileSystemSingleton;
29 PFileSystem* PANSIFileSystemSingleton = (PFileSystem*)NULL;
30 
31 #define MTAG NULL
32 
33 
34 #ifdef USE_THREAD
35 /* Prototype of private function */
36 PORTABLE_API ESR_ReturnCode PtrdFlush();
37 #endif
38 
39 /**
40  * [file path, PFileSystem*] mapping.
41  */
42 extern PHashTable* PFileSystemPathMap;
43 
44 
PANSIFileSystemCreate(void)45 ESR_ReturnCode PANSIFileSystemCreate(void)
46 {
47   PANSIFileSystemImpl* impl;
48   ESR_ReturnCode rc;
49 
50   if (PANSIFileSystemSingleton != NULL)
51     return ESR_SUCCESS;
52   impl = NEW(PANSIFileSystemImpl, MTAG);
53   if (impl == NULL)
54     return ESR_OUT_OF_MEMORY;
55   impl->super.super.destroy = &PANSIFileSystemDestroyImpl;
56   impl->super.super.createPFile = &PANSIFileSystemCreatePFileImpl;
57   impl->super.addPath = &PANSIFileSystemAddPathImpl;
58   impl->super.removePath = &PANSIFileSystemRemovePathImpl;
59   impl->super.getcwd = &PANSIFileSystemGetcwdImpl;
60   impl->super.super.mkdir = &PANSIFileSystemMkdirImpl;
61   impl->super.super.chdir = &PANSIFileSystemChdirImpl;
62 
63   CHKLOG(rc, PHashTableCreate(NULL, MTAG, &impl->directoryMap));
64   PANSIFileSystemSingleton = &impl->super.super;
65   return ESR_SUCCESS;
66 CLEANUP:
67   return rc;
68 }
69 
PANSIFileSystemDestroyImpl(PFileSystem * self)70 ESR_ReturnCode PANSIFileSystemDestroyImpl(PFileSystem* self)
71 {
72   PANSIFileSystemImpl* impl = (PANSIFileSystemImpl*) self;
73   PHashTableEntry* entry;
74   PHashTableEntry* oldEntry;
75   LCHAR* key;
76   LCHAR* value;
77   ESR_ReturnCode rc;
78 
79   if (impl->directoryMap != NULL)
80   {
81     CHKLOG(rc, PHashTableEntryGetFirst(impl->directoryMap, &entry));
82     while (entry != NULL)
83     {
84       CHKLOG(rc, PHashTableEntryGetKeyValue(entry, (void **)&key, (void **)&value));
85       oldEntry = entry;
86       CHKLOG(rc, PHashTableEntryAdvance(&entry));
87       CHKLOG(rc, PHashTableEntryRemove(oldEntry));
88       CHKLOG(rc, PHashTableRemoveValue(PFileSystemPathMap, key, NULL));
89       FREE(key);
90       FREE(value);
91     }
92     CHKLOG(rc, PHashTableDestroy(impl->directoryMap));
93     impl->directoryMap = NULL;
94   }
95   FREE(self);
96   return ESR_SUCCESS;
97 CLEANUP:
98   return rc;
99 }
100 
PANSIFileSystemAddPathImpl(PFileSystem * self,const LCHAR * virtualPath,const LCHAR * realPath)101 ESR_ReturnCode PANSIFileSystemAddPathImpl(PFileSystem* self, const LCHAR* virtualPath, const LCHAR* realPath)
102 {
103   PANSIFileSystemImpl* impl = (PANSIFileSystemImpl*) self;
104   ESR_BOOL exists;
105   LCHAR* key = NULL;
106   LCHAR* value = NULL;
107   ESR_ReturnCode rc;
108   size_t len;
109 
110   if (virtualPath == NULL || realPath == NULL)
111   {
112     rc = ESR_INVALID_ARGUMENT;
113     PLogError(ESR_rc2str(rc));
114     goto CLEANUP;
115   }
116 
117   len = LSTRLEN(virtualPath) + 1;
118   if (virtualPath[LSTRLEN(virtualPath)-1] != L('/'))
119     ++len;
120   key = MALLOC(sizeof(LCHAR) * len, MTAG);
121   if (key == NULL)
122   {
123     rc = ESR_OUT_OF_MEMORY;
124     PLogError(ESR_rc2str(rc));
125     goto CLEANUP;
126   }
127   LSTRCPY(key, virtualPath);
128   /* Make sure paths end with '/' */
129   CHKLOG(rc, PFileSystemCanonicalSlashes(key));
130   if (key[LSTRLEN(key)-1] != L('/'))
131     LSTRCAT(key, L("/"));
132   value = MALLOC(sizeof(LCHAR) * (LSTRLEN(realPath) + 1), MTAG);
133   if (value == NULL)
134   {
135     rc = ESR_OUT_OF_MEMORY;
136     PLogError(ESR_rc2str(rc));
137     goto CLEANUP;
138   }
139   LSTRCPY(value, realPath);
140 
141   /* Make sure realPath is not an empty string */
142   lstrtrim(value);
143   if (LSTRLEN(value) == 0)
144   {
145     FREE(value);
146     value = NULL;
147     rc = ESR_INVALID_ARGUMENT;
148     PLogError(L("%s: realPath cannot be empty"), ESR_rc2str(rc));
149     goto CLEANUP;
150   }
151 
152   /* Make sure paths end with '/' */
153   CHKLOG(rc, PFileSystemCanonicalSlashes(value));
154   if (value[LSTRLEN(value)-1] != L('/'))
155     LSTRCAT(value, L("/"));
156 
157   CHKLOG(rc, PHashTableContainsKey(impl->directoryMap, key, &exists));
158   if (exists)
159   {
160     LCHAR* oldValue;
161 
162     CHKLOG(rc, PHashTableGetValue(impl->directoryMap, key, (void **)&oldValue));
163     if (LSTRCMP(oldValue, value) != 0)
164     {
165       rc = ESR_IDENTIFIER_COLLISION;
166       PLogError(ESR_rc2str(rc));
167       goto CLEANUP;
168     }
169   }
170   CHKLOG(rc, PHashTablePutValue(impl->directoryMap, key, value, NULL));
171   CHKLOG(rc, PHashTablePutValue(PFileSystemPathMap, key, self, NULL));
172   return ESR_SUCCESS;
173 CLEANUP:
174   FREE(key);
175   FREE(value);
176   return rc;
177 }
178 
PANSIFileSystemRemovePathImpl(PFileSystem * self,const LCHAR * virtualPath)179 ESR_ReturnCode PANSIFileSystemRemovePathImpl(PFileSystem* self, const LCHAR* virtualPath)
180 {
181   PANSIFileSystemImpl* impl = (PANSIFileSystemImpl*) self;
182   LCHAR path[P_PATH_MAX];
183   LCHAR* key;
184   LCHAR* value;
185   PHashTableEntry* entry;
186   ESR_ReturnCode rc;
187 
188   if (virtualPath == NULL)
189   {
190     rc = ESR_INVALID_ARGUMENT;
191     PLogError(ESR_rc2str(rc));
192     goto CLEANUP;
193   }
194   /* Make sure paths end with '/' */
195   LSTRCPY(path, virtualPath);
196   CHKLOG(rc, PFileSystemCanonicalSlashes(path));
197   if (path[LSTRLEN(path)-1] != L('/'))
198     LSTRCAT(path, L("/"));
199   CHKLOG(rc, PHashTableGetEntry(impl->directoryMap, path, &entry));
200   CHKLOG(rc, PHashTableEntryGetKeyValue(entry, (void **)&key, (void **)&value));
201   CHKLOG(rc, PHashTableEntryRemove(entry));
202   CHKLOG(rc, PHashTableRemoveValue(PFileSystemPathMap, key, NULL));
203   FREE(key);
204   FREE(value);
205   return ESR_SUCCESS;
206 CLEANUP:
207   return rc;
208 }
209 
PANSIFileSystemGetRealPathImpl(PFileSystem * self,LCHAR * path,size_t * len)210 ESR_ReturnCode PANSIFileSystemGetRealPathImpl(PFileSystem* self, LCHAR* path, size_t* len)
211 {
212   PANSIFileSystemImpl* impl = (PANSIFileSystemImpl*) self;
213   PHashTableEntry* entry;
214   LCHAR* key;
215   LCHAR* value;
216   LCHAR* bestKey = NULL;
217   LCHAR* bestValue = NULL;
218   ESR_BOOL isAbsolute;
219   ESR_ReturnCode rc;
220 
221   CHKLOG(rc, PFileSystemGetAbsolutePath(path, len));
222   CHKLOG(rc, PHashTableEntryGetFirst(impl->directoryMap, &entry));
223   while (entry != NULL)
224   {
225     CHKLOG(rc, PHashTableEntryGetKeyValue(entry, (void**)&key, (void**)&value));
226     if (LSTRNCMP(path, key, LSTRLEN(key)) == 0)
227     {
228       /* File-system handles file path */
229       if (bestKey == NULL || LSTRLEN(key) > LSTRLEN(bestKey))
230       {
231         /* Found a better match -- the new key is a subdirectory of the previous bestKey */
232         bestKey = key;
233         bestValue = value;
234       }
235     }
236     CHKLOG(rc, PHashTableEntryAdvance(&entry));
237   }
238   if (bestKey == NULL)
239   {
240     rc = ESR_INVALID_STATE;
241     PLogError(L("PANSIFileSystem does not handle the specified path: %s"), path);
242     goto CLEANUP;
243   }
244 
245   if (LSTRLEN(bestValue) + 1 > *len)
246   {
247     *len = LSTRLEN(bestValue) + 1;
248     rc = ESR_BUFFER_OVERFLOW;
249     PLogError(ESR_rc2str(rc));
250     goto CLEANUP;
251   }
252   /* Delete the virtual-path */
253   LSTRCPY(path, path + LSTRLEN(bestKey));
254 
255   CHKLOG(rc, PFileSystemIsAbsolutePath(path, &isAbsolute));
256   if (LSTRCMP(bestValue, L("/")) == 0 && isAbsolute)
257   {
258     /* do nothing */
259   }
260   else
261   {
262     /* Insert the key-path */
263     CHKLOG(rc, lstrinsert(bestValue, path, 0, len));
264   }
265   return ESR_SUCCESS;
266 CLEANUP:
267   return rc;
268 }
269 
PANSIFileSystemCreatePFileImpl(PFileSystem * self,const LCHAR * path,ESR_BOOL littleEndian,PFile ** file)270 ESR_ReturnCode PANSIFileSystemCreatePFileImpl(PFileSystem* self, const LCHAR* path, ESR_BOOL littleEndian, PFile** file)
271 {
272   LCHAR realPath[P_PATH_MAX];
273   size_t len;
274   ESR_ReturnCode rc;
275 
276   LSTRCPY(realPath, path);
277   len = P_PATH_MAX;
278   CHKLOG(rc, PANSIFileSystemGetRealPathImpl(self, realPath, &len));
279   return PANSIFileCreateImpl(realPath, littleEndian, file);
280 CLEANUP:
281   return rc;
282 }
283 
PANSIFileSystemSetDefault(ESR_BOOL isDefault)284 ESR_ReturnCode PANSIFileSystemSetDefault(ESR_BOOL isDefault)
285 {
286   PANSIFileSystemImpl* impl = (PANSIFileSystemImpl*) PANSIFileSystemSingleton;
287   ESR_BOOL exists;
288   LCHAR* key = NULL;
289   LCHAR* value = NULL;
290   PHashTableEntry* entry;
291   ESR_ReturnCode rc;
292 
293   if (isDefault)
294   {
295 
296 		key = MALLOC(sizeof(LCHAR), MTAG);
297     if (key == NULL)
298     {
299       rc = ESR_OUT_OF_MEMORY;
300       PLogError(ESR_rc2str(rc));
301       goto CLEANUP;
302     }
303     LSTRCPY(key, L(""));
304     value = MALLOC(sizeof(LCHAR), MTAG);
305     if (value == NULL)
306     {
307       rc = ESR_OUT_OF_MEMORY;
308       PLogError(ESR_rc2str(rc));
309       goto CLEANUP;
310     }
311     LSTRCPY(value, L(""));
312 
313     CHKLOG(rc, PHashTableContainsKey(impl->directoryMap, key, &exists));
314     if (exists)
315     {
316       LCHAR* key;
317       LCHAR* value;
318 
319       CHKLOG(rc, PHashTableGetEntry(impl->directoryMap, L(""), &entry));
320       CHKLOG(rc, PHashTableEntryGetKeyValue(entry, (void **)&key, (void **)&value));
321       CHKLOG(rc, PHashTableEntryRemove(entry));
322       CHKLOG(rc, PHashTableRemoveValue(PFileSystemPathMap, key, NULL));
323       FREE(key);
324       FREE(value);
325     }
326     CHKLOG(rc, PHashTablePutValue(impl->directoryMap, key, value, NULL));
327     CHKLOG(rc, PHashTablePutValue(PFileSystemPathMap, key, PANSIFileSystemSingleton, NULL));
328 
329 		/* Set virtual current working directory to native current working directory */
330   }
331   else
332   {
333     CHKLOG(rc, PHashTableContainsKey(impl->directoryMap, L(""), &exists));
334     if (exists)
335     {
336       LCHAR* key;
337       LCHAR* value;
338 
339       CHKLOG(rc, PHashTableGetEntry(impl->directoryMap, L(""), &entry));
340       CHKLOG(rc, PHashTableEntryGetKeyValue(entry, (void **)&key, (void **)&value));
341 
342       CHKLOG(rc, PHashTableContainsKey(PFileSystemPathMap, L(""), &exists));
343       if (exists)
344       {
345         LCHAR* key;
346         PFileSystem* value;
347         PHashTableEntry* entry;
348 
349         CHKLOG(rc, PHashTableGetEntry(PFileSystemPathMap, L(""), &entry));
350         CHKLOG(rc, PHashTableEntryGetKeyValue(entry, (void **)&key, (void **)&value));
351         if (value == PANSIFileSystemSingleton)
352           CHKLOG(rc, PHashTableEntryRemove(entry));
353       }
354 
355       CHKLOG(rc, PHashTableEntryRemove(entry));
356       FREE(key);
357       FREE(value);
358     }
359   }
360   return ESR_SUCCESS;
361 CLEANUP:
362   FREE(key);
363   FREE(value);
364   return rc;
365 }
366