Update ooo320-m1
[ooovba.git] / tools / source / fsys / filecopy.cxx
blob472e07b2980fccf4061bf66636245ce87071822f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: filecopy.cxx,v $
10 * $Revision: 1.10 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_tools.hxx"
34 #if defined WNT
35 #ifndef _SVWIN_H
36 #include <io.h>
37 #include <tools/svwin.h>
38 #endif
40 #elif defined(OS2)
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <fcntl.h>
44 #include <share.h>
45 #include <io.h>
47 #elif defined UNX
48 #include <fcntl.h>
49 #include <unistd.h>
50 #include <sys/stat.h>
52 #endif
54 #include <ctype.h>
55 #include <errno.h>
56 #include <stdlib.h>
57 #include <string.h>
59 #include <stdio.h>
60 #include "comdep.hxx"
61 #include <tools/fsys.hxx>
62 #include <tools/stream.hxx>
63 #include <osl/file.hxx>
65 using namespace ::osl;
67 /*************************************************************************
69 |* FileCopier::FileCopier()
71 |* Beschreibung FSYS.SDW
72 |* Ersterstellung MI 13.04.94
73 |* Letzte Aenderung MI 13.04.94
75 *************************************************************************/
77 FileCopier::FileCopier() :
79 nBytesTotal ( 0 ),
80 nBytesCopied( 0 ),
81 nBlockSize ( 4096 ),
82 pImp ( new FileCopier_Impl )
87 // -----------------------------------------------------------------------
89 FileCopier::FileCopier( const DirEntry& rSource, const DirEntry& rTarget ) :
91 aSource ( rSource ),
92 aTarget ( rTarget ),
93 nBytesTotal ( 0 ),
94 nBytesCopied( 0 ),
95 nBlockSize ( 4096 ),
96 pImp ( new FileCopier_Impl )
101 // -----------------------------------------------------------------------
103 FileCopier::FileCopier( const FileCopier& rCopier ) :
105 aSource ( rCopier.aSource ),
106 aTarget ( rCopier.aTarget ),
107 nBytesTotal ( 0 ),
108 nBytesCopied ( 0 ),
109 aProgressLink ( rCopier.aProgressLink ),
110 nBlockSize ( 4096 ),
111 pImp ( new FileCopier_Impl )
116 /*************************************************************************
118 |* FileCopier::~FileCopier()
120 |* Beschreibung FSYS.SDW
121 |* Ersterstellung MI 13.04.94
122 |* Letzte Aenderung MI 13.04.94
124 *************************************************************************/
126 FileCopier::~FileCopier()
128 delete pImp;
131 /*************************************************************************
133 |* FileCopier::operator =()
135 |* Beschreibung FSYS.SDW
136 |* Ersterstellung MI 13.04.94
137 |* Letzte Aenderung MI 13.04.94
139 *************************************************************************/
141 FileCopier& FileCopier::operator = ( const FileCopier &rCopier )
143 aSource = rCopier.aSource;
144 aTarget = rCopier.aTarget;
145 nBytesTotal = rCopier.nBytesTotal;
146 nBytesCopied = rCopier.nBytesCopied;
147 nBytesCopied = rCopier.nBytesCopied;
148 nBlockSize = rCopier.nBlockSize;
149 aProgressLink = rCopier.aProgressLink;
150 *pImp = *(rCopier.pImp);
151 return *this;
154 /*************************************************************************
156 |* FileCopier::Progress()
158 |* Beschreibung FSYS.SDW
159 |* Ersterstellung MI 13.04.94
160 |* Letzte Aenderung MI 13.04.94
162 *************************************************************************/
164 BOOL FileCopier::Progress()
166 if ( !aProgressLink )
167 return TRUE;
168 else
170 if ( aProgressLink.Call( this ) )
171 return TRUE;
172 return ( 0 == Error( ERRCODE_ABORT, 0, 0 ) );
176 //---------------------------------------------------------------------------
178 ErrCode FileCopier::Error( ErrCode eErr, const DirEntry* pSource, const DirEntry* pTarget )
180 // kein Fehler oder kein ErrorHandler?
181 if ( !eErr || !pImp->aErrorLink )
182 // => Error beibehalten
183 return eErr;
185 // sonst gesetzten ErrorHandler fragen
186 pImp->pErrSource = pSource;
187 pImp->pErrTarget = pTarget;
188 pImp->eErr = eErr;
189 ErrCode eRet = (ErrCode) pImp->aErrorLink.Call( this );
190 pImp->pErrSource = 0;
191 pImp->pErrTarget = 0;
192 return eRet;
195 //---------------------------------------------------------------------------
197 const DirEntry* FileCopier::GetErrorSource() const
199 return pImp->pErrSource;
202 //---------------------------------------------------------------------------
204 const DirEntry* FileCopier::GetErrorTarget() const
206 return pImp->pErrTarget;
209 //---------------------------------------------------------------------------
211 ErrCode FileCopier::GetError() const
213 return pImp->eErr;
216 //---------------------------------------------------------------------------
218 void FileCopier::SetErrorHdl( const Link &rLink )
220 pImp->aErrorLink = rLink;
223 //---------------------------------------------------------------------------
225 const Link& FileCopier::GetErrorHdl() const
227 return pImp->aErrorLink ;
230 /*************************************************************************
232 |* FileCopier::Execute()
234 |* Beschreibung FSYS.SDW
235 |* Ersterstellung MI 13.04.94
236 |* Letzte Aenderung PB 16.06.00
238 *************************************************************************/
240 FSysError FileCopier::DoCopy_Impl(
241 const DirEntry &rSource, const DirEntry &rTarget )
243 FSysError eRet = FSYS_ERR_OK;
244 ErrCode eWarn = FSYS_ERR_OK;
246 // HPFS->FAT?
247 FSysPathStyle eSourceStyle = DirEntry::GetPathStyle( rSource.ImpGetTopPtr()->GetName() );
248 FSysPathStyle eTargetStyle = DirEntry::GetPathStyle( rTarget.ImpGetTopPtr()->GetName() );
249 BOOL bMakeShortNames = ( eSourceStyle == FSYS_STYLE_HPFS && eTargetStyle == FSYS_STYLE_FAT );
251 // Zieldateiname ggf. kuerzen
252 DirEntry aTgt;
253 if ( bMakeShortNames )
255 aTgt = rTarget.GetPath();
256 aTgt.MakeShortName( rTarget.GetName() );
258 else
259 aTgt = rTarget;
261 // kein Move wenn Namen gekuerzt werden muessten
262 if ( bMakeShortNames && FSYS_ACTION_MOVE == ( pImp->nActions & FSYS_ACTION_MOVE ) && aTgt != rTarget )
263 return ERRCODE_IO_NAMETOOLONG;
265 // source is directory?
266 FileStat aSourceFileStat( rSource );
267 if ( aSourceFileStat.IsKind( FSYS_KIND_DIR ) )
269 #ifdef OS2
270 CHAR szSource[CCHMAXPATHCOMP];
271 HOBJECT hSourceObject;
273 strcpy(szSource, ByteString(rSource.GetFull(), osl_getThreadTextEncoding()).GetBuffer());
274 hSourceObject = WinQueryObject(szSource);
276 if ( hSourceObject )
278 PSZ pszSourceName;
279 PSZ pszTargetName;
280 CHAR szTarget[CCHMAXPATHCOMP];
281 HOBJECT hTargetObject;
282 HOBJECT hReturn = NULLHANDLE;
284 strcpy(szTarget, ByteString(rTarget.GetFull(), osl_getThreadTextEncoding()).GetBuffer());
285 pszTargetName = strrchr(szTarget, '\\');
286 pszSourceName = strrchr(szSource, '\\');
288 hTargetObject = WinQueryObject(szTarget);
290 if ( hTargetObject )
291 WinDestroyObject(hTargetObject);
293 if ( pszTargetName && pszSourceName )
295 *pszTargetName = '\0';
296 pszSourceName++;
297 pszTargetName++;
299 if(strcmp(pszSourceName, pszTargetName) == 0)
301 hTargetObject = WinQueryObject(szTarget);
303 if(pImp->nActions & FSYS_ACTION_MOVE)
305 hReturn = WinMoveObject(hSourceObject, hTargetObject, 0);
307 else
309 hReturn = WinCopyObject(hSourceObject, hTargetObject, 0);
311 if ( bMakeShortNames && aTarget.Exists() )
312 aTarget.Kill();
313 return hReturn ? FSYS_ERR_OK : FSYS_ERR_UNKNOWN;
317 #endif
318 // recursive copy
319 eRet = Error( aTgt.MakeDir() ? FSYS_ERR_OK : FSYS_ERR_UNKNOWN, 0, &aTgt );
320 Dir aSourceDir( rSource, FSYS_KIND_DIR|FSYS_KIND_FILE );
321 for ( USHORT n = 0; ERRCODE_TOERROR(eRet) == FSYS_ERR_OK && n < aSourceDir.Count(); ++n )
323 const DirEntry &rSubSource = aSourceDir[n];
324 DirEntryFlag eFlag = rSubSource.GetFlag();
325 if ( eFlag != FSYS_FLAG_CURRENT && eFlag != FSYS_FLAG_PARENT )
327 DirEntry aSubTarget( aTgt );
328 aSubTarget += rSubSource.GetName();
329 eRet = DoCopy_Impl( rSubSource, aSubTarget );
330 if ( eRet && !eWarn )
331 eWarn = eRet;
335 else if ( aSourceFileStat.IsKind(FSYS_KIND_FILE) )
337 if ( ( FSYS_ACTION_KEEP_EXISTING == ( pImp->nActions & FSYS_ACTION_KEEP_EXISTING ) ) &&
338 aTgt.Exists() )
340 // Do not overwrite existing file in target folder.
341 return ERRCODE_NONE;
344 // copy file
345 nBytesCopied = 0;
346 nBytesTotal = FileStat( rSource ).GetSize();
348 ::rtl::OUString aFileName;
349 FileBase::getFileURLFromSystemPath( ::rtl::OUString(rSource.GetFull()), aFileName );
350 SvFileStream aSrc( aFileName, STREAM_READ|STREAM_NOCREATE|STREAM_SHARE_DENYNONE );
352 if ( !aSrc.GetError() )
354 #ifdef UNX
355 struct stat buf;
356 if ( fstat( aSrc.GetFileHandle(), &buf ) == -1 )
357 eRet = Error( FSYS_ERR_ACCESSDENIED, 0, &aTgt );
358 #endif
359 ::rtl::OUString aTargetFileName;
360 FileBase::getFileURLFromSystemPath( ::rtl::OUString(aTgt.GetFull()), aTargetFileName );
362 SvFileStream aTargetStream( aTargetFileName, STREAM_WRITE | STREAM_TRUNC | STREAM_SHARE_DENYWRITE );
363 if ( !aTargetStream.GetError() )
365 #ifdef UNX
366 if ( fchmod( aTargetStream.GetFileHandle(), buf.st_mode ) == -1 )
367 eRet = Error( FSYS_ERR_ACCESSDENIED, 0, &aTgt );
368 #endif
369 size_t nAllocSize = 0, nSize = 0;
370 char *pBuf = 0;
371 while ( Progress() && nSize == nAllocSize && eRet == FSYS_ERR_OK )
373 // adjust the block-size
374 if ( nBlockSize > nAllocSize )
376 delete[] pBuf;
377 nAllocSize = nBlockSize;
378 pBuf = new char[nAllocSize];
381 // copy one block
382 nSize = aSrc.Read( pBuf, nBlockSize );
383 aTargetStream.Write( pBuf, nSize );
384 if ( aTargetStream.GetError() )
385 eRet = Error( aTargetStream.GetError(), 0, &aTgt );
387 // adjust counters
388 nBytesCopied += nSize;
389 if ( nBytesCopied > nBytesTotal )
390 nBytesTotal = nBytesCopied;
392 delete[] pBuf;
394 else
395 eRet = Error( aTargetStream.GetError(), 0, &aTgt );
397 // unvollstaendiges File wieder loeschen
398 aTargetStream.Close();
400 if ( nBytesCopied != nBytesTotal )
402 aTgt.Kill();
405 else
406 eRet = Error( aSrc.GetError(), &rSource, 0 );
408 else if ( aSourceFileStat.IsKind(FSYS_KIND_NONE) )
409 eRet = Error( ERRCODE_IO_NOTEXISTS, &rSource, 0 );
410 else
411 eRet = Error( ERRCODE_IO_NOTSUPPORTED, &rSource, 0 );
413 #ifdef WNT
414 // Set LastWriteTime and Attributes of the target identical with the source
416 if ( FSYS_ERR_OK == ERRCODE_TOERROR(eRet) )
418 WIN32_FIND_DATA fdSource;
419 ByteString aFullSource(aSource.GetFull(), osl_getThreadTextEncoding());
420 ByteString aFullTarget(aTgt.GetFull(), osl_getThreadTextEncoding());
421 HANDLE hFind = FindFirstFile( aFullSource.GetBuffer() , &fdSource );
422 if ( hFind != INVALID_HANDLE_VALUE )
424 FindClose( hFind );
426 HANDLE hFile = CreateFile( aFullTarget.GetBuffer(), GENERIC_WRITE,
427 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
428 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
430 if ( hFile != INVALID_HANDLE_VALUE )
432 SetFileTime( hFile, NULL, NULL, &fdSource.ftLastWriteTime );
433 CloseHandle( hFile );
436 SetFileAttributes( aFullTarget.GetBuffer(), fdSource.dwFileAttributes );
439 #endif
440 // bei Move ggf. das File/Dir loeschen
441 if ( FSYS_ERR_OK == ERRCODE_TOERROR(eRet) && ( pImp->nActions & FSYS_ACTION_MOVE ) )
443 ErrCode eKillErr = Error( rSource.Kill() | ERRCODE_WARNING_MASK, &rSource, 0 );
444 if ( eKillErr != ERRCODE_WARNING_MASK )
446 if ( rSource.Exists() )
447 // loeschen ging nicht => dann die Kopie wieder loeschen
448 aTgt.Kill( pImp->nActions );
449 if ( !eWarn )
450 eWarn = eKillErr;
454 return !eRet ? eWarn : eRet;
457 // -----------------------------------------------------------------------
459 FSysError FileCopier::Execute( FSysAction nActions )
461 return ExecuteExact( nActions );
464 // -----------------------------------------------------------------------
466 FSysError FileCopier::ExecuteExact( FSysAction nActions, FSysExact eExact )
468 DirEntry aAbsSource = DirEntry( aSource);
469 DirEntry aAbsTarget = DirEntry( aTarget );
470 pImp->nActions = nActions;
472 // check if both pathes are accessible and source and target are different
473 if ( !aAbsTarget.ToAbs() || !aAbsSource.ToAbs() || aAbsTarget == aAbsSource )
474 return FSYS_ERR_ACCESSDENIED;
476 // check if copy would be endless recursive into itself
477 if ( FSYS_ACTION_RECURSIVE == ( nActions & FSYS_ACTION_RECURSIVE ) &&
478 aAbsSource.Contains( aAbsTarget ) )
479 return ERRCODE_IO_RECURSIVE;
481 // target is directory?
482 if ( eExact == FSYS_NOTEXACT &&
483 FileStat( aAbsTarget ).IsKind(FSYS_KIND_DIR) && FileStat( aAbsSource ).IsKind(FSYS_KIND_FILE) )
484 // append name of source
485 aAbsTarget += aSource.GetName();
487 // recursive copy
488 return DoCopy_Impl( aAbsSource, aAbsTarget );