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 :
48 : #if defined(SOLARIS)
49 :
50 : #include <sys/mnttab.h>
51 : #include <sys/statvfs.h>
52 : #define HAVE_STATFS_H
53 :
54 : #elif defined(LINUX)
55 :
56 : #include <mntent.h>
57 : #include <sys/vfs.h>
58 : #define HAVE_STATFS_H
59 :
60 : #elif defined(NETBSD) || defined(FREEBSD) || defined(OPENBSD) || defined(DRAGONFLY)
61 :
62 : #include <sys/param.h>
63 : #include <sys/ucred.h>
64 : #include <sys/mount.h>
65 : #define HAVE_STATFS_H
66 :
67 : #elif defined(MACOSX)
68 :
69 : #include <sys/param.h>
70 : #include <sys/mount.h>
71 : #define HAVE_STATFS_H
72 :
73 : #endif /* HAVE_STATFS_H */
74 :
75 : /************************************************************************
76 : * ToDo
77 : *
78 : * - Fix: check for corresponding struct sizes in exported functions
79 : * - check size/use of oslVolumeDeviceHandle
80 : * - check size/use of oslVolumeInfo
81 : ***********************************************************************/
82 : /******************************************************************************
83 : *
84 : * Data Type Definition
85 : *
86 : ******************************************************************************/
87 :
88 : typedef struct _oslVolumeDeviceHandleImpl
89 : {
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;
96 :
97 : /******************************************************************************
98 : *
99 : * C-String Function Declarations
100 : *
101 : *****************************************************************************/
102 :
103 : static oslFileError osl_psz_getVolumeInformation(const sal_Char* , oslVolumeInfo* pInfo, sal_uInt32 uFieldMask);
104 :
105 : /****************************************************************************/
106 : /* osl_getVolumeInformation */
107 : /****************************************************************************/
108 :
109 10 : oslFileError osl_getVolumeInformation( rtl_uString* ustrDirectoryURL, oslVolumeInfo* pInfo, sal_uInt32 uFieldMask )
110 : {
111 : char path[PATH_MAX];
112 : oslFileError eRet;
113 :
114 : OSL_ASSERT( ustrDirectoryURL );
115 : OSL_ASSERT( pInfo );
116 :
117 : /* convert directory url to system path */
118 10 : eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL );
119 10 : if( eRet != osl_File_E_None )
120 1 : return eRet;
121 :
122 : #ifdef MACOSX
123 : if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
124 : return oslTranslateFileError( OSL_FET_ERROR, errno );
125 : #endif/* MACOSX */
126 :
127 9 : return osl_psz_getVolumeInformation( path, pInfo, uFieldMask);
128 : }
129 :
130 : /******************************************************************************
131 : *
132 : * C-String Versions of Exported Module Functions
133 : *
134 : *****************************************************************************/
135 :
136 : #ifdef HAVE_STATFS_H
137 :
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
148 :
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 */
155 :
156 : #if defined(NETBSD)
157 :
158 : #include <sys/param.h>
159 :
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)
166 :
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)
172 :
173 : # endif /* >2.0D */
174 :
175 : # define __OSL_STATFS_BLKSIZ(a) ((sal_uInt64)((a).f_bsize))
176 : # define __OSL_STATFS_TYPENAME(a) ((a).f_fstypename)
177 :
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 */
181 :
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 */
196 :
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)
203 :
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 */
210 :
211 : # define __OSL_STATFS_INIT(a) (memset(&(a), 0, sizeof(__OSL_STATFS_STRUCT)))
212 :
213 : #else /* no statfs available */
214 :
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 */
222 :
223 :
224 9 : static oslFileError osl_psz_getVolumeInformation (
225 : const sal_Char* pszDirectory, oslVolumeInfo* pInfo, sal_uInt32 uFieldMask)
226 : {
227 : __OSL_STATFS_STRUCT sfs;
228 :
229 9 : if (!pInfo)
230 0 : return osl_File_E_INVAL;
231 :
232 9 : __OSL_STATFS_INIT(sfs);
233 :
234 9 : pInfo->uValidFields = 0;
235 9 : pInfo->uAttributes = 0;
236 :
237 9 : if ((__OSL_STATFS(pszDirectory, &sfs)) < 0)
238 : {
239 1 : oslFileError result = oslTranslateFileError(OSL_FET_ERROR, errno);
240 1 : return (result);
241 : }
242 :
243 : /* FIXME: how to detect the kind of storage (fixed, cdrom, ...) */
244 8 : if (uFieldMask & osl_VolumeInfo_Mask_Attributes)
245 : {
246 1 : if (__OSL_STATFS_ISREMOTE(sfs))
247 0 : pInfo->uAttributes |= osl_Volume_Attribute_Remote;
248 :
249 1 : pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
250 : }
251 :
252 8 : if (uFieldMask & osl_VolumeInfo_Mask_FileSystemCaseHandling)
253 : {
254 1 : if (__OSL_STATFS_IS_CASE_SENSITIVE_FS(sfs))
255 1 : pInfo->uAttributes |= osl_Volume_Attribute_Case_Sensitive;
256 :
257 1 : if (__OSL_STATFS_IS_CASE_PRESERVING_FS(sfs))
258 1 : pInfo->uAttributes |= osl_Volume_Attribute_Case_Is_Preserved;
259 :
260 1 : pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
261 : }
262 :
263 8 : pInfo->uTotalSpace = 0;
264 8 : pInfo->uFreeSpace = 0;
265 8 : pInfo->uUsedSpace = 0;
266 :
267 : #if defined(__OSL_STATFS_BLKSIZ)
268 :
269 8 : if ((uFieldMask & osl_VolumeInfo_Mask_TotalSpace) ||
270 : (uFieldMask & osl_VolumeInfo_Mask_UsedSpace))
271 : {
272 2 : pInfo->uTotalSpace = __OSL_STATFS_BLKSIZ(sfs);
273 2 : pInfo->uTotalSpace *= (sal_uInt64)(sfs.f_blocks);
274 2 : pInfo->uValidFields |= osl_VolumeInfo_Mask_TotalSpace;
275 : }
276 :
277 8 : if ((uFieldMask & osl_VolumeInfo_Mask_FreeSpace) ||
278 : (uFieldMask & osl_VolumeInfo_Mask_UsedSpace))
279 : {
280 2 : pInfo->uFreeSpace = __OSL_STATFS_BLKSIZ(sfs);
281 :
282 2 : if (getuid() == 0)
283 2 : pInfo->uFreeSpace *= (sal_uInt64)(sfs.f_bfree);
284 : else
285 0 : pInfo->uFreeSpace *= (sal_uInt64)(sfs.f_bavail);
286 :
287 2 : pInfo->uValidFields |= osl_VolumeInfo_Mask_FreeSpace;
288 : }
289 :
290 : #endif /* __OSL_STATFS_BLKSIZ */
291 :
292 8 : if ((pInfo->uValidFields & osl_VolumeInfo_Mask_TotalSpace) &&
293 : (pInfo->uValidFields & osl_VolumeInfo_Mask_FreeSpace ))
294 : {
295 1 : pInfo->uUsedSpace = pInfo->uTotalSpace - pInfo->uFreeSpace;
296 1 : pInfo->uValidFields |= osl_VolumeInfo_Mask_UsedSpace;
297 : }
298 :
299 8 : pInfo->uMaxNameLength = 0;
300 8 : if (uFieldMask & osl_VolumeInfo_Mask_MaxNameLength)
301 : {
302 1 : long nLen = pathconf(pszDirectory, _PC_NAME_MAX);
303 1 : if (nLen > 0)
304 : {
305 1 : pInfo->uMaxNameLength = (sal_uInt32)nLen;
306 1 : pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxNameLength;
307 : }
308 : }
309 :
310 8 : pInfo->uMaxPathLength = 0;
311 8 : if (uFieldMask & osl_VolumeInfo_Mask_MaxPathLength)
312 : {
313 1 : long nLen = pathconf (pszDirectory, _PC_PATH_MAX);
314 1 : if (nLen > 0)
315 : {
316 1 : pInfo->uMaxPathLength = (sal_uInt32)nLen;
317 1 : pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxPathLength;
318 : }
319 : }
320 :
321 : #if defined(__OSL_STATFS_TYPENAME)
322 :
323 : if (uFieldMask & osl_VolumeInfo_Mask_FileSystemName)
324 : {
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);
332 :
333 : pInfo->uValidFields |= osl_VolumeInfo_Mask_FileSystemName;
334 : }
335 :
336 : #endif /* __OSL_STATFS_TYPENAME */
337 :
338 8 : return osl_File_E_None;
339 : }
340 :
341 : /******************************************************************************
342 : *
343 : * GENERIC FLOPPY FUNCTIONS
344 : *
345 : *****************************************************************************/
346 :
347 : /*****************************************
348 : * osl_getVolumeDeviceMountPath
349 : ****************************************/
350 0 : static rtl_uString* oslMakeUStrFromPsz(const sal_Char* pszStr, rtl_uString** ustrValid)
351 : {
352 : rtl_string2UString(
353 : ustrValid,
354 : pszStr,
355 : rtl_str_getLength( pszStr ),
356 0 : osl_getThreadTextEncoding(),
357 0 : OUSTRING_TO_OSTRING_CVTFLAGS );
358 : OSL_ASSERT(*ustrValid != 0);
359 :
360 0 : return *ustrValid;
361 : }
362 :
363 0 : oslFileError osl_getVolumeDeviceMountPath( oslVolumeDeviceHandle Handle, rtl_uString **pstrPath )
364 : {
365 0 : oslVolumeDeviceHandleImpl* pItem = (oslVolumeDeviceHandleImpl*) Handle;
366 : sal_Char Buffer[PATH_MAX];
367 :
368 0 : Buffer[0] = '\0';
369 :
370 0 : if ( pItem == 0 || pstrPath == 0 )
371 : {
372 0 : return osl_File_E_INVAL;
373 : }
374 :
375 0 : if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
376 : {
377 0 : return osl_File_E_INVAL;
378 : }
379 :
380 0 : snprintf(Buffer, sizeof(Buffer), "file://%s", pItem->pszMountPoint);
381 :
382 : #ifdef DEBUG_OSL_FILE
383 : fprintf(stderr,"Mount Point is: '%s'\n",Buffer);
384 : #endif
385 :
386 0 : oslMakeUStrFromPsz(Buffer, pstrPath);
387 :
388 0 : return osl_File_E_None;
389 : }
390 :
391 : /*****************************************
392 : * osl_acquireVolumeDeviceHandle
393 : ****************************************/
394 :
395 0 : oslFileError SAL_CALL osl_acquireVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
396 : {
397 0 : oslVolumeDeviceHandleImpl* pItem =(oslVolumeDeviceHandleImpl*) Handle;
398 :
399 0 : if ( pItem == 0 )
400 : {
401 0 : return osl_File_E_INVAL;
402 : }
403 :
404 0 : if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
405 : {
406 0 : return osl_File_E_INVAL;
407 : }
408 :
409 0 : ++pItem->RefCount;
410 :
411 0 : return osl_File_E_None;
412 : }
413 :
414 : /*****************************************
415 : * osl_releaseVolumeDeviceHandle
416 : ****************************************/
417 :
418 0 : oslFileError osl_releaseVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
419 : {
420 0 : oslVolumeDeviceHandleImpl* pItem =(oslVolumeDeviceHandleImpl*) Handle;
421 :
422 0 : if ( pItem == 0 )
423 : {
424 0 : return osl_File_E_INVAL;
425 : }
426 :
427 0 : if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
428 : {
429 0 : return osl_File_E_INVAL;
430 : }
431 :
432 0 : --pItem->RefCount;
433 :
434 0 : if ( pItem->RefCount == 0 )
435 : {
436 0 : rtl_freeMemory(pItem);
437 : }
438 :
439 0 : return osl_File_E_None;
440 : }
441 :
442 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|