xref: /trunk/main/tools/source/fsys/fstat.cxx (revision cdf0e10c)
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