Version 4.2.0.1, tag libreoffice-4.2.0.1
[LibreOffice.git] / sal / osl / unx / file_volume.cxx
blob576ead4e3cd877452d3fc665d56cb58d7a678e71
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "osl/file.h"
22 #include "osl/diagnose.h"
23 #include "osl/thread.h"
24 #include "rtl/alloc.h"
26 #include "file_error_transl.h"
27 #include "file_url.h"
28 #include "system.h"
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>
38 #ifdef HAVE_STATFS_H
39 #undef HAVE_STATFS_H
40 #endif
42 #if defined(LINUX) && defined(__FreeBSD_kernel__)
43 #undef LINUX
44 #define FREEBSD 1
45 #endif
48 #if defined(SOLARIS)
50 #include <sys/mnttab.h>
51 #include <sys/statvfs.h>
52 #define HAVE_STATFS_H
54 #elif defined(LINUX)
56 #include <mntent.h>
57 #include <sys/vfs.h>
58 #define HAVE_STATFS_H
60 #elif defined(NETBSD) || defined(FREEBSD) || defined(OPENBSD) || defined(DRAGONFLY)
62 #include <sys/param.h>
63 #include <sys/ucred.h>
64 #include <sys/mount.h>
65 #define HAVE_STATFS_H
67 #elif defined(MACOSX)
69 #include <sys/param.h>
70 #include <sys/mount.h>
71 #define HAVE_STATFS_H
73 #endif /* HAVE_STATFS_H */
75 /************************************************************************
76 * ToDo
78 * - Fix: check for corresponding struct sizes in exported functions
79 * - check size/use of oslVolumeDeviceHandle
80 * - check size/use of oslVolumeInfo
81 ***********************************************************************/
82 /******************************************************************************
84 * Data Type Definition
86 ******************************************************************************/
88 typedef struct _oslVolumeDeviceHandleImpl
90 sal_Char pszMountPoint[PATH_MAX];
91 sal_Char pszFilePath[PATH_MAX];
92 sal_Char pszDevice[PATH_MAX];
93 sal_Char ident[4];
94 sal_uInt32 RefCount;
95 } oslVolumeDeviceHandleImpl;
97 /******************************************************************************
99 * C-String Function Declarations
101 *****************************************************************************/
103 static oslFileError osl_psz_getVolumeInformation(const sal_Char* , oslVolumeInfo* pInfo, sal_uInt32 uFieldMask);
105 /****************************************************************************/
106 /* osl_getVolumeInformation */
107 /****************************************************************************/
109 oslFileError osl_getVolumeInformation( rtl_uString* ustrDirectoryURL, oslVolumeInfo* pInfo, sal_uInt32 uFieldMask )
111 char path[PATH_MAX];
112 oslFileError eRet;
114 OSL_ASSERT( ustrDirectoryURL );
115 OSL_ASSERT( pInfo );
117 /* convert directory url to system path */
118 eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL );
119 if( eRet != osl_File_E_None )
120 return eRet;
122 #ifdef MACOSX
123 if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
124 return oslTranslateFileError( OSL_FET_ERROR, errno );
125 #endif/* MACOSX */
127 return osl_psz_getVolumeInformation( path, pInfo, uFieldMask);
130 /******************************************************************************
132 * C-String Versions of Exported Module Functions
134 *****************************************************************************/
136 #ifdef HAVE_STATFS_H
138 #if defined(FREEBSD) || defined(MACOSX) || defined(OPENBSD) || defined(DRAGONFLY)
139 # define __OSL_STATFS_STRUCT struct statfs
140 # define __OSL_STATFS(dir, sfs) statfs((dir), (sfs))
141 # define __OSL_STATFS_BLKSIZ(a) ((sal_uInt64)((a).f_bsize))
142 # define __OSL_STATFS_TYPENAME(a) ((a).f_fstypename)
143 #if defined(OPENBSD)
144 # define __OSL_STATFS_ISREMOTE(a) (rtl_str_compare((a).f_fstypename, "nfs") == 0)
145 #else
146 # define __OSL_STATFS_ISREMOTE(a) (((a).f_type & MNT_LOCAL) == 0)
147 #endif
149 /* always return true if queried for the properties of
150 the file system. If you think this is wrong under any
151 of the target platforms fix it!!!! */
152 # define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a) (1)
153 # define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) (1)
154 #endif /* FREEBSD || MACOSX || OPENBSD */
156 #if defined(NETBSD)
158 #include <sys/param.h>
160 /* statvfs() replaced statfs() in 2.99.9 */
161 # if __NetBSD_Version__ >= 299000900
162 /* 2.0D or later */
163 # define __OSL_STATFS_STRUCT struct statvfs
164 # define __OSL_STATFS(dir, sfs) statvfs((dir), (sfs))
165 # define __OSL_STATFS_ISREMOTE(a) (((a).f_flag & ST_LOCAL) == 0)
167 # else
168 /* version before 2.0D */
169 # define __OSL_STATFS_STRUCT struct statfs
170 # define __OSL_STATFS(dir, sfs) statfs((dir), (sfs))
171 # define __OSL_STATFS_ISREMOTE(a) (((a).f_type & MNT_LOCAL) == 0)
173 # endif /* >2.0D */
175 # define __OSL_STATFS_BLKSIZ(a) ((sal_uInt64)((a).f_bsize))
176 # define __OSL_STATFS_TYPENAME(a) ((a).f_fstypename)
178 # 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)
179 # define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) (strcmp((a).f_fstypename, "msdos") != 0)
180 #endif /* NETBSD */
182 #if defined(LINUX)
183 # define __OSL_NFS_SUPER_MAGIC 0x6969
184 # define __OSL_SMB_SUPER_MAGIC 0x517B
185 # define __OSL_MSDOS_SUPER_MAGIC 0x4d44
186 # define __OSL_NTFS_SUPER_MAGIC 0x5346544e
187 # define __OSL_STATFS_STRUCT struct statfs
188 # define __OSL_STATFS(dir, sfs) statfs((dir), (sfs))
189 # define __OSL_STATFS_BLKSIZ(a) ((sal_uInt64)((a).f_bsize))
190 # define __OSL_STATFS_IS_NFS(a) (__OSL_NFS_SUPER_MAGIC == (a).f_type)
191 # define __OSL_STATFS_IS_SMB(a) (__OSL_SMB_SUPER_MAGIC == (a).f_type)
192 # define __OSL_STATFS_ISREMOTE(a) (__OSL_STATFS_IS_NFS((a)) || __OSL_STATFS_IS_SMB((a)))
193 # define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a) ((__OSL_MSDOS_SUPER_MAGIC != (a).f_type) && (__OSL_NTFS_SUPER_MAGIC != (a).f_type))
194 # define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) ((__OSL_MSDOS_SUPER_MAGIC != (a).f_type))
195 #endif /* LINUX */
197 #if defined(SOLARIS)
198 # define __OSL_STATFS_STRUCT struct statvfs
199 # define __OSL_STATFS(dir, sfs) statvfs((dir), (sfs))
200 # define __OSL_STATFS_BLKSIZ(a) ((sal_uInt64)((a).f_frsize))
201 # define __OSL_STATFS_TYPENAME(a) ((a).f_basetype)
202 # define __OSL_STATFS_ISREMOTE(a) (rtl_str_compare((a).f_basetype, "nfs") == 0)
204 /* always return true if queried for the properties of
205 the file system. If you think this is wrong under any
206 of the target platforms fix it!!!! */
207 # define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a) (1)
208 # define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) (1)
209 #endif /* SOLARIS */
211 # define __OSL_STATFS_INIT(a) (memset(&(a), 0, sizeof(__OSL_STATFS_STRUCT)))
213 #else /* no statfs available */
215 # define __OSL_STATFS_STRUCT struct dummy {int i;}
216 # define __OSL_STATFS_INIT(a) ((void)a)
217 # define __OSL_STATFS(dir, sfs) (1)
218 # define __OSL_STATFS_ISREMOTE(sfs) (0)
219 # define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a) (1)
220 # define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) (1)
221 #endif /* HAVE_STATFS_H */
224 static oslFileError osl_psz_getVolumeInformation (
225 const sal_Char* pszDirectory, oslVolumeInfo* pInfo, sal_uInt32 uFieldMask)
227 __OSL_STATFS_STRUCT sfs;
229 if (!pInfo)
230 return osl_File_E_INVAL;
232 __OSL_STATFS_INIT(sfs);
234 pInfo->uValidFields = 0;
235 pInfo->uAttributes = 0;
237 if ((__OSL_STATFS(pszDirectory, &sfs)) < 0)
239 oslFileError result = oslTranslateFileError(OSL_FET_ERROR, errno);
240 return (result);
243 /* FIXME: how to detect the kind of storage (fixed, cdrom, ...) */
244 if (uFieldMask & osl_VolumeInfo_Mask_Attributes)
246 if (__OSL_STATFS_ISREMOTE(sfs))
247 pInfo->uAttributes |= osl_Volume_Attribute_Remote;
249 pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
252 if (uFieldMask & osl_VolumeInfo_Mask_FileSystemCaseHandling)
254 if (__OSL_STATFS_IS_CASE_SENSITIVE_FS(sfs))
255 pInfo->uAttributes |= osl_Volume_Attribute_Case_Sensitive;
257 if (__OSL_STATFS_IS_CASE_PRESERVING_FS(sfs))
258 pInfo->uAttributes |= osl_Volume_Attribute_Case_Is_Preserved;
260 pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
263 pInfo->uTotalSpace = 0;
264 pInfo->uFreeSpace = 0;
265 pInfo->uUsedSpace = 0;
267 #if defined(__OSL_STATFS_BLKSIZ)
269 if ((uFieldMask & osl_VolumeInfo_Mask_TotalSpace) ||
270 (uFieldMask & osl_VolumeInfo_Mask_UsedSpace))
272 pInfo->uTotalSpace = __OSL_STATFS_BLKSIZ(sfs);
273 pInfo->uTotalSpace *= (sal_uInt64)(sfs.f_blocks);
274 pInfo->uValidFields |= osl_VolumeInfo_Mask_TotalSpace;
277 if ((uFieldMask & osl_VolumeInfo_Mask_FreeSpace) ||
278 (uFieldMask & osl_VolumeInfo_Mask_UsedSpace))
280 pInfo->uFreeSpace = __OSL_STATFS_BLKSIZ(sfs);
282 if (getuid() == 0)
283 pInfo->uFreeSpace *= (sal_uInt64)(sfs.f_bfree);
284 else
285 pInfo->uFreeSpace *= (sal_uInt64)(sfs.f_bavail);
287 pInfo->uValidFields |= osl_VolumeInfo_Mask_FreeSpace;
290 #endif /* __OSL_STATFS_BLKSIZ */
292 if ((pInfo->uValidFields & osl_VolumeInfo_Mask_TotalSpace) &&
293 (pInfo->uValidFields & osl_VolumeInfo_Mask_FreeSpace ))
295 pInfo->uUsedSpace = pInfo->uTotalSpace - pInfo->uFreeSpace;
296 pInfo->uValidFields |= osl_VolumeInfo_Mask_UsedSpace;
299 pInfo->uMaxNameLength = 0;
300 if (uFieldMask & osl_VolumeInfo_Mask_MaxNameLength)
302 long nLen = pathconf(pszDirectory, _PC_NAME_MAX);
303 if (nLen > 0)
305 pInfo->uMaxNameLength = (sal_uInt32)nLen;
306 pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxNameLength;
310 pInfo->uMaxPathLength = 0;
311 if (uFieldMask & osl_VolumeInfo_Mask_MaxPathLength)
313 long nLen = pathconf (pszDirectory, _PC_PATH_MAX);
314 if (nLen > 0)
316 pInfo->uMaxPathLength = (sal_uInt32)nLen;
317 pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxPathLength;
321 #if defined(__OSL_STATFS_TYPENAME)
323 if (uFieldMask & osl_VolumeInfo_Mask_FileSystemName)
325 rtl_string2UString(
326 &(pInfo->ustrFileSystemName),
327 __OSL_STATFS_TYPENAME(sfs),
328 rtl_str_getLength(__OSL_STATFS_TYPENAME(sfs)),
329 osl_getThreadTextEncoding(),
330 OUSTRING_TO_OSTRING_CVTFLAGS);
331 OSL_ASSERT(pInfo->ustrFileSystemName != 0);
333 pInfo->uValidFields |= osl_VolumeInfo_Mask_FileSystemName;
336 #endif /* __OSL_STATFS_TYPENAME */
338 return osl_File_E_None;
341 /******************************************************************************
343 * GENERIC FLOPPY FUNCTIONS
345 *****************************************************************************/
347 /*****************************************
348 * osl_getVolumeDeviceMountPath
349 ****************************************/
350 static rtl_uString* oslMakeUStrFromPsz(const sal_Char* pszStr, rtl_uString** ustrValid)
352 rtl_string2UString(
353 ustrValid,
354 pszStr,
355 rtl_str_getLength( pszStr ),
356 osl_getThreadTextEncoding(),
357 OUSTRING_TO_OSTRING_CVTFLAGS );
358 OSL_ASSERT(*ustrValid != 0);
360 return *ustrValid;
363 oslFileError osl_getVolumeDeviceMountPath( oslVolumeDeviceHandle Handle, rtl_uString **pstrPath )
365 oslVolumeDeviceHandleImpl* pItem = (oslVolumeDeviceHandleImpl*) Handle;
366 sal_Char Buffer[PATH_MAX];
368 Buffer[0] = '\0';
370 if ( pItem == 0 || pstrPath == 0 )
372 return osl_File_E_INVAL;
375 if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
377 return osl_File_E_INVAL;
380 snprintf(Buffer, sizeof(Buffer), "file://%s", pItem->pszMountPoint);
382 #ifdef DEBUG_OSL_FILE
383 fprintf(stderr,"Mount Point is: '%s'\n",Buffer);
384 #endif
386 oslMakeUStrFromPsz(Buffer, pstrPath);
388 return osl_File_E_None;
391 /*****************************************
392 * osl_acquireVolumeDeviceHandle
393 ****************************************/
395 oslFileError SAL_CALL osl_acquireVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
397 oslVolumeDeviceHandleImpl* pItem =(oslVolumeDeviceHandleImpl*) Handle;
399 if ( pItem == 0 )
401 return osl_File_E_INVAL;
404 if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
406 return osl_File_E_INVAL;
409 ++pItem->RefCount;
411 return osl_File_E_None;
414 /*****************************************
415 * osl_releaseVolumeDeviceHandle
416 ****************************************/
418 oslFileError osl_releaseVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
420 oslVolumeDeviceHandleImpl* pItem =(oslVolumeDeviceHandleImpl*) Handle;
422 if ( pItem == 0 )
424 return osl_File_E_INVAL;
427 if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
429 return osl_File_E_INVAL;
432 --pItem->RefCount;
434 if ( pItem->RefCount == 0 )
436 rtl_freeMemory(pItem);
439 return osl_File_E_None;
442 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */