1/*---------------------------------------------------------------------------*
2 *  PANSIFileSystemUNIXImpl.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#include <sys/types.h>
21#include <sys/stat.h>
22
23#include "errno.h"
24#include "PFileSystemImpl.h"
25#include "PANSIFileSystem.h"
26#include "PANSIFileSystemImpl.h"
27#include "phashtable.h"
28#include "LCHAR.h"
29#include "plog.h"
30
31ESR_ReturnCode PANSIFileSystemGetVirtualPathImpl(PFileSystem* self, LCHAR* path, size_t* len)
32{
33  PANSIFileSystemImpl* impl = (PANSIFileSystemImpl*) self;
34  PHashTableEntry* entry;
35  LCHAR driveLetter = 0;
36  LCHAR* key;
37  LCHAR* value;
38  LCHAR* bestKey = NULL;
39  LCHAR* bestValue = NULL;
40  ESR_BOOL isAbsolute;
41  ESR_ReturnCode rc;
42
43  CHKLOG(rc, lstrtrim(path));
44  CHKLOG(rc, PFileSystemCanonicalSlashes(path));
45  CHKLOG(rc, PFileSystemIsAbsolutePath(path, &isAbsolute));
46  if (isAbsolute && path[0] != L('/'))
47  {
48    /* Skip drive letters in absolute paths */
49    driveLetter = path[0];
50    LSTRCPY(path, path + 2);
51  }
52  CHKLOG(rc, PHashTableEntryGetFirst(impl->directoryMap, &entry));
53  while (entry!=NULL)
54  {
55    CHKLOG(rc, PHashTableEntryGetKeyValue(entry, (void **)&key, (void **)&value));
56    if (LSTRSTR(path, value)==path)
57    {
58      /* File-system handles file path */
59
60      if (bestValue==NULL || LSTRLEN(value) > LSTRLEN(bestValue))
61      {
62        /* Found a better match -- the new key is a subdirectory of the previous bestKey */
63        bestKey = key;
64        bestValue = value;
65      }
66    }
67    CHKLOG(rc, PHashTableEntryAdvance(&entry));
68  }
69  if (bestKey == NULL)
70  {
71    rc = ESR_INVALID_STATE;
72    PLogError(L("PANSIFileSystem does not handle the specified path: %s"), path);
73    goto CLEANUP;
74  }
75
76  /* Delete the real-path */
77  LSTRCPY(path, path + LSTRLEN(bestValue));
78  /* Insert the virtual-path */
79  CHKLOG(rc, lstrinsert(bestKey, path, 0, len));
80
81  /* Bring back the drive letter */
82  if (driveLetter!=0)
83  {
84    CHKLOG(rc, lstrinsert(L("X:/"), path, LSTRLEN(bestKey), len));
85    path[LSTRLEN(bestKey)] = driveLetter;
86  }
87  return ESR_SUCCESS;
88 CLEANUP:
89  return rc;
90}
91ESR_ReturnCode PANSIFileSystemMkdirImpl(PFileSystem* self, const LCHAR* path)
92{
93  LCHAR realPath[P_PATH_MAX];
94  size_t len;
95  ESR_ReturnCode rc;
96
97  passert(path!=NULL);
98  LSTRCPY(realPath, path);
99  len = P_PATH_MAX;
100  CHKLOG(rc, PANSIFileSystemGetRealPathImpl(self, realPath, &len));
101
102  if (mkdir(realPath, S_IRWXU|S_IRWXG|S_IRWXO ) != 0)
103    {
104      switch (errno)
105      {
106       case EEXIST:
107         return ESR_IDENTIFIER_COLLISION;
108       case ENOENT:
109         return ESR_NO_MATCH_ERROR;
110       default:
111         PLogError(L("ESR_INVALID_STATE"));
112         return ESR_INVALID_STATE;
113      }
114    }
115  return ESR_SUCCESS;
116CLEANUP:
117  return rc;
118}
119
120ESR_ReturnCode PANSIFileSystemGetcwdImpl(PFileSystem* self, LCHAR* path, size_t* len)
121{
122	ESR_ReturnCode rc;
123
124	if (path==NULL)
125	{
126		rc = ESR_INVALID_ARGUMENT;
127		PLogError(ESR_rc2str(rc));
128		goto CLEANUP;
129	}
130    if (getcwd(path, *len) == NULL)
131    {
132      switch (errno)
133      {
134       case ERANGE:
135         *len = P_PATH_MAX;
136         return ESR_BUFFER_OVERFLOW;
137       case ENOMEM:
138       default:
139         PLogError(L("ESR_INVALID_STATE"));
140         return ESR_INVALID_STATE;
141      }
142    }
143
144	CHKLOG(rc, PANSIFileSystemGetVirtualPathImpl(self, path, len));
145	return ESR_SUCCESS;
146CLEANUP:
147	return rc;
148}
149
150ESR_ReturnCode PANSIFileSystemChdirImpl(PFileSystem* self, const LCHAR* path)
151{
152	LCHAR realPath[P_PATH_MAX];
153	size_t len;
154	ESR_ReturnCode rc;
155
156	passert(path!=NULL);
157	LSTRCPY(realPath, path);
158	len = P_PATH_MAX;
159	CHKLOG(rc, PANSIFileSystemGetRealPathImpl(self, realPath, &len));
160
161	if ((*path != '\0') && (chdir(realPath) != 0))
162		return ESR_NO_MATCH_ERROR;
163	return ESR_SUCCESS;
164CLEANUP:
165	return rc;
166}
167