xref: /trunk/main/tools/source/fsys/fstat.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_tools.hxx"
30 
31 #ifdef UNX
32 #include <errno.h>
33 #endif
34 
35 #include <limits.h>
36 #include <string.h>
37 
38 #include "comdep.hxx"
39 #include <tools/fsys.hxx>
40 
41 /*************************************************************************
42 |*
43 |*    FileStat::FileStat()
44 |*
45 |*    Beschreibung      FSYS.SDW
46 |*    Ersterstellung    MI 11.06.91
47 |*    Letzte Aenderung  MI 11.06.91
48 |*
49 *************************************************************************/
50 
51 FileStat::FileStat()
52 :   // don't use Default-Ctors!
53     aDateCreated( sal_uIntPtr(0) ),
54     aTimeCreated( sal_uIntPtr(0) ),
55     aDateModified( sal_uIntPtr(0) ),
56     aTimeModified( sal_uIntPtr(0) ),
57     aDateAccessed( sal_uIntPtr(0) ),
58     aTimeAccessed( sal_uIntPtr(0) )
59 {
60     nSize = 0;
61     nKindFlags = FSYS_KIND_UNKNOWN;
62     nError = FSYS_ERR_OK;
63 }
64 
65 /*************************************************************************
66 |*
67 |*    FileStat::FileStat()
68 |*
69 |*    Beschreibung      FSYS.SDW
70 |*    Ersterstellung    MI 11.06.91
71 |*    Letzte Aenderung  MI 11.06.91
72 |*
73 *************************************************************************/
74 
75 FileStat::FileStat( const DirEntry& rDirEntry, FSysAccess nAccess )
76 :   // don't use Default-Ctors!
77     aDateCreated( sal_uIntPtr(0) ),
78     aTimeCreated( sal_uIntPtr(0) ),
79     aDateModified( sal_uIntPtr(0) ),
80     aTimeModified( sal_uIntPtr(0) ),
81     aDateAccessed( sal_uIntPtr(0) ),
82     aTimeAccessed( sal_uIntPtr(0) )
83 {
84     sal_Bool bCached = FSYS_ACCESS_CACHED == (nAccess & FSYS_ACCESS_CACHED);
85     sal_Bool bFloppy = FSYS_ACCESS_FLOPPY == (nAccess & FSYS_ACCESS_FLOPPY);
86 
87 #ifdef FEAT_FSYS_DOUBLESPEED
88     const FileStat *pStatFromDir = bCached ? rDirEntry.ImpGetStat() : 0;
89     if ( pStatFromDir )
90     {
91         nError = pStatFromDir->nError;
92         nKindFlags = pStatFromDir->nKindFlags;
93         nSize = pStatFromDir->nSize;
94         aCreator = pStatFromDir->aCreator;
95         aType = pStatFromDir->aType;
96         aDateCreated = pStatFromDir->aDateCreated;
97         aTimeCreated = pStatFromDir->aTimeCreated;
98         aDateModified = pStatFromDir->aDateModified;
99         aTimeModified = pStatFromDir->aTimeModified;
100         aDateAccessed = pStatFromDir->aDateAccessed;
101         aTimeAccessed = pStatFromDir->aTimeAccessed;
102     }
103     else
104 #endif
105         Update( rDirEntry, bFloppy );
106 }
107 
108 /*************************************************************************
109 |*
110 |*    FileStat::IsYounger()
111 |*
112 |*    Beschreibung      FSYS.SDW
113 |*    Ersterstellung    MA 11.11.91
114 |*    Letzte Aenderung  MA 11.11.91
115 |*
116 *************************************************************************/
117 
118 // sal_True  wenn die Instanz j"unger als rIsOlder ist.
119 // sal_False wenn die Instanz "alter oder gleich alt wie rIsOlder ist.
120 
121 sal_Bool FileStat::IsYounger( const FileStat& rIsOlder ) const
122 {
123     if ( aDateModified > rIsOlder.aDateModified )
124         return sal_True;
125     if ( ( aDateModified == rIsOlder.aDateModified ) &&
126          ( aTimeModified > rIsOlder.aTimeModified ) )
127         return sal_True;
128 
129     return sal_False;
130 }
131 
132 /*************************************************************************
133 |*
134 |*    FileStat::IsKind()
135 |*
136 |*    Ersterstellung    MA 11.11.91 (?)
137 |*    Letzte Aenderung  KH 16.01.95
138 |*
139 *************************************************************************/
140 
141 sal_Bool FileStat::IsKind( DirEntryKind nKind ) const
142 {
143     sal_Bool bRet = ( ( nKind == FSYS_KIND_UNKNOWN ) &&
144                   ( nKindFlags == FSYS_KIND_UNKNOWN ) ) ||
145                 ( ( nKindFlags & nKind ) == nKind );
146     return bRet;
147 }
148 
149 /*************************************************************************
150 |*
151 |*    FileStat::HasReadOnlyFlag()
152 |*
153 |*    Ersterstellung    MI 06.03.97
154 |*    Letzte Aenderung  UT 01.07.98
155 |*
156 *************************************************************************/
157 
158 sal_Bool FileStat::HasReadOnlyFlag()
159 {
160 #if defined WNT || defined UNX || defined OS2
161     return sal_True;
162 #else
163     return sal_False;
164 #endif
165 }
166 
167 /*************************************************************************
168 |*
169 |*    FileStat::GetReadOnlyFlag()
170 |*
171 |*    Ersterstellung    MI 06.03.97
172 |*    Letzte Aenderung  UT 02.07.98
173 |*
174 *************************************************************************/
175 
176 sal_Bool FileStat::GetReadOnlyFlag( const DirEntry &rEntry )
177 {
178 
179     ByteString aFPath(rEntry.GetFull(), osl_getThreadTextEncoding());
180 #if defined WNT
181     DWORD nRes = GetFileAttributes( (LPCTSTR) aFPath.GetBuffer() );
182     return ULONG_MAX != nRes &&
183            ( FILE_ATTRIBUTE_READONLY & nRes ) == FILE_ATTRIBUTE_READONLY;
184 #elif defined OS2
185     FILESTATUS3 aFileStat;
186     APIRET nRet = DosQueryPathInfo( (PSZ)aFPath.GetBuffer(), 1, &aFileStat, sizeof(aFileStat) );
187     switch ( nRet )
188     {
189         case NO_ERROR:
190             return FILE_READONLY == ( aFileStat.attrFile & FILE_READONLY );
191         default:
192             return sal_False;
193     }
194 #elif defined UNX
195     /* could we stat the object? */
196     struct stat aBuf;
197     if (stat(aFPath.GetBuffer(), &aBuf))
198         return sal_False;
199     /* jupp, is writable for user? */
200     return((aBuf.st_mode & S_IWUSR) != S_IWUSR);
201 #else
202     return sal_False;
203 #endif
204 }
205 
206 /*************************************************************************
207 |*
208 |*    FileStat::SetReadOnlyFlag()
209 |*
210 |*    Ersterstellung    MI 06.03.97
211 |*    Letzte Aenderung  UT 01.07.98
212 |*
213 *************************************************************************/
214 
215 sal_uIntPtr FileStat::SetReadOnlyFlag( const DirEntry &rEntry, sal_Bool bRO )
216 {
217 
218     ByteString aFPath(rEntry.GetFull(), osl_getThreadTextEncoding());
219 
220 #if defined WNT
221     DWORD nRes = GetFileAttributes( (LPCTSTR) aFPath.GetBuffer() );
222     if ( ULONG_MAX != nRes )
223         nRes = SetFileAttributes( (LPCTSTR) aFPath.GetBuffer(),
224                     ( nRes & ~FILE_ATTRIBUTE_READONLY ) |
225                     ( bRO ? FILE_ATTRIBUTE_READONLY : 0 ) );
226     return ( ULONG_MAX == nRes ) ? ERRCODE_IO_UNKNOWN : 0;
227 #elif defined OS2
228     FILESTATUS3 aFileStat;
229     APIRET nRet = DosQueryPathInfo( (PSZ)aFPath.GetBuffer(), 1, &aFileStat, sizeof(aFileStat) );
230     if ( !nRet )
231     {
232         aFileStat.attrFile = ( aFileStat.attrFile & ~FILE_READONLY ) |
233                              ( bRO ? FILE_READONLY : 0 );
234         nRet = DosSetPathInfo( (PSZ)aFPath.GetBuffer(), 1, &aFileStat, sizeof(aFileStat), 0 );
235     }
236     switch ( nRet )
237     {
238         case NO_ERROR:
239             return ERRCODE_NONE;
240 
241         case ERROR_SHARING_VIOLATION:
242             return ERRCODE_IO_LOCKVIOLATION;
243 
244         default:
245             return ERRCODE_IO_NOTEXISTS;
246     }
247 #elif defined UNX
248     /* first, stat the object to get permissions */
249     struct stat aBuf;
250     if (stat(aFPath.GetBuffer(), &aBuf))
251         return ERRCODE_IO_NOTEXISTS;
252     /* set or clear write bit for user */
253     mode_t nMode;
254     if (bRO)
255     {
256         nMode = aBuf.st_mode & ~S_IWUSR;
257         nMode = aBuf.st_mode & ~S_IWGRP;
258         nMode = aBuf.st_mode & ~S_IWOTH;
259     }
260     else
261         nMode = aBuf.st_mode | S_IWUSR;
262     /* change it on fs */
263     if (chmod(aFPath.GetBuffer(), nMode))
264     {
265         switch (errno)
266         {
267             case EPERM :
268             case EROFS :
269                 return ERRCODE_IO_ACCESSDENIED;
270             default    :
271                 return ERRCODE_IO_NOTEXISTS;
272         }
273     }
274     else
275         return ERRCODE_NONE;
276 #else
277     return ERRCODE_IO_NOTSUPPORTED;
278 #endif
279 }
280 
281 /*************************************************************************
282 |*
283 |*    FileStat::SetDateTime
284 |*
285 |*    Ersterstellung    PB  27.06.97
286 |*    Letzte Aenderung
287 |*
288 *************************************************************************/
289 #if defined WNT || defined OS2
290 
291 void FileStat::SetDateTime( const String& rFileName,
292                             const DateTime& rNewDateTime )
293 {
294     ByteString aFileName(rFileName, osl_getThreadTextEncoding());
295 
296     Date aNewDate = rNewDateTime;
297     Time aNewTime = rNewDateTime;
298 
299 #if defined WNT
300     TIME_ZONE_INFORMATION aTZI;
301     DWORD dwTZI = GetTimeZoneInformation( &aTZI );
302 
303     if ( dwTZI != (DWORD)-1 && dwTZI != TIME_ZONE_ID_UNKNOWN )
304     {
305         // 1. Korrektur der Zeitzone
306         LONG nDiff = aTZI.Bias;
307         Time aOldTime = aNewTime; // alte Zeit merken
308 
309         // 2. evt. Korrektur Sommer-/Winterzeit
310         if ( dwTZI == TIME_ZONE_ID_DAYLIGHT )
311             nDiff += aTZI.DaylightBias;
312 
313         Time aDiff( abs( nDiff / 60 /*Min -> Std*/ ), 0 );
314 
315         if ( nDiff > 0 )
316         {
317             aNewTime += aDiff;                  // Stundenkorrektur
318 
319             // bei "Uberlauf korrigieren
320             if ( aNewTime >= Time( 24, 0 ) )
321                 aNewTime -= Time( 24, 0 );
322 
323             // Tages"uberlauf?
324             if ( aOldTime == Time( 0, 0 ) ||    // 00:00 -> 01:00
325                  aNewTime < aOldTime )          // 23:00 -> 00:00 | 01:00 ...
326                 aNewDate++;
327         }
328         else if ( nDiff < 0 )
329         {
330             aNewTime -= aDiff;                  // Stundenkorrektur
331 
332             // negative Zeit (-1:00) korrigieren: 23:00
333             if (aNewTime < Time( 0, 0 ) )
334                 aNewTime += Time( 24, 0 );
335 
336             // Tagesunterlauf ?
337             if ( aOldTime == Time( 0, 0 ) ||    // 00:00 -> 23:00
338                  aNewTime > aOldTime )          // 01:00 -> 23:00 | 22:00 ...
339                 aNewDate--;
340         }
341     }
342 
343 
344     SYSTEMTIME aTime;
345     aTime.wYear = aNewDate.GetYear();
346     aTime.wMonth = aNewDate.GetMonth();
347     aTime.wDayOfWeek = 0;
348     aTime.wDay = aNewDate.GetDay();
349     aTime.wHour = aNewTime.GetHour();
350     aTime.wMinute = aNewTime.GetMin();
351     aTime.wSecond = aNewTime.GetSec();
352     aTime.wMilliseconds = 0;
353     FILETIME aFileTime;
354     SystemTimeToFileTime( &aTime, &aFileTime );
355 
356     HANDLE hFile = CreateFile( aFileName.GetBuffer(), GENERIC_WRITE, 0, 0,
357                                OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
358 
359     if ( hFile != INVALID_HANDLE_VALUE )
360     {
361         SetFileTime( hFile, &aFileTime, &aFileTime, &aFileTime );
362         CloseHandle( hFile );
363     }
364 #elif defined OS2
365 
366     // open file
367     ULONG nAction = FILE_EXISTED;
368     HFILE hFile = 0;
369     ULONG nFlags = OPEN_FLAGS_WRITE_THROUGH |
370                    OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_CACHE   |
371                    OPEN_FLAGS_RANDOM        | OPEN_FLAGS_NOINHERIT  |
372                    OPEN_SHARE_DENYNONE      | OPEN_ACCESS_READWRITE;
373 
374     APIRET nRet = DosOpen((PSZ)aFileName.GetBuffer(), &hFile, (PULONG)&nAction,
375                           0/*size*/, FILE_NORMAL,
376                           OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
377                           nFlags, 0/*ea*/);
378 
379     if ( nRet == 0 )
380     {
381         FILESTATUS3 FileInfoBuffer;
382 
383         nRet = DosQueryFileInfo(
384             hFile, 1, &FileInfoBuffer, sizeof(FileInfoBuffer));
385 
386         if ( nRet == 0 )
387         {
388             FDATE aNewDate;
389             FTIME aNewTime;
390 
391              // create date and time words
392             aNewDate.day     = rNewDateTime.GetDay();
393             aNewDate.month   = rNewDateTime.GetMonth();
394             aNewDate.year    = rNewDateTime.GetYear() - 1980;
395             aNewTime.twosecs = rNewDateTime.GetSec() / 2;
396             aNewTime.minutes = rNewDateTime.GetMin();
397             aNewTime.hours   = rNewDateTime.GetHour();
398 
399             // set file date and time
400             FileInfoBuffer.fdateCreation   = aNewDate;
401             FileInfoBuffer.ftimeCreation   = aNewTime;
402             FileInfoBuffer.fdateLastAccess = aNewDate;
403             FileInfoBuffer.ftimeLastAccess = aNewTime;
404             FileInfoBuffer.fdateLastWrite  = aNewDate;
405             FileInfoBuffer.ftimeLastWrite  = aNewTime;
406 
407             DosSetFileInfo(hFile, 1, &FileInfoBuffer, sizeof(FileInfoBuffer));
408         }
409         DosClose(hFile);
410     }
411 #endif
412 
413 }
414 #endif
415