Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "osl/file.h"
21 :
22 : #include "osl/diagnose.h"
23 : #include "osl/thread.h"
24 : #include "rtl/alloc.h"
25 :
26 : #include "file_error_transl.h"
27 : #include "file_url.h"
28 : #include "system.h"
29 :
30 : #include <errno.h>
31 : #include <limits.h>
32 : #include <stdio.h>
33 : #include <string.h>
34 : #include <unistd.h>
35 : #include <sys/wait.h>
36 : #include <sal/macros.h>
37 :
38 : #ifdef HAVE_STATFS_H
39 : #undef HAVE_STATFS_H
40 : #endif
41 :
42 : #if defined(LINUX) && defined(__FreeBSD_kernel__)
43 : #undef LINUX
44 : #define FREEBSD 1
45 : #endif
46 :
47 : #if defined(SOLARIS)
48 :
49 : #include <sys/mnttab.h>
50 : #include <sys/statvfs.h>
51 : #define HAVE_STATFS_H
52 :
53 : #elif defined(LINUX)
54 :
55 : #include <mntent.h>
56 : #include <sys/vfs.h>
57 : #define HAVE_STATFS_H
58 :
59 : #elif defined(NETBSD) || defined(FREEBSD) || defined(OPENBSD) || defined(DRAGONFLY)
60 :
61 : #include <sys/param.h>
62 : #include <sys/ucred.h>
63 : #include <sys/mount.h>
64 : #define HAVE_STATFS_H
65 :
66 : #elif defined(MACOSX)
67 :
68 : #include <sys/param.h>
69 : #include <sys/mount.h>
70 : #define HAVE_STATFS_H
71 :
72 : #endif /* HAVE_STATFS_H */
73 :
74 : /************************************************************************
75 : * ToDo
76 : *
77 : * - Fix: check for corresponding struct sizes in exported functions
78 : * - check size/use of oslVolumeDeviceHandle
79 : * - check size/use of oslVolumeInfo
80 : ***********************************************************************/
81 : /******************************************************************************
82 : *
83 : * Data Type Definition
84 : *
85 : ******************************************************************************/
86 :
87 : typedef struct _oslVolumeDeviceHandleImpl
88 : {
89 : sal_Char pszMountPoint[PATH_MAX];
90 : sal_Char pszFilePath[PATH_MAX];
91 : sal_Char pszDevice[PATH_MAX];
92 : sal_Char ident[4];
93 : sal_uInt32 RefCount;
94 : } oslVolumeDeviceHandleImpl;
95 :
96 : /******************************************************************************
97 : *
98 : * C-String Function Declarations
99 : *
100 : *****************************************************************************/
101 :
102 : static oslFileError osl_psz_getVolumeInformation(const sal_Char* , oslVolumeInfo* pInfo, sal_uInt32 uFieldMask);
103 :
104 : /****************************************************************************/
105 : /* osl_getVolumeInformation */
106 : /****************************************************************************/
107 :
108 0 : oslFileError osl_getVolumeInformation( rtl_uString* ustrDirectoryURL, oslVolumeInfo* pInfo, sal_uInt32 uFieldMask )
109 : {
110 : char path[PATH_MAX];
111 : oslFileError eRet;
112 :
113 : OSL_ASSERT( ustrDirectoryURL );
114 : OSL_ASSERT( pInfo );
115 :
116 : /* convert directory url to system path */
117 0 : eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL );
118 0 : if( eRet != osl_File_E_None )
119 0 : return eRet;
120 :
121 : #ifdef MACOSX
122 : if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
123 : return oslTranslateFileError( OSL_FET_ERROR, errno );
124 : #endif/* MACOSX */
125 :
126 0 : return osl_psz_getVolumeInformation( path, pInfo, uFieldMask);
127 : }
128 :
129 : /******************************************************************************
130 : *
131 : * C-String Versions of Exported Module Functions
132 : *
133 : *****************************************************************************/
134 :
135 : #ifdef HAVE_STATFS_H
136 :
137 : #if defined(FREEBSD) || defined(MACOSX) || defined(OPENBSD) || defined(DRAGONFLY)
138 : # define __OSL_STATFS_STRUCT struct statfs
139 : # define __OSL_STATFS(dir, sfs) statfs((dir), (sfs))
140 : # define __OSL_STATFS_BLKSIZ(a) ((sal_uInt64)((a).f_bsize))
141 : # define __OSL_STATFS_TYPENAME(a) ((a).f_fstypename)
142 : #if defined(OPENBSD)
143 : # define __OSL_STATFS_ISREMOTE(a) (rtl_str_compare((a).f_fstypename, "nfs") == 0)
144 : #else
145 : # define __OSL_STATFS_ISREMOTE(a) (((a).f_type & MNT_LOCAL) == 0)
146 : #endif
147 :
148 : /* always return true if queried for the properties of
149 : the file system. If you think this is wrong under any
150 : of the target platforms fix it!!!! */
151 : # define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a) (true)
152 : # define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) (true)
153 : #endif /* FREEBSD || MACOSX || OPENBSD */
154 :
155 : #if defined(NETBSD)
156 :
157 : #include <sys/param.h>
158 :
159 : /* statvfs() replaced statfs() in 2.99.9 */
160 : # if __NetBSD_Version__ >= 299000900
161 : /* 2.0D or later */
162 : # define __OSL_STATFS_STRUCT struct statvfs
163 : # define __OSL_STATFS(dir, sfs) statvfs((dir), (sfs))
164 : # define __OSL_STATFS_ISREMOTE(a) (((a).f_flag & ST_LOCAL) == 0)
165 :
166 : # else
167 : /* version before 2.0D */
168 : # define __OSL_STATFS_STRUCT struct statfs
169 : # define __OSL_STATFS(dir, sfs) statfs((dir), (sfs))
170 : # define __OSL_STATFS_ISREMOTE(a) (((a).f_type & MNT_LOCAL) == 0)
171 :
172 : # endif /* >2.0D */
173 :
174 : # define __OSL_STATFS_BLKSIZ(a) ((sal_uInt64)((a).f_bsize))
175 : # define __OSL_STATFS_TYPENAME(a) ((a).f_fstypename)
176 :
177 : # define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a) (strcmp((a).f_fstypename, "msdos") != 0 && strcmp((a).f_fstypename, "ntfs") != 0 && strcmp((a).f_fstypename, "smbfs") != 0)
178 : # define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) (strcmp((a).f_fstypename, "msdos") != 0)
179 : #endif /* NETBSD */
180 :
181 : #if defined(LINUX)
182 : # define __OSL_NFS_SUPER_MAGIC 0x6969
183 : # define __OSL_SMB_SUPER_MAGIC 0x517B
184 : # define __OSL_MSDOS_SUPER_MAGIC 0x4d44
185 : # define __OSL_NTFS_SUPER_MAGIC 0x5346544e
186 : # define __OSL_STATFS_STRUCT struct statfs
187 : # define __OSL_STATFS(dir, sfs) statfs((dir), (sfs))
188 : # define __OSL_STATFS_BLKSIZ(a) ((sal_uInt64)((a).f_bsize))
189 : # define __OSL_STATFS_IS_NFS(a) (__OSL_NFS_SUPER_MAGIC == (a).f_type)
190 : # define __OSL_STATFS_IS_SMB(a) (__OSL_SMB_SUPER_MAGIC == (a).f_type)
191 : # define __OSL_STATFS_ISREMOTE(a) (__OSL_STATFS_IS_NFS((a)) || __OSL_STATFS_IS_SMB((a)))
192 : # define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a) ((__OSL_MSDOS_SUPER_MAGIC != (a).f_type) && (__OSL_NTFS_SUPER_MAGIC != (a).f_type))
193 : # define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) ((__OSL_MSDOS_SUPER_MAGIC != (a).f_type))
194 : #endif /* LINUX */
195 :
196 : #if defined(SOLARIS)
197 : # define __OSL_STATFS_STRUCT struct statvfs
198 : # define __OSL_STATFS(dir, sfs) statvfs((dir), (sfs))
199 : # define __OSL_STATFS_BLKSIZ(a) ((sal_uInt64)((a).f_frsize))
200 : # define __OSL_STATFS_TYPENAME(a) ((a).f_basetype)
201 : # define __OSL_STATFS_ISREMOTE(a) (rtl_str_compare((a).f_basetype, "nfs") == 0)
202 :
203 : /* always return true if queried for the properties of
204 : the file system. If you think this is wrong under any
205 : of the target platforms fix it!!!! */
206 : # define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a) (true)
207 : # define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) (true)
208 : #endif /* SOLARIS */
209 :
210 : # define __OSL_STATFS_INIT(a) (memset(&(a), 0, sizeof(__OSL_STATFS_STRUCT)))
211 :
212 : #else /* no statfs available */
213 :
214 : # define __OSL_STATFS_STRUCT struct dummy {int i;}
215 : # define __OSL_STATFS_INIT(a) ((void)a)
216 : # define __OSL_STATFS(dir, sfs) (1)
217 : # define __OSL_STATFS_ISREMOTE(sfs) (false)
218 : # define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a) (true)
219 : # define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) (true)
220 : #endif /* HAVE_STATFS_H */
221 :
222 0 : static oslFileError osl_psz_getVolumeInformation (
223 : const sal_Char* pszDirectory, oslVolumeInfo* pInfo, sal_uInt32 uFieldMask)
224 : {
225 : __OSL_STATFS_STRUCT sfs;
226 :
227 0 : if (!pInfo)
228 0 : return osl_File_E_INVAL;
229 :
230 0 : __OSL_STATFS_INIT(sfs);
231 :
232 0 : pInfo->uValidFields = 0;
233 0 : pInfo->uAttributes = 0;
234 :
235 0 : if ((__OSL_STATFS(pszDirectory, &sfs)) < 0)
236 : {
237 0 : oslFileError result = oslTranslateFileError(OSL_FET_ERROR, errno);
238 0 : return (result);
239 : }
240 :
241 : /* FIXME: how to detect the kind of storage (fixed, cdrom, ...) */
242 0 : if (uFieldMask & osl_VolumeInfo_Mask_Attributes)
243 : {
244 0 : if (__OSL_STATFS_ISREMOTE(sfs))
245 0 : pInfo->uAttributes |= osl_Volume_Attribute_Remote;
246 :
247 0 : pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
248 : }
249 :
250 0 : if (uFieldMask & osl_VolumeInfo_Mask_FileSystemCaseHandling)
251 : {
252 0 : if (__OSL_STATFS_IS_CASE_SENSITIVE_FS(sfs))
253 0 : pInfo->uAttributes |= osl_Volume_Attribute_Case_Sensitive;
254 :
255 0 : if (__OSL_STATFS_IS_CASE_PRESERVING_FS(sfs))
256 0 : pInfo->uAttributes |= osl_Volume_Attribute_Case_Is_Preserved;
257 :
258 0 : pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
259 : }
260 :
261 0 : pInfo->uTotalSpace = 0;
262 0 : pInfo->uFreeSpace = 0;
263 0 : pInfo->uUsedSpace = 0;
264 :
265 : #if defined(__OSL_STATFS_BLKSIZ)
266 :
267 0 : if ((uFieldMask & osl_VolumeInfo_Mask_TotalSpace) ||
268 0 : (uFieldMask & osl_VolumeInfo_Mask_UsedSpace))
269 : {
270 0 : pInfo->uTotalSpace = __OSL_STATFS_BLKSIZ(sfs);
271 0 : pInfo->uTotalSpace *= (sal_uInt64)(sfs.f_blocks);
272 0 : pInfo->uValidFields |= osl_VolumeInfo_Mask_TotalSpace;
273 : }
274 :
275 0 : if ((uFieldMask & osl_VolumeInfo_Mask_FreeSpace) ||
276 0 : (uFieldMask & osl_VolumeInfo_Mask_UsedSpace))
277 : {
278 0 : pInfo->uFreeSpace = __OSL_STATFS_BLKSIZ(sfs);
279 :
280 0 : if (getuid() == 0)
281 0 : pInfo->uFreeSpace *= (sal_uInt64)(sfs.f_bfree);
282 : else
283 0 : pInfo->uFreeSpace *= (sal_uInt64)(sfs.f_bavail);
284 :
285 0 : pInfo->uValidFields |= osl_VolumeInfo_Mask_FreeSpace;
286 : }
287 :
288 : #endif /* __OSL_STATFS_BLKSIZ */
289 :
290 0 : if ((pInfo->uValidFields & osl_VolumeInfo_Mask_TotalSpace) &&
291 0 : (pInfo->uValidFields & osl_VolumeInfo_Mask_FreeSpace ))
292 : {
293 0 : pInfo->uUsedSpace = pInfo->uTotalSpace - pInfo->uFreeSpace;
294 0 : pInfo->uValidFields |= osl_VolumeInfo_Mask_UsedSpace;
295 : }
296 :
297 0 : pInfo->uMaxNameLength = 0;
298 0 : if (uFieldMask & osl_VolumeInfo_Mask_MaxNameLength)
299 : {
300 0 : long nLen = pathconf(pszDirectory, _PC_NAME_MAX);
301 0 : if (nLen > 0)
302 : {
303 0 : pInfo->uMaxNameLength = (sal_uInt32)nLen;
304 0 : pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxNameLength;
305 : }
306 : }
307 :
308 0 : pInfo->uMaxPathLength = 0;
309 0 : if (uFieldMask & osl_VolumeInfo_Mask_MaxPathLength)
310 : {
311 0 : long nLen = pathconf (pszDirectory, _PC_PATH_MAX);
312 0 : if (nLen > 0)
313 : {
314 0 : pInfo->uMaxPathLength = (sal_uInt32)nLen;
315 0 : pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxPathLength;
316 : }
317 : }
318 :
319 : #if defined(__OSL_STATFS_TYPENAME)
320 :
321 : if (uFieldMask & osl_VolumeInfo_Mask_FileSystemName)
322 : {
323 : rtl_string2UString(
324 : &(pInfo->ustrFileSystemName),
325 : __OSL_STATFS_TYPENAME(sfs),
326 : rtl_str_getLength(__OSL_STATFS_TYPENAME(sfs)),
327 : osl_getThreadTextEncoding(),
328 : OUSTRING_TO_OSTRING_CVTFLAGS);
329 : OSL_ASSERT(pInfo->ustrFileSystemName != 0);
330 :
331 : pInfo->uValidFields |= osl_VolumeInfo_Mask_FileSystemName;
332 : }
333 :
334 : #endif /* __OSL_STATFS_TYPENAME */
335 :
336 0 : return osl_File_E_None;
337 : }
338 :
339 : /******************************************************************************
340 : *
341 : * GENERIC FLOPPY FUNCTIONS
342 : *
343 : *****************************************************************************/
344 :
345 : /*****************************************
346 : * osl_getVolumeDeviceMountPath
347 : ****************************************/
348 0 : static rtl_uString* oslMakeUStrFromPsz(const sal_Char* pszStr, rtl_uString** ustrValid)
349 : {
350 : rtl_string2UString(
351 : ustrValid,
352 : pszStr,
353 : rtl_str_getLength( pszStr ),
354 0 : osl_getThreadTextEncoding(),
355 0 : OUSTRING_TO_OSTRING_CVTFLAGS );
356 : OSL_ASSERT(*ustrValid != 0);
357 :
358 0 : return *ustrValid;
359 : }
360 :
361 0 : oslFileError osl_getVolumeDeviceMountPath( oslVolumeDeviceHandle Handle, rtl_uString **pstrPath )
362 : {
363 0 : oslVolumeDeviceHandleImpl* pItem = (oslVolumeDeviceHandleImpl*) Handle;
364 : sal_Char Buffer[PATH_MAX];
365 :
366 0 : Buffer[0] = '\0';
367 :
368 0 : if ( pItem == 0 || pstrPath == 0 )
369 : {
370 0 : return osl_File_E_INVAL;
371 : }
372 :
373 0 : if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
374 : {
375 0 : return osl_File_E_INVAL;
376 : }
377 :
378 0 : snprintf(Buffer, sizeof(Buffer), "file://%s", pItem->pszMountPoint);
379 :
380 : #ifdef DEBUG_OSL_FILE
381 : fprintf(stderr,"Mount Point is: '%s'\n",Buffer);
382 : #endif
383 :
384 0 : oslMakeUStrFromPsz(Buffer, pstrPath);
385 :
386 0 : return osl_File_E_None;
387 : }
388 :
389 : /*****************************************
390 : * osl_acquireVolumeDeviceHandle
391 : ****************************************/
392 :
393 0 : oslFileError SAL_CALL osl_acquireVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
394 : {
395 0 : oslVolumeDeviceHandleImpl* pItem =(oslVolumeDeviceHandleImpl*) Handle;
396 :
397 0 : if ( pItem == 0 )
398 : {
399 0 : return osl_File_E_INVAL;
400 : }
401 :
402 0 : if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
403 : {
404 0 : return osl_File_E_INVAL;
405 : }
406 :
407 0 : ++pItem->RefCount;
408 :
409 0 : return osl_File_E_None;
410 : }
411 :
412 : /*****************************************
413 : * osl_releaseVolumeDeviceHandle
414 : ****************************************/
415 :
416 0 : oslFileError osl_releaseVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
417 : {
418 0 : oslVolumeDeviceHandleImpl* pItem =(oslVolumeDeviceHandleImpl*) Handle;
419 :
420 0 : if ( pItem == 0 )
421 : {
422 0 : return osl_File_E_INVAL;
423 : }
424 :
425 0 : if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
426 : {
427 0 : return osl_File_E_INVAL;
428 : }
429 :
430 0 : --pItem->RefCount;
431 :
432 0 : if ( pItem->RefCount == 0 )
433 : {
434 0 : rtl_freeMemory(pItem);
435 : }
436 :
437 0 : return osl_File_E_None;
438 : }
439 :
440 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|