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 <stdio.h>
21 : #include <ctype.h>
22 : #include <stdlib.h>
23 : #include <unistd.h>
24 : #include <utime.h>
25 :
26 : #if defined LINUX || defined ANDROID
27 : #include <mntent.h>
28 : #define mnttab mntent
29 : #elif defined AIX
30 : #include <sys/mntctl.h>
31 : #include <sys/vmount.h>
32 : extern "C" int mntctl( int cmd, size_t size, char* buf );
33 : #elif defined(NETBSD)
34 : #include <sys/mount.h>
35 : #elif defined(FREEBSD) || defined(MACOSX) || defined(OPENBSD) || \
36 : defined(DRAGONFLY) || defined(IOS)
37 : struct mnttab
38 : {
39 : char *mnt_dir;
40 : char *mnt_fsname;
41 : };
42 : #else
43 : #include <sys/mnttab.h>
44 : #endif
45 :
46 : #ifndef MAXPATHLEN
47 : #define MAXPATHLEN 1024
48 : #endif
49 :
50 : #include <tools/debug.hxx>
51 : #include <tools/fsys.hxx>
52 : #include "comdep.hxx"
53 : #include <rtl/instance.hxx>
54 :
55 : #if defined SOLARIS
56 : #define MOUNTSPECIAL mnt_special
57 : #define MOUNTPOINT mnt_mountp
58 : #define MOUNTOPTS mnt_mntopts
59 : #define MOUNTFS mnt_fstype
60 : #else
61 : #define MOUNTSPECIAL mnt_fsname
62 : #define MOUNTPOINT mnt_dir
63 : #define MOUNTFS mnt_type
64 : #endif
65 :
66 0 : struct mymnttab
67 : {
68 : dev_t mountdevice;
69 : rtl::OString mountspecial;
70 : rtl::OString mountpoint;
71 : rtl::OString mymnttab_filesystem;
72 0 : mymnttab() { mountdevice = (dev_t) -1; }
73 : };
74 :
75 : #if defined(NETBSD) || defined(FREEBSD) || defined(MACOSX) || \
76 : defined(OPENBSD) || defined(DRAGONFLY) || defined(IOS)
77 : sal_Bool GetMountEntry(dev_t /* dev */, struct mymnttab * /* mytab */ )
78 : {
79 : DBG_WARNING( "Sorry, not implemented: GetMountEntry" );
80 : return sal_False;
81 : }
82 : #elif defined AIX
83 : sal_Bool GetMountEntry(dev_t dev, struct mymnttab *mytab)
84 : {
85 : int bufsize;
86 : if (mntctl (MCTL_QUERY, sizeof bufsize, (char*) &bufsize))
87 : return sal_False;
88 :
89 : char* buffer = (char *)malloc( bufsize * sizeof(char) );
90 : if (mntctl (MCTL_QUERY, bufsize, buffer) != -1)
91 : for ( char* vmt = buffer;
92 : vmt < buffer + bufsize;
93 : vmt += ((struct vmount*)vmt)->vmt_length)
94 : {
95 : struct stat buf;
96 : char *mountp = vmt2dataptr((struct vmount*)vmt, VMT_STUB);
97 : if ((stat (mountp, &buf) != -1) && (buf.st_dev == dev))
98 : {
99 : mytab->mountpoint = mountp;
100 : mytab->mountspecial
101 : = vmt2dataptr((struct vmount*)vmt, VMT_HOSTNAME);
102 : if (mytab->mountspecial.Len())
103 : mytab->mountspecial += ':';
104 : mytab->mountspecial
105 : += vmt2dataptr((struct vmount*)vmt, VMT_OBJECT);
106 : mytab->mountdevice = dev;
107 : free( buffer );
108 : return sal_True;
109 : }
110 : }
111 : free( buffer );
112 : return sal_False;
113 : }
114 : #else
115 0 : static sal_Bool GetMountEntry(dev_t dev, struct mymnttab *mytab)
116 : {
117 : #if defined SOLARIS
118 : FILE *fp = fopen (MNTTAB, "r");
119 : if (! fp)
120 : return sal_False;
121 : struct mnttab mnt[1];
122 : while (getmntent (fp, mnt) != -1)
123 : #elif defined AIX || defined ANDROID
124 : FILE *fp = NULL;
125 : if (! fp)
126 : return sal_False;
127 : struct mnttab mnt[1];
128 : while ( 0 )
129 : #else
130 0 : FILE *fp = setmntent (MOUNTED, "r");
131 0 : if (! fp)
132 0 : return sal_False;
133 : struct mnttab *mnt;
134 0 : while ((mnt = getmntent (fp)) != NULL)
135 : #endif
136 : {
137 : #ifdef SOLARIS
138 : char *devopt = NULL;
139 : if ( mnt->MOUNTOPTS != NULL )
140 : devopt = strstr (mnt->MOUNTOPTS, "dev=");
141 : if (devopt)
142 : {
143 : if (dev != (dev_t) strtoul (devopt+4, NULL, 16))
144 : continue;
145 : }
146 : else
147 : #endif
148 : {
149 : struct stat buf;
150 0 : if ((stat (mnt->MOUNTPOINT, &buf) == -1) || (buf.st_dev != dev))
151 0 : continue;
152 : }
153 : # ifdef LINUX
154 : // #61624# Opening file with setmntent and closing with fclose fails for glibc-2.1
155 0 : endmntent( fp );
156 : # else
157 : fclose (fp);
158 : # endif
159 0 : mytab->mountspecial = mnt->MOUNTSPECIAL;
160 0 : mytab->mountpoint = mnt->MOUNTPOINT;
161 0 : mytab->mountdevice = dev;
162 0 : mytab->mymnttab_filesystem = mnt->MOUNTFS;
163 :
164 0 : return sal_True;
165 : }
166 : # ifdef LINUX
167 : /* #61624# see above */
168 0 : endmntent( fp );
169 : # else
170 : fclose (fp);
171 : # endif
172 0 : return sal_False;
173 : }
174 : #endif
175 :
176 13237 : sal_Bool DirEntry::ToAbs()
177 : {
178 13237 : if ( FSYS_FLAG_VOLUME == eFlag )
179 : {
180 0 : eFlag = FSYS_FLAG_ABSROOT;
181 0 : return sal_True;
182 : }
183 :
184 13237 : if ( IsAbs() )
185 13237 : return sal_True;
186 :
187 : char sBuf[MAXPATHLEN + 1];
188 0 : *this = DirEntry( String( getcwd( sBuf, MAXPATHLEN ), osl_getThreadTextEncoding() ) ) + *this;
189 0 : return IsAbs();
190 : }
191 :
192 : namespace { struct mymnt : public rtl::Static< mymnttab, mymnt > {}; }
193 :
194 0 : String DirEntry::GetVolume() const
195 : {
196 : DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
197 :
198 0 : DirEntry aPath( *this );
199 0 : aPath.ToAbs();
200 :
201 : struct stat buf;
202 0 : while (stat(rtl::OUStringToOString(aPath.GetFull(), osl_getThreadTextEncoding()).getStr(), &buf))
203 : {
204 0 : if (aPath.Level() <= 1)
205 0 : return String();
206 0 : aPath = aPath [1];
207 : }
208 0 : mymnttab &rMnt = mymnt::get();
209 0 : return ((buf.st_dev == rMnt.mountdevice || GetMountEntry(buf.st_dev, &rMnt)) ?
210 0 : rtl::OStringToOUString(rMnt.mountspecial, osl_getThreadTextEncoding()) :
211 0 : rtl::OUString());
212 : }
213 :
214 0 : sal_Bool DirEntry::SetCWD( sal_Bool bSloppy ) const
215 : {
216 : DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
217 :
218 0 : rtl::OString aPath(rtl::OUStringToOString(GetFull(), osl_getThreadTextEncoding()));
219 0 : if (!chdir(aPath.getStr()))
220 : {
221 0 : return sal_True;
222 : }
223 : else
224 : {
225 0 : if (bSloppy && !chdir(aPath.getStr()))
226 : {
227 0 : return sal_True;
228 : }
229 : else
230 : {
231 0 : return sal_False;
232 : }
233 0 : }
234 : }
235 :
236 0 : sal_uInt16 DirReader_Impl::Init()
237 : {
238 0 : return 0;
239 : }
240 :
241 0 : sal_uInt16 DirReader_Impl::Read()
242 : {
243 0 : if (!pDosDir)
244 : {
245 0 : pDosDir = opendir(rtl::OUStringToOString(aPath, osl_getThreadTextEncoding()).getStr());
246 : }
247 :
248 0 : if (!pDosDir)
249 : {
250 0 : bReady = sal_True;
251 0 : return 0;
252 : }
253 :
254 : // List directories and dirs
255 0 : if ( ( pDir->eAttrMask & FSYS_KIND_DIR || pDir->eAttrMask & FSYS_KIND_FILE ) &&
256 0 : ( ( pDosEntry = readdir( pDosDir ) ) != NULL ) )
257 : {
258 0 : String aD_Name(pDosEntry->d_name, osl_getThreadTextEncoding());
259 0 : if ( pDir->aNameMask.Matches( aD_Name ) )
260 : {
261 : DirEntryFlag eFlag =
262 0 : 0 == strcmp( pDosEntry->d_name, "." ) ? FSYS_FLAG_CURRENT
263 0 : : 0 == strcmp( pDosEntry->d_name, ".." ) ? FSYS_FLAG_PARENT
264 0 : : FSYS_FLAG_NORMAL;
265 0 : DirEntry *pTemp = new DirEntry(rtl::OString(pDosEntry->d_name), eFlag);
266 0 : if ( pParent )
267 0 : pTemp->ImpChangeParent( new DirEntry( *pParent ), sal_False);
268 0 : FileStat aStat( *pTemp );
269 0 : if ( ( ( ( pDir->eAttrMask & FSYS_KIND_DIR ) &&
270 0 : ( aStat.IsKind( FSYS_KIND_DIR ) ) ) ||
271 : ( ( pDir->eAttrMask & FSYS_KIND_FILE ) &&
272 0 : !( aStat.IsKind( FSYS_KIND_DIR ) ) ) ) &&
273 : !( pDir->eAttrMask & FSYS_KIND_VISIBLE &&
274 0 : pDosEntry->d_name[0] == '.' ) )
275 : {
276 0 : if ( pDir->pStatLst ) // Does sorting criteria require status?
277 0 : pDir->ImpSortedInsert( pTemp, new FileStat( aStat ) );
278 : else
279 0 : pDir->ImpSortedInsert( pTemp, NULL );
280 0 : return 1;
281 : }
282 : else
283 0 : delete pTemp;
284 0 : }
285 : }
286 : else
287 0 : bReady = sal_True;
288 0 : return 0;
289 : }
290 :
291 13255 : sal_Bool FileStat::Update( const DirEntry& rDirEntry, SAL_UNUSED_PARAMETER sal_Bool )
292 : {
293 :
294 13255 : nSize = 0;
295 13255 : nKindFlags = 0;
296 13255 : aCreator.Erase();
297 13255 : aType.Erase();
298 13255 : aDateCreated = Date(0);
299 13255 : aTimeCreated = Time(0);
300 13255 : aDateModified = Date(0);
301 13255 : aTimeModified = Time(0);
302 13255 : aDateAccessed = Date(0);
303 13255 : aTimeAccessed = Time(0);
304 :
305 13255 : if ( !rDirEntry.IsValid() )
306 : {
307 0 : nError = FSYS_ERR_NOTEXISTS;
308 0 : return sal_False;
309 : }
310 :
311 : // Special case if DirEntry is root
312 13255 : if ( rDirEntry.eFlag == FSYS_FLAG_ABSROOT )
313 : {
314 0 : nKindFlags = FSYS_KIND_DIR;
315 0 : nError = FSYS_ERR_OK;
316 0 : return sal_True;
317 : }
318 :
319 : struct stat aStat;
320 13255 : rtl::OString aPath(rtl::OUStringToOString(rDirEntry.GetFull(), osl_getThreadTextEncoding()));
321 13255 : if (stat(aPath.getStr(), &aStat))
322 : {
323 : // pl: #67851#
324 : // do this here, because an existing filename containing "wildcards"
325 : // should be handled as a file, not a wildcard
326 : // note that this is not a solution, since filenames containing special characters
327 : // are handled badly across the whole Office
328 :
329 : // special treatment if name contains wildcards
330 8644 : rtl::OString aTempName(rtl::OUStringToOString(rDirEntry.GetName(), osl_getThreadTextEncoding()));
331 25932 : if ( aTempName.indexOf('?') != -1 ||
332 8644 : aTempName.indexOf('*') != -1 ||
333 8644 : aTempName.indexOf(';') != -1 )
334 : {
335 0 : nKindFlags = FSYS_KIND_WILD;
336 0 : nError = FSYS_ERR_OK;
337 0 : return sal_True;
338 : }
339 :
340 8644 : nError = FSYS_ERR_NOTEXISTS;
341 8644 : return sal_False;
342 : }
343 :
344 4611 : nError = FSYS_ERR_OK;
345 4611 : nSize = aStat.st_size;
346 :
347 4611 : nKindFlags = FSYS_KIND_UNKNOWN;
348 4611 : if ( ( aStat.st_mode & S_IFDIR ) == S_IFDIR )
349 0 : nKindFlags = nKindFlags | FSYS_KIND_DIR;
350 4611 : if ( ( aStat.st_mode & S_IFREG ) == S_IFREG )
351 4611 : nKindFlags = nKindFlags | FSYS_KIND_FILE;
352 4611 : if ( ( aStat.st_mode & S_IFCHR ) == S_IFCHR )
353 0 : nKindFlags = nKindFlags | FSYS_KIND_DEV | FSYS_KIND_CHAR;
354 4611 : if ( ( aStat.st_mode & S_IFBLK ) == S_IFBLK )
355 0 : nKindFlags = nKindFlags | FSYS_KIND_DEV | FSYS_KIND_BLOCK;
356 4611 : if ( nKindFlags == FSYS_KIND_UNKNOWN )
357 0 : nKindFlags = nKindFlags | FSYS_KIND_FILE;
358 :
359 4611 : Unx2DateAndTime( aStat.st_ctime, aTimeCreated, aDateCreated );
360 4611 : Unx2DateAndTime( aStat.st_mtime, aTimeModified, aDateModified );
361 4611 : Unx2DateAndTime( aStat.st_atime, aTimeAccessed, aDateAccessed );
362 :
363 4611 : return sal_True;
364 : }
365 :
366 0 : const char *TempDirImpl( char *pBuf )
367 : {
368 : #ifdef MACOSX
369 : // P_tmpdir is /var/tmp on Mac OS X, and it is not cleaned up on system
370 : // startup
371 : strcpy( pBuf, "/tmp" );
372 : #else
373 0 : const char *pValue = getenv( "TEMP" );
374 0 : if ( !pValue )
375 0 : pValue = getenv( "TMP" );
376 0 : if ( pValue )
377 0 : strcpy( pBuf, pValue );
378 : else
379 : // P_tempdir exists in Solaris and Linux
380 0 : strcpy( pBuf, P_tmpdir );
381 : // don't use "/tmp" as hard coded directory
382 : //strcpy( pBuf, "/tmp" );
383 : #endif /* MACOSX */
384 :
385 0 : return pBuf;
386 : }
387 :
388 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|