1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: filecopy.cxx,v $
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"
37 #include <tools/svwin.h>
41 #include <sys/types.h>
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() :
82 pImp ( new FileCopier_Impl
)
87 // -----------------------------------------------------------------------
89 FileCopier::FileCopier( const DirEntry
& rSource
, const DirEntry
& rTarget
) :
96 pImp ( new FileCopier_Impl
)
101 // -----------------------------------------------------------------------
103 FileCopier::FileCopier( const FileCopier
& rCopier
) :
105 aSource ( rCopier
.aSource
),
106 aTarget ( rCopier
.aTarget
),
109 aProgressLink ( rCopier
.aProgressLink
),
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()
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
);
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
)
170 if ( aProgressLink
.Call( this ) )
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
185 // sonst gesetzten ErrorHandler fragen
186 pImp
->pErrSource
= pSource
;
187 pImp
->pErrTarget
= pTarget
;
189 ErrCode eRet
= (ErrCode
) pImp
->aErrorLink
.Call( this );
190 pImp
->pErrSource
= 0;
191 pImp
->pErrTarget
= 0;
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
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
;
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
253 if ( bMakeShortNames
)
255 aTgt
= rTarget
.GetPath();
256 aTgt
.MakeShortName( rTarget
.GetName() );
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
) )
270 CHAR szSource
[CCHMAXPATHCOMP
];
271 HOBJECT hSourceObject
;
273 strcpy(szSource
, ByteString(rSource
.GetFull(), osl_getThreadTextEncoding()).GetBuffer());
274 hSourceObject
= WinQueryObject(szSource
);
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
);
291 WinDestroyObject(hTargetObject
);
293 if ( pszTargetName
&& pszSourceName
)
295 *pszTargetName
= '\0';
299 if(strcmp(pszSourceName
, pszTargetName
) == 0)
301 hTargetObject
= WinQueryObject(szTarget
);
303 if(pImp
->nActions
& FSYS_ACTION_MOVE
)
305 hReturn
= WinMoveObject(hSourceObject
, hTargetObject
, 0);
309 hReturn
= WinCopyObject(hSourceObject
, hTargetObject
, 0);
311 if ( bMakeShortNames
&& aTarget
.Exists() )
313 return hReturn
? FSYS_ERR_OK
: FSYS_ERR_UNKNOWN
;
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
)
335 else if ( aSourceFileStat
.IsKind(FSYS_KIND_FILE
) )
337 if ( ( FSYS_ACTION_KEEP_EXISTING
== ( pImp
->nActions
& FSYS_ACTION_KEEP_EXISTING
) ) &&
340 // Do not overwrite existing file in target folder.
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() )
356 if ( fstat( aSrc
.GetFileHandle(), &buf
) == -1 )
357 eRet
= Error( FSYS_ERR_ACCESSDENIED
, 0, &aTgt
);
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() )
366 if ( fchmod( aTargetStream
.GetFileHandle(), buf
.st_mode
) == -1 )
367 eRet
= Error( FSYS_ERR_ACCESSDENIED
, 0, &aTgt
);
369 size_t nAllocSize
= 0, nSize
= 0;
371 while ( Progress() && nSize
== nAllocSize
&& eRet
== FSYS_ERR_OK
)
373 // adjust the block-size
374 if ( nBlockSize
> nAllocSize
)
377 nAllocSize
= nBlockSize
;
378 pBuf
= new char[nAllocSize
];
382 nSize
= aSrc
.Read( pBuf
, nBlockSize
);
383 aTargetStream
.Write( pBuf
, nSize
);
384 if ( aTargetStream
.GetError() )
385 eRet
= Error( aTargetStream
.GetError(), 0, &aTgt
);
388 nBytesCopied
+= nSize
;
389 if ( nBytesCopied
> nBytesTotal
)
390 nBytesTotal
= nBytesCopied
;
395 eRet
= Error( aTargetStream
.GetError(), 0, &aTgt
);
397 // unvollstaendiges File wieder loeschen
398 aTargetStream
.Close();
400 if ( nBytesCopied
!= nBytesTotal
)
406 eRet
= Error( aSrc
.GetError(), &rSource
, 0 );
408 else if ( aSourceFileStat
.IsKind(FSYS_KIND_NONE
) )
409 eRet
= Error( ERRCODE_IO_NOTEXISTS
, &rSource
, 0 );
411 eRet
= Error( ERRCODE_IO_NOTSUPPORTED
, &rSource
, 0 );
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
)
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
);
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
);
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();
488 return DoCopy_Impl( aAbsSource
, aAbsTarget
);