moving common implementation for osx closer to unix, by using threadspsx.cpp and unix/dir.cpp, getting rid of morefile(x) and moving colour.cpp to core
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@54889 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
860
Makefile.in
860
Makefile.in
File diff suppressed because it is too large
Load Diff
@@ -61,10 +61,12 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
|
||||
src/unix/epolldispatcher.cpp
|
||||
src/unix/appunix.cpp
|
||||
src/unix/evtloopunix.cpp
|
||||
src/unix/dir.cpp
|
||||
src/unix/dlunix.cpp
|
||||
src/unix/snglinst.cpp
|
||||
src/unix/stdpaths.cpp
|
||||
src/unix/timerunx.cpp
|
||||
src/unix/threadpsx.cpp
|
||||
src/unix/stackwalk.cpp
|
||||
src/unix/utilsunx.cpp
|
||||
</set>
|
||||
@@ -89,9 +91,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
|
||||
-->
|
||||
<set var="BASE_UNIX_AND_DARWIN_NOTWXMAC_SRC" hints="files">
|
||||
$(BASE_UNIX_AND_DARWIN_SRC)
|
||||
src/unix/dir.cpp
|
||||
src/unix/mimetype.cpp
|
||||
src/unix/threadpsx.cpp
|
||||
</set>
|
||||
|
||||
<set var="BASE_UNIX_AND_DARWIN_NOTWXMAC_HDR" hints="files">
|
||||
@@ -180,7 +180,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
|
||||
<!-- Mac -->
|
||||
<!-- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -->
|
||||
|
||||
<!-- Used on Mac OS CarbonLib, Mac OS X wxMac base, and Mac OS X darwin base -->
|
||||
<!-- Used on Mac OS X wxMac base, and Mac OS X darwin base -->
|
||||
<set var="BASE_COREFOUNDATION_SRC" hints="files">
|
||||
src/osx/core/cfstring.cpp
|
||||
src/osx/core/gsockosx.cpp
|
||||
@@ -197,48 +197,22 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
|
||||
wx/osx/core/private/strconv_cf.h
|
||||
</set>
|
||||
|
||||
<!-- Base files used by Carbon on OS X and CarbonLib (not true Classic) -->
|
||||
<!-- Base files used by wxMac on OS X -->
|
||||
<!-- FIXME: Maybe this ought to be named BASE_MAC_CARBON_SRC -->
|
||||
<set var="BASE_MAC_SRC" hints="files">
|
||||
src/osx/carbon/dirmac.cpp
|
||||
src/osx/carbon/mimetmac.cpp
|
||||
src/osx/carbon/thread.cpp
|
||||
<!-- One would think MoreFilesX is only for OS X but it seems to
|
||||
apply to CarbonLib as well (FSRefMakeFSSpec) -->
|
||||
src/osx/carbon/morefilex/MoreFilesX.c
|
||||
$(BASE_COREFOUNDATION_SRC)
|
||||
</set>
|
||||
<set var="BASE_MAC_HDR" hints="files">
|
||||
$(BASE_COREFOUNDATION_HDR)
|
||||
</set>
|
||||
<!-- Base and GUI files used by both OS X and CarbonLib -->
|
||||
<!-- Base and GUI files used by OS X -->
|
||||
<set var="BASE_AND_GUI_MAC_SRC" hints="files">
|
||||
src/osx/carbon/utils.cpp
|
||||
src/osx/carbon/uma.cpp
|
||||
</set>
|
||||
|
||||
<!-- Base files used by Classic (not CarbonLib or OS X builds) -->
|
||||
<!-- set var="BASE_MAC_CLASSIC_SRC">
|
||||
</set -->
|
||||
<!-- set var="BASE_MAC_CLASSIC_HDR">
|
||||
</set -->
|
||||
|
||||
<!-- Base files used only by CarbonLib builds (not Classic or OS X) -->
|
||||
<set var="BASE_MAC_CARBONLIB_SRC" hints="files">
|
||||
src/osx/carbon/morefile/DirectoryCopy.c
|
||||
src/osx/carbon/morefile/FSpCompat.c
|
||||
src/osx/carbon/morefile/FileCopy.c
|
||||
src/osx/carbon/morefile/FullPath.c
|
||||
src/osx/carbon/morefile/IterateDirectory.c
|
||||
src/osx/carbon/morefile/MoreDesktopMgr.c
|
||||
src/osx/carbon/morefile/MoreFiles.c
|
||||
src/osx/carbon/morefile/MoreFilesExtras.c
|
||||
src/osx/carbon/morefile/Search.c
|
||||
</set>
|
||||
<!-- set var="BASE_MAC_CARBONLIB_HDR" hints="files">
|
||||
</set -->
|
||||
|
||||
<!-- Base files used only by OS X builds (not CarbonLib or Classic) -->
|
||||
<!-- Base files used only by OS X builds -->
|
||||
<set var="BASE_MACOSX_WXMAC_SRC" hints="files">
|
||||
$(BASE_MAC_SRC)
|
||||
$(BASE_UNIX_AND_DARWIN_SRC)
|
||||
@@ -408,7 +382,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
|
||||
src/common/txtstrm.cpp
|
||||
src/common/unichar.cpp
|
||||
src/common/uri.cpp
|
||||
src/common/ustring.cpp
|
||||
<!-- src/common/ustring.cpp -->
|
||||
src/common/variant.cpp
|
||||
src/common/wfstream.cpp
|
||||
src/common/wxcrt.cpp
|
||||
@@ -535,7 +509,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
|
||||
wx/types.h
|
||||
wx/unichar.h
|
||||
wx/uri.h
|
||||
wx/ustring.h
|
||||
<!-- wx/ustring.h -->
|
||||
wx/utils.h
|
||||
wx/variant.h
|
||||
wx/vector.h
|
||||
@@ -594,11 +568,6 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
|
||||
<set var="NET_OS2_HDR" hints="files">
|
||||
wx/unix/gsockunx.h
|
||||
</set>
|
||||
<!-- Net files used only by CarbonLib (not Classic or OS X) -->
|
||||
<set var="NET_MAC_CARBONLIB_SRC" hints="files">
|
||||
</set>
|
||||
<set var="NET_MAC_CARBONLIB_HDR" hints="files">
|
||||
</set>
|
||||
|
||||
<set var="NET_CMN_SRC" hints="files">
|
||||
src/common/fs_inet.cpp
|
||||
@@ -3431,7 +3400,6 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
|
||||
<if cond="PLATFORM_UNIX=='1'">$(BASE_UNIX_SRC)</if>
|
||||
<if cond="PLATFORM_WIN32=='1'">$(BASE_WIN32_SRC) $(BASE_WINCE_SRC)</if>
|
||||
<if cond="PLATFORM_MACOSX=='1'">$(BASE_MACOSX_SRC)</if>
|
||||
<if cond="PLATFORM_MACOS=='1'">$(BASE_MAC_SRC) $(BASE_MAC_CARBONLIB_SRC)</if>
|
||||
<if cond="PLATFORM_OS2=='1'">$(BASE_OS2_SRC)</if>
|
||||
<if cond="PLATFORM_PALMOS=='1'">$(BASE_PALMOS_SRC)</if>
|
||||
<if cond="PLATFORM_MSDOS=='1'">$(BASE_MSDOS_SRC)</if>
|
||||
@@ -3484,7 +3452,6 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
|
||||
<if cond="PLATFORM_UNIX=='1'">$(NET_UNIX_SRC)</if>
|
||||
<if cond="PLATFORM_WIN32=='1'">$(NET_WIN32_SRC) $(NET_WINCE_SRC)</if>
|
||||
<if cond="PLATFORM_MACOSX=='1'">$(NET_UNIX_SRC)</if>
|
||||
<if cond="PLATFORM_MACOS=='1'">$(NET_MAC_CARBONLIB_SRC)</if>
|
||||
<if cond="PLATFORM_OS2=='1'">$(NET_OS2_SRC)</if>
|
||||
</set>
|
||||
<set var="NET_PLATFORM_HDR" hints="files">
|
||||
@@ -3492,7 +3459,6 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
|
||||
<if cond="PLATFORM_WIN32=='1'">$(NET_WIN32_HDR) $(NET_WINCE_HDR)</if>
|
||||
<if cond="PLATFORM_OS2=='1'">$(NET_OS2_HDR)</if>
|
||||
<if cond="PLATFORM_MACOSX=='1'">$(NET_UNIX_HDR)</if>
|
||||
<if cond="PLATFORM_MACOS=='1'">$(NET_MAC_CARBONLIB_HDR)</if>
|
||||
</set>
|
||||
|
||||
<set var="NET_SRC" hints="files">
|
||||
@@ -3676,7 +3642,6 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
|
||||
$(NET_WIN32_HDR) $(NET_WINCE_HDR)
|
||||
$(NET_OS2_HDR)
|
||||
$(NET_UNIX_HDR)
|
||||
$(NET_MAC_CARBONLIB_HDR)
|
||||
$(XML_HDR)
|
||||
</set>
|
||||
|
||||
|
@@ -204,7 +204,7 @@ private:
|
||||
|
||||
// in order to avoid any overhead under platforms where critical sections are
|
||||
// just mutexes make all wxCriticalSection class functions inline
|
||||
#if !defined(__WXMSW__) && ( !defined(__WXMAC__) || wxOSX_USE_COCOA_OR_IPHONE )
|
||||
#if !defined(__WXMSW__)
|
||||
#define wxCRITSECT_IS_MUTEX 1
|
||||
|
||||
#define wxCRITSECT_INLINE inline
|
||||
@@ -256,8 +256,6 @@ private:
|
||||
|
||||
wxCritSectBuffer m_buffer;
|
||||
};
|
||||
#elif defined(__WXMAC__)
|
||||
void *m_critRegion ;
|
||||
#endif // Unix&OS2/Win32
|
||||
|
||||
DECLARE_NO_COPY_CLASS(wxCriticalSection)
|
||||
@@ -774,7 +772,7 @@ public:
|
||||
|
||||
#if wxUSE_THREADS
|
||||
|
||||
#if defined(__WXMSW__) || defined(__WXMAC__) || defined(__OS2__) || defined(__EMX__)
|
||||
#if defined(__WXMSW__) || defined(__OS2__) || defined(__EMX__)
|
||||
// unlock GUI if there are threads waiting for and lock it back when
|
||||
// there are no more of them - should be called periodically by the main
|
||||
// thread
|
||||
@@ -789,7 +787,7 @@ public:
|
||||
// return true if the main thread is waiting for some other to terminate:
|
||||
// wxApp then should block all "dangerous" messages
|
||||
extern bool WXDLLIMPEXP_BASE wxIsWaitingForThread();
|
||||
#endif // MSW, Mac, OS/2
|
||||
#endif // MSW, OS/2
|
||||
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
|
@@ -340,13 +340,9 @@ wxSemaError wxSemaphore::Post()
|
||||
// wxThread
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __WXMAC__
|
||||
|
||||
#include "wx/utils.h"
|
||||
|
||||
void wxThread::Sleep(unsigned long milliseconds)
|
||||
{
|
||||
wxMilliSleep(milliseconds);
|
||||
}
|
||||
|
||||
#endif // __WXMAC__
|
||||
|
@@ -62,7 +62,7 @@ bool wxDir::HasFiles(const wxString& spec) const
|
||||
}
|
||||
|
||||
// we have a (much) faster version for Unix
|
||||
#if (defined(__CYGWIN__) && defined(__WINDOWS__)) || !defined(__UNIX_LIKE__) || ( defined(__WXMAC__) && !wxOSX_USE_IPHONE) || defined(__EMX__) || defined(__WINE__)
|
||||
#if (defined(__CYGWIN__) && defined(__WINDOWS__)) || !defined(__UNIX_LIKE__) || defined(__EMX__) || defined(__WINE__)
|
||||
|
||||
bool wxDir::HasSubDirs(const wxString& spec) const
|
||||
{
|
||||
|
@@ -1177,7 +1177,14 @@ void wxApp::MacDoOneEvent()
|
||||
if ( wxTheApp->ProcessIdle() )
|
||||
sleepTime = kEventDurationNoWait ;
|
||||
else
|
||||
{
|
||||
sleepTime = kEventDurationSecond;
|
||||
#if wxUSE_THREADS
|
||||
wxMutexGuiLeave();
|
||||
wxMilliSleep(20);
|
||||
wxMutexGuiEnter();
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case eventLoopQuitErr :
|
||||
@@ -1230,11 +1237,6 @@ void wxApp::MacHandleOneEvent( WXEVENTREF evr )
|
||||
OSStatus status = SendEventToEventTarget((EventRef) evr , theTarget);
|
||||
if (status == eventNotHandledErr)
|
||||
MacHandleUnhandledEvent(evr);
|
||||
|
||||
#if wxUSE_THREADS
|
||||
wxMutexGuiLeaveOrEnter();
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
#else
|
||||
// TODO Threads
|
||||
#endif
|
||||
|
@@ -1,147 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/mac/carbon/colour.cpp
|
||||
// Purpose: wxColour class
|
||||
// Author: Stefan Csomor
|
||||
// Modified by:
|
||||
// Created: 1998-01-01
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) Stefan Csomor
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#include "wx/colour.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/gdicmn.h"
|
||||
#endif
|
||||
|
||||
#include "wx/osx/private.h"
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxColour, wxObject)
|
||||
|
||||
#if wxOSX_USE_CARBON
|
||||
wxColour::wxColour(const RGBColor& col)
|
||||
{
|
||||
InitRGBColor(col);
|
||||
}
|
||||
#endif
|
||||
|
||||
wxColour::wxColour(CGColorRef col)
|
||||
{
|
||||
InitCGColorRef(col);
|
||||
}
|
||||
|
||||
#if wxOSX_USE_CARBON
|
||||
void wxColour::GetRGBColor( RGBColor *col ) const
|
||||
{
|
||||
col->red = (m_red << 8) + m_red;
|
||||
col->blue = (m_blue << 8) + m_blue;
|
||||
col->green = (m_green << 8) + m_green;
|
||||
}
|
||||
|
||||
wxColour& wxColour::operator=(const RGBColor& col)
|
||||
{
|
||||
InitRGBColor(col);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
wxColour& wxColour::operator=(CGColorRef col)
|
||||
{
|
||||
InitCGColorRef(col);
|
||||
return *this;
|
||||
}
|
||||
|
||||
wxColour& wxColour::operator=(const wxColour& col)
|
||||
{
|
||||
m_red = col.m_red;
|
||||
m_green = col.m_green;
|
||||
m_blue = col.m_blue;
|
||||
m_alpha = col.m_alpha;
|
||||
m_cgColour = col.m_cgColour;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void wxColour::InitRGBA (ChannelType r, ChannelType g, ChannelType b, ChannelType a)
|
||||
{
|
||||
m_red = r;
|
||||
m_green = g;
|
||||
m_blue = b;
|
||||
m_alpha = a ;
|
||||
|
||||
CGColorRef col = 0 ;
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
|
||||
if ( CGColorCreateGenericRGB )
|
||||
col = CGColorCreateGenericRGB( (CGFloat)(r / 255.0), (CGFloat) (g / 255.0), (CGFloat) (b / 255.0), (CGFloat) (a / 255.0) );
|
||||
else
|
||||
#endif
|
||||
{
|
||||
CGFloat components[4] = { (CGFloat)(r / 255.0), (CGFloat) (g / 255.0), (CGFloat) (b / 255.0), (CGFloat) (a / 255.0) } ;
|
||||
col = CGColorCreate( wxMacGetGenericRGBColorSpace() , components ) ;
|
||||
}
|
||||
m_cgColour.reset( col );
|
||||
}
|
||||
|
||||
#if wxOSX_USE_CARBON
|
||||
void wxColour::InitRGBColor( const RGBColor& col )
|
||||
{
|
||||
m_red = col.red >> 8;
|
||||
m_blue = col.blue >> 8;
|
||||
m_green = col.green >> 8;
|
||||
m_alpha = wxALPHA_OPAQUE;
|
||||
CGColorRef cfcol;
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
|
||||
if ( CGColorCreateGenericRGB )
|
||||
cfcol = CGColorCreateGenericRGB((CGFloat)(col.red / 65535.0), (CGFloat)(col.green / 65535.0),
|
||||
(CGFloat)(col.blue / 65535.0), (CGFloat) 1.0 );
|
||||
else
|
||||
#endif
|
||||
{
|
||||
CGFloat components[4] = { (CGFloat)(col.red / 65535.0), (CGFloat)(col.green / 65535.0),
|
||||
(CGFloat)(col.blue / 65535.0), (CGFloat) 1.0 } ;
|
||||
cfcol = CGColorCreate( wxMacGetGenericRGBColorSpace() , components ) ;
|
||||
}
|
||||
m_cgColour.reset( cfcol );
|
||||
}
|
||||
#endif
|
||||
|
||||
void wxColour::InitCGColorRef( CGColorRef col )
|
||||
{
|
||||
m_cgColour.reset( col );
|
||||
size_t noComp = CGColorGetNumberOfComponents( col );
|
||||
if ( noComp >= 1 && noComp <= 4 )
|
||||
{
|
||||
// TODO verify whether we really are on a RGB color space
|
||||
m_alpha = wxALPHA_OPAQUE;
|
||||
const CGFloat *components = CGColorGetComponents( col );
|
||||
if ( noComp >= 3 )
|
||||
{
|
||||
m_red = (int)(components[0]*255+0.5);
|
||||
m_green = (int)(components[1]*255+0.5);
|
||||
m_blue = (int)(components[2]*255+0.5);
|
||||
if ( noComp == 4 )
|
||||
m_alpha = (int)(components[3]*255+0.5);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_red = (int)(components[0]*255+0.5);
|
||||
m_green = (int)(components[0]*255+0.5);
|
||||
m_blue = (int)(components[0]*255+0.5);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_alpha = wxALPHA_OPAQUE;
|
||||
m_red = m_green = m_blue = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool wxColour::operator == (const wxColour& colour) const
|
||||
{
|
||||
return ( (IsOk() == colour.IsOk()) && (!IsOk() ||
|
||||
CGColorEqualToColor( m_cgColour, colour.m_cgColour ) ) );
|
||||
}
|
||||
|
||||
|
@@ -1,685 +0,0 @@
|
||||
/*
|
||||
File: DirectoryCopy.c
|
||||
|
||||
Contains: A robust, general purpose directory copy routine.
|
||||
|
||||
Version: MoreFiles
|
||||
|
||||
Copyright: <09> 1992-2001 by Apple Computer, Inc., all rights reserved.
|
||||
|
||||
You may incorporate this sample code into your applications without
|
||||
restriction, though the sample code has been provided "AS IS" and the
|
||||
responsibility for its operation is 100% yours. However, what you are
|
||||
not permitted to do is to redistribute the source as "DSC Sample Code"
|
||||
after having made changes. If you're going to re-distribute the source,
|
||||
we require that you make it clear in the source that the code was
|
||||
descended from Apple Sample Code, but that you've made changes.
|
||||
|
||||
File Ownership:
|
||||
|
||||
DRI: Apple Macintosh Developer Technical Support
|
||||
|
||||
Other Contact: Apple Macintosh Developer Technical Support
|
||||
<http://developer.apple.com/bugreporter/>
|
||||
|
||||
Technology: DTS Sample Code
|
||||
|
||||
Writers:
|
||||
|
||||
(JL) Jim Luther
|
||||
|
||||
Change History (most recent first):
|
||||
|
||||
<2> 2/7/01 JL Added standard header. Updated names of includes.
|
||||
<1> 12/06/99 JL MoreFiles 1.5.
|
||||
*/
|
||||
|
||||
#include <MacTypes.h>
|
||||
#include <MacErrors.h>
|
||||
#include <MacMemory.h>
|
||||
#include <Files.h>
|
||||
#include <Script.h>
|
||||
#include <Math64.h>
|
||||
|
||||
#define __COMPILINGMOREFILES
|
||||
|
||||
#include "MoreFiles.h"
|
||||
#include "MoreFilesExtras.h"
|
||||
#include "MoreDesktopMgr.h"
|
||||
#include "FileCopy.h"
|
||||
#include "DirectoryCopy.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* local constants */
|
||||
|
||||
enum
|
||||
{
|
||||
dirCopyBigCopyBuffSize = 0x00004000,
|
||||
dirCopyMinCopyBuffSize = 0x00000200
|
||||
};
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* local data structures */
|
||||
|
||||
/* The EnumerateGlobals structure is used to minimize the amount of
|
||||
** stack space used when recursively calling CopyLevel and to hold
|
||||
** global information that might be needed at any time. */
|
||||
|
||||
#if PRAGMA_STRUCT_ALIGN
|
||||
#pragma options align=mac68k
|
||||
#endif
|
||||
struct EnumerateGlobals
|
||||
{
|
||||
Ptr copyBuffer; /* pointer to buffer used for file copy operations */
|
||||
long bufferSize; /* the size of the copy buffer */
|
||||
CopyErrProcPtr errorHandler; /* pointer to error handling function */
|
||||
CopyFilterProcPtr copyFilterProc; /* pointer to filter function */
|
||||
OSErr error; /* temporary holder of results - saves 2 bytes of stack each level */
|
||||
Boolean bailout; /* set to true to by error handling function if fatal error */
|
||||
short destinationVRefNum; /* the destination vRefNum */
|
||||
Str63 itemName; /* the name of the current item */
|
||||
CInfoPBRec myCPB; /* the parameter block used for PBGetCatInfo calls */
|
||||
};
|
||||
#if PRAGMA_STRUCT_ALIGN
|
||||
#pragma options align=reset
|
||||
#endif
|
||||
|
||||
typedef struct EnumerateGlobals EnumerateGlobals;
|
||||
typedef EnumerateGlobals *EnumerateGlobalsPtr;
|
||||
|
||||
|
||||
/* The PreflightGlobals structure is used to minimize the amount of
|
||||
** stack space used when recursively calling GetLevelSize and to hold
|
||||
** global information that might be needed at any time. */
|
||||
|
||||
#if PRAGMA_STRUCT_ALIGN
|
||||
#pragma options align=mac68k
|
||||
#endif
|
||||
struct PreflightGlobals
|
||||
{
|
||||
OSErr result; /* temporary holder of results - saves 2 bytes of stack each level */
|
||||
Str63 itemName; /* the name of the current item */
|
||||
CInfoPBRec myCPB; /* the parameter block used for PBGetCatInfo calls */
|
||||
|
||||
unsigned long dstBlksPerAllocBlk; /* the number of 512 byte blocks per allocation block on destination */
|
||||
|
||||
unsigned long allocBlksNeeded; /* the total number of allocation blocks needed */
|
||||
|
||||
unsigned long tempBlocks; /* temporary storage for calculations (save some stack space) */
|
||||
CopyFilterProcPtr copyFilterProc; /* pointer to filter function */
|
||||
};
|
||||
#if PRAGMA_STRUCT_ALIGN
|
||||
#pragma options align=reset
|
||||
#endif
|
||||
|
||||
typedef struct PreflightGlobals PreflightGlobals;
|
||||
typedef PreflightGlobals *PreflightGlobalsPtr;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* static prototypes */
|
||||
|
||||
static void GetLevelSize(long currentDirID,
|
||||
PreflightGlobals *theGlobals);
|
||||
|
||||
static OSErr PreflightDirectoryCopySpace(short srcVRefNum,
|
||||
long srcDirID,
|
||||
short dstVRefNum,
|
||||
CopyFilterProcPtr copyFilterProc,
|
||||
Boolean *spaceOK);
|
||||
|
||||
static void CopyLevel(long sourceDirID,
|
||||
long dstDirID,
|
||||
EnumerateGlobals *theGlobals);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void GetLevelSize(long currentDirID,
|
||||
PreflightGlobals *theGlobals)
|
||||
{
|
||||
short index = 1;
|
||||
|
||||
do
|
||||
{
|
||||
theGlobals->myCPB.dirInfo.ioFDirIndex = index;
|
||||
theGlobals->myCPB.dirInfo.ioDrDirID = currentDirID; /* we need to do this every time */
|
||||
/* through, since GetCatInfo */
|
||||
/* returns ioFlNum in this field */
|
||||
theGlobals->result = PBGetCatInfoSync(&theGlobals->myCPB);
|
||||
if ( theGlobals->result == noErr )
|
||||
{
|
||||
if ( (theGlobals->copyFilterProc == NULL) ||
|
||||
CallCopyFilterProc(theGlobals->copyFilterProc, &theGlobals->myCPB) ) /* filter if filter proc was supplied */
|
||||
{
|
||||
/* Either there's no filter proc OR the filter proc says to use this item */
|
||||
if ( (theGlobals->myCPB.dirInfo.ioFlAttrib & kioFlAttribDirMask) != 0 )
|
||||
{
|
||||
/* we have a directory */
|
||||
|
||||
GetLevelSize(theGlobals->myCPB.dirInfo.ioDrDirID, theGlobals); /* recurse */
|
||||
theGlobals->result = noErr; /* clear error return on way back */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We have a file - add its allocation blocks to allocBlksNeeded. */
|
||||
/* Since space on Mac OS disks is always allocated in allocation blocks, */
|
||||
/* this takes into account rounding up to the end of an allocation block. */
|
||||
|
||||
/* get number of 512-byte blocks needed for data fork */
|
||||
if ( ((unsigned long)theGlobals->myCPB.hFileInfo.ioFlLgLen & 0x000001ff) != 0 )
|
||||
{
|
||||
theGlobals->tempBlocks = ((unsigned long)theGlobals->myCPB.hFileInfo.ioFlLgLen >> 9) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
theGlobals->tempBlocks = (unsigned long)theGlobals->myCPB.hFileInfo.ioFlLgLen >> 9;
|
||||
}
|
||||
/* now, calculate number of new allocation blocks needed for the data fork and add it to the total */
|
||||
if ( theGlobals->tempBlocks % theGlobals->dstBlksPerAllocBlk )
|
||||
{
|
||||
theGlobals->allocBlksNeeded += (theGlobals->tempBlocks / theGlobals->dstBlksPerAllocBlk) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
theGlobals->allocBlksNeeded += theGlobals->tempBlocks / theGlobals->dstBlksPerAllocBlk;
|
||||
}
|
||||
|
||||
/* get number of 512-byte blocks needed for resource fork */
|
||||
if ( ((unsigned long)theGlobals->myCPB.hFileInfo.ioFlRLgLen & 0x000001ff) != 0 )
|
||||
{
|
||||
theGlobals->tempBlocks = ((unsigned long)theGlobals->myCPB.hFileInfo.ioFlRLgLen >> 9) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
theGlobals->tempBlocks = (unsigned long)theGlobals->myCPB.hFileInfo.ioFlRLgLen >> 9;
|
||||
}
|
||||
/* now, calculate number of new allocation blocks needed for the resource fork and add it to the total */
|
||||
if ( theGlobals->tempBlocks % theGlobals->dstBlksPerAllocBlk )
|
||||
{
|
||||
theGlobals->allocBlksNeeded += (theGlobals->tempBlocks / theGlobals->dstBlksPerAllocBlk) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
theGlobals->allocBlksNeeded += theGlobals->tempBlocks / theGlobals->dstBlksPerAllocBlk;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
++index;
|
||||
} while ( theGlobals->result == noErr );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static OSErr PreflightDirectoryCopySpace(short srcVRefNum,
|
||||
long srcDirID,
|
||||
short dstVRefNum,
|
||||
CopyFilterProcPtr copyFilterProc,
|
||||
Boolean *spaceOK)
|
||||
{
|
||||
XVolumeParam pb;
|
||||
OSErr error;
|
||||
unsigned long dstFreeBlocks;
|
||||
PreflightGlobals theGlobals;
|
||||
|
||||
error = XGetVolumeInfoNoName(NULL, dstVRefNum, &pb);
|
||||
if ( error == noErr )
|
||||
{
|
||||
/* Convert freeBytes to free disk blocks (512-byte blocks) */
|
||||
dstFreeBlocks = U32SetU(U64ShiftRight(pb.ioVFreeBytes, 9));
|
||||
|
||||
/* get allocation block size (always multiple of 512) and divide by 512
|
||||
to get number of 512-byte blocks per allocation block */
|
||||
theGlobals.dstBlksPerAllocBlk = ((unsigned long)pb.ioVAlBlkSiz >> 9);
|
||||
|
||||
theGlobals.allocBlksNeeded = 0;
|
||||
|
||||
theGlobals.myCPB.dirInfo.ioNamePtr = theGlobals.itemName;
|
||||
theGlobals.myCPB.dirInfo.ioVRefNum = srcVRefNum;
|
||||
|
||||
theGlobals.copyFilterProc = copyFilterProc;
|
||||
|
||||
GetLevelSize(srcDirID, &theGlobals);
|
||||
|
||||
/* Is there enough room on the destination volume for the source file? */
|
||||
/* Note: This will work because the largest number of disk blocks supported */
|
||||
/* on a 2TB volume is 0xffffffff and (allocBlksNeeded * dstBlksPerAllocBlk) */
|
||||
/* will always be less than 0xffffffff. */
|
||||
*spaceOK = ((theGlobals.allocBlksNeeded * theGlobals.dstBlksPerAllocBlk) <= dstFreeBlocks);
|
||||
}
|
||||
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void CopyLevel(long sourceDirID,
|
||||
long dstDirID,
|
||||
EnumerateGlobals *theGlobals)
|
||||
{
|
||||
long currentSrcDirID = 0 ;
|
||||
long newDirID;
|
||||
short index = 1;
|
||||
|
||||
do
|
||||
{
|
||||
/* Get next source item at the current directory level */
|
||||
|
||||
theGlobals->myCPB.dirInfo.ioFDirIndex = index;
|
||||
theGlobals->myCPB.dirInfo.ioDrDirID = sourceDirID;
|
||||
theGlobals->error = PBGetCatInfoSync(&theGlobals->myCPB);
|
||||
|
||||
if ( theGlobals->error == noErr )
|
||||
{
|
||||
if ( (theGlobals->copyFilterProc == NULL) ||
|
||||
CallCopyFilterProc(theGlobals->copyFilterProc, &theGlobals->myCPB) ) /* filter if filter proc was supplied */
|
||||
{
|
||||
/* Either there's no filter proc OR the filter proc says to use this item */
|
||||
|
||||
/* We have an item. Is it a file or directory? */
|
||||
if ( (theGlobals->myCPB.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 )
|
||||
{
|
||||
/* We have a directory */
|
||||
|
||||
/* Create a new directory at the destination. No errors allowed! */
|
||||
theGlobals->error = DirCreate(theGlobals->destinationVRefNum, dstDirID, theGlobals->itemName, &newDirID);
|
||||
if ( theGlobals->error == noErr )
|
||||
{
|
||||
/* Save the current source directory ID where we can get it when we come back
|
||||
** from recursion land. */
|
||||
currentSrcDirID = theGlobals->myCPB.dirInfo.ioDrDirID;
|
||||
|
||||
/* Dive again (copy the directory level we just found below this one) */
|
||||
CopyLevel(theGlobals->myCPB.dirInfo.ioDrDirID, newDirID, theGlobals);
|
||||
|
||||
if ( !theGlobals->bailout )
|
||||
{
|
||||
/* Copy comment from old to new directory. */
|
||||
/* Ignore the result because we really don't care if it worked or not. */
|
||||
(void) DTCopyComment(theGlobals->myCPB.dirInfo.ioVRefNum, currentSrcDirID, NULL, theGlobals->destinationVRefNum, newDirID, NULL);
|
||||
|
||||
/* Copy directory attributes (dates, etc.) to newDirID. */
|
||||
/* No errors allowed */
|
||||
theGlobals->error = CopyFileMgrAttributes(theGlobals->myCPB.dirInfo.ioVRefNum, currentSrcDirID, NULL, theGlobals->destinationVRefNum, newDirID, NULL, true);
|
||||
|
||||
/* handle any errors from CopyFileMgrAttributes */
|
||||
if ( theGlobals->error != noErr )
|
||||
{
|
||||
if ( theGlobals->errorHandler != NULL )
|
||||
{
|
||||
theGlobals->bailout = CallCopyErrProc(theGlobals->errorHandler, theGlobals->error, copyDirFMAttributesOp,
|
||||
theGlobals->myCPB.dirInfo.ioVRefNum, currentSrcDirID, NULL,
|
||||
theGlobals->destinationVRefNum, newDirID, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If you don't handle the errors with an error handler, */
|
||||
/* then the copy stops here. */
|
||||
theGlobals->bailout = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* error handling for DirCreate */
|
||||
{
|
||||
/* note that currentSrcDirID has not been initialised when entering this execution path */
|
||||
if ( theGlobals->errorHandler != NULL )
|
||||
{
|
||||
theGlobals->bailout = CallCopyErrProc(theGlobals->errorHandler, theGlobals->error, dirCreateOp,
|
||||
theGlobals->myCPB.dirInfo.ioVRefNum, currentSrcDirID, NULL,
|
||||
theGlobals->destinationVRefNum, dstDirID, theGlobals->itemName);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If you don't handle the errors with an error handler, */
|
||||
/* then the copy stops here. */
|
||||
theGlobals->bailout = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !theGlobals->bailout )
|
||||
{
|
||||
/* clear error return on way back if we aren't bailing out */
|
||||
theGlobals->error = noErr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We have a file, so copy it */
|
||||
|
||||
theGlobals->error = FileCopy(theGlobals->myCPB.hFileInfo.ioVRefNum,
|
||||
theGlobals->myCPB.hFileInfo.ioFlParID,
|
||||
theGlobals->itemName,
|
||||
theGlobals->destinationVRefNum,
|
||||
dstDirID,
|
||||
NULL,
|
||||
NULL,
|
||||
theGlobals->copyBuffer,
|
||||
theGlobals->bufferSize,
|
||||
false);
|
||||
|
||||
/* handle any errors from FileCopy */
|
||||
if ( theGlobals->error != noErr )
|
||||
{
|
||||
if ( theGlobals->errorHandler != NULL )
|
||||
{
|
||||
theGlobals->bailout = CallCopyErrProc(theGlobals->errorHandler, theGlobals->error, fileCopyOp,
|
||||
theGlobals->myCPB.hFileInfo.ioVRefNum, theGlobals->myCPB.hFileInfo.ioFlParID, theGlobals->itemName,
|
||||
theGlobals->destinationVRefNum, dstDirID, NULL);
|
||||
if ( !theGlobals->bailout )
|
||||
{
|
||||
/* If the CopyErrProc handled the problem, clear the error here */
|
||||
theGlobals->error = noErr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If you don't handle the errors with an error handler, */
|
||||
/* then the copy stops here. */
|
||||
theGlobals->bailout = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* error handling for PBGetCatInfo */
|
||||
/* it's normal to get a fnfErr when indexing; that only means you've hit the end of the directory */
|
||||
if ( theGlobals->error != fnfErr )
|
||||
{
|
||||
if ( theGlobals->errorHandler != NULL )
|
||||
{
|
||||
theGlobals->bailout = CallCopyErrProc(theGlobals->errorHandler, theGlobals->error, getNextItemOp,
|
||||
theGlobals->myCPB.dirInfo.ioVRefNum, sourceDirID, NULL, 0, 0, NULL);
|
||||
if ( !theGlobals->bailout )
|
||||
{
|
||||
/* If the CopyErrProc handled the problem, clear the error here */
|
||||
theGlobals->error = noErr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If you don't handle the errors with an error handler, */
|
||||
/* then the copy stops here. */
|
||||
theGlobals->bailout = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
++index; /* prepare to get next item */
|
||||
} while ( (theGlobals->error == noErr) && (!theGlobals->bailout) ); /* time to fall back a level? */
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FilteredDirectoryCopy(short srcVRefNum,
|
||||
long srcDirID,
|
||||
ConstStr255Param srcName,
|
||||
short dstVRefNum,
|
||||
long dstDirID,
|
||||
ConstStr255Param dstName,
|
||||
ConstStr255Param copyName,
|
||||
void *copyBufferPtr,
|
||||
long copyBufferSize,
|
||||
Boolean preflight,
|
||||
CopyErrProcPtr copyErrHandler,
|
||||
CopyFilterProcPtr copyFilterProc)
|
||||
{
|
||||
EnumerateGlobals theGlobals;
|
||||
Boolean isDirectory;
|
||||
OSErr error;
|
||||
Boolean ourCopyBuffer = false;
|
||||
Str63 srcDirName, oldDiskName;
|
||||
Boolean spaceOK;
|
||||
|
||||
/* Make sure a copy buffer is allocated. */
|
||||
if ( copyBufferPtr == NULL )
|
||||
{
|
||||
/* The caller didn't supply a copy buffer so grab one from the application heap.
|
||||
** Try to get a big copy buffer, if we can't, try for a 512-byte buffer.
|
||||
** If 512 bytes aren't available, we're in trouble. */
|
||||
copyBufferSize = dirCopyBigCopyBuffSize;
|
||||
copyBufferPtr = NewPtr(copyBufferSize);
|
||||
if ( copyBufferPtr == NULL )
|
||||
{
|
||||
copyBufferSize = dirCopyMinCopyBuffSize;
|
||||
copyBufferPtr = NewPtr(copyBufferSize);
|
||||
if ( copyBufferPtr == NULL )
|
||||
{
|
||||
return ( memFullErr );
|
||||
}
|
||||
}
|
||||
ourCopyBuffer = true;
|
||||
}
|
||||
|
||||
/* Get the real dirID where we're copying from and make sure it is a directory. */
|
||||
error = GetDirectoryID(srcVRefNum, srcDirID, srcName, &srcDirID, &isDirectory);
|
||||
if ( error != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
if ( !isDirectory )
|
||||
{
|
||||
error = dirNFErr;
|
||||
goto ErrorExit;
|
||||
}
|
||||
|
||||
/* Special case destination if it is the root parent directory. */
|
||||
/* Since you can't create the root directory, this is needed if */
|
||||
/* you want to copy a directory's content to a disk's root directory. */
|
||||
if ( (dstDirID == fsRtParID) && (dstName == NULL) )
|
||||
{
|
||||
dstDirID = fsRtParID;
|
||||
isDirectory = true;
|
||||
error = noErr;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get the real dirID where we're going to put the copy and make sure it is a directory. */
|
||||
error = GetDirectoryID(dstVRefNum, dstDirID, dstName, &dstDirID, &isDirectory);
|
||||
if ( error != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
if ( !isDirectory )
|
||||
{
|
||||
error = dirNFErr;
|
||||
goto ErrorExit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the real vRefNum of both the source and destination */
|
||||
error = DetermineVRefNum(srcName, srcVRefNum, &srcVRefNum);
|
||||
if ( error != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
error = DetermineVRefNum(dstName, dstVRefNum, &dstVRefNum);
|
||||
if ( error != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
|
||||
if ( preflight )
|
||||
{
|
||||
error = PreflightDirectoryCopySpace(srcVRefNum, srcDirID, dstVRefNum, copyFilterProc, &spaceOK);
|
||||
if ( error != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
if ( !spaceOK )
|
||||
{
|
||||
error = dskFulErr; /* not enough room on destination */
|
||||
goto ErrorExit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create the new directory in the destination directory with the */
|
||||
/* same name as the source directory. */
|
||||
error = GetDirName(srcVRefNum, srcDirID, srcDirName);
|
||||
if ( error != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
|
||||
/* Again, special case destination if the destination is the */
|
||||
/* root parent directory. This time, we'll rename the disk to */
|
||||
/* the source directory name. */
|
||||
if ( dstDirID == fsRtParID )
|
||||
{
|
||||
/* Get the current name of the destination disk */
|
||||
error = GetDirName(dstVRefNum, fsRtDirID, oldDiskName);
|
||||
if ( error == noErr )
|
||||
{
|
||||
/* use the copyName as srcDirName if supplied */
|
||||
if ( copyName != NULL )
|
||||
{
|
||||
/* make a copy since copyName is a const input */
|
||||
BlockMoveData(copyName, srcDirName, sizeof(Str31));
|
||||
}
|
||||
/* Shorten the name if it's too long to be the volume name */
|
||||
TruncPString(srcDirName, srcDirName, 27);
|
||||
|
||||
/* Rename the disk */
|
||||
error = HRename(dstVRefNum, fsRtParID, oldDiskName, srcDirName);
|
||||
|
||||
/* and copy to the root directory */
|
||||
dstDirID = fsRtDirID;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* use the copyName as srcDirName if supplied */
|
||||
error = DirCreate(dstVRefNum, dstDirID, ((copyName != NULL) ? copyName : srcDirName), &dstDirID);
|
||||
}
|
||||
if ( error != noErr )
|
||||
{
|
||||
/* handle any errors from DirCreate */
|
||||
if ( copyErrHandler != NULL )
|
||||
{
|
||||
if ( CallCopyErrProc(copyErrHandler, error, dirCreateOp,
|
||||
srcVRefNum, srcDirID, NULL,
|
||||
dstVRefNum, dstDirID, srcDirName) )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the CopyErrProc handled the problem, clear the error here */
|
||||
/* and continue */
|
||||
error = noErr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If you don't handle the errors with an error handler, */
|
||||
/* then the copy stops here. */
|
||||
goto ErrorExit;
|
||||
}
|
||||
}
|
||||
|
||||
/* dstDirID is now the newly created directory! */
|
||||
|
||||
/* Set up the globals we need to access from the recursive routine. */
|
||||
theGlobals.copyBuffer = (Ptr)copyBufferPtr;
|
||||
theGlobals.bufferSize = copyBufferSize;
|
||||
theGlobals.destinationVRefNum = dstVRefNum; /* so we can get to it always */
|
||||
theGlobals.myCPB.hFileInfo.ioNamePtr = (StringPtr)&theGlobals.itemName;
|
||||
theGlobals.myCPB.hFileInfo.ioVRefNum = srcVRefNum;
|
||||
theGlobals.errorHandler = copyErrHandler;
|
||||
theGlobals.bailout = false;
|
||||
theGlobals.copyFilterProc = copyFilterProc;
|
||||
|
||||
/* Here we go into recursion land... */
|
||||
CopyLevel(srcDirID, dstDirID, &theGlobals);
|
||||
error = theGlobals.error; /* get the result */
|
||||
|
||||
if ( !theGlobals.bailout )
|
||||
{
|
||||
/* Copy comment from source to destination directory. */
|
||||
/* Ignore the result because we really don't care if it worked or not. */
|
||||
(void) DTCopyComment(srcVRefNum, srcDirID, NULL, dstVRefNum, dstDirID, NULL);
|
||||
|
||||
/* Copy the File Manager attributes */
|
||||
error = CopyFileMgrAttributes(srcVRefNum, srcDirID, NULL,
|
||||
dstVRefNum, dstDirID, NULL, true);
|
||||
|
||||
/* handle any errors from CopyFileMgrAttributes */
|
||||
if ( (error != noErr) && (copyErrHandler != NULL) )
|
||||
{
|
||||
theGlobals.bailout = CallCopyErrProc(copyErrHandler, error, copyDirFMAttributesOp,
|
||||
srcVRefNum, srcDirID, NULL,
|
||||
dstVRefNum, dstDirID, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
ErrorExit:
|
||||
/* Get rid of the copy buffer if we allocated it. */
|
||||
if ( ourCopyBuffer )
|
||||
{
|
||||
DisposePtr((Ptr)copyBufferPtr);
|
||||
}
|
||||
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr DirectoryCopy(short srcVRefNum,
|
||||
long srcDirID,
|
||||
ConstStr255Param srcName,
|
||||
short dstVRefNum,
|
||||
long dstDirID,
|
||||
ConstStr255Param dstName,
|
||||
ConstStr255Param copyName,
|
||||
void *copyBufferPtr,
|
||||
long copyBufferSize,
|
||||
Boolean preflight,
|
||||
CopyErrProcPtr copyErrHandler)
|
||||
{
|
||||
return ( FilteredDirectoryCopy(srcVRefNum, srcDirID, srcName,
|
||||
dstVRefNum, dstDirID, dstName,
|
||||
copyName,
|
||||
copyBufferPtr, copyBufferSize, preflight,
|
||||
copyErrHandler, NULL) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpFilteredDirectoryCopy(const FSSpec *srcSpec,
|
||||
const FSSpec *dstSpec,
|
||||
ConstStr255Param copyName,
|
||||
void *copyBufferPtr,
|
||||
long copyBufferSize,
|
||||
Boolean preflight,
|
||||
CopyErrProcPtr copyErrHandler,
|
||||
CopyFilterProcPtr copyFilterProc)
|
||||
{
|
||||
return ( FilteredDirectoryCopy(srcSpec->vRefNum, srcSpec->parID, srcSpec->name,
|
||||
dstSpec->vRefNum, dstSpec->parID, dstSpec->name,
|
||||
copyName,
|
||||
copyBufferPtr, copyBufferSize, preflight,
|
||||
copyErrHandler, copyFilterProc) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpDirectoryCopy(const FSSpec *srcSpec,
|
||||
const FSSpec *dstSpec,
|
||||
ConstStr255Param copyName,
|
||||
void *copyBufferPtr,
|
||||
long copyBufferSize,
|
||||
Boolean preflight,
|
||||
CopyErrProcPtr copyErrHandler)
|
||||
{
|
||||
return ( FilteredDirectoryCopy(srcSpec->vRefNum, srcSpec->parID, srcSpec->name,
|
||||
dstSpec->vRefNum, dstSpec->parID, dstSpec->name,
|
||||
copyName,
|
||||
copyBufferPtr, copyBufferSize, preflight,
|
||||
copyErrHandler, NULL) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@@ -1,559 +0,0 @@
|
||||
/*
|
||||
File: DirectoryCopy.h
|
||||
|
||||
Contains: A robust, general purpose directory copy routine.
|
||||
|
||||
Version: Technology: MoreFiles
|
||||
Release: 1.5.2
|
||||
|
||||
Copyright: <20> 1992-2001 by Apple Computer, Inc., all rights reserved.
|
||||
|
||||
Bugs?: For bug reports, consult the following page on
|
||||
the World Wide Web:
|
||||
|
||||
http://developer.apple.com/bugreporter/
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
You may incorporate this sample code into your applications without
|
||||
restriction, though the sample code has been provided "AS IS" and the
|
||||
responsibility for its operation is 100% yours. However, what you are
|
||||
not permitted to do is to redistribute the source as "DSC Sample Code"
|
||||
after having made changes. If you're going to re-distribute the source,
|
||||
we require that you make it clear in the source that the code was
|
||||
descended from Apple Sample Code, but that you've made changes.
|
||||
*/
|
||||
|
||||
#ifndef __DIRECTORYCOPY__
|
||||
#define __DIRECTORYCOPY__
|
||||
|
||||
#ifndef __MACTYPES__
|
||||
#include <MacTypes.h>
|
||||
#endif
|
||||
|
||||
#ifndef __FILES__
|
||||
#include <Files.h>
|
||||
#endif
|
||||
|
||||
#include "Optimization.h"
|
||||
|
||||
|
||||
#if PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if PRAGMA_IMPORT
|
||||
#pragma import on
|
||||
#endif
|
||||
|
||||
#if PRAGMA_STRUCT_ALIGN
|
||||
#pragma options align=mac68k
|
||||
#elif PRAGMA_STRUCT_PACKPUSH
|
||||
#pragma pack(push, 2)
|
||||
#elif PRAGMA_STRUCT_PACK
|
||||
#pragma pack(2)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
enum {
|
||||
getNextItemOp = 1, /* couldn't access items in this directory - no access privileges */
|
||||
copyDirCommentOp = 2, /* couldn't copy directory's Finder comment */
|
||||
copyDirAccessPrivsOp = 3, /* couldn't copy directory's AFP access privileges */
|
||||
copyDirFMAttributesOp = 4, /* couldn't copy directory's File Manager attributes */
|
||||
dirCreateOp = 5, /* couldn't create destination directory */
|
||||
fileCopyOp = 6 /* couldn't copy file */
|
||||
};
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef CALLBACK_API( Boolean , CopyErrProcPtr )(OSErr error, short failedOperation, short srcVRefNum, long srcDirID, ConstStr255Param srcName, short dstVRefNum, long dstDirID, ConstStr255Param dstName);
|
||||
/*
|
||||
This is the prototype for the CopyErrProc function DirectoryCopy
|
||||
calls if an error condition is detected sometime during the copy. If
|
||||
CopyErrProc returns false, then DirectoryCopy attempts to continue with
|
||||
the directory copy operation. If CopyErrProc returns true, then
|
||||
DirectoryCopy stops the directory copy operation.
|
||||
|
||||
error input: The error result code that caused CopyErrProc to
|
||||
be called.
|
||||
failedOperation input: The operation that returned an error to
|
||||
DirectoryCopy.
|
||||
srcVRefNum input: Source volume specification.
|
||||
srcDirID input: Source directory ID.
|
||||
srcName input: Source file or directory name, or nil if
|
||||
srcDirID specifies the directory.
|
||||
dstVRefNum input: Destination volume specification.
|
||||
dstDirID input: Destination directory ID.
|
||||
dstName input: Destination file or directory name, or nil if
|
||||
dstDirID specifies the directory.
|
||||
|
||||
__________
|
||||
|
||||
Also see: FilteredDirectoryCopy, FSpFilteredDirectoryCopy, DirectoryCopy, FSpDirectoryCopy
|
||||
*/
|
||||
#define CallCopyErrProc(userRoutine, error, failedOperation, srcVRefNum, srcDirID, srcName, dstVRefNum, dstDirID, dstName) \
|
||||
(*(userRoutine))((error), (failedOperation), (srcVRefNum), (srcDirID), (srcName), (dstVRefNum), (dstDirID), (dstName))
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef CALLBACK_API( Boolean , CopyFilterProcPtr )(const CInfoPBRec * cpbPtr);
|
||||
/*
|
||||
This is the prototype for the CopyFilterProc function called by
|
||||
FilteredDirectoryCopy and GetLevelSize. If true is returned,
|
||||
the file/folder is included in the copy, otherwise it is excluded.
|
||||
|
||||
pb input: Points to the CInfoPBRec for the item under consideration.
|
||||
|
||||
__________
|
||||
|
||||
Also see: FilteredDirectoryCopy, FSpFilteredDirectoryCopy
|
||||
*/
|
||||
#define CallCopyFilterProc(userRoutine, cpbPtr) \
|
||||
(*(userRoutine))((cpbPtr))
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
FilteredDirectoryCopy(
|
||||
short srcVRefNum,
|
||||
long srcDirID,
|
||||
ConstStr255Param srcName,
|
||||
short dstVRefNum,
|
||||
long dstDirID,
|
||||
ConstStr255Param dstName,
|
||||
ConstStr255Param copyName,
|
||||
void * copyBufferPtr,
|
||||
long copyBufferSize,
|
||||
Boolean preflight,
|
||||
CopyErrProcPtr copyErrHandler,
|
||||
CopyFilterProcPtr copyFilterProc);
|
||||
|
||||
|
||||
/*
|
||||
The FilteredDirectoryCopy function makes a copy of a directory
|
||||
structure in a new location. If copyBufferPtr <> NIL, it points to
|
||||
a buffer of copyBufferSize that is used to copy files data. The
|
||||
larger the supplied buffer, the faster the copy. If
|
||||
copyBufferPtr = NIL, then this routine allocates a buffer in the
|
||||
application heap. If you pass a copy buffer to this routine, make
|
||||
its size a multiple of 512 ($200) bytes for optimum performance.
|
||||
|
||||
The optional copyFilterProc parameter lets a routine you define
|
||||
decide what files or directories are copied to the destination.
|
||||
|
||||
FilteredDirectoryCopy normally creates a new directory *in* the
|
||||
specified destination directory and copies the source directory's
|
||||
content into the new directory. However, if root parent directory
|
||||
(fsRtParID) is passed as the dstDirID parameter and NULL is
|
||||
passed as the dstName parameter, DirectoryCopy renames the
|
||||
destination volume to the source directory's name (truncating
|
||||
if the name is longer than 27 characters) and copies the source
|
||||
directory's content into the destination volume's root directory.
|
||||
This special case is supported by FilteredDirectoryCopy, but
|
||||
not by FSpFilteredDirectoryCopy since with FSpFilteredDirectoryCopy,
|
||||
the dstName parameter can not be NULL.
|
||||
|
||||
srcVRefNum input: Source volume specification.
|
||||
srcDirID input: Source directory ID.
|
||||
srcName input: Source directory name, or nil if
|
||||
srcDirID specifies the directory.
|
||||
dstVRefNum input: Destination volume specification.
|
||||
dstDirID input: Destination directory ID.
|
||||
dstName input: Destination directory name, or nil if
|
||||
dstDirID specifies the directory.
|
||||
copyName input: Points to the new directory name if the directory
|
||||
is to be renamed or nil if the directory isn't to
|
||||
be renamed.
|
||||
copyBufferPtr input: Points to a buffer of copyBufferSize that
|
||||
is used the i/o buffer for the copy or
|
||||
nil if you want DirectoryCopy to allocate its
|
||||
own buffer in the application heap.
|
||||
copyBufferSize input: The size of the buffer pointed to
|
||||
by copyBufferPtr.
|
||||
preflight input: If true, DirectoryCopy makes sure there are
|
||||
enough allocation blocks on the destination
|
||||
volume to hold the directory's files before
|
||||
starting the copy.
|
||||
copyErrHandler input: A pointer to the routine you want called if an
|
||||
error condition is detected during the copy, or
|
||||
nil if you don't want to handle error conditions.
|
||||
If you don't handle error conditions, the first
|
||||
error will cause the copy to quit and
|
||||
DirectoryCopy will return the error.
|
||||
Error handling is recommended...
|
||||
copyFilterProc input: A pointer to the filter routine you want called
|
||||
for each item in the source directory, or NULL
|
||||
if you don't want to filter.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
readErr <20>19 Driver does not respond to read requests
|
||||
writErr <20>20 Driver does not respond to write requests
|
||||
badUnitErr <20>21 Driver reference number does not
|
||||
match unit table
|
||||
unitEmptyErr <20>22 Driver reference number specifies a
|
||||
nil handle in unit table
|
||||
abortErr <20>27 Request aborted by KillIO
|
||||
notOpenErr <20>28 Driver not open
|
||||
dskFulErr -34 Destination volume is full
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
tmfoErr -42 Too many files open
|
||||
fnfErr -43 Source file not found, or destination
|
||||
directory does not exist
|
||||
wPrErr -44 Volume locked by hardware
|
||||
fLckdErr -45 File is locked
|
||||
vLckdErr -46 Destination volume is read-only
|
||||
fBsyErr -47 The source or destination file could
|
||||
not be opened with the correct access
|
||||
modes
|
||||
dupFNErr -48 Destination file already exists
|
||||
opWrErr -49 File already open for writing
|
||||
paramErr -50 No default volume or function not
|
||||
supported by volume
|
||||
permErr -54 File is already open and cannot be opened using specified deny modes
|
||||
memFullErr -108 Copy buffer could not be allocated
|
||||
dirNFErr -120 Directory not found or incomplete pathname
|
||||
wrgVolTypErr -123 Function not supported by volume
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
afpDenyConflict -5006 The source or destination file could
|
||||
not be opened with the correct access
|
||||
modes
|
||||
afpObjectTypeErr -5025 Source is a directory, directory not found
|
||||
or incomplete pathname
|
||||
|
||||
__________
|
||||
|
||||
Also see: CopyErrProcPtr, CopyFilterProcPtr, FSpFilteredDirectoryCopy,
|
||||
DirectoryCopy, FSpDirectoryCopy, FileCopy, FSpFileCopy
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
FSpFilteredDirectoryCopy(
|
||||
const FSSpec * srcSpec,
|
||||
const FSSpec * dstSpec,
|
||||
ConstStr255Param copyName,
|
||||
void * copyBufferPtr,
|
||||
long copyBufferSize,
|
||||
Boolean preflight,
|
||||
CopyErrProcPtr copyErrHandler,
|
||||
CopyFilterProcPtr copyFilterProc);
|
||||
|
||||
|
||||
/*
|
||||
The FSpFilteredDirectoryCopy function makes a copy of a directory
|
||||
structure in a new location. If copyBufferPtr <> NIL, it points to
|
||||
a buffer of copyBufferSize that is used to copy files data. The
|
||||
larger the supplied buffer, the faster the copy. If
|
||||
copyBufferPtr = NIL, then this routine allocates a buffer in the
|
||||
application heap. If you pass a copy buffer to this routine, make
|
||||
its size a multiple of 512 ($200) bytes for optimum performance.
|
||||
|
||||
The optional copyFilterProc parameter lets a routine you define
|
||||
decide what files or directories are copied to the destination.
|
||||
|
||||
srcSpec input: An FSSpec record specifying the directory to copy.
|
||||
dstSpec input: An FSSpec record specifying destination directory
|
||||
of the copy.
|
||||
copyName input: Points to the new directory name if the directory
|
||||
is to be renamed or nil if the directory isn't to
|
||||
be renamed.
|
||||
copyBufferPtr input: Points to a buffer of copyBufferSize that
|
||||
is used the i/o buffer for the copy or
|
||||
nil if you want DirectoryCopy to allocate its
|
||||
own buffer in the application heap.
|
||||
copyBufferSize input: The size of the buffer pointed to
|
||||
by copyBufferPtr.
|
||||
preflight input: If true, FSpDirectoryCopy makes sure there are
|
||||
enough allocation blocks on the destination
|
||||
volume to hold the directory's files before
|
||||
starting the copy.
|
||||
copyErrHandler input: A pointer to the routine you want called if an
|
||||
error condition is detected during the copy, or
|
||||
nil if you don't want to handle error conditions.
|
||||
If you don't handle error conditions, the first
|
||||
error will cause the copy to quit and
|
||||
DirectoryCopy will return the error.
|
||||
Error handling is recommended...
|
||||
copyFilterProc input: A pointer to the filter routine you want called
|
||||
for each item in the source directory, or NULL
|
||||
if you don't want to filter.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
readErr <20>19 Driver does not respond to read requests
|
||||
writErr <20>20 Driver does not respond to write requests
|
||||
badUnitErr <20>21 Driver reference number does not
|
||||
match unit table
|
||||
unitEmptyErr <20>22 Driver reference number specifies a
|
||||
nil handle in unit table
|
||||
abortErr <20>27 Request aborted by KillIO
|
||||
notOpenErr <20>28 Driver not open
|
||||
dskFulErr -34 Destination volume is full
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
tmfoErr -42 Too many files open
|
||||
fnfErr -43 Source file not found, or destination
|
||||
directory does not exist
|
||||
wPrErr -44 Volume locked by hardware
|
||||
fLckdErr -45 File is locked
|
||||
vLckdErr -46 Destination volume is read-only
|
||||
fBsyErr -47 The source or destination file could
|
||||
not be opened with the correct access
|
||||
modes
|
||||
dupFNErr -48 Destination file already exists
|
||||
opWrErr -49 File already open for writing
|
||||
paramErr -50 No default volume or function not
|
||||
supported by volume
|
||||
permErr -54 File is already open and cannot be opened using specified deny modes
|
||||
memFullErr -108 Copy buffer could not be allocated
|
||||
dirNFErr -120 Directory not found or incomplete pathname
|
||||
wrgVolTypErr -123 Function not supported by volume
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
afpDenyConflict -5006 The source or destination file could
|
||||
not be opened with the correct access
|
||||
modes
|
||||
afpObjectTypeErr -5025 Source is a directory, directory not found
|
||||
or incomplete pathname
|
||||
|
||||
__________
|
||||
|
||||
Also see: CopyErrProcPtr, CopyFilterProcPtr, FilteredDirectoryCopy,
|
||||
DirectoryCopy, FSpDirectoryCopy, FileCopy, FSpFileCopy
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
DirectoryCopy(
|
||||
short srcVRefNum,
|
||||
long srcDirID,
|
||||
ConstStr255Param srcName,
|
||||
short dstVRefNum,
|
||||
long dstDirID,
|
||||
ConstStr255Param dstName,
|
||||
ConstStr255Param copyName,
|
||||
void * copyBufferPtr,
|
||||
long copyBufferSize,
|
||||
Boolean preflight,
|
||||
CopyErrProcPtr copyErrHandler);
|
||||
|
||||
|
||||
/*
|
||||
The DirectoryCopy function makes a copy of a directory structure in a
|
||||
new location. If copyBufferPtr <> NIL, it points to a buffer of
|
||||
copyBufferSize that is used to copy files data. The larger the
|
||||
supplied buffer, the faster the copy. If copyBufferPtr = NIL, then this
|
||||
routine allocates a buffer in the application heap. If you pass a
|
||||
copy buffer to this routine, make its size a multiple of 512
|
||||
($200) bytes for optimum performance.
|
||||
|
||||
DirectoryCopy normally creates a new directory *in* the specified
|
||||
destination directory and copies the source directory's content into
|
||||
the new directory. However, if root parent directory (fsRtParID)
|
||||
is passed as the dstDirID parameter and NULL is passed as the
|
||||
dstName parameter, DirectoryCopy renames the destination volume to
|
||||
the source directory's name (truncating if the name is longer than
|
||||
27 characters) and copies the source directory's content into the
|
||||
destination volume's root directory. This special case is supported
|
||||
by DirectoryCopy, but not by FSpDirectoryCopy since with
|
||||
FSpDirectoryCopy, the dstName parameter can not be NULL.
|
||||
|
||||
srcVRefNum input: Source volume specification.
|
||||
srcDirID input: Source directory ID.
|
||||
srcName input: Source directory name, or nil if
|
||||
srcDirID specifies the directory.
|
||||
dstVRefNum input: Destination volume specification.
|
||||
dstDirID input: Destination directory ID.
|
||||
dstName input: Destination directory name, or nil if
|
||||
dstDirID specifies the directory.
|
||||
copyName input: Points to the new directory name if the directory
|
||||
is to be renamed or nil if the directory isn't to
|
||||
be renamed.
|
||||
copyBufferPtr input: Points to a buffer of copyBufferSize that
|
||||
is used the i/o buffer for the copy or
|
||||
nil if you want DirectoryCopy to allocate its
|
||||
own buffer in the application heap.
|
||||
copyBufferSize input: The size of the buffer pointed to
|
||||
by copyBufferPtr.
|
||||
preflight input: If true, DirectoryCopy makes sure there are
|
||||
enough allocation blocks on the destination
|
||||
volume to hold the directory's files before
|
||||
starting the copy.
|
||||
copyErrHandler input: A pointer to the routine you want called if an
|
||||
error condition is detected during the copy, or
|
||||
nil if you don't want to handle error conditions.
|
||||
If you don't handle error conditions, the first
|
||||
error will cause the copy to quit and
|
||||
DirectoryCopy will return the error.
|
||||
Error handling is recommended...
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
readErr <20>19 Driver does not respond to read requests
|
||||
writErr <20>20 Driver does not respond to write requests
|
||||
badUnitErr <20>21 Driver reference number does not
|
||||
match unit table
|
||||
unitEmptyErr <20>22 Driver reference number specifies a
|
||||
nil handle in unit table
|
||||
abortErr <20>27 Request aborted by KillIO
|
||||
notOpenErr <20>28 Driver not open
|
||||
dskFulErr -34 Destination volume is full
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
tmfoErr -42 Too many files open
|
||||
fnfErr -43 Source file not found, or destination
|
||||
directory does not exist
|
||||
wPrErr -44 Volume locked by hardware
|
||||
fLckdErr -45 File is locked
|
||||
vLckdErr -46 Destination volume is read-only
|
||||
fBsyErr -47 The source or destination file could
|
||||
not be opened with the correct access
|
||||
modes
|
||||
dupFNErr -48 Destination file already exists
|
||||
opWrErr -49 File already open for writing
|
||||
paramErr -50 No default volume or function not
|
||||
supported by volume
|
||||
permErr -54 File is already open and cannot be opened using specified deny modes
|
||||
memFullErr -108 Copy buffer could not be allocated
|
||||
dirNFErr -120 Directory not found or incomplete pathname
|
||||
wrgVolTypErr -123 Function not supported by volume
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
afpDenyConflict -5006 The source or destination file could
|
||||
not be opened with the correct access
|
||||
modes
|
||||
afpObjectTypeErr -5025 Source is a directory, directory not found
|
||||
or incomplete pathname
|
||||
|
||||
__________
|
||||
|
||||
Also see: CopyErrProcPtr, FSpDirectoryCopy, FilteredDirectoryCopy,
|
||||
FSpFilteredDirectoryCopy, FileCopy, FSpFileCopy
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
FSpDirectoryCopy(
|
||||
const FSSpec * srcSpec,
|
||||
const FSSpec * dstSpec,
|
||||
ConstStr255Param copyName,
|
||||
void * copyBufferPtr,
|
||||
long copyBufferSize,
|
||||
Boolean preflight,
|
||||
CopyErrProcPtr copyErrHandler);
|
||||
|
||||
|
||||
/*
|
||||
The FSpDirectoryCopy function makes a copy of a directory structure in a
|
||||
new location. If copyBufferPtr <> NIL, it points to a buffer of
|
||||
copyBufferSize that is used to copy files data. The larger the
|
||||
supplied buffer, the faster the copy. If copyBufferPtr = NIL, then this
|
||||
routine allocates a buffer in the application heap. If you pass a
|
||||
copy buffer to this routine, make its size a multiple of 512
|
||||
($200) bytes for optimum performance.
|
||||
|
||||
srcSpec input: An FSSpec record specifying the directory to copy.
|
||||
dstSpec input: An FSSpec record specifying destination directory
|
||||
of the copy.
|
||||
copyName input: Points to the new directory name if the directory
|
||||
is to be renamed or nil if the directory isn't to
|
||||
be renamed.
|
||||
copyBufferPtr input: Points to a buffer of copyBufferSize that
|
||||
is used the i/o buffer for the copy or
|
||||
nil if you want DirectoryCopy to allocate its
|
||||
own buffer in the application heap.
|
||||
copyBufferSize input: The size of the buffer pointed to
|
||||
by copyBufferPtr.
|
||||
preflight input: If true, FSpDirectoryCopy makes sure there are
|
||||
enough allocation blocks on the destination
|
||||
volume to hold the directory's files before
|
||||
starting the copy.
|
||||
copyErrHandler input: A pointer to the routine you want called if an
|
||||
error condition is detected during the copy, or
|
||||
nil if you don't want to handle error conditions.
|
||||
If you don't handle error conditions, the first
|
||||
error will cause the copy to quit and
|
||||
DirectoryCopy will return the error.
|
||||
Error handling is recommended...
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
readErr <20>19 Driver does not respond to read requests
|
||||
writErr <20>20 Driver does not respond to write requests
|
||||
badUnitErr <20>21 Driver reference number does not
|
||||
match unit table
|
||||
unitEmptyErr <20>22 Driver reference number specifies a
|
||||
nil handle in unit table
|
||||
abortErr <20>27 Request aborted by KillIO
|
||||
notOpenErr <20>28 Driver not open
|
||||
dskFulErr -34 Destination volume is full
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
tmfoErr -42 Too many files open
|
||||
fnfErr -43 Source file not found, or destination
|
||||
directory does not exist
|
||||
wPrErr -44 Volume locked by hardware
|
||||
fLckdErr -45 File is locked
|
||||
vLckdErr -46 Destination volume is read-only
|
||||
fBsyErr -47 The source or destination file could
|
||||
not be opened with the correct access
|
||||
modes
|
||||
dupFNErr -48 Destination file already exists
|
||||
opWrErr -49 File already open for writing
|
||||
paramErr -50 No default volume or function not
|
||||
supported by volume
|
||||
permErr -54 File is already open and cannot be opened using specified deny modes
|
||||
memFullErr -108 Copy buffer could not be allocated
|
||||
dirNFErr -120 Directory not found or incomplete pathname
|
||||
wrgVolTypErr -123 Function not supported by volume
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
afpDenyConflict -5006 The source or destination file could
|
||||
not be opened with the correct access
|
||||
modes
|
||||
afpObjectTypeErr -5025 Source is a directory, directory not found
|
||||
or incomplete pathname
|
||||
|
||||
__________
|
||||
|
||||
Also see: CopyErrProcPtr, DirectoryCopy, FilteredDirectoryCopy,
|
||||
FSpFilteredDirectoryCopy, FileCopy, FSpFileCopy
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "OptimizationEnd.h"
|
||||
|
||||
#if PRAGMA_STRUCT_ALIGN
|
||||
#pragma options align=reset
|
||||
#elif PRAGMA_STRUCT_PACKPUSH
|
||||
#pragma pack(pop)
|
||||
#elif PRAGMA_STRUCT_PACK
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef PRAGMA_IMPORT_OFF
|
||||
#pragma import off
|
||||
#elif PRAGMA_IMPORT
|
||||
#pragma import reset
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __DIRECTORYCOPY__ */
|
||||
|
@@ -1,946 +0,0 @@
|
||||
/*
|
||||
File: FSpCompat.c
|
||||
|
||||
Contains: FSSpec compatibility functions.
|
||||
|
||||
Version: MoreFiles
|
||||
|
||||
Copyright: <09> 1992-2001 by Apple Computer, Inc., all rights reserved.
|
||||
|
||||
You may incorporate this sample code into your applications without
|
||||
restriction, though the sample code has been provided "AS IS" and the
|
||||
responsibility for its operation is 100% yours. However, what you are
|
||||
not permitted to do is to redistribute the source as "DSC Sample Code"
|
||||
after having made changes. If you're going to re-distribute the source,
|
||||
we require that you make it clear in the source that the code was
|
||||
descended from Apple Sample Code, but that you've made changes.
|
||||
|
||||
File Ownership:
|
||||
|
||||
DRI: Apple Macintosh Developer Technical Support
|
||||
|
||||
Other Contact: Apple Macintosh Developer Technical Support
|
||||
<http://developer.apple.com/bugreporter/>
|
||||
|
||||
Technology: DTS Sample Code
|
||||
|
||||
Writers:
|
||||
|
||||
(JL) Jim Luther
|
||||
|
||||
Change History (most recent first):
|
||||
|
||||
<2> 2/7/01 JL Added standard header. Updated names of includes. Updated
|
||||
various routines to use new calling convention of the
|
||||
MoreFilesExtras accessor functions.
|
||||
<1> 12/06/99 JL MoreFiles 1.5.
|
||||
*/
|
||||
|
||||
/*
|
||||
** If building application 68K code, set GENERATENODATA to 0 for faster code.
|
||||
** If building stand-alone 68K code, set GENERATENODATA to 1 so globals
|
||||
** (static variables) are not used.
|
||||
*/
|
||||
#ifndef GENERATENODATA
|
||||
#define GENERATENODATA 0
|
||||
#endif
|
||||
|
||||
#include <MacTypes.h>
|
||||
#include <MacErrors.h>
|
||||
#include <Files.h>
|
||||
#include <LowMem.h>
|
||||
#include <Gestalt.h>
|
||||
#include <Resources.h>
|
||||
#include <Script.h>
|
||||
|
||||
#define __COMPILINGMOREFILES
|
||||
|
||||
#include "MoreFilesExtras.h"
|
||||
#include "FSpCompat.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* local constants */
|
||||
|
||||
enum {
|
||||
gestaltBugFixAttrsTwo = 'bugy',
|
||||
gestaltFSpExchangeFilesCompatibilityFix = 26,
|
||||
gestaltBugFixAttrsThree = 'bugx',
|
||||
gestaltFSpCreateScriptSupportFix = 1
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* static prototypes */
|
||||
|
||||
|
||||
#if !__MACOSSEVENORLATER
|
||||
static Boolean FSHasFSSpecCalls(void);
|
||||
|
||||
static Boolean QTHasFSSpecCalls(void);
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
|
||||
#if !__MACOSSEVENFIVEORLATER
|
||||
static Boolean HasFSpExchangeFilesCompatibilityFix(void);
|
||||
|
||||
static OSErr GenerateUniqueName(short volume,
|
||||
long *startSeed,
|
||||
long dir1,
|
||||
long dir2,
|
||||
StringPtr uniqueName);
|
||||
#endif /* !__MACOSSEVENFIVEORLATER */
|
||||
|
||||
#if !__MACOSSEVENFIVEONEORLATER
|
||||
static Boolean HasFSpCreateScriptSupportFix(void);
|
||||
#endif /* !__MACOSSEVENFIVEONEORLATER */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* FSHasFSSpecCalls returns true if the file system provides FSSpec calls. */
|
||||
|
||||
#if !__MACOSSEVENORLATER
|
||||
static Boolean FSHasFSSpecCalls(void)
|
||||
{
|
||||
long response;
|
||||
#if !GENERATENODATA
|
||||
static Boolean tested = false;
|
||||
static Boolean result = false;
|
||||
#else
|
||||
Boolean result = false;
|
||||
#endif
|
||||
|
||||
#if !GENERATENODATA
|
||||
if ( !tested )
|
||||
{
|
||||
tested = true;
|
||||
#endif
|
||||
if ( Gestalt(gestaltFSAttr, &response) == noErr )
|
||||
{
|
||||
result = ((response & (1L << gestaltHasFSSpecCalls)) != 0);
|
||||
}
|
||||
#if !GENERATENODATA
|
||||
}
|
||||
#endif
|
||||
return ( result );
|
||||
}
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* QTHasFSSpecCalls returns true if QuickTime provides FSSpec calls */
|
||||
/* except for FSpExchangeFiles. */
|
||||
|
||||
#if !__MACOSSEVENORLATER
|
||||
static Boolean QTHasFSSpecCalls(void)
|
||||
{
|
||||
long response;
|
||||
#if !GENERATENODATA
|
||||
static Boolean tested = false;
|
||||
static Boolean result = false;
|
||||
#else
|
||||
Boolean result = false;
|
||||
#endif
|
||||
|
||||
#if !GENERATENODATA
|
||||
if ( !tested )
|
||||
{
|
||||
tested = true;
|
||||
#endif
|
||||
result = (Gestalt(gestaltQuickTimeVersion, &response) == noErr);
|
||||
#if !GENERATENODATA
|
||||
}
|
||||
#endif
|
||||
return ( result );
|
||||
}
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* HasFSpExchangeFilesCompatibilityFix returns true if FSpExchangeFiles */
|
||||
/* compatibility code has been fixed in system software. */
|
||||
/* This was fixed by System Update 3.0, so if SystemSevenFiveOrLater */
|
||||
/* is true, then we know the fix is in. */
|
||||
|
||||
#if !__MACOSSEVENFIVEORLATER
|
||||
static Boolean HasFSpExchangeFilesCompatibilityFix(void)
|
||||
{
|
||||
long response;
|
||||
#if !GENERATENODATA
|
||||
static Boolean tested = false;
|
||||
static Boolean result = false;
|
||||
#else /* !GENERATENODATA */
|
||||
Boolean result = false;
|
||||
#endif /* !GENERATENODATA */
|
||||
|
||||
#if !GENERATENODATA
|
||||
if ( !tested )
|
||||
{
|
||||
tested = true;
|
||||
#endif /* !GENERATENODATA */
|
||||
if ( Gestalt(gestaltBugFixAttrsTwo, &response) == noErr )
|
||||
{
|
||||
result = ((response & (1L << gestaltFSpExchangeFilesCompatibilityFix)) != 0);
|
||||
}
|
||||
#if !GENERATENODATA
|
||||
}
|
||||
#endif /* !GENERATENODATA */
|
||||
return ( result );
|
||||
}
|
||||
#endif /* !__MACOSSEVENFIVEORLATER */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* HasFSpCreateScriptSupportFix returns true if FSpCreate and */
|
||||
/* FSpCreateResFile have been fixed in system software to correctly set */
|
||||
/* the scriptCode in the volume's catalog. */
|
||||
/* This was fixed by System 7.5 Update 1.0 */
|
||||
|
||||
#if !__MACOSSEVENFIVEONEORLATER
|
||||
static Boolean HasFSpCreateScriptSupportFix(void)
|
||||
{
|
||||
long response;
|
||||
#if !GENERATENODATA
|
||||
static Boolean tested = false;
|
||||
static Boolean result = false;
|
||||
#else
|
||||
Boolean result = false;
|
||||
#endif /* !GENERATENODATA */
|
||||
|
||||
#if !GENERATENODATA
|
||||
if ( !tested )
|
||||
{
|
||||
tested = true;
|
||||
#endif /* !GENERATENODATA */
|
||||
if ( Gestalt(gestaltBugFixAttrsThree, &response) == noErr )
|
||||
{
|
||||
result = ((response & (1L << gestaltFSpCreateScriptSupportFix)) != 0);
|
||||
}
|
||||
#if !GENERATENODATA
|
||||
}
|
||||
#endif /* !GENERATENODATA */
|
||||
return ( result );
|
||||
}
|
||||
#endif /* !__MACOSSEVENFIVEONEORLATER */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/*
|
||||
** File Manager FSp calls
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSMakeFSSpecCompat(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param fileName,
|
||||
FSSpec *spec)
|
||||
{
|
||||
OSErr result;
|
||||
|
||||
#if !__MACOSSEVENORLATER
|
||||
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
|
||||
{
|
||||
Boolean isDirectory;
|
||||
|
||||
result = GetObjectLocation(vRefNum, dirID, fileName,
|
||||
&(spec->vRefNum), &(spec->parID), spec->name,
|
||||
&isDirectory);
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
{
|
||||
/* Let the file system create the FSSpec if it can since it does the job */
|
||||
/* much more efficiently than I can. */
|
||||
result = FSMakeFSSpec(vRefNum, dirID, fileName, spec);
|
||||
|
||||
/* Fix a bug in Macintosh PC Exchange's MakeFSSpec code where 0 is */
|
||||
/* returned in the parID field when making an FSSpec to the volume's */
|
||||
/* root directory by passing a full pathname in MakeFSSpec's */
|
||||
/* fileName parameter. Fixed in Mac OS 8.1 */
|
||||
if ( (result == noErr) && (spec->parID == 0) )
|
||||
spec->parID = fsRtParID;
|
||||
}
|
||||
return ( result );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpOpenDFCompat(const FSSpec *spec,
|
||||
char permission,
|
||||
short *refNum)
|
||||
{
|
||||
#if !__MACOSSEVENORLATER
|
||||
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
|
||||
{
|
||||
OSErr result;
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.ioParam.ioVRefNum = spec->vRefNum;
|
||||
pb.fileParam.ioDirID = spec->parID;
|
||||
pb.ioParam.ioNamePtr = (StringPtr) &(spec->name);
|
||||
pb.ioParam.ioVersNum = 0;
|
||||
pb.ioParam.ioPermssn = permission;
|
||||
pb.ioParam.ioMisc = NULL;
|
||||
result = PBHOpenSync(&pb); /* OpenDF not supported by System 6, so use Open */
|
||||
*refNum = pb.ioParam.ioRefNum;
|
||||
return ( result );
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
{
|
||||
return ( FSpOpenDF(spec, permission, refNum) );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpOpenRFCompat(const FSSpec *spec,
|
||||
char permission,
|
||||
short *refNum)
|
||||
{
|
||||
#if !__MACOSSEVENORLATER
|
||||
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
|
||||
{
|
||||
OSErr result;
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.ioParam.ioVRefNum = spec->vRefNum;
|
||||
pb.fileParam.ioDirID = spec->parID;
|
||||
pb.ioParam.ioNamePtr = (StringPtr) &(spec->name);
|
||||
pb.ioParam.ioVersNum = 0;
|
||||
pb.ioParam.ioPermssn = permission;
|
||||
pb.ioParam.ioMisc = NULL;
|
||||
result = PBHOpenRFSync(&pb);
|
||||
*refNum = pb.ioParam.ioRefNum;
|
||||
return ( result );
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
{
|
||||
return ( FSpOpenRF(spec, permission, refNum) );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpCreateCompat(const FSSpec *spec,
|
||||
OSType creator,
|
||||
OSType fileType,
|
||||
ScriptCode scriptTag)
|
||||
{
|
||||
#if !__MACOSSEVENFIVEONEORLATER
|
||||
OSErr result;
|
||||
UniversalFMPB pb;
|
||||
|
||||
|
||||
if (
|
||||
#if !__MACOSSEVENORLATER
|
||||
(!FSHasFSSpecCalls() && !QTHasFSSpecCalls()) ||
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
!HasFSpCreateScriptSupportFix() )
|
||||
{
|
||||
/* If FSpCreate isn't called, this code will be executed */
|
||||
pb.hPB.fileParam.ioVRefNum = spec->vRefNum;
|
||||
pb.hPB.fileParam.ioDirID = spec->parID;
|
||||
pb.hPB.fileParam.ioNamePtr = (StringPtr) &(spec->name);
|
||||
pb.hPB.fileParam.ioFVersNum = 0;
|
||||
result = PBHCreateSync(&(pb.hPB));
|
||||
if ( result == noErr )
|
||||
{
|
||||
/* get info on created item */
|
||||
pb.ciPB.hFileInfo.ioFDirIndex = 0;
|
||||
result = PBGetCatInfoSync(&(pb.ciPB));
|
||||
if ( result == noErr )
|
||||
{
|
||||
/* Set fdScript in FXInfo */
|
||||
/* The negative script constants (smSystemScript, smCurrentScript, and smAllScripts) */
|
||||
/* don't make sense on disk, so only use scriptTag if scriptTag >= smRoman */
|
||||
/* (smRoman is 0). fdScript is valid if high bit is set (see IM-6, page 9-38) */
|
||||
pb.ciPB.hFileInfo.ioFlXFndrInfo.fdScript = (scriptTag >= smRoman) ?
|
||||
((char)scriptTag | (char)0x80) :
|
||||
(smRoman);
|
||||
/* Set creator/fileType */
|
||||
pb.ciPB.hFileInfo.ioFlFndrInfo.fdCreator = creator;
|
||||
pb.ciPB.hFileInfo.ioFlFndrInfo.fdType = fileType;
|
||||
/* Restore ioDirID field in pb which was changed by PBGetCatInfo */
|
||||
pb.ciPB.hFileInfo.ioDirID = spec->parID;
|
||||
result = PBSetCatInfoSync(&(pb.ciPB));
|
||||
}
|
||||
}
|
||||
return ( result );
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENFIVEONEORLATER */
|
||||
{
|
||||
return ( FSpCreate(spec, creator, fileType, scriptTag) );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpDirCreateCompat(const FSSpec *spec,
|
||||
ScriptCode scriptTag,
|
||||
long *createdDirID)
|
||||
{
|
||||
#if !__MACOSSEVENORLATER
|
||||
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
|
||||
{
|
||||
OSErr result;
|
||||
UniversalFMPB pb;
|
||||
|
||||
pb.hPB.fileParam.ioVRefNum = spec->vRefNum;
|
||||
pb.hPB.fileParam.ioDirID = spec->parID;
|
||||
pb.hPB.fileParam.ioNamePtr = (StringPtr) &(spec->name);
|
||||
result = PBDirCreateSync(&(pb.hPB));
|
||||
*createdDirID = pb.hPB.fileParam.ioDirID;
|
||||
if ( result == noErr )
|
||||
{
|
||||
/* get info on created item */
|
||||
pb.ciPB.dirInfo.ioFDirIndex = 0;
|
||||
pb.ciPB.dirInfo.ioDrDirID = spec->parID;
|
||||
result = PBGetCatInfoSync(&(pb.ciPB));
|
||||
if ( result == noErr )
|
||||
{
|
||||
/* Set frScript in DXInfo */
|
||||
/* The negative script constants (smSystemScript, smCurrentScript, and smAllScripts) */
|
||||
/* don't make sense on disk, so only use scriptTag if scriptTag >= smRoman */
|
||||
/* (smRoman is 0). frScript is valid if high bit is set (see IM-6, page 9-38) */
|
||||
pb.ciPB.dirInfo.ioDrFndrInfo.frScript = (scriptTag >= smRoman) ?
|
||||
((char)scriptTag | (char)0x80) :
|
||||
(smRoman);
|
||||
/* Restore ioDirID field in pb which was changed by PBGetCatInfo */
|
||||
pb.ciPB.dirInfo.ioDrDirID = spec->parID;
|
||||
result = PBSetCatInfoSync(&(pb.ciPB));
|
||||
}
|
||||
}
|
||||
return ( result );
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
{
|
||||
return ( FSpDirCreate(spec, scriptTag, createdDirID) );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpDeleteCompat(const FSSpec *spec)
|
||||
{
|
||||
#if !__MACOSSEVENORLATER
|
||||
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.ioParam.ioVRefNum = spec->vRefNum;
|
||||
pb.fileParam.ioDirID = spec->parID;
|
||||
pb.ioParam.ioNamePtr = (StringPtr) &(spec->name);
|
||||
pb.ioParam.ioVersNum = 0;
|
||||
return ( PBHDeleteSync(&pb) );
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
{
|
||||
return ( FSpDelete(spec) );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpGetFInfoCompat(const FSSpec *spec,
|
||||
FInfo *fndrInfo)
|
||||
{
|
||||
#if !__MACOSSEVENORLATER
|
||||
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
|
||||
{
|
||||
OSErr result;
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.fileParam.ioVRefNum = spec->vRefNum;
|
||||
pb.fileParam.ioDirID = spec->parID;
|
||||
pb.fileParam.ioNamePtr = (StringPtr) &(spec->name);
|
||||
pb.fileParam.ioFVersNum = 0;
|
||||
pb.fileParam.ioFDirIndex = 0;
|
||||
result = PBHGetFInfoSync(&pb);
|
||||
*fndrInfo = pb.fileParam.ioFlFndrInfo;
|
||||
return ( result );
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
{
|
||||
return ( FSpGetFInfo(spec, fndrInfo) );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpSetFInfoCompat(const FSSpec *spec,
|
||||
const FInfo *fndrInfo)
|
||||
{
|
||||
#if !__MACOSSEVENORLATER
|
||||
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
|
||||
{
|
||||
OSErr result;
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.fileParam.ioVRefNum = spec->vRefNum;
|
||||
pb.fileParam.ioDirID = spec->parID;
|
||||
pb.fileParam.ioNamePtr = (StringPtr) &(spec->name);
|
||||
pb.fileParam.ioFVersNum = 0;
|
||||
pb.fileParam.ioFDirIndex = 0;
|
||||
result = PBHGetFInfoSync(&pb);
|
||||
if ( result == noErr )
|
||||
{
|
||||
pb.fileParam.ioFlFndrInfo = *fndrInfo;
|
||||
pb.fileParam.ioDirID = spec->parID;
|
||||
result = PBHSetFInfoSync(&pb);
|
||||
}
|
||||
return ( result );
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
{
|
||||
return ( FSpSetFInfo(spec, fndrInfo) );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpSetFLockCompat(const FSSpec *spec)
|
||||
{
|
||||
#if !__MACOSSEVENORLATER
|
||||
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.fileParam.ioVRefNum = spec->vRefNum;
|
||||
pb.fileParam.ioDirID = spec->parID;
|
||||
pb.fileParam.ioNamePtr = (StringPtr) &(spec->name);
|
||||
pb.fileParam.ioFVersNum = 0;
|
||||
return ( PBHSetFLockSync(&pb) );
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
{
|
||||
return ( FSpSetFLock(spec) );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpRstFLockCompat(const FSSpec *spec)
|
||||
{
|
||||
#if !__MACOSSEVENORLATER
|
||||
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.fileParam.ioVRefNum = spec->vRefNum;
|
||||
pb.fileParam.ioDirID = spec->parID;
|
||||
pb.fileParam.ioNamePtr = (StringPtr) &(spec->name);
|
||||
pb.fileParam.ioFVersNum = 0;
|
||||
return ( PBHRstFLockSync(&pb) );
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
{
|
||||
return ( FSpRstFLock(spec) );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpRenameCompat(const FSSpec *spec,
|
||||
ConstStr255Param newName)
|
||||
{
|
||||
#if !__MACOSSEVENORLATER
|
||||
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.ioParam.ioVRefNum = spec->vRefNum;
|
||||
pb.fileParam.ioDirID = spec->parID;
|
||||
pb.ioParam.ioNamePtr = (StringPtr) &(spec->name);
|
||||
pb.ioParam.ioVersNum = 0;
|
||||
pb.ioParam.ioMisc = (Ptr) newName;
|
||||
return ( PBHRenameSync(&pb) );
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
{
|
||||
return ( FSpRename(spec, newName) );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpCatMoveCompat(const FSSpec *source,
|
||||
const FSSpec *dest)
|
||||
{
|
||||
#if !__MACOSSEVENORLATER
|
||||
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
|
||||
{
|
||||
CMovePBRec pb;
|
||||
|
||||
/* source and destination volume must be the same */
|
||||
if ( source->vRefNum != dest->vRefNum )
|
||||
return ( paramErr );
|
||||
|
||||
pb.ioNamePtr = (StringPtr) &(source->name);
|
||||
pb.ioVRefNum = source->vRefNum;
|
||||
pb.ioDirID = source->parID;
|
||||
pb.ioNewDirID = dest->parID;
|
||||
pb.ioNewName = (StringPtr) &(dest->name);
|
||||
return ( PBCatMoveSync(&pb) );
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
{
|
||||
return ( FSpCatMove(source, dest) );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* GenerateUniqueName generates a name that is unique in both dir1 and dir2 */
|
||||
/* on the specified volume. Ripped off from Feldman's code. */
|
||||
|
||||
#if !__MACOSSEVENFIVEORLATER
|
||||
static OSErr GenerateUniqueName(short volume,
|
||||
long *startSeed,
|
||||
long dir1,
|
||||
long dir2,
|
||||
StringPtr uniqueName)
|
||||
{
|
||||
OSErr error = noErr;
|
||||
long i;
|
||||
CInfoPBRec cinfo;
|
||||
unsigned char hexStr[16];
|
||||
|
||||
for ( i = 0; i < 16; ++i )
|
||||
{
|
||||
if ( i < 10 )
|
||||
{
|
||||
hexStr[i] = 0x30 + i;
|
||||
}
|
||||
else
|
||||
{
|
||||
hexStr[i] = 0x37 + i;
|
||||
}
|
||||
}
|
||||
|
||||
cinfo.hFileInfo.ioVRefNum = volume;
|
||||
cinfo.hFileInfo.ioFDirIndex = 0;
|
||||
cinfo.hFileInfo.ioNamePtr = uniqueName;
|
||||
|
||||
while ( error != fnfErr )
|
||||
{
|
||||
(*startSeed)++;
|
||||
cinfo.hFileInfo.ioNamePtr[0] = 8;
|
||||
for ( i = 1; i <= 8; i++ )
|
||||
{
|
||||
cinfo.hFileInfo.ioNamePtr[i] = hexStr[((*startSeed >> ((8-i)*4)) & 0xf)];
|
||||
}
|
||||
cinfo.hFileInfo.ioDirID = dir1;
|
||||
error = fnfErr;
|
||||
for ( i = 1; i <= 2; i++ )
|
||||
{
|
||||
error = error & PBGetCatInfoSync(&cinfo);
|
||||
cinfo.hFileInfo.ioDirID = dir2;
|
||||
if ( (error != fnfErr) && (error != noErr) )
|
||||
{
|
||||
return ( error );
|
||||
}
|
||||
}
|
||||
}
|
||||
return ( noErr );
|
||||
}
|
||||
#endif /* !__MACOSSEVENFIVEORLATER */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpExchangeFilesCompat(const FSSpec *source,
|
||||
const FSSpec *dest)
|
||||
{
|
||||
#if !__MACOSSEVENFIVEORLATER
|
||||
if (
|
||||
#if !__MACOSSEVENORLATER
|
||||
!FSHasFSSpecCalls() ||
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
!HasFSpExchangeFilesCompatibilityFix() )
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
CInfoPBRec catInfoSource, catInfoDest;
|
||||
OSErr result, result2;
|
||||
Str31 unique1, unique2;
|
||||
StringPtr unique1Ptr, unique2Ptr, swapola;
|
||||
GetVolParmsInfoBuffer volInfo;
|
||||
long theSeed, temp;
|
||||
|
||||
/* Make sure the source and destination are on the same volume */
|
||||
if ( source->vRefNum != dest->vRefNum )
|
||||
{
|
||||
result = diffVolErr;
|
||||
goto errorExit3;
|
||||
}
|
||||
|
||||
/* Try PBExchangeFiles first since it preserves the file ID reference */
|
||||
pb.fidParam.ioNamePtr = (StringPtr) &(source->name);
|
||||
pb.fidParam.ioVRefNum = source->vRefNum;
|
||||
pb.fidParam.ioDestNamePtr = (StringPtr) &(dest->name);
|
||||
pb.fidParam.ioDestDirID = dest->parID;
|
||||
pb.fidParam.ioSrcDirID = source->parID;
|
||||
|
||||
result = PBExchangeFilesSync(&pb);
|
||||
|
||||
/* Note: The compatibility case won't work for files with *Btree control blocks. */
|
||||
/* Right now the only *Btree files are created by the system. */
|
||||
if ( result != noErr )
|
||||
{
|
||||
pb.ioParam.ioNamePtr = NULL;
|
||||
pb.ioParam.ioBuffer = (Ptr) &volInfo;
|
||||
pb.ioParam.ioReqCount = sizeof(volInfo);
|
||||
result2 = PBHGetVolParmsSync(&pb);
|
||||
|
||||
/* continue if volume has no fileID support (or no GetVolParms support) */
|
||||
if ( (result2 == noErr) && hasFileIDs(&volInfo) )
|
||||
{
|
||||
goto errorExit3;
|
||||
}
|
||||
|
||||
/* Get the catalog information for each file */
|
||||
/* and make sure both files are *really* files */
|
||||
catInfoSource.hFileInfo.ioVRefNum = source->vRefNum;
|
||||
catInfoSource.hFileInfo.ioFDirIndex = 0;
|
||||
catInfoSource.hFileInfo.ioNamePtr = (StringPtr) &(source->name);
|
||||
catInfoSource.hFileInfo.ioDirID = source->parID;
|
||||
catInfoSource.hFileInfo.ioACUser = 0; /* ioACUser used to be filler2 */
|
||||
result = PBGetCatInfoSync(&catInfoSource);
|
||||
if ( result != noErr )
|
||||
{
|
||||
goto errorExit3;
|
||||
}
|
||||
if ( (catInfoSource.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 )
|
||||
{
|
||||
result = notAFileErr;
|
||||
goto errorExit3;
|
||||
}
|
||||
|
||||
catInfoDest.hFileInfo.ioVRefNum = dest->vRefNum;
|
||||
catInfoDest.hFileInfo.ioFDirIndex = 0;
|
||||
catInfoDest.hFileInfo.ioNamePtr = (StringPtr) &(dest->name);
|
||||
catInfoDest.hFileInfo.ioDirID = dest->parID;
|
||||
catInfoDest.hFileInfo.ioACUser = 0; /* ioACUser used to be filler2 */
|
||||
result = PBGetCatInfoSync(&catInfoDest);
|
||||
if ( result != noErr )
|
||||
{
|
||||
goto errorExit3;
|
||||
}
|
||||
if ( (catInfoDest.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 )
|
||||
{
|
||||
result = notAFileErr;
|
||||
goto errorExit3;
|
||||
}
|
||||
|
||||
/* generate 2 filenames that are unique in both directories */
|
||||
theSeed = 0x64666A6C; /* a fine unlikely filename */
|
||||
unique1Ptr = (StringPtr)&unique1;
|
||||
unique2Ptr = (StringPtr)&unique2;
|
||||
|
||||
result = GenerateUniqueName(source->vRefNum, &theSeed, source->parID, dest->parID, unique1Ptr);
|
||||
if ( result != noErr )
|
||||
{
|
||||
goto errorExit3;
|
||||
}
|
||||
|
||||
GenerateUniqueName(source->vRefNum, &theSeed, source->parID, dest->parID, unique2Ptr);
|
||||
if ( result != noErr )
|
||||
{
|
||||
goto errorExit3;
|
||||
}
|
||||
|
||||
/* rename source to unique1 */
|
||||
pb.fileParam.ioNamePtr = (StringPtr) &(source->name);
|
||||
pb.ioParam.ioMisc = (Ptr) unique1Ptr;
|
||||
pb.ioParam.ioVersNum = 0;
|
||||
result = PBHRenameSync(&pb);
|
||||
if ( result != noErr )
|
||||
{
|
||||
goto errorExit3;
|
||||
}
|
||||
|
||||
/* rename dest to unique2 */
|
||||
pb.ioParam.ioMisc = (Ptr) unique2Ptr;
|
||||
pb.ioParam.ioVersNum = 0;
|
||||
pb.fileParam.ioNamePtr = (StringPtr) &(dest->name);
|
||||
pb.fileParam.ioDirID = dest->parID;
|
||||
result = PBHRenameSync(&pb);
|
||||
if ( result != noErr )
|
||||
{
|
||||
goto errorExit2; /* back out gracefully by renaming unique1 back to source */
|
||||
}
|
||||
|
||||
/* If files are not in same directory, swap their locations */
|
||||
if ( source->parID != dest->parID )
|
||||
{
|
||||
/* move source file to dest directory */
|
||||
pb.copyParam.ioNamePtr = unique1Ptr;
|
||||
pb.copyParam.ioNewName = NULL;
|
||||
pb.copyParam.ioNewDirID = dest->parID;
|
||||
pb.copyParam.ioDirID = source->parID;
|
||||
result = PBCatMoveSync((CMovePBPtr) &pb);
|
||||
if ( result != noErr )
|
||||
{
|
||||
goto errorExit1; /* back out gracefully by renaming both files to original names */
|
||||
}
|
||||
|
||||
/* move dest file to source directory */
|
||||
pb.copyParam.ioNamePtr = unique2Ptr;
|
||||
pb.copyParam.ioNewDirID = source->parID;
|
||||
pb.copyParam.ioDirID = dest->parID;
|
||||
result = PBCatMoveSync((CMovePBPtr) &pb);
|
||||
if ( result != noErr)
|
||||
{
|
||||
/* life is very bad. We'll at least try to move source back */
|
||||
pb.copyParam.ioNamePtr = unique1Ptr;
|
||||
pb.copyParam.ioNewName = NULL;
|
||||
pb.copyParam.ioNewDirID = source->parID;
|
||||
pb.copyParam.ioDirID = dest->parID;
|
||||
(void) PBCatMoveSync((CMovePBPtr) &pb); /* ignore errors */
|
||||
goto errorExit1; /* back out gracefully by renaming both files to original names */
|
||||
}
|
||||
}
|
||||
|
||||
/* Make unique1Ptr point to file in source->parID */
|
||||
/* and unique2Ptr point to file in dest->parID */
|
||||
/* This lets us fall through to the rename code below */
|
||||
swapola = unique1Ptr;
|
||||
unique1Ptr = unique2Ptr;
|
||||
unique2Ptr = swapola;
|
||||
|
||||
/* At this point, the files are in their new locations (if they were moved) */
|
||||
/* Source is named Unique1 (name pointed to by unique2Ptr) and is in dest->parID */
|
||||
/* Dest is named Unique2 (name pointed to by unique1Ptr) and is in source->parID */
|
||||
/* Need to swap attributes except mod date and swap names */
|
||||
|
||||
/* swap the catalog info by re-aiming the CInfoPB's */
|
||||
catInfoSource.hFileInfo.ioNamePtr = unique1Ptr;
|
||||
catInfoDest.hFileInfo.ioNamePtr = unique2Ptr;
|
||||
|
||||
catInfoSource.hFileInfo.ioDirID = source->parID;
|
||||
catInfoDest.hFileInfo.ioDirID = dest->parID;
|
||||
|
||||
/* Swap the original mod dates with each file */
|
||||
temp = catInfoSource.hFileInfo.ioFlMdDat;
|
||||
catInfoSource.hFileInfo.ioFlMdDat = catInfoDest.hFileInfo.ioFlMdDat;
|
||||
catInfoDest.hFileInfo.ioFlMdDat = temp;
|
||||
|
||||
/* Here's the swap (ignore errors) */
|
||||
(void) PBSetCatInfoSync(&catInfoSource);
|
||||
(void) PBSetCatInfoSync(&catInfoDest);
|
||||
|
||||
/* rename unique2 back to dest */
|
||||
errorExit1:
|
||||
pb.ioParam.ioMisc = (Ptr) &(dest->name);
|
||||
pb.ioParam.ioVersNum = 0;
|
||||
pb.fileParam.ioNamePtr = unique2Ptr;
|
||||
pb.fileParam.ioDirID = dest->parID;
|
||||
(void) PBHRenameSync(&pb); /* ignore errors */
|
||||
|
||||
/* rename unique1 back to source */
|
||||
errorExit2:
|
||||
pb.ioParam.ioMisc = (Ptr) &(source->name);
|
||||
pb.ioParam.ioVersNum = 0;
|
||||
pb.fileParam.ioNamePtr = unique1Ptr;
|
||||
pb.fileParam.ioDirID = source->parID;
|
||||
(void) PBHRenameSync(&pb); /* ignore errors */
|
||||
}
|
||||
errorExit3: { /* null statement */ }
|
||||
return ( result );
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENFIVEORLATER */
|
||||
{
|
||||
return ( FSpExchangeFiles(source, dest) );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/*
|
||||
** Resource Manager FSp calls
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal short FSpOpenResFileCompat(const FSSpec *spec,
|
||||
SignedByte permission)
|
||||
{
|
||||
#if !__MACOSSEVENORLATER
|
||||
if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
|
||||
{
|
||||
return ( HOpenResFile(spec->vRefNum, spec->parID, spec->name, permission) );
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
{
|
||||
return ( FSpOpenResFile(spec, permission) );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal void FSpCreateResFileCompat(const FSSpec *spec,
|
||||
OSType creator,
|
||||
OSType fileType,
|
||||
ScriptCode scriptTag)
|
||||
{
|
||||
#if !__MACOSSEVENFIVEONEORLATER
|
||||
if (
|
||||
#if !__MACOSSEVENORLATER
|
||||
(!FSHasFSSpecCalls() && !QTHasFSSpecCalls()) ||
|
||||
#endif /* !__MACOSSEVENORLATER */
|
||||
!HasFSpCreateScriptSupportFix() )
|
||||
{
|
||||
OSErr result;
|
||||
CInfoPBRec pb;
|
||||
|
||||
HCreateResFile(spec->vRefNum, spec->parID, spec->name);
|
||||
if ( ResError() == noErr )
|
||||
{
|
||||
/* get info on created item */
|
||||
pb.hFileInfo.ioVRefNum = spec->vRefNum;
|
||||
pb.hFileInfo.ioDirID = spec->parID;
|
||||
pb.hFileInfo.ioNamePtr = (StringPtr) &(spec->name);
|
||||
pb.hFileInfo.ioFDirIndex = 0;
|
||||
result = PBGetCatInfoSync(&pb);
|
||||
if ( result == noErr )
|
||||
{
|
||||
/* Set fdScript in FXInfo */
|
||||
/* The negative script constants (smSystemScript, smCurrentScript, and smAllScripts) */
|
||||
/* don't make sense on disk, so only use scriptTag if scriptTag >= smRoman */
|
||||
/* (smRoman is 0). fdScript is valid if high bit is set (see IM-6, page 9-38) */
|
||||
pb.hFileInfo.ioFlXFndrInfo.fdScript = (scriptTag >= smRoman) ?
|
||||
((char)scriptTag | (char)0x80) :
|
||||
(smRoman);
|
||||
/* Set creator/fileType */
|
||||
pb.hFileInfo.ioFlFndrInfo.fdCreator = creator;
|
||||
pb.hFileInfo.ioFlFndrInfo.fdType = fileType;
|
||||
|
||||
/* Restore ioDirID field in pb which was changed by PBGetCatInfo */
|
||||
pb.hFileInfo.ioDirID = spec->parID;
|
||||
result = PBSetCatInfoSync(&pb);
|
||||
}
|
||||
/* Set ResErr low memory global to result */
|
||||
LMSetResErr(result);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
#endif /* !__MACOSSEVENFIVEONEORLATER */
|
||||
{
|
||||
FSpCreateResFile(spec, creator, fileType, scriptTag);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
@@ -1,586 +0,0 @@
|
||||
/*
|
||||
File: FSpCompat.h
|
||||
|
||||
Contains: FSSpec compatibility functions.
|
||||
|
||||
Version: Technology: MoreFiles
|
||||
Release: 1.5.2
|
||||
|
||||
Copyright: <20> 1992-2001 by Apple Computer, Inc., all rights reserved.
|
||||
|
||||
Bugs?: For bug reports, consult the following page on
|
||||
the World Wide Web:
|
||||
|
||||
http://developer.apple.com/bugreporter/
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
You may incorporate this sample code into your applications without
|
||||
restriction, though the sample code has been provided "AS IS" and the
|
||||
responsibility for its operation is 100% yours. However, what you are
|
||||
not permitted to do is to redistribute the source as "DSC Sample Code"
|
||||
after having made changes. If you're going to re-distribute the source,
|
||||
we require that you make it clear in the source that the code was
|
||||
descended from Apple Sample Code, but that you've made changes.
|
||||
*/
|
||||
|
||||
#ifndef __FSPCOMPAT__
|
||||
#define __FSPCOMPAT__
|
||||
|
||||
#ifndef __MACTYPES__
|
||||
#include <MacTypes.h>
|
||||
#endif
|
||||
|
||||
#ifndef __FILES__
|
||||
#include <Files.h>
|
||||
#endif
|
||||
|
||||
#include "Optimization.h"
|
||||
|
||||
|
||||
#if PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if PRAGMA_IMPORT
|
||||
#pragma import on
|
||||
#endif
|
||||
|
||||
#if PRAGMA_STRUCT_ALIGN
|
||||
#pragma options align=mac68k
|
||||
#elif PRAGMA_STRUCT_PACKPUSH
|
||||
#pragma pack(push, 2)
|
||||
#elif PRAGMA_STRUCT_PACK
|
||||
#pragma pack(2)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
FSMakeFSSpecCompat(
|
||||
short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param fileName,
|
||||
FSSpec * spec);
|
||||
|
||||
|
||||
/*
|
||||
The FSMakeFSSpecCompat function fills in the fields of an FSSpec record.
|
||||
If the file system can't create the FSSpec, then the compatibility code
|
||||
creates a FSSpec that is exactly like an FSSpec except that spec.name
|
||||
for a file may not have the same capitalization as the file's catalog
|
||||
entry on the disk volume. That is because fileName is parsed to get the
|
||||
name instead of getting the name back from the file system. This works
|
||||
fine with System 6 where FSMakeSpec isn't available.
|
||||
|
||||
vRefNum input: Volume specification.
|
||||
dirID input: Directory ID.
|
||||
fileName input: Pointer to object name, or nil when dirID specifies
|
||||
a directory that's the object.
|
||||
spec output: A file system specification to be filled in by
|
||||
FSMakeFSSpecCompat.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume doesn<73>t exist
|
||||
fnfErr -43 File or directory does not exist
|
||||
(FSSpec is still valid)
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
FSpOpenDFCompat(
|
||||
const FSSpec * spec,
|
||||
char permission,
|
||||
short * refNum);
|
||||
|
||||
|
||||
/*
|
||||
The FSpOpenDFCompat function opens the data fork of the file specified
|
||||
by spec.
|
||||
Differences from FSpOpenDF: If FSpOpenDF isn't available,
|
||||
FSpOpenDFCompat uses PHBOpen because System 6 doesn't support PBHOpenDF.
|
||||
This means FSpOpenDFCompat could accidentally open a driver if the
|
||||
spec->name begins with a period.
|
||||
|
||||
spec input: An FSSpec record specifying the file whose data
|
||||
fork is to be opened.
|
||||
permission input: A constant indicating the desired file access
|
||||
permissions.
|
||||
refNum output: A reference number of an access path to the file's
|
||||
data fork.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
tmfoErr -42 Too many files open
|
||||
fnfErr -43 File not found
|
||||
opWrErr -49 File already open for writing
|
||||
permErr -54 Attempt to open locked file for writing
|
||||
dirNFErr -120 Directory not found or incomplete pathname
|
||||
afpAccessDenied -5000 User does not have the correct access to
|
||||
the file
|
||||
|
||||
__________
|
||||
|
||||
See also: FSpOpenAware
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
FSpOpenRFCompat(
|
||||
const FSSpec * spec,
|
||||
char permission,
|
||||
short * refNum);
|
||||
|
||||
|
||||
/*
|
||||
The FSpOpenRFCompat function opens the resource fork of the file
|
||||
specified by spec.
|
||||
|
||||
spec input: An FSSpec record specifying the file whose resource
|
||||
fork is to be opened.
|
||||
permission input: A constant indicating the desired file access
|
||||
permissions.
|
||||
refNum output: A reference number of an access path to the file's
|
||||
resource fork.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
tmfoErr -42 Too many files open
|
||||
fnfErr -43 File not found
|
||||
opWrErr -49 File already open for writing
|
||||
permErr -54 Attempt to open locked file for writing
|
||||
dirNFErr -120 Directory not found or incomplete pathname
|
||||
afpAccessDenied -5000 User does not have the correct access to
|
||||
the file
|
||||
|
||||
__________
|
||||
|
||||
See also: FSpOpenRFAware
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
FSpCreateCompat(
|
||||
const FSSpec * spec,
|
||||
OSType creator,
|
||||
OSType fileType,
|
||||
ScriptCode scriptTag);
|
||||
|
||||
|
||||
/*
|
||||
The FSpCreateCompat function creates a new file with the specified
|
||||
type, creator, and script code.
|
||||
Differences from FSpCreate: FSpCreateCompat correctly sets the
|
||||
fdScript in the file's FXInfo record to scriptTag if the problem
|
||||
isn't fixed in the File Manager code.
|
||||
|
||||
spec input: An FSSpec record specifying the file to create.
|
||||
creator input: The creator of the new file.
|
||||
fileType input The file type of the new file.
|
||||
scriptCode input: The code of the script system in which the file
|
||||
name is to be displayed.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
dirFulErr -33 File directory full
|
||||
dskFulErr -34 Disk is full
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
fnfErr -43 Directory not found or incomplete pathname
|
||||
wPrErr -44 Hardware volume lock
|
||||
vLckdErr -46 Software volume lock
|
||||
dupFNErr -48 Duplicate filename and version
|
||||
dirNFErrdirNFErr -120 Directory not found or incomplete pathname
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
afpObjectTypeErr -5025 A directory exists with that name
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
FSpDirCreateCompat(
|
||||
const FSSpec * spec,
|
||||
ScriptCode scriptTag,
|
||||
long * createdDirID);
|
||||
|
||||
|
||||
/*
|
||||
The FSpDirCreateCompat function creates a new directory and returns the
|
||||
directory ID of the newDirectory.
|
||||
|
||||
spec input: An FSSpec record specifying the directory to
|
||||
create.
|
||||
scriptCode input: The code of the script system in which the
|
||||
directory name is to be displayed.
|
||||
createdDirID output: The directory ID of the directory that was
|
||||
created.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
dirFulErr -33 File directory full
|
||||
dskFulErr -34 Disk is full
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
fnfErr -43 Directory not found or incomplete pathname
|
||||
wPrErr -44 Hardware volume lock
|
||||
vLckdErr -46 Software volume lock
|
||||
dupFNErr -48 Duplicate filename and version
|
||||
dirNFErrdirNFErr -120 Directory not found or incomplete pathname
|
||||
wrgVolTypErr -123 Not an HFS volume
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
FSpDeleteCompat(const FSSpec * spec);
|
||||
|
||||
|
||||
/*
|
||||
The FSpDeleteCompat function deletes a file or directory.
|
||||
|
||||
spec input: An FSSpec record specifying the file or
|
||||
directory to delete.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
fnfErr -43 File not found
|
||||
wPrErr -44 Hardware volume lock
|
||||
fLckdErr -45 File is locked
|
||||
vLckdErr -46 Software volume lock
|
||||
fBsyErr -47 File busy, directory not empty, or
|
||||
working directory control block open
|
||||
dirNFErrdirNFErr -120 Directory not found or incomplete pathname
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
FSpGetFInfoCompat(
|
||||
const FSSpec * spec,
|
||||
FInfo * fndrInfo);
|
||||
|
||||
|
||||
/*
|
||||
The FSpGetFInfoCompat function gets the finder information for a file.
|
||||
|
||||
spec input: An FSSpec record specifying the file.
|
||||
fndrInfo output: If the object is a file, then its FInfo.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
fnfErr -43 File not found
|
||||
paramErr -50 No default volume
|
||||
dirNFErrdirNFErr -120 Directory not found or incomplete pathname
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
afpObjectTypeErr -5025 Directory not found or incomplete pathname
|
||||
|
||||
__________
|
||||
|
||||
Also see: FSpGetDInfo
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
FSpSetFInfoCompat(
|
||||
const FSSpec * spec,
|
||||
const FInfo * fndrInfo);
|
||||
|
||||
|
||||
/*
|
||||
The FSpSetFInfoCompat function sets the finder information for a file.
|
||||
|
||||
spec input: An FSSpec record specifying the file.
|
||||
fndrInfo input: The FInfo.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
fnfErr -43 File not found
|
||||
wPrErr -44 Hardware volume lock
|
||||
fLckdErr -45 File is locked
|
||||
vLckdErr -46 Software volume lock
|
||||
dirNFErrdirNFErr -120 Directory not found or incomplete pathname
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
afpObjectTypeErr -5025 Object was a directory
|
||||
|
||||
__________
|
||||
|
||||
Also see: FSpSetDInfo
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
FSpSetFLockCompat(const FSSpec * spec);
|
||||
|
||||
|
||||
/*
|
||||
The FSpSetFLockCompat function locks a file.
|
||||
|
||||
spec input: An FSSpec record specifying the file.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
fnfErr -43 File not found
|
||||
wPrErr -44 Hardware volume lock
|
||||
vLckdErr -46 Software volume lock
|
||||
dirNFErrdirNFErr -120 Directory not found or incomplete pathname
|
||||
afpAccessDenied -5000 User does not have the correct access to
|
||||
the file
|
||||
afpObjectTypeErr -5025 Folder locking not supported by volume
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
FSpRstFLockCompat(const FSSpec * spec);
|
||||
|
||||
|
||||
/*
|
||||
The FSpRstFLockCompat function unlocks a file.
|
||||
|
||||
spec input: An FSSpec record specifying the file.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
fnfErr -43 File not found
|
||||
wPrErr -44 Hardware volume lock
|
||||
vLckdErr -46 Software volume lock
|
||||
dirNFErrdirNFErr -120 Directory not found or incomplete pathname
|
||||
afpAccessDenied -5000 User does not have the correct access to
|
||||
the file
|
||||
afpObjectTypeErr -5025 Folder locking not supported by volume
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
FSpRenameCompat(
|
||||
const FSSpec * spec,
|
||||
ConstStr255Param newName);
|
||||
|
||||
|
||||
/*
|
||||
The FSpRenameCompat function renames a file or directory.
|
||||
|
||||
spec input: An FSSpec record specifying the file.
|
||||
newName input: The new name of the file or directory.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
dirFulErr -33 File directory full
|
||||
dskFulErr -34 Volume is full
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
fnfErr -43 File not found
|
||||
wPrErr -44 Hardware volume lock
|
||||
fLckdErr -45 File is locked
|
||||
vLckdErr -46 Software volume lock
|
||||
dupFNErr -48 Duplicate filename and version
|
||||
paramErr -50 No default volume
|
||||
fsRnErr -59 Problem during rename
|
||||
dirNFErrdirNFErr -120 Directory not found or incomplete pathname
|
||||
afpAccessDenied -5000 User does not have the correct access to
|
||||
the file
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
FSpCatMoveCompat(
|
||||
const FSSpec * source,
|
||||
const FSSpec * dest);
|
||||
|
||||
|
||||
/*
|
||||
The FSpCatMoveCompat function moves a file or directory to a different
|
||||
location on on the same volume.
|
||||
|
||||
source input: An FSSpec record specifying the file or directory.
|
||||
dest input: An FSSpec record specifying the name and location
|
||||
of the directory into which the source file or
|
||||
directory is to be moved.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename or attempt to move into
|
||||
a file
|
||||
fnfErr -43 File not found
|
||||
wPrErr -44 Hardware volume lock
|
||||
fLckdErr -45 Target directory is locked
|
||||
vLckdErr -46 Software volume lock
|
||||
dupFNErr -48 Duplicate filename and version
|
||||
paramErr -50 No default volume
|
||||
badMovErr -122 Attempt to move into offspring
|
||||
wrgVolTypErr -123 Not an HFS volume
|
||||
afpAccessDenied -5000 User does not have the correct access to
|
||||
the file
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
FSpExchangeFilesCompat(
|
||||
const FSSpec * source,
|
||||
const FSSpec * dest);
|
||||
|
||||
|
||||
/*
|
||||
The FSpExchangeFilesCompat function swaps the data in two files by
|
||||
changing the information in the volume's catalog and, if the files
|
||||
are open, in the file control blocks.
|
||||
Differences from FSpExchangeFiles: Correctly exchanges files on volumes
|
||||
that don't support PBExchangeFiles. FSpExchangeFiles attempts to support
|
||||
volumes that don't support PBExchangeFiles, but in System 7, 7.0.1, 7.1,
|
||||
and 7 Pro, the compatibility code just doesn't work on volumes that
|
||||
don't support PBExchangeFiles (even though you may get a noErr result).
|
||||
System Update 3.0 and System 7.5 and later have the problems in
|
||||
FSpExchangeFiles corrected.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
fnfErr -43 File not found
|
||||
fLckdErr -45 File is locked
|
||||
vLckdErr -46 Volume is locked or read-only
|
||||
paramErr -50 Function not supported by volume
|
||||
volOfflinErr -53 Volume is offline
|
||||
wrgVolTypErr -123 Not an HFS volume
|
||||
diffVolErr -1303 Files on different volumes
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
afpObjectTypeErr -5025 Object is a directory, not a file
|
||||
afpSameObjectErr -5038 Source and destination files are the same
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( short )
|
||||
FSpOpenResFileCompat(
|
||||
const FSSpec * spec,
|
||||
SignedByte permission);
|
||||
|
||||
|
||||
/*
|
||||
The FSpOpenResFileCompat function opens the resource file specified
|
||||
by spec.
|
||||
|
||||
spec input: An FSSpec record specifying the file whose
|
||||
resource file is to be opened.
|
||||
permission input: A constant indicating the desired file access
|
||||
permissions.
|
||||
function result output: A resource file reference number, or if there's
|
||||
an error -1.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr <20>35 No such volume
|
||||
ioErr <20>36 I/O error
|
||||
bdNamErr <20>37 Bad filename or volume name (perhaps zero
|
||||
length)
|
||||
eofErr <20>39 End of file
|
||||
tmfoErr <20>42 Too many files open
|
||||
fnfErr <20>43 File not found
|
||||
opWrErr <20>49 File already open with write permission
|
||||
permErr <20>54 Permissions error (on file open)
|
||||
extFSErr <20>58 Volume belongs to an external file system
|
||||
memFullErr <20>108 Not enough room in heap zone
|
||||
dirNFErr <20>120 Directory not found
|
||||
mapReadErr <20>199 Map inconsistent with operation
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( void )
|
||||
FSpCreateResFileCompat(
|
||||
const FSSpec * spec,
|
||||
OSType creator,
|
||||
OSType fileType,
|
||||
ScriptCode scriptTag);
|
||||
|
||||
|
||||
/*
|
||||
The FSpCreateResFileCompat function creates a new resource file with
|
||||
the specified type, creator, and script code.
|
||||
Differences from FSpCreateResFile: FSpCreateResFileCompat correctly
|
||||
sets the fdScript in the file's FXInfo record to scriptTag if the
|
||||
problem isn't fixed in the File Manager code.
|
||||
|
||||
spec input: An FSSpec record specifying the resource file to create.
|
||||
creator input: The creator of the new file.
|
||||
fileType input The file type of the new file.
|
||||
scriptCode input: The code of the script system in which the file
|
||||
name is to be displayed.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
dirFulErr <20>33 Directory full
|
||||
dskFulErr <20>34 Disk full
|
||||
nsvErr <20>35 No such volume
|
||||
ioErr <20>36 I/O error
|
||||
bdNamErr <20>37 Bad filename or volume name (perhaps zero
|
||||
length)
|
||||
tmfoErr <20>42 Too many files open
|
||||
wPrErrw <20>44 Disk is write-protected
|
||||
fLckdErr <20>45 File is locked
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "OptimizationEnd.h"
|
||||
|
||||
#if PRAGMA_STRUCT_ALIGN
|
||||
#pragma options align=reset
|
||||
#elif PRAGMA_STRUCT_PACKPUSH
|
||||
#pragma pack(pop)
|
||||
#elif PRAGMA_STRUCT_PACK
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef PRAGMA_IMPORT_OFF
|
||||
#pragma import off
|
||||
#elif PRAGMA_IMPORT
|
||||
#pragma import reset
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __FSPCOMPAT__ */
|
||||
|
@@ -1,611 +0,0 @@
|
||||
/*
|
||||
File: FileCopy.c
|
||||
|
||||
Contains: A robust, general purpose file copy routine.
|
||||
|
||||
Version: MoreFiles
|
||||
|
||||
Copyright: <09> 1992-2001 by Apple Computer, Inc., all rights reserved.
|
||||
|
||||
You may incorporate this sample code into your applications without
|
||||
restriction, though the sample code has been provided "AS IS" and the
|
||||
responsibility for its operation is 100% yours. However, what you are
|
||||
not permitted to do is to redistribute the source as "DSC Sample Code"
|
||||
after having made changes. If you're going to re-distribute the source,
|
||||
we require that you make it clear in the source that the code was
|
||||
descended from Apple Sample Code, but that you've made changes.
|
||||
|
||||
File Ownership:
|
||||
|
||||
DRI: Apple Macintosh Developer Technical Support
|
||||
|
||||
Other Contact: Apple Macintosh Developer Technical Support
|
||||
<http://developer.apple.com/bugreporter/>
|
||||
|
||||
Technology: DTS Sample Code
|
||||
|
||||
Writers:
|
||||
|
||||
(JL) Jim Luther
|
||||
|
||||
Change History (most recent first):
|
||||
|
||||
<2> 2/7/01 JL Added standard header. Updated names of includes. Updated
|
||||
various routines to use new calling convention of the
|
||||
MoreFilesExtras accessor functions.
|
||||
<1> 12/06/99 JL MoreFiles 1.5.
|
||||
*/
|
||||
|
||||
#include <MacTypes.h>
|
||||
#include <MacErrors.h>
|
||||
#include <MacMemory.h>
|
||||
#include <Files.h>
|
||||
#include <Math64.h>
|
||||
|
||||
#define __COMPILINGMOREFILES
|
||||
|
||||
#include "MoreFiles.h"
|
||||
#include "MoreFilesExtras.h"
|
||||
#include "MoreDesktopMgr.h"
|
||||
#include "FileCopy.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* local constants */
|
||||
|
||||
/* The deny-mode privileges to use when opening the source and destination files. */
|
||||
|
||||
enum
|
||||
{
|
||||
srcCopyMode = dmRdDenyWr,
|
||||
dstCopyMode = dmWrDenyRdWr
|
||||
};
|
||||
|
||||
/* The largest (16K) and smallest (.5K) copy buffer to use if the caller doesn't supply
|
||||
** their own copy buffer. */
|
||||
|
||||
enum
|
||||
{
|
||||
bigCopyBuffSize = 0x00004000,
|
||||
minCopyBuffSize = 0x00000200
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* static prototypes */
|
||||
|
||||
static OSErr GetDestinationDirInfo(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name,
|
||||
long *theDirID,
|
||||
Boolean *isDirectory,
|
||||
Boolean *isDropBox);
|
||||
/* GetDestinationDirInfo tells us if the destination is a directory, it's
|
||||
directory ID, and if it's an AppleShare drop box (write privileges only --
|
||||
no read or search privileges).
|
||||
vRefNum input: Volume specification.
|
||||
dirID input: Directory ID.
|
||||
name input: Pointer to object name, or nil when dirID
|
||||
specifies a directory that's the object.
|
||||
theDirID output: If the object is a file, then its parent directory
|
||||
ID. If the object is a directory, then its ID.
|
||||
isDirectory output: True if object is a directory; false if
|
||||
object is a file.
|
||||
isDropBox output: True if directory is an AppleShare drop box.
|
||||
*/
|
||||
|
||||
static OSErr CheckForForks(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name,
|
||||
Boolean *hasDataFork,
|
||||
Boolean *hasResourceFork);
|
||||
/* CheckForForks tells us if there is a data or resource fork to copy.
|
||||
vRefNum input: Volume specification of the file's current
|
||||
location.
|
||||
dirID input: Directory ID of the file's current location.
|
||||
name input: The name of the file.
|
||||
*/
|
||||
|
||||
static OSErr PreflightFileCopySpace(short srcVRefNum,
|
||||
long srcDirID,
|
||||
ConstStr255Param srcName,
|
||||
ConstStr255Param dstVolName,
|
||||
short dstVRefNum,
|
||||
Boolean *spaceOK);
|
||||
/* PreflightFileCopySpace determines if there's enough space on a
|
||||
volume to copy the specified file to that volume.
|
||||
Note: The results of this routine are not perfect. For example if the
|
||||
volume's catalog or extents overflow file grows when the new file is
|
||||
created, more allocation blocks may be needed beyond those needed for
|
||||
the file's data and resource forks.
|
||||
|
||||
srcVRefNum input: Volume specification of the file's current
|
||||
location.
|
||||
srcDirID input: Directory ID of the file's current location.
|
||||
srcName input: The name of the file.
|
||||
dstVolName input: A pointer to the name of the volume where
|
||||
the file will be copied or NULL.
|
||||
dstVRefNum input: Volume specification indicating the volume
|
||||
where the file will be copied.
|
||||
spaceOK output: true if there's enough space on the volume for
|
||||
the file's data and resource forks.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static OSErr GetDestinationDirInfo(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name,
|
||||
long *theDirID,
|
||||
Boolean *isDirectory,
|
||||
Boolean *isDropBox)
|
||||
{
|
||||
CInfoPBRec pb;
|
||||
OSErr error;
|
||||
|
||||
pb.dirInfo.ioACUser = 0; /* ioACUser used to be filler2, clear it before calling GetCatInfo */
|
||||
error = GetCatInfoNoName(vRefNum, dirID, name, &pb);
|
||||
*theDirID = pb.dirInfo.ioDrDirID;
|
||||
*isDirectory = (pb.dirInfo.ioFlAttrib & kioFlAttribDirMask) != 0;
|
||||
/* see if access priviledges are make changes, not see folder, and not see files (drop box) */
|
||||
*isDropBox = userHasDropBoxAccess(pb.dirInfo.ioACUser);
|
||||
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static OSErr CheckForForks(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name,
|
||||
Boolean *hasDataFork,
|
||||
Boolean *hasResourceFork)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
OSErr error;
|
||||
|
||||
pb.fileParam.ioNamePtr = (StringPtr)name;
|
||||
pb.fileParam.ioVRefNum = vRefNum;
|
||||
pb.fileParam.ioFVersNum = 0;
|
||||
pb.fileParam.ioDirID = dirID;
|
||||
pb.fileParam.ioFDirIndex = 0;
|
||||
error = PBHGetFInfoSync(&pb);
|
||||
*hasDataFork = (pb.fileParam.ioFlLgLen != 0);
|
||||
*hasResourceFork = (pb.fileParam.ioFlRLgLen != 0);
|
||||
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static OSErr PreflightFileCopySpace(short srcVRefNum,
|
||||
long srcDirID,
|
||||
ConstStr255Param srcName,
|
||||
ConstStr255Param dstVolName,
|
||||
short dstVRefNum,
|
||||
Boolean *spaceOK)
|
||||
{
|
||||
UniversalFMPB pb;
|
||||
OSErr error;
|
||||
unsigned long dstFreeBlocks;
|
||||
unsigned long dstBlksPerAllocBlk;
|
||||
unsigned long srcDataBlks;
|
||||
unsigned long srcResourceBlks;
|
||||
|
||||
error = XGetVolumeInfoNoName(dstVolName, dstVRefNum, &pb.xPB);
|
||||
if ( error == noErr )
|
||||
{
|
||||
/* get allocation block size (always multiple of 512) and divide by 512
|
||||
to get number of 512-byte blocks per allocation block */
|
||||
dstBlksPerAllocBlk = ((unsigned long)pb.xPB.ioVAlBlkSiz >> 9);
|
||||
|
||||
/* Convert freeBytes to free disk blocks (512-byte blocks) */
|
||||
dstFreeBlocks = U32SetU(U64ShiftRight(pb.xPB.ioVFreeBytes, 9));
|
||||
|
||||
/* Now, get the size of the file's data resource forks */
|
||||
pb.hPB.fileParam.ioNamePtr = (StringPtr)srcName;
|
||||
pb.hPB.fileParam.ioVRefNum = srcVRefNum;
|
||||
pb.hPB.fileParam.ioFVersNum = 0;
|
||||
pb.hPB.fileParam.ioDirID = srcDirID;
|
||||
pb.hPB.fileParam.ioFDirIndex = 0;
|
||||
error = PBHGetFInfoSync(&pb.hPB);
|
||||
if ( error == noErr )
|
||||
{
|
||||
/* Since space on Mac OS disks is always allocated in allocation blocks, */
|
||||
/* this code takes into account rounding up to the end of an allocation block. */
|
||||
|
||||
/* get number of 512-byte blocks needed for data fork */
|
||||
if ( ((unsigned long)pb.hPB.fileParam.ioFlLgLen & 0x000001ff) != 0 )
|
||||
{
|
||||
srcDataBlks = ((unsigned long)pb.hPB.fileParam.ioFlLgLen >> 9) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
srcDataBlks = (unsigned long)pb.hPB.fileParam.ioFlLgLen >> 9;
|
||||
}
|
||||
|
||||
/* now, calculate number of new allocation blocks needed */
|
||||
if ( srcDataBlks % dstBlksPerAllocBlk )
|
||||
{
|
||||
srcDataBlks = (srcDataBlks / dstBlksPerAllocBlk) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
srcDataBlks /= dstBlksPerAllocBlk;
|
||||
}
|
||||
|
||||
/* get number of 512-byte blocks needed for resource fork */
|
||||
if ( ((unsigned long)pb.hPB.fileParam.ioFlRLgLen & 0x000001ff) != 0 )
|
||||
{
|
||||
srcResourceBlks = ((unsigned long)pb.hPB.fileParam.ioFlRLgLen >> 9) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
srcResourceBlks = (unsigned long)pb.hPB.fileParam.ioFlRLgLen >> 9;
|
||||
}
|
||||
|
||||
/* now, calculate number of new allocation blocks needed */
|
||||
if ( srcResourceBlks % dstBlksPerAllocBlk )
|
||||
{
|
||||
srcResourceBlks = (srcResourceBlks / dstBlksPerAllocBlk) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
srcResourceBlks /= dstBlksPerAllocBlk;
|
||||
}
|
||||
|
||||
/* Is there enough room on the destination volume for the source file? */
|
||||
*spaceOK = ( ((srcDataBlks + srcResourceBlks) * dstBlksPerAllocBlk) <= dstFreeBlocks );
|
||||
}
|
||||
}
|
||||
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FileCopy(short srcVRefNum,
|
||||
long srcDirID,
|
||||
ConstStr255Param srcName,
|
||||
short dstVRefNum,
|
||||
long dstDirID,
|
||||
ConstStr255Param dstPathname,
|
||||
ConstStr255Param copyName,
|
||||
void *copyBufferPtr,
|
||||
long copyBufferSize,
|
||||
Boolean preflight)
|
||||
{
|
||||
OSErr err;
|
||||
|
||||
short srcRefNum = 0, /* 0 when source data and resource fork are closed */
|
||||
dstDataRefNum = 0, /* 0 when destination data fork is closed */
|
||||
dstRsrcRefNum = 0; /* 0 when destination resource fork is closed */
|
||||
|
||||
Str63 dstName; /* The filename of the destination. It might be the
|
||||
** source filename, it might be a new name... */
|
||||
|
||||
GetVolParmsInfoBuffer infoBuffer; /* Where PBGetVolParms dumps its info */
|
||||
long srcServerAdr; /* AppleTalk server address of source (if any) */
|
||||
|
||||
Boolean dstCreated = false, /* true when destination file has been created */
|
||||
ourCopyBuffer = false, /* true if we had to allocate the copy buffer */
|
||||
isDirectory, /* true if destination is really a directory */
|
||||
isDropBox; /* true if destination is an AppleShare drop box */
|
||||
|
||||
long tempLong;
|
||||
short tempInt;
|
||||
|
||||
Boolean spaceOK; /* true if there's enough room to copy the file to the destination volume */
|
||||
|
||||
Boolean hasDataFork;
|
||||
Boolean hasResourceFork;
|
||||
|
||||
/* Preflight for size */
|
||||
if ( preflight )
|
||||
{
|
||||
err = PreflightFileCopySpace(srcVRefNum, srcDirID, srcName,
|
||||
dstPathname, dstVRefNum, &spaceOK);
|
||||
if ( err != noErr )
|
||||
{
|
||||
return ( err );
|
||||
}
|
||||
|
||||
if ( !spaceOK )
|
||||
{
|
||||
return ( dskFulErr );
|
||||
}
|
||||
}
|
||||
|
||||
/* get the destination's real dirID and make sure it really is a directory */
|
||||
err = GetDestinationDirInfo(dstVRefNum, dstDirID, dstPathname,
|
||||
&dstDirID, &isDirectory, &isDropBox);
|
||||
if ( err != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
|
||||
if ( !isDirectory )
|
||||
{
|
||||
return ( dirNFErr );
|
||||
}
|
||||
|
||||
/* get the destination's real vRefNum */
|
||||
err = DetermineVRefNum(dstPathname, dstVRefNum, &dstVRefNum);
|
||||
if ( err != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
|
||||
/* See if PBHCopyFile can be used. Using PBHCopyFile saves time by letting the file server
|
||||
** copy the file if the source and destination locations are on the same file server. */
|
||||
tempLong = sizeof(infoBuffer);
|
||||
err = HGetVolParms(srcName, srcVRefNum, &infoBuffer, &tempLong);
|
||||
if ( (err != noErr) && (err != paramErr) )
|
||||
{
|
||||
return ( err );
|
||||
}
|
||||
|
||||
if ( (err != paramErr) && hasCopyFile(&infoBuffer) )
|
||||
{
|
||||
/* The source volume supports PBHCopyFile. */
|
||||
srcServerAdr = infoBuffer.vMServerAdr;
|
||||
|
||||
/* Now, see if the destination volume is on the same file server. */
|
||||
tempLong = sizeof(infoBuffer);
|
||||
err = HGetVolParms(NULL, dstVRefNum, &infoBuffer, &tempLong);
|
||||
if ( (err != noErr) && (err != paramErr) )
|
||||
{
|
||||
return ( err );
|
||||
}
|
||||
if ( (err != paramErr) && (srcServerAdr == infoBuffer.vMServerAdr) )
|
||||
{
|
||||
/* Source and Dest are on same server and PBHCopyFile is supported. Copy with CopyFile. */
|
||||
err = HCopyFile(srcVRefNum, srcDirID, srcName, dstVRefNum, dstDirID, NULL, copyName);
|
||||
if ( err != noErr )
|
||||
{
|
||||
return ( err );
|
||||
}
|
||||
|
||||
/* AppleShare's CopyFile clears the isAlias bit, so I still need to attempt to copy
|
||||
the File's attributes to attempt to get things right. */
|
||||
if ( copyName != NULL ) /* Did caller supply copy file name? */
|
||||
{
|
||||
/* Yes, use the caller supplied copy file name. */
|
||||
(void) CopyFileMgrAttributes(srcVRefNum, srcDirID, srcName,
|
||||
dstVRefNum, dstDirID, copyName, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* They didn't, so get the source file name and use it. */
|
||||
if ( GetFilenameFromPathname(srcName, dstName) == noErr )
|
||||
{
|
||||
/* */
|
||||
(void) CopyFileMgrAttributes(srcVRefNum, srcDirID, srcName,
|
||||
dstVRefNum, dstDirID, dstName, true);
|
||||
}
|
||||
}
|
||||
return ( err );
|
||||
}
|
||||
}
|
||||
|
||||
/* If we're here, then PBHCopyFile couldn't be used so we have to copy the file by hand. */
|
||||
|
||||
/* Make sure a copy buffer is allocated. */
|
||||
if ( copyBufferPtr == NULL )
|
||||
{
|
||||
/* The caller didn't supply a copy buffer so grab one from the application heap.
|
||||
** Try to get a big copy buffer, if we can't, try for a 512-byte buffer.
|
||||
** If 512 bytes aren't available, we're in trouble. */
|
||||
copyBufferSize = bigCopyBuffSize;
|
||||
copyBufferPtr = NewPtr(copyBufferSize);
|
||||
if ( copyBufferPtr == NULL )
|
||||
{
|
||||
copyBufferSize = minCopyBuffSize;
|
||||
copyBufferPtr = NewPtr(copyBufferSize);
|
||||
if ( copyBufferPtr == NULL )
|
||||
{
|
||||
return ( memFullErr );
|
||||
}
|
||||
}
|
||||
ourCopyBuffer = true;
|
||||
}
|
||||
|
||||
/* Open the source data fork. */
|
||||
err = HOpenAware(srcVRefNum, srcDirID, srcName, srcCopyMode, &srcRefNum);
|
||||
if ( err != noErr )
|
||||
return ( err );
|
||||
|
||||
/* Once a file is opened, we have to exit via ErrorExit to make sure things are cleaned up */
|
||||
|
||||
/* See if the copy will be renamed. */
|
||||
if ( copyName != NULL ) /* Did caller supply copy file name? */
|
||||
BlockMoveData(copyName, dstName, copyName[0] + 1); /* Yes, use the caller supplied copy file name. */
|
||||
else
|
||||
{ /* They didn't, so get the source file name and use it. */
|
||||
err = GetFileLocation(srcRefNum, &tempInt, &tempLong, dstName);
|
||||
if ( err != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create the destination file. */
|
||||
err = HCreateMinimum(dstVRefNum, dstDirID, dstName);
|
||||
if ( err != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
dstCreated = true; /* After creating the destination file, any
|
||||
** error conditions should delete the destination file */
|
||||
|
||||
/* An AppleShare dropbox folder is a folder for which the user has the Make Changes
|
||||
** privilege (write access), but not See Files (read access) and See Folders (search access).
|
||||
** Copying a file into an AppleShare dropbox presents some special problems. Here are the
|
||||
** rules we have to follow to copy a file into a dropbox:
|
||||
** <20> File attributes can be changed only when both forks of a file are empty.
|
||||
** <20> DeskTop Manager comments can be added to a file only when both forks of a file
|
||||
** are empty.
|
||||
** <20> A fork can be opened for write access only when both forks of a file are empty.
|
||||
** So, with those rules to live with, we'll do those operations now while both forks
|
||||
** are empty. */
|
||||
|
||||
if ( isDropBox )
|
||||
{
|
||||
/* We only set the file attributes now if the file is being copied into a
|
||||
** drop box. In all other cases, it is better to set the attributes last
|
||||
** so that if FileCopy is modified to give up time to other processes
|
||||
** periodicly, the Finder won't try to read any bundle information (because
|
||||
** the bundle-bit will still be clear) from a partially copied file. If the
|
||||
** copy is into a drop box, we have to set the attributes now, but since the
|
||||
** destination forks are opened with write/deny-read/deny-write permissions,
|
||||
** any Finder that might see the file in the drop box won't be able to open
|
||||
** its resource fork until the resource fork is closed.
|
||||
**
|
||||
** Note: if you do modify FileCopy to give up time to other processes, don't
|
||||
** give up time between the time the destination file is created (above) and
|
||||
** the time both forks are opened (below). That way, you stand the best chance
|
||||
** of making sure the Finder doesn't read a partially copied resource fork.
|
||||
*/
|
||||
/* Copy attributes but don't lock the destination. */
|
||||
err = CopyFileMgrAttributes(srcVRefNum, srcDirID, srcName,
|
||||
dstVRefNum, dstDirID, dstName, false);
|
||||
if ( err != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Attempt to copy the comments while both forks are empty.
|
||||
** Ignore the result because we really don't care if it worked or not. */
|
||||
(void) DTCopyComment(srcVRefNum, srcDirID, srcName, dstVRefNum, dstDirID, dstName);
|
||||
|
||||
/* See which forks we need to copy. By doing this, we won't create a data or resource fork
|
||||
** for the destination unless it's really needed (some foreign file systems such as
|
||||
** the ProDOS File System and Macintosh PC Exchange have to create additional disk
|
||||
** structures to support resource forks). */
|
||||
err = CheckForForks(srcVRefNum, srcDirID, srcName, &hasDataFork, &hasResourceFork);
|
||||
if ( err != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
|
||||
if ( hasDataFork )
|
||||
{
|
||||
/* Open the destination data fork. */
|
||||
err = HOpenAware(dstVRefNum, dstDirID, dstName, dstCopyMode, &dstDataRefNum);
|
||||
if ( err != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
}
|
||||
|
||||
if ( hasResourceFork )
|
||||
{
|
||||
/* Open the destination resource fork. */
|
||||
err = HOpenRFAware(dstVRefNum, dstDirID, dstName, dstCopyMode, &dstRsrcRefNum);
|
||||
if ( err != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
}
|
||||
|
||||
if ( hasDataFork )
|
||||
{
|
||||
/* Copy the data fork. */
|
||||
err = CopyFork(srcRefNum, dstDataRefNum, copyBufferPtr, copyBufferSize);
|
||||
if ( err != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
|
||||
/* Close both data forks and clear reference numbers. */
|
||||
(void) FSClose(srcRefNum);
|
||||
(void) FSClose(dstDataRefNum);
|
||||
srcRefNum = dstDataRefNum = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Close the source data fork since it was opened earlier */
|
||||
(void) FSClose(srcRefNum);
|
||||
srcRefNum = 0;
|
||||
}
|
||||
|
||||
if ( hasResourceFork )
|
||||
{
|
||||
/* Open the source resource fork. */
|
||||
err = HOpenRFAware(srcVRefNum, srcDirID, srcName, srcCopyMode, &srcRefNum);
|
||||
if ( err != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
|
||||
/* Copy the resource fork. */
|
||||
err = CopyFork(srcRefNum, dstRsrcRefNum, copyBufferPtr, copyBufferSize);
|
||||
if ( err != noErr )
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
|
||||
/* Close both resource forks and clear reference numbers. */
|
||||
(void) FSClose(srcRefNum);
|
||||
(void) FSClose(dstRsrcRefNum);
|
||||
srcRefNum = dstRsrcRefNum = 0;
|
||||
}
|
||||
|
||||
/* Get rid of the copy buffer if we allocated it. */
|
||||
if ( ourCopyBuffer )
|
||||
{
|
||||
DisposePtr((Ptr)copyBufferPtr);
|
||||
}
|
||||
|
||||
/* Attempt to copy attributes again to set mod date. Copy lock condition this time
|
||||
** since we're done with the copy operation. This operation will fail if we're copying
|
||||
** into an AppleShare dropbox, so we don't check for error conditions. */
|
||||
CopyFileMgrAttributes(srcVRefNum, srcDirID, srcName,
|
||||
dstVRefNum, dstDirID, dstName, true);
|
||||
|
||||
/* Hey, we did it! */
|
||||
return ( noErr );
|
||||
|
||||
ErrorExit:
|
||||
if ( srcRefNum != 0 )
|
||||
{
|
||||
(void) FSClose(srcRefNum); /* Close the source file */
|
||||
}
|
||||
if ( dstDataRefNum != 0 )
|
||||
{
|
||||
(void) FSClose(dstDataRefNum); /* Close the destination file data fork */
|
||||
}
|
||||
if ( dstRsrcRefNum != 0 )
|
||||
{
|
||||
(void) FSClose(dstRsrcRefNum); /* Close the destination file resource fork */
|
||||
}
|
||||
if ( dstCreated )
|
||||
{
|
||||
(void) HDelete(dstVRefNum, dstDirID, dstName); /* Delete dest file. This may fail if the file
|
||||
is in a "drop folder" */
|
||||
}
|
||||
if ( ourCopyBuffer ) /* dispose of any memory we allocated */
|
||||
{
|
||||
DisposePtr((Ptr)copyBufferPtr);
|
||||
}
|
||||
|
||||
return ( err );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpFileCopy(const FSSpec *srcSpec,
|
||||
const FSSpec *dstSpec,
|
||||
ConstStr255Param copyName,
|
||||
void *copyBufferPtr,
|
||||
long copyBufferSize,
|
||||
Boolean preflight)
|
||||
{
|
||||
return ( FileCopy(srcSpec->vRefNum, srcSpec->parID, srcSpec->name,
|
||||
dstSpec->vRefNum, dstSpec->parID, dstSpec->name,
|
||||
copyName, copyBufferPtr, copyBufferSize, preflight) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@@ -1,271 +0,0 @@
|
||||
/*
|
||||
File: FileCopy.h
|
||||
|
||||
Contains: A robust, general purpose file copy routine.
|
||||
|
||||
Version: Technology: MoreFiles
|
||||
Release: 1.5.2
|
||||
|
||||
Copyright: <20> 1992-2001 by Apple Computer, Inc., all rights reserved.
|
||||
|
||||
Bugs?: For bug reports, consult the following page on
|
||||
the World Wide Web:
|
||||
|
||||
http://developer.apple.com/bugreporter/
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
You may incorporate this sample code into your applications without
|
||||
restriction, though the sample code has been provided "AS IS" and the
|
||||
responsibility for its operation is 100% yours. However, what you are
|
||||
not permitted to do is to redistribute the source as "DSC Sample Code"
|
||||
after having made changes. If you're going to re-distribute the source,
|
||||
we require that you make it clear in the source that the code was
|
||||
descended from Apple Sample Code, but that you've made changes.
|
||||
*/
|
||||
|
||||
#ifndef __FILECOPY__
|
||||
#define __FILECOPY__
|
||||
|
||||
#ifndef __MACTYPES__
|
||||
#include <MacTypes.h>
|
||||
#endif
|
||||
|
||||
#ifndef __FILES__
|
||||
#include <Files.h>
|
||||
#endif
|
||||
|
||||
#include "Optimization.h"
|
||||
|
||||
|
||||
#if PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if PRAGMA_IMPORT
|
||||
#pragma import on
|
||||
#endif
|
||||
|
||||
#if PRAGMA_STRUCT_ALIGN
|
||||
#pragma options align=mac68k
|
||||
#elif PRAGMA_STRUCT_PACKPUSH
|
||||
#pragma pack(push, 2)
|
||||
#elif PRAGMA_STRUCT_PACK
|
||||
#pragma pack(2)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
FileCopy(
|
||||
short srcVRefNum,
|
||||
long srcDirID,
|
||||
ConstStr255Param srcName,
|
||||
short dstVRefNum,
|
||||
long dstDirID,
|
||||
ConstStr255Param dstPathname,
|
||||
ConstStr255Param copyName,
|
||||
void * copyBufferPtr,
|
||||
long copyBufferSize,
|
||||
Boolean preflight);
|
||||
|
||||
|
||||
/*
|
||||
The FileCopy function duplicates a file and optionally renames it.
|
||||
Since the PBHCopyFile routine is only available on some
|
||||
AFP server volumes under specific conditions, this routine
|
||||
either uses PBHCopyFile, or does all of the work PBHCopyFile
|
||||
does. The srcVRefNum, srcDirID and srcName are used to
|
||||
determine the location of the file to copy. The dstVRefNum
|
||||
dstDirID and dstPathname are used to determine the location of
|
||||
the destination directory. If copyName <> NIL, then it points
|
||||
to the name of the new file. If copyBufferPtr <> NIL, it
|
||||
points to a buffer of copyBufferSize that is used to copy
|
||||
the file's data. The larger the supplied buffer, the
|
||||
faster the copy. If copyBufferPtr = NIL, then this routine
|
||||
allocates a buffer in the application heap. If you pass a
|
||||
copy buffer to this routine, make its size a multiple of 512
|
||||
($200) bytes for optimum performance.
|
||||
|
||||
srcVRefNum input: Source volume specification.
|
||||
srcDirID input: Source directory ID.
|
||||
srcName input: Source file name.
|
||||
dstVRefNum input: Destination volume specification.
|
||||
dstDirID input: Destination directory ID.
|
||||
dstPathname input: Pointer to destination directory name, or
|
||||
nil when dstDirID specifies a directory.
|
||||
copyName input: Points to the new file name if the file is
|
||||
to be renamed or nil if the file isn't to
|
||||
be renamed.
|
||||
copyBufferPtr input: Points to a buffer of copyBufferSize that
|
||||
is used the i/o buffer for the copy or
|
||||
nil if you want FileCopy to allocate its
|
||||
own buffer in the application heap.
|
||||
copyBufferSize input: The size of the buffer pointed to
|
||||
by copyBufferPtr.
|
||||
preflight input: If true, FileCopy makes sure there are enough
|
||||
allocation blocks on the destination volume to
|
||||
hold both the data and resource forks before
|
||||
starting the copy.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
readErr <20>19 Driver does not respond to read requests
|
||||
writErr <20>20 Driver does not respond to write requests
|
||||
badUnitErr <20>21 Driver reference number does not
|
||||
match unit table
|
||||
unitEmptyErr <20>22 Driver reference number specifies a
|
||||
nil handle in unit table
|
||||
abortErr <20>27 Request aborted by KillIO
|
||||
notOpenErr <20>28 Driver not open
|
||||
dskFulErr -34 Destination volume is full
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
tmfoErr -42 Too many files open
|
||||
fnfErr -43 Source file not found, or destination
|
||||
directory does not exist
|
||||
wPrErr -44 Volume locked by hardware
|
||||
fLckdErr -45 File is locked
|
||||
vLckdErr -46 Destination volume is read-only
|
||||
fBsyErr -47 The source or destination file could
|
||||
not be opened with the correct access
|
||||
modes
|
||||
dupFNErr -48 Destination file already exists
|
||||
opWrErr -49 File already open for writing
|
||||
paramErr -50 No default volume or function not
|
||||
supported by volume
|
||||
permErr -54 File is already open and cannot be opened using specified deny modes
|
||||
memFullErr -108 Copy buffer could not be allocated
|
||||
dirNFErr -120 Directory not found or incomplete pathname
|
||||
wrgVolTypErr -123 Function not supported by volume
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
afpDenyConflict -5006 The source or destination file could
|
||||
not be opened with the correct access
|
||||
modes
|
||||
afpObjectTypeErr -5025 Source is a directory, directory not found
|
||||
or incomplete pathname
|
||||
|
||||
__________
|
||||
|
||||
Also see: FSpFileCopy, DirectoryCopy, FSpDirectoryCopy
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
FSpFileCopy(
|
||||
const FSSpec * srcSpec,
|
||||
const FSSpec * dstSpec,
|
||||
ConstStr255Param copyName,
|
||||
void * copyBufferPtr,
|
||||
long copyBufferSize,
|
||||
Boolean preflight);
|
||||
|
||||
|
||||
/*
|
||||
The FSpFileCopy function duplicates a file and optionally renames it.
|
||||
Since the PBHCopyFile routine is only available on some
|
||||
AFP server volumes under specific conditions, this routine
|
||||
either uses PBHCopyFile, or does all of the work PBHCopyFile
|
||||
does. The srcSpec is used to
|
||||
determine the location of the file to copy. The dstSpec is
|
||||
used to determine the location of the
|
||||
destination directory. If copyName <> NIL, then it points
|
||||
to the name of the new file. If copyBufferPtr <> NIL, it
|
||||
points to a buffer of copyBufferSize that is used to copy
|
||||
the file's data. The larger the supplied buffer, the
|
||||
faster the copy. If copyBufferPtr = NIL, then this routine
|
||||
allocates a buffer in the application heap. If you pass a
|
||||
copy buffer to this routine, make its size a multiple of 512
|
||||
($200) bytes for optimum performance.
|
||||
|
||||
srcSpec input: An FSSpec record specifying the source file.
|
||||
dstSpec input: An FSSpec record specifying the destination
|
||||
directory.
|
||||
copyName input: Points to the new file name if the file is
|
||||
to be renamed or nil if the file isn't to
|
||||
be renamed.
|
||||
copyBufferPtr input: Points to a buffer of copyBufferSize that
|
||||
is used the i/o buffer for the copy or
|
||||
nil if you want FileCopy to allocate its
|
||||
own buffer in the application heap.
|
||||
copyBufferSize input: The size of the buffer pointed to
|
||||
by copyBufferPtr.
|
||||
preflight input: If true, FSpFileCopy makes sure there are
|
||||
enough allocation blocks on the destination
|
||||
volume to hold both the data and resource forks
|
||||
before starting the copy.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
readErr <20>19 Driver does not respond to read requests
|
||||
writErr <20>20 Driver does not respond to write requests
|
||||
badUnitErr <20>21 Driver reference number does not
|
||||
match unit table
|
||||
unitEmptyErr <20>22 Driver reference number specifies a
|
||||
nil handle in unit table
|
||||
abortErr <20>27 Request aborted by KillIO
|
||||
notOpenErr <20>28 Driver not open
|
||||
dskFulErr -34 Destination volume is full
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
tmfoErr -42 Too many files open
|
||||
fnfErr -43 Source file not found, or destination
|
||||
directory does not exist
|
||||
wPrErr -44 Volume locked by hardware
|
||||
fLckdErr -45 File is locked
|
||||
vLckdErr -46 Destination volume is read-only
|
||||
fBsyErr -47 The source or destination file could
|
||||
not be opened with the correct access
|
||||
modes
|
||||
dupFNErr -48 Destination file already exists
|
||||
opWrErr -49 File already open for writing
|
||||
paramErr -50 No default volume or function not
|
||||
supported by volume
|
||||
permErr -54 File is already open and cannot be opened using specified deny modes
|
||||
memFullErr -108 Copy buffer could not be allocated
|
||||
dirNFErr -120 Directory not found or incomplete pathname
|
||||
wrgVolTypErr -123 Function not supported by volume
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
afpDenyConflict -5006 The source or destination file could
|
||||
not be opened with the correct access
|
||||
modes
|
||||
afpObjectTypeErr -5025 Source is a directory, directory not found
|
||||
or incomplete pathname
|
||||
|
||||
__________
|
||||
|
||||
Also see: FileCopy, DirectoryCopy, FSpDirectoryCopy
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "OptimizationEnd.h"
|
||||
|
||||
#if PRAGMA_STRUCT_ALIGN
|
||||
#pragma options align=reset
|
||||
#elif PRAGMA_STRUCT_PACKPUSH
|
||||
#pragma pack(pop)
|
||||
#elif PRAGMA_STRUCT_PACK
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef PRAGMA_IMPORT_OFF
|
||||
#pragma import off
|
||||
#elif PRAGMA_IMPORT
|
||||
#pragma import reset
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __FILECOPY__ */
|
||||
|
@@ -1,282 +0,0 @@
|
||||
/*
|
||||
File: FullPath.c
|
||||
|
||||
Contains: Routines for dealing with full pathnames... if you really must.
|
||||
|
||||
Version: MoreFiles
|
||||
|
||||
Copyright: <09> 1995-2001 by Apple Computer, Inc., all rights reserved.
|
||||
|
||||
You may incorporate this sample code into your applications without
|
||||
restriction, though the sample code has been provided "AS IS" and the
|
||||
responsibility for its operation is 100% yours. However, what you are
|
||||
not permitted to do is to redistribute the source as "DSC Sample Code"
|
||||
after having made changes. If you're going to re-distribute the source,
|
||||
we require that you make it clear in the source that the code was
|
||||
descended from Apple Sample Code, but that you've made changes.
|
||||
|
||||
File Ownership:
|
||||
|
||||
DRI: Apple Macintosh Developer Technical Support
|
||||
|
||||
Other Contact: Apple Macintosh Developer Technical Support
|
||||
<http://developer.apple.com/bugreporter/>
|
||||
|
||||
Technology: DTS Sample Code
|
||||
|
||||
Writers:
|
||||
|
||||
(JL) Jim Luther
|
||||
|
||||
Change History (most recent first):
|
||||
|
||||
<2> 2/7/01 JL Added standard header. Updated names of includes.
|
||||
<1> 12/06/99 JL MoreFiles 1.5.
|
||||
*/
|
||||
|
||||
#include <MacTypes.h>
|
||||
#include <MacErrors.h>
|
||||
#include <MacMemory.h>
|
||||
#include <Files.h>
|
||||
#include <TextUtils.h>
|
||||
#include <Aliases.h>
|
||||
|
||||
#define __COMPILINGMOREFILES
|
||||
|
||||
#include "FSpCompat.h"
|
||||
#include "FullPath.h"
|
||||
|
||||
/*
|
||||
IMPORTANT NOTE:
|
||||
|
||||
The use of full pathnames is strongly discouraged. Full pathnames are
|
||||
particularly unreliable as a means of identifying files, directories
|
||||
or volumes within your application, for two primary reasons:
|
||||
|
||||
<09> The user can change the name of any element in the path at virtually
|
||||
any time.
|
||||
<09> Volume names on the Macintosh are *not* unique. Multiple
|
||||
mounted volumes can have the same name. For this reason, the use of
|
||||
a full pathname to identify a specific volume may not produce the
|
||||
results you expect. If more than one volume has the same name and
|
||||
a full pathname is used, the File Manager currently uses the first
|
||||
mounted volume it finds with a matching name in the volume queue.
|
||||
|
||||
In general, you should use a file<6C>s name, parent directory ID, and
|
||||
volume reference number to identify a file you want to open, delete,
|
||||
or otherwise manipulate.
|
||||
|
||||
If you need to remember the location of a particular file across
|
||||
subsequent system boots, use the Alias Manager to create an alias record
|
||||
describing the file. If the Alias Manager is not available, you can save
|
||||
the file<6C>s name, its parent directory ID, and the name of the volume on
|
||||
which it<69>s located. Although none of these methods is foolproof, they are
|
||||
much more reliable than using full pathnames to identify files.
|
||||
|
||||
Nonetheless, it is sometimes useful to display a file<6C>s full pathname to
|
||||
the user. For example, a backup utility might display a list of full
|
||||
pathnames of files as it copies them onto the backup medium. Or, a
|
||||
utility might want to display a dialog box showing the full pathname of
|
||||
a file when it needs the user<65>s confirmation to delete the file. No
|
||||
matter how unreliable full pathnames may be from a file-specification
|
||||
viewpoint, users understand them more readily than volume reference
|
||||
numbers or directory IDs. (Hint: Use the TruncString function from
|
||||
TextUtils.h with truncMiddle as the truncWhere argument to shorten
|
||||
full pathnames to a displayable length.)
|
||||
|
||||
The following technique for constructing the full pathname of a file is
|
||||
intended for display purposes only. Applications that depend on any
|
||||
particular structure of a full pathname are likely to fail on alternate
|
||||
foreign file systems or under future system software versions.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr GetFullPath(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name,
|
||||
short *fullPathLength,
|
||||
Handle *fullPath)
|
||||
{
|
||||
OSErr result;
|
||||
FSSpec spec;
|
||||
|
||||
*fullPathLength = 0;
|
||||
*fullPath = NULL;
|
||||
|
||||
result = FSMakeFSSpecCompat(vRefNum, dirID, name, &spec);
|
||||
if ( (result == noErr) || (result == fnfErr) )
|
||||
{
|
||||
result = FSpGetFullPath(&spec, fullPathLength, fullPath);
|
||||
}
|
||||
|
||||
return ( result );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpGetFullPath(const FSSpec *spec,
|
||||
short *fullPathLength,
|
||||
Handle *fullPath)
|
||||
{
|
||||
OSErr result;
|
||||
OSErr realResult;
|
||||
FSSpec tempSpec;
|
||||
CInfoPBRec pb;
|
||||
|
||||
*fullPathLength = 0;
|
||||
*fullPath = NULL;
|
||||
|
||||
|
||||
/* Default to noErr */
|
||||
realResult = result = noErr;
|
||||
|
||||
/* work around Nav Services "bug" (it returns invalid FSSpecs with empty names) */
|
||||
if ( spec->name[0] == 0 )
|
||||
{
|
||||
result = FSMakeFSSpecCompat(spec->vRefNum, spec->parID, spec->name, &tempSpec);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Make a copy of the input FSSpec that can be modified */
|
||||
BlockMoveData(spec, &tempSpec, sizeof(FSSpec));
|
||||
}
|
||||
|
||||
if ( result == noErr )
|
||||
{
|
||||
if ( tempSpec.parID == fsRtParID )
|
||||
{
|
||||
/* The object is a volume */
|
||||
|
||||
/* Add a colon to make it a full pathname */
|
||||
++tempSpec.name[0];
|
||||
tempSpec.name[tempSpec.name[0]] = ':';
|
||||
|
||||
/* We're done */
|
||||
result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The object isn't a volume */
|
||||
|
||||
/* Is the object a file or a directory? */
|
||||
pb.dirInfo.ioNamePtr = tempSpec.name;
|
||||
pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
|
||||
pb.dirInfo.ioDrDirID = tempSpec.parID;
|
||||
pb.dirInfo.ioFDirIndex = 0;
|
||||
result = PBGetCatInfoSync(&pb);
|
||||
// Allow file/directory name at end of path to not exist.
|
||||
realResult = result;
|
||||
if ( (result == noErr) || (result == fnfErr) )
|
||||
{
|
||||
/* if the object is a directory, append a colon so full pathname ends with colon */
|
||||
if ( (result == noErr) && (pb.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 )
|
||||
{
|
||||
++tempSpec.name[0];
|
||||
tempSpec.name[tempSpec.name[0]] = ':';
|
||||
}
|
||||
|
||||
/* Put the object name in first */
|
||||
result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
|
||||
if ( result == noErr )
|
||||
{
|
||||
/* Get the ancestor directory names */
|
||||
pb.dirInfo.ioNamePtr = tempSpec.name;
|
||||
pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
|
||||
pb.dirInfo.ioDrParID = tempSpec.parID;
|
||||
do /* loop until we have an error or find the root directory */
|
||||
{
|
||||
pb.dirInfo.ioFDirIndex = -1;
|
||||
pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
|
||||
result = PBGetCatInfoSync(&pb);
|
||||
if ( result == noErr )
|
||||
{
|
||||
/* Append colon to directory name */
|
||||
++tempSpec.name[0];
|
||||
tempSpec.name[tempSpec.name[0]] = ':';
|
||||
|
||||
/* Add directory name to beginning of fullPath */
|
||||
(void) Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1], tempSpec.name[0]);
|
||||
result = MemError();
|
||||
}
|
||||
} while ( (result == noErr) && (pb.dirInfo.ioDrDirID != fsRtDirID) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( result == noErr )
|
||||
{
|
||||
/* Return the length */
|
||||
*fullPathLength = GetHandleSize(*fullPath);
|
||||
result = realResult; // return realResult in case it was fnfErr
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Dispose of the handle and return NULL and zero length */
|
||||
if ( *fullPath != NULL )
|
||||
{
|
||||
DisposeHandle(*fullPath);
|
||||
}
|
||||
*fullPath = NULL;
|
||||
*fullPathLength = 0;
|
||||
}
|
||||
|
||||
return ( result );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpLocationFromFullPath(short fullPathLength,
|
||||
const void *fullPath,
|
||||
FSSpec *spec)
|
||||
{
|
||||
AliasHandle alias;
|
||||
OSErr result;
|
||||
Boolean wasChanged;
|
||||
Str32 nullString;
|
||||
|
||||
/* Create a minimal alias from the full pathname */
|
||||
nullString[0] = 0; /* null string to indicate no zone or server name */
|
||||
result = NewAliasMinimalFromFullPath(fullPathLength, fullPath, nullString, nullString, &alias);
|
||||
if ( result == noErr )
|
||||
{
|
||||
/* Let the Alias Manager resolve the alias. */
|
||||
result = ResolveAlias(NULL, alias, spec, &wasChanged);
|
||||
|
||||
/* work around Alias Mgr sloppy volume matching bug */
|
||||
if ( spec->vRefNum == 0 )
|
||||
{
|
||||
/* invalidate wrong FSSpec */
|
||||
spec->parID = 0;
|
||||
spec->name[0] = 0;
|
||||
result = nsvErr;
|
||||
}
|
||||
DisposeHandle((Handle)alias); /* Free up memory used */
|
||||
}
|
||||
return ( result );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr LocationFromFullPath(short fullPathLength,
|
||||
const void *fullPath,
|
||||
short *vRefNum,
|
||||
long *parID,
|
||||
Str31 name)
|
||||
{
|
||||
OSErr result;
|
||||
FSSpec spec;
|
||||
|
||||
result = FSpLocationFromFullPath(fullPathLength, fullPath, &spec);
|
||||
if ( result == noErr )
|
||||
{
|
||||
*vRefNum = spec.vRefNum;
|
||||
*parID = spec.parID;
|
||||
BlockMoveData(&spec.name[0], &name[0], spec.name[0] + 1);
|
||||
}
|
||||
return ( result );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@@ -1,311 +0,0 @@
|
||||
/*
|
||||
File: FullPath.h
|
||||
|
||||
Contains: Routines for dealing with full pathnames... if you really must.
|
||||
|
||||
Version: Technology: MoreFiles
|
||||
Release: 1.5.2
|
||||
|
||||
Copyright: <20> 1995-2001 by Apple Computer, Inc., all rights reserved.
|
||||
|
||||
Bugs?: For bug reports, consult the following page on
|
||||
the World Wide Web:
|
||||
|
||||
http://developer.apple.com/bugreporter/
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
You may incorporate this sample code into your applications without
|
||||
restriction, though the sample code has been provided "AS IS" and the
|
||||
responsibility for its operation is 100% yours. However, what you are
|
||||
not permitted to do is to redistribute the source as "DSC Sample Code"
|
||||
after having made changes. If you're going to re-distribute the source,
|
||||
we require that you make it clear in the source that the code was
|
||||
descended from Apple Sample Code, but that you've made changes.
|
||||
*/
|
||||
|
||||
/*
|
||||
IMPORTANT NOTE:
|
||||
|
||||
The use of full pathnames is strongly discouraged. Full pathnames are
|
||||
particularly unreliable as a means of identifying files, directories
|
||||
or volumes within your application, for two primary reasons:
|
||||
|
||||
<20> The user can change the name of any element in the path at
|
||||
virtually any time.
|
||||
<20> Volume names on the Macintosh are *not* unique. Multiple
|
||||
mounted volumes can have the same name. For this reason, the use of
|
||||
a full pathname to identify a specific volume may not produce the
|
||||
results you expect. If more than one volume has the same name and
|
||||
a full pathname is used, the File Manager currently uses the first
|
||||
mounted volume it finds with a matching name in the volume queue.
|
||||
|
||||
In general, you should use a file<6C>s name, parent directory ID, and
|
||||
volume reference number to identify a file you want to open, delete,
|
||||
or otherwise manipulate.
|
||||
|
||||
If you need to remember the location of a particular file across
|
||||
subsequent system boots, use the Alias Manager to create an alias
|
||||
record describing the file. If the Alias Manager is not available, you
|
||||
can save the file<6C>s name, its parent directory ID, and the name of the
|
||||
volume on which it<69>s located. Although none of these methods is
|
||||
foolproof, they are much more reliable than using full pathnames to
|
||||
identify files.
|
||||
|
||||
Nonetheless, it is sometimes useful to display a file<6C>s full pathname
|
||||
to the user. For example, a backup utility might display a list of full
|
||||
pathnames of files as it copies them onto the backup medium. Or, a
|
||||
utility might want to display a dialog box showing the full pathname of
|
||||
a file when it needs the user<65>s confirmation to delete the file. No
|
||||
matter how unreliable full pathnames may be from a file-specification
|
||||
viewpoint, users understand them more readily than volume reference
|
||||
numbers or directory IDs. (Hint: Use the TruncString function from
|
||||
TextUtils.h with truncMiddle as the truncWhere argument to shorten
|
||||
full pathnames to a displayable length.)
|
||||
|
||||
The following technique for constructing the full pathname of a file is
|
||||
intended for display purposes only. Applications that depend on any
|
||||
particular structure of a full pathname are likely to fail on alternate
|
||||
foreign file systems or under future system software versions.
|
||||
*/
|
||||
|
||||
#ifndef __FULLPATH__
|
||||
#define __FULLPATH__
|
||||
|
||||
#ifndef __MACTYPES__
|
||||
#include <MacTypes.h>
|
||||
#endif
|
||||
|
||||
#ifndef __FILES__
|
||||
#include <Files.h>
|
||||
#endif
|
||||
|
||||
#include "Optimization.h"
|
||||
|
||||
|
||||
#if PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if PRAGMA_IMPORT
|
||||
#pragma import on
|
||||
#endif
|
||||
|
||||
#if PRAGMA_STRUCT_ALIGN
|
||||
#pragma options align=mac68k
|
||||
#elif PRAGMA_STRUCT_PACKPUSH
|
||||
#pragma pack(push, 2)
|
||||
#elif PRAGMA_STRUCT_PACK
|
||||
#pragma pack(2)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
GetFullPath(
|
||||
short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name,
|
||||
short * fullPathLength,
|
||||
Handle * fullPath);
|
||||
|
||||
|
||||
/*
|
||||
The GetFullPath function builds a full pathname to the specified
|
||||
object. The full pathname is returned in the newly created handle
|
||||
fullPath and the length of the full pathname is returned in
|
||||
fullPathLength. Your program is responsible for disposing of the
|
||||
fullPath handle.
|
||||
|
||||
Note that a full pathname can be made to a file/directory that does not
|
||||
yet exist if all directories up to that file/directory exist. In this case,
|
||||
GetFullPath will return a fnfErr.
|
||||
|
||||
vRefNum input: Volume specification.
|
||||
dirID input: Directory ID.
|
||||
name input: Pointer to object name, or nil when dirID
|
||||
specifies a directory that's the object.
|
||||
fullPathLength output: The number of characters in the full pathname.
|
||||
If the function fails to create a full
|
||||
pathname, it sets fullPathLength to 0.
|
||||
fullPath output: A handle to the newly created full pathname
|
||||
buffer. If the function fails to create a
|
||||
full pathname, it sets fullPath to NULL.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
fnfErr -43 File or directory does not exist (fullPath
|
||||
and fullPathLength are still valid)
|
||||
paramErr -50 No default volume
|
||||
memFullErr -108 Not enough memory
|
||||
dirNFErr -120 Directory not found or incomplete pathname
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
afpObjectTypeErr -5025 Directory not found or incomplete pathname
|
||||
|
||||
__________
|
||||
|
||||
See also: FSpGetFullPath
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
FSpGetFullPath(
|
||||
const FSSpec * spec,
|
||||
short * fullPathLength,
|
||||
Handle * fullPath);
|
||||
|
||||
|
||||
/*
|
||||
The GetFullPath function builds a full pathname to the specified
|
||||
object. The full pathname is returned in the newly created handle
|
||||
fullPath and the length of the full pathname is returned in
|
||||
fullPathLength. Your program is responsible for disposing of the
|
||||
fullPath handle.
|
||||
|
||||
Note that a full pathname can be made to a file/directory that does not
|
||||
yet exist if all directories up to that file/directory exist. In this case,
|
||||
FSpGetFullPath will return a fnfErr.
|
||||
|
||||
IMPORTANT: The definition of a FSSpec is a volume reference number (not a
|
||||
drive number, working directory number, or 0), a parent directory ID (not 0),
|
||||
and the name of a file or folder (not an empty name, a full pathname, or
|
||||
a partial pathname containing one or more colon (:) characters).
|
||||
FSpGetFullPath assumes it is getting a FSSpec that matches the rules.
|
||||
If you have an FSSpec record that wasn't created by FSMakeFSSpec (or
|
||||
FSMakeFSSpecCompat from FSpCompat in MoreFiles which correctly builds
|
||||
FSSpecs), you should call GetFullPath instead of FSpGetFullPath.
|
||||
|
||||
spec input: An FSSpec record specifying the object.
|
||||
fullPathLength output: The number of characters in the full pathname.
|
||||
If the function fails to create a full pathname,
|
||||
it sets fullPathLength to 0.
|
||||
fullPath output: A handle to the newly created full pathname
|
||||
buffer. If the function fails to create a
|
||||
full pathname, it sets fullPath to NULL.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
fnfErr -43 File or directory does not exist (fullPath
|
||||
and fullPathLength are still valid)
|
||||
paramErr -50 No default volume
|
||||
memFullErr -108 Not enough memory
|
||||
dirNFErr -120 Directory not found or incomplete pathname
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
afpObjectTypeErr -5025 Directory not found or incomplete pathname
|
||||
|
||||
__________
|
||||
|
||||
See also: GetFullPath
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
FSpLocationFromFullPath(
|
||||
short fullPathLength,
|
||||
const void * fullPath,
|
||||
FSSpec * spec);
|
||||
|
||||
|
||||
/*
|
||||
The FSpLocationFromFullPath function returns a FSSpec to the object
|
||||
specified by full pathname. This function requires the Alias Manager.
|
||||
|
||||
fullPathLength input: The number of characters in the full pathname
|
||||
of the target.
|
||||
fullPath input: A pointer to a buffer that contains the full
|
||||
pathname of the target. The full pathname
|
||||
starts with the name of the volume, includes
|
||||
all of the directory names in the path to the
|
||||
target, and ends with the target name.
|
||||
spec output: An FSSpec record specifying the object.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 The volume is not mounted
|
||||
fnfErr -43 Target not found, but volume and parent
|
||||
directory found
|
||||
paramErr -50 Parameter error
|
||||
usrCanceledErr -128 The user canceled the operation
|
||||
|
||||
__________
|
||||
|
||||
See also: LocationFromFullPath
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
LocationFromFullPath(
|
||||
short fullPathLength,
|
||||
const void * fullPath,
|
||||
short * vRefNum,
|
||||
long * parID,
|
||||
Str31 name);
|
||||
|
||||
|
||||
/*
|
||||
The LocationFromFullPath function returns the volume reference number,
|
||||
parent directory ID and name of the object specified by full pathname.
|
||||
This function requires the Alias Manager.
|
||||
|
||||
fullPathLength input: The number of characters in the full pathname
|
||||
of the target.
|
||||
fullPath input: A pointer to a buffer that contains the full
|
||||
pathname of the target. The full pathname starts
|
||||
with the name of the volume, includes all of
|
||||
the directory names in the path to the target,
|
||||
and ends with the target name.
|
||||
vRefNum output: The volume reference number.
|
||||
parID output: The parent directory ID of the specified object.
|
||||
name output: The name of the specified object.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 The volume is not mounted
|
||||
fnfErr -43 Target not found, but volume and parent
|
||||
directory found
|
||||
paramErr -50 Parameter error
|
||||
usrCanceledErr -128 The user canceled the operation
|
||||
|
||||
__________
|
||||
|
||||
See also: FSpLocationFromFullPath
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "OptimizationEnd.h"
|
||||
|
||||
#if PRAGMA_STRUCT_ALIGN
|
||||
#pragma options align=reset
|
||||
#elif PRAGMA_STRUCT_PACKPUSH
|
||||
#pragma pack(pop)
|
||||
#elif PRAGMA_STRUCT_PACK
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef PRAGMA_IMPORT_OFF
|
||||
#pragma import off
|
||||
#elif PRAGMA_IMPORT
|
||||
#pragma import reset
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __FULLPATH__ */
|
||||
|
@@ -1,207 +0,0 @@
|
||||
/*
|
||||
File: IterateDirectory.c
|
||||
|
||||
Contains: File Manager directory iterator routines.
|
||||
|
||||
Version: MoreFiles
|
||||
|
||||
Copyright: <09> 1995-2001 by Jim Luther and Apple Computer, Inc., all rights reserved.
|
||||
|
||||
You may incorporate this sample code into your applications without
|
||||
restriction, though the sample code has been provided "AS IS" and the
|
||||
responsibility for its operation is 100% yours. However, what you are
|
||||
not permitted to do is to redistribute the source as "DSC Sample Code"
|
||||
after having made changes. If you're going to re-distribute the source,
|
||||
we require that you make it clear in the source that the code was
|
||||
descended from Apple Sample Code, but that you've made changes.
|
||||
|
||||
File Ownership:
|
||||
|
||||
DRI: Apple Macintosh Developer Technical Support
|
||||
|
||||
Other Contact: Apple Macintosh Developer Technical Support
|
||||
<http://developer.apple.com/bugreporter/>
|
||||
|
||||
Technology: DTS Sample Code
|
||||
|
||||
Writers:
|
||||
|
||||
(JL) Jim Luther
|
||||
|
||||
Change History (most recent first):
|
||||
|
||||
<2> 2/7/01 JL Added standard header. Updated names of includes.
|
||||
<1> 12/06/99 JL MoreFiles 1.5.
|
||||
*/
|
||||
|
||||
#include <MacTypes.h>
|
||||
#include <MacErrors.h>
|
||||
#include <Files.h>
|
||||
|
||||
#define __COMPILINGMOREFILES
|
||||
|
||||
#include "MoreFilesExtras.h"
|
||||
#include "IterateDirectory.h"
|
||||
|
||||
/*
|
||||
** Type definitions
|
||||
*/
|
||||
|
||||
/* The IterateGlobals structure is used to minimize the amount of
|
||||
** stack space used when recursively calling IterateDirectoryLevel
|
||||
** and to hold global information that might be needed at any time.
|
||||
*/
|
||||
#if PRAGMA_STRUCT_ALIGN
|
||||
#pragma options align=mac68k
|
||||
#endif
|
||||
struct IterateGlobals
|
||||
{
|
||||
IterateFilterProcPtr iterateFilter; /* pointer to IterateFilterProc */
|
||||
CInfoPBRec cPB; /* the parameter block used for PBGetCatInfo calls */
|
||||
Str63 itemName; /* the name of the current item */
|
||||
OSErr result; /* temporary holder of results - saves 2 bytes of stack each level */
|
||||
Boolean quitFlag; /* set to true if filter wants to kill interation */
|
||||
unsigned short maxLevels; /* Maximum levels to iterate through */
|
||||
unsigned short currentLevel; /* The current level IterateLevel is on */
|
||||
void *yourDataPtr; /* A pointer to caller data the filter may need to access */
|
||||
};
|
||||
#if PRAGMA_STRUCT_ALIGN
|
||||
#pragma options align=reset
|
||||
#endif
|
||||
|
||||
typedef struct IterateGlobals IterateGlobals;
|
||||
typedef IterateGlobals *IterateGlobalsPtr;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Static Prototype */
|
||||
|
||||
static void IterateDirectoryLevel(long dirID,
|
||||
IterateGlobals *theGlobals);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/*
|
||||
** Functions
|
||||
*/
|
||||
|
||||
static void IterateDirectoryLevel(long dirID,
|
||||
IterateGlobals *theGlobals)
|
||||
{
|
||||
if ( (theGlobals->maxLevels == 0) || /* if maxLevels is zero, we aren't checking levels */
|
||||
(theGlobals->currentLevel < theGlobals->maxLevels) ) /* if currentLevel < maxLevels, look at this level */
|
||||
{
|
||||
short index = 1;
|
||||
|
||||
++theGlobals->currentLevel; /* go to next level */
|
||||
|
||||
do
|
||||
{ /* Isn't C great... What I'd give for a "WITH theGlobals DO" about now... */
|
||||
|
||||
/* Get next source item at the current directory level */
|
||||
|
||||
theGlobals->cPB.dirInfo.ioFDirIndex = index;
|
||||
theGlobals->cPB.dirInfo.ioDrDirID = dirID;
|
||||
theGlobals->result = PBGetCatInfoSync((CInfoPBPtr)&theGlobals->cPB);
|
||||
|
||||
if ( theGlobals->result == noErr )
|
||||
{
|
||||
/* Call the IterateFilterProc */
|
||||
CallIterateFilterProc(theGlobals->iterateFilter, &theGlobals->cPB, &theGlobals->quitFlag, theGlobals->yourDataPtr);
|
||||
|
||||
/* Is it a directory? */
|
||||
if ( (theGlobals->cPB.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 )
|
||||
{
|
||||
/* We have a directory */
|
||||
if ( !theGlobals->quitFlag )
|
||||
{
|
||||
/* Dive again if the IterateFilterProc didn't say "quit" */
|
||||
IterateDirectoryLevel(theGlobals->cPB.dirInfo.ioDrDirID, theGlobals);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
++index; /* prepare to get next item */
|
||||
} while ( (theGlobals->result == noErr) && (!theGlobals->quitFlag) ); /* time to fall back a level? */
|
||||
|
||||
if ( (theGlobals->result == fnfErr) || /* fnfErr is OK - it only means we hit the end of this level */
|
||||
(theGlobals->result == afpAccessDenied) ) /* afpAccessDenied is OK, too - it only means we cannot see inside a directory */
|
||||
{
|
||||
theGlobals->result = noErr;
|
||||
}
|
||||
|
||||
--theGlobals->currentLevel; /* return to previous level as we leave */
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr IterateDirectory(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name,
|
||||
unsigned short maxLevels,
|
||||
IterateFilterProcPtr iterateFilter,
|
||||
void *yourDataPtr)
|
||||
{
|
||||
IterateGlobals theGlobals;
|
||||
OSErr result;
|
||||
long theDirID;
|
||||
short theVRefNum;
|
||||
Boolean isDirectory;
|
||||
|
||||
/* Make sure there is a IterateFilter */
|
||||
if ( iterateFilter != NULL )
|
||||
{
|
||||
/* Get the real directory ID and make sure it is a directory */
|
||||
result = GetDirectoryID(vRefNum, dirID, name, &theDirID, &isDirectory);
|
||||
if ( result == noErr )
|
||||
{
|
||||
if ( isDirectory == true )
|
||||
{
|
||||
/* Get the real vRefNum */
|
||||
result = DetermineVRefNum(name, vRefNum, &theVRefNum);
|
||||
if ( result == noErr )
|
||||
{
|
||||
/* Set up the globals we need to access from the recursive routine. */
|
||||
theGlobals.iterateFilter = iterateFilter;
|
||||
theGlobals.cPB.hFileInfo.ioNamePtr = (StringPtr)&theGlobals.itemName;
|
||||
theGlobals.cPB.hFileInfo.ioVRefNum = theVRefNum;
|
||||
theGlobals.itemName[0] = 0;
|
||||
theGlobals.result = noErr;
|
||||
theGlobals.quitFlag = false;
|
||||
theGlobals.maxLevels = maxLevels;
|
||||
theGlobals.currentLevel = 0; /* start at level 0 */
|
||||
theGlobals.yourDataPtr = yourDataPtr;
|
||||
|
||||
/* Here we go into recursion land... */
|
||||
IterateDirectoryLevel(theDirID, &theGlobals);
|
||||
|
||||
result = theGlobals.result; /* set the result */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = dirNFErr; /* a file was passed instead of a directory */
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = paramErr; /* iterateFilter was NULL */
|
||||
}
|
||||
|
||||
return ( result );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpIterateDirectory(const FSSpec *spec,
|
||||
unsigned short maxLevels,
|
||||
IterateFilterProcPtr iterateFilter,
|
||||
void *yourDataPtr)
|
||||
{
|
||||
return ( IterateDirectory(spec->vRefNum, spec->parID, spec->name,
|
||||
maxLevels, iterateFilter, yourDataPtr) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
@@ -1,222 +0,0 @@
|
||||
/*
|
||||
File: IterateDirectory.h
|
||||
|
||||
Contains: File Manager directory iterator routines.
|
||||
|
||||
Version: Technology: MoreFiles
|
||||
Release: 1.5.2
|
||||
|
||||
Copyright: <20> 1995-2001 by Jim Luther and Apple Computer, Inc., all rights reserved.
|
||||
|
||||
Bugs?: For bug reports, consult the following page on
|
||||
the World Wide Web:
|
||||
|
||||
http://developer.apple.com/bugreporter/
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
You may incorporate this sample code into your applications without
|
||||
restriction, though the sample code has been provided "AS IS" and the
|
||||
responsibility for its operation is 100% yours. However, what you are
|
||||
not permitted to do is to redistribute the source as "DSC Sample Code"
|
||||
after having made changes. If you're going to re-distribute the source,
|
||||
we require that you make it clear in the source that the code was
|
||||
descended from Apple Sample Code, but that you've made changes.
|
||||
*/
|
||||
|
||||
#ifndef __ITERATEDIRECTORY__
|
||||
#define __ITERATEDIRECTORY__
|
||||
|
||||
#ifndef __MACTYPES__
|
||||
#include <MacTypes.h>
|
||||
#endif
|
||||
|
||||
#ifndef __FILES__
|
||||
#include <Files.h>
|
||||
#endif
|
||||
|
||||
#include "Optimization.h"
|
||||
|
||||
|
||||
#if PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if PRAGMA_IMPORT
|
||||
#pragma import on
|
||||
#endif
|
||||
|
||||
#if PRAGMA_STRUCT_ALIGN
|
||||
#pragma options align=mac68k
|
||||
#elif PRAGMA_STRUCT_PACKPUSH
|
||||
#pragma pack(push, 2)
|
||||
#elif PRAGMA_STRUCT_PACK
|
||||
#pragma pack(2)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef CALLBACK_API( void , IterateFilterProcPtr )(const CInfoPBRec *cpbPtr, Boolean *quitFlag, void *yourDataPtr);
|
||||
/*
|
||||
This is the prototype for the IterateFilterProc function which is
|
||||
called once for each file and directory found by IterateDirectory. The
|
||||
IterateFilterProc gets a pointer to the CInfoPBRec that IterateDirectory
|
||||
used to call PBGetCatInfo. The IterateFilterProc can use the read-only
|
||||
data in the CInfoPBRec for whatever it wants.
|
||||
|
||||
If the IterateFilterProc wants to stop IterateDirectory, it can set
|
||||
quitFlag to true (quitFlag will be passed to the IterateFilterProc
|
||||
false).
|
||||
|
||||
The yourDataPtr parameter can point to whatever data structure you might
|
||||
want to access from within the IterateFilterProc.
|
||||
|
||||
cpbPtr input: A pointer to the CInfoPBRec that IterateDirectory
|
||||
used to call PBGetCatInfo. The CInfoPBRec and the
|
||||
data it points to must not be changed by your
|
||||
IterateFilterProc.
|
||||
quitFlag output: Your IterateFilterProc can set quitFlag to true
|
||||
if it wants to stop IterateDirectory.
|
||||
yourDataPtr input: A pointer to whatever data structure you might
|
||||
want to access from within the IterateFilterProc.
|
||||
|
||||
__________
|
||||
|
||||
Also see: IterateDirectory, FSpIterateDirectory
|
||||
*/
|
||||
#define CallIterateFilterProc(userRoutine, cpbPtr, quitFlag, yourDataPtr) \
|
||||
(*(userRoutine))((cpbPtr), (quitFlag), (yourDataPtr))
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
IterateDirectory(
|
||||
short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name,
|
||||
unsigned short maxLevels,
|
||||
IterateFilterProcPtr iterateFilter,
|
||||
void * yourDataPtr);
|
||||
|
||||
|
||||
/*
|
||||
The IterateDirectory function performs a recursive iteration (scan) of
|
||||
the specified directory and calls your IterateFilterProc function once
|
||||
for each file and directory found.
|
||||
|
||||
The maxLevels parameter lets you control how deep the recursion goes.
|
||||
If maxLevels is 1, IterateDirectory only scans the specified directory;
|
||||
if maxLevels is 2, IterateDirectory scans the specified directory and
|
||||
one subdirectory below the specified directory; etc. Set maxLevels to
|
||||
zero to scan all levels.
|
||||
|
||||
The yourDataPtr parameter can point to whatever data structure you might
|
||||
want to access from within the IterateFilterProc.
|
||||
|
||||
vRefNum input: Volume specification.
|
||||
dirID input: Directory ID.
|
||||
name input: Pointer to object name, or nil when dirID
|
||||
specifies a directory that's the object.
|
||||
maxLevels input: Maximum number of directory levels to scan or
|
||||
zero to scan all directory levels.
|
||||
iterateFilter input: A pointer to the routine you want called once
|
||||
for each file and directory found by
|
||||
IterateDirectory.
|
||||
yourDataPtr input: A pointer to whatever data structure you might
|
||||
want to access from within the IterateFilterProc.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
fnfErr -43 File not found
|
||||
paramErr -50 No default volume or iterateFilter was NULL
|
||||
dirNFErr -120 Directory not found or incomplete pathname
|
||||
or a file was passed instead of a directory
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
afpObjectTypeErr -5025 Directory not found or incomplete pathname
|
||||
|
||||
__________
|
||||
|
||||
See also: IterateFilterProcPtr, FSpIterateDirectory
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
FSpIterateDirectory(
|
||||
const FSSpec * spec,
|
||||
unsigned short maxLevels,
|
||||
IterateFilterProcPtr iterateFilter,
|
||||
void * yourDataPtr);
|
||||
|
||||
|
||||
/*
|
||||
The FSpIterateDirectory function performs a recursive iteration (scan)
|
||||
of the specified directory and calls your IterateFilterProc function once
|
||||
for each file and directory found.
|
||||
|
||||
The maxLevels parameter lets you control how deep the recursion goes.
|
||||
If maxLevels is 1, FSpIterateDirectory only scans the specified directory;
|
||||
if maxLevels is 2, FSpIterateDirectory scans the specified directory and
|
||||
one subdirectory below the specified directory; etc. Set maxLevels to
|
||||
zero to scan all levels.
|
||||
|
||||
The yourDataPtr parameter can point to whatever data structure you might
|
||||
want to access from within the IterateFilterProc.
|
||||
|
||||
spec input: An FSSpec record specifying the directory to scan.
|
||||
maxLevels input: Maximum number of directory levels to scan or
|
||||
zero to scan all directory levels.
|
||||
iterateFilter input: A pointer to the routine you want called once
|
||||
for each file and directory found by
|
||||
FSpIterateDirectory.
|
||||
yourDataPtr input: A pointer to whatever data structure you might
|
||||
want to access from within the IterateFilterProc.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 No such volume
|
||||
ioErr -36 I/O error
|
||||
bdNamErr -37 Bad filename
|
||||
fnfErr -43 File not found
|
||||
paramErr -50 No default volume or iterateFilter was NULL
|
||||
dirNFErr -120 Directory not found or incomplete pathname
|
||||
afpAccessDenied -5000 User does not have the correct access
|
||||
afpObjectTypeErr -5025 Directory not found or incomplete pathname
|
||||
|
||||
__________
|
||||
|
||||
See also: IterateFilterProcPtr, IterateDirectory
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "OptimizationEnd.h"
|
||||
|
||||
#if PRAGMA_STRUCT_ALIGN
|
||||
#pragma options align=reset
|
||||
#elif PRAGMA_STRUCT_PACKPUSH
|
||||
#pragma pack(pop)
|
||||
#elif PRAGMA_STRUCT_PACK
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef PRAGMA_IMPORT_OFF
|
||||
#pragma import off
|
||||
#elif PRAGMA_IMPORT
|
||||
#pragma import reset
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ITERATEDIRECTORY__ */
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,628 +0,0 @@
|
||||
/*
|
||||
File: MoreDesktopMgr.h
|
||||
|
||||
Contains: A collection of useful high-level Desktop Manager routines. If the Desktop Manager is not available, use the Desktop file for 'read' operations.
|
||||
|
||||
Version: Technology: MoreFiles
|
||||
Release: 1.5.2
|
||||
|
||||
Copyright: <20> 1992-2001 by Apple Computer, Inc., all rights reserved.
|
||||
|
||||
Bugs?: For bug reports, consult the following page on
|
||||
the World Wide Web:
|
||||
|
||||
http://developer.apple.com/bugreporter/
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
You may incorporate this sample code into your applications without
|
||||
restriction, though the sample code has been provided "AS IS" and the
|
||||
responsibility for its operation is 100% yours. However, what you are
|
||||
not permitted to do is to redistribute the source as "DSC Sample Code"
|
||||
after having made changes. If you're going to re-distribute the source,
|
||||
we require that you make it clear in the source that the code was
|
||||
descended from Apple Sample Code, but that you've made changes.
|
||||
*/
|
||||
|
||||
#ifndef __MOREDESKTOPMGR__
|
||||
#define __MOREDESKTOPMGR__
|
||||
|
||||
#ifndef __MACTYPES__
|
||||
#include <MacTypes.h>
|
||||
#endif
|
||||
|
||||
#ifndef __FILES__
|
||||
#include <Files.h>
|
||||
#endif
|
||||
|
||||
#include "Optimization.h"
|
||||
|
||||
|
||||
#if PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if PRAGMA_IMPORT
|
||||
#pragma import on
|
||||
#endif
|
||||
|
||||
#if PRAGMA_STRUCT_ALIGN
|
||||
#pragma options align=mac68k
|
||||
#elif PRAGMA_STRUCT_PACKPUSH
|
||||
#pragma pack(push, 2)
|
||||
#elif PRAGMA_STRUCT_PACK
|
||||
#pragma pack(2)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
DTOpen(
|
||||
ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
short * dtRefNum,
|
||||
Boolean * newDTDatabase);
|
||||
|
||||
|
||||
/*
|
||||
The DTOpen function opens a volume's desktop database. It returns
|
||||
the reference number of the desktop database and indicates if the
|
||||
desktop database was created as a result of this call (if it was created,
|
||||
then it is empty).
|
||||
|
||||
volName input: A pointer to the name of a mounted volume
|
||||
or nil.
|
||||
vRefNum input: Volume specification.
|
||||
dtRefNum output: The reference number of Desktop Manager's
|
||||
desktop database on the specified volume.
|
||||
newDTDatabase output: true if the desktop database was created as a
|
||||
result of this call and thus empty.
|
||||
false if the desktop database was already created,
|
||||
or if it could not be determined if it was already
|
||||
created.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
paramErr -50 Volume doesn't support this function
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call.
|
||||
desktopDamagedErr -1305 The desktop database has become corrupted -
|
||||
the Finder will fix this, but if your
|
||||
application is not running with the
|
||||
Finder, use PBDTReset or PBDTDelete
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
DTXGetAPPL(
|
||||
ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
OSType creator,
|
||||
Boolean searchCatalog,
|
||||
short * applVRefNum,
|
||||
long * applParID,
|
||||
Str255 applName);
|
||||
|
||||
|
||||
/*
|
||||
The DTXGetAPPL function finds an application (file type 'APPL') with
|
||||
the specified creator on the specified volume. It first tries to get
|
||||
the application mapping from the desktop database. If that fails,
|
||||
then it tries to find an application in the Desktop file. If that
|
||||
fails and searchCatalog is true, then it tries to find an application
|
||||
with the specified creator using the File Manager's CatSearch routine.
|
||||
|
||||
volName input: A pointer to the name of a mounted volume
|
||||
or nil.
|
||||
vRefNum input: Volume specification.
|
||||
creator input: The file's creator type.
|
||||
searchCatalog input: If true, search the catalog for the application
|
||||
if it isn't found in the desktop database.
|
||||
applVRefNum output: The volume reference number of the volume the
|
||||
application is on.
|
||||
applParID output: The parent directory ID of the application.
|
||||
applName output: The name of the application.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
paramErr -50 No default volume
|
||||
rfNumErr -51 Reference number invalid
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call
|
||||
desktopDamagedErr -1305 The desktop database has become corrupted -
|
||||
the Finder will fix this, but if your
|
||||
application is not running with the
|
||||
Finder, use PBDTReset or PBDTDelete
|
||||
afpItemNotFound -5012 Information not found
|
||||
|
||||
__________
|
||||
|
||||
Also see: FSpDTGetAPPL
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
FSpDTXGetAPPL(
|
||||
ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
OSType creator,
|
||||
Boolean searchCatalog,
|
||||
FSSpec * spec);
|
||||
|
||||
|
||||
/*
|
||||
The FSpDTXGetAPPL function finds an application (file type 'APPL') with
|
||||
the specified creator on the specified volume. It first tries to get
|
||||
the application mapping from the desktop database. If that fails,
|
||||
then it tries to find an application in the Desktop file. If that
|
||||
fails and searchCatalog is true, then it tries to find an application
|
||||
with the specified creator using the File Manager's CatSearch routine.
|
||||
|
||||
volName input: A pointer to the name of a mounted volume
|
||||
or nil.
|
||||
vRefNum input: Volume specification.
|
||||
creator input: The file's creator type.
|
||||
searchCatalog input: If true, search the catalog for the application
|
||||
if it isn't found in the desktop database.
|
||||
spec output: FSSpec record containing the application name and
|
||||
location.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
paramErr -50 No default volume
|
||||
rfNumErr -51 Reference number invalid
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call
|
||||
desktopDamagedErr -1305 The desktop database has become corrupted -
|
||||
the Finder will fix this, but if your
|
||||
application is not running with the
|
||||
Finder, use PBDTReset or PBDTDelete
|
||||
afpItemNotFound -5012 Information not found
|
||||
|
||||
__________
|
||||
|
||||
Also see: FSpDTGetAPPL
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
DTGetAPPL(
|
||||
ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
OSType creator,
|
||||
short * applVRefNum,
|
||||
long * applParID,
|
||||
Str255 applName);
|
||||
|
||||
|
||||
/*
|
||||
The DTGetAPPL function finds an application (file type 'APPL') with
|
||||
the specified creator on the specified volume. It first tries to get
|
||||
the application mapping from the desktop database. If that fails,
|
||||
then it tries to find an application in the Desktop file. If that
|
||||
fails, then it tries to find an application with the specified creator
|
||||
using the File Manager's CatSearch routine.
|
||||
|
||||
volName input: A pointer to the name of a mounted volume
|
||||
or nil.
|
||||
vRefNum input: Volume specification.
|
||||
creator input: The file's creator type.
|
||||
applVRefNum output: The volume reference number of the volume the
|
||||
application is on.
|
||||
applParID output: The parent directory ID of the application.
|
||||
applName output: The name of the application.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
paramErr -50 No default volume
|
||||
rfNumErr -51 Reference number invalid
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call
|
||||
desktopDamagedErr -1305 The desktop database has become corrupted -
|
||||
the Finder will fix this, but if your
|
||||
application is not running with the
|
||||
Finder, use PBDTReset or PBDTDelete
|
||||
afpItemNotFound -5012 Information not found
|
||||
|
||||
__________
|
||||
|
||||
Also see: FSpDTGetAPPL
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
FSpDTGetAPPL(
|
||||
ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
OSType creator,
|
||||
FSSpec * spec);
|
||||
|
||||
|
||||
/*
|
||||
The FSpDTGetAPPL function finds an application (file type 'APPL') with
|
||||
the specified creator on the specified volume. It first tries to get
|
||||
the application mapping from the desktop database. If that fails,
|
||||
then it tries to find an application in the Desktop file. If that
|
||||
fails, then it tries to find an application with the specified creator
|
||||
using the File Manager's CatSearch routine.
|
||||
|
||||
volName input: A pointer to the name of a mounted volume
|
||||
or nil.
|
||||
vRefNum input: Volume specification.
|
||||
creator input: The file's creator type.
|
||||
spec output: FSSpec record containing the application name and
|
||||
location.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
paramErr -50 No default volume
|
||||
rfNumErr -51 Reference number invalid
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call
|
||||
desktopDamagedErr -1305 The desktop database has become corrupted -
|
||||
the Finder will fix this, but if your
|
||||
application is not running with the
|
||||
Finder, use PBDTReset or PBDTDelete
|
||||
afpItemNotFound -5012 Information not found
|
||||
|
||||
__________
|
||||
|
||||
Also see: DTGetAPPL
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
DTGetIcon(
|
||||
ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
short iconType,
|
||||
OSType fileCreator,
|
||||
OSType fileType,
|
||||
Handle * iconHandle);
|
||||
|
||||
|
||||
/*
|
||||
The DTGetIcon function retrieves the specified icon and returns it in
|
||||
a newly created handle. The icon is retrieves from the Desktop Manager
|
||||
or if the Desktop Manager is not available, from the Finder's Desktop
|
||||
file. Your program is responsible for disposing of the handle when it is
|
||||
done using the icon.
|
||||
|
||||
volName input: A pointer to the name of a mounted volume
|
||||
or nil.
|
||||
vRefNum input: Volume specification.
|
||||
iconType input: The icon type as defined in Files.h. Valid values are:
|
||||
kLargeIcon
|
||||
kLarge4BitIcon
|
||||
kLarge8BitIcon
|
||||
kSmallIcon
|
||||
kSmall4BitIcon
|
||||
kSmall8BitIcon
|
||||
fileCreator input: The icon's creator type.
|
||||
fileType input: The icon's file type.
|
||||
iconHandle output: A Handle containing the newly created icon.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
paramErr -50 Volume doesn't support this function
|
||||
rfNumErr -51 Reference number invalid
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call
|
||||
memFullErr -108 iconHandle could not be allocated
|
||||
desktopDamagedErr -1305 The desktop database has become corrupted -
|
||||
the Finder will fix this, but if your
|
||||
application is not running with the
|
||||
Finder, use PBDTReset or PBDTDelete
|
||||
afpItemNotFound -5012 Information not found
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
DTSetComment(
|
||||
short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name,
|
||||
ConstStr255Param comment);
|
||||
|
||||
|
||||
/*
|
||||
The DTSetComment function sets a file or directory's Finder comment
|
||||
field. The volume must support the Desktop Manager because you only
|
||||
have read access to the Desktop file.
|
||||
|
||||
vRefNum input: Volume specification.
|
||||
dirID input: Directory ID.
|
||||
name input: Pointer to object name, or nil when dirID
|
||||
specifies a directory that's the object.
|
||||
comment input: The comment to add. Comments are limited to 200 characters;
|
||||
longer comments are truncated.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
fnfErr <20>43 File or directory doesn<73>t exist
|
||||
paramErr -50 Volume doesn't support this function
|
||||
wPrErr <20>44 Volume is locked through hardware
|
||||
vLckdErr <20>46 Volume is locked through software
|
||||
rfNumErr <20>51 Reference number invalid
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call.
|
||||
desktopDamagedErr -1305 The desktop database has become corrupted -
|
||||
the Finder will fix this, but if your
|
||||
application is not running with the
|
||||
Finder, use PBDTReset or PBDTDelete
|
||||
|
||||
__________
|
||||
|
||||
Also see: DTCopyComment, FSpDTCopyComment, FSpDTSetComment, DTGetComment,
|
||||
FSpDTGetComment
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
FSpDTSetComment(
|
||||
const FSSpec * spec,
|
||||
ConstStr255Param comment);
|
||||
|
||||
|
||||
/*
|
||||
The FSpDTSetComment function sets a file or directory's Finder comment
|
||||
field. The volume must support the Desktop Manager because you only
|
||||
have read access to the Desktop file.
|
||||
|
||||
spec input: An FSSpec record specifying the file or directory.
|
||||
comment input: The comment to add. Comments are limited to 200 characters;
|
||||
longer comments are truncated.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
fnfErr <20>43 File or directory doesn<73>t exist
|
||||
wPrErr <20>44 Volume is locked through hardware
|
||||
vLckdErr <20>46 Volume is locked through software
|
||||
rfNumErr <20>51 Reference number invalid
|
||||
paramErr -50 Volume doesn't support this function
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call.
|
||||
desktopDamagedErr -1305 The desktop database has become corrupted -
|
||||
the Finder will fix this, but if your
|
||||
application is not running with the
|
||||
Finder, use PBDTReset or PBDTDelete
|
||||
|
||||
__________
|
||||
|
||||
Also see: DTCopyComment, FSpDTCopyComment, DTSetComment, DTGetComment,
|
||||
FSpDTGetComment
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
DTGetComment(
|
||||
short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name,
|
||||
Str255 comment);
|
||||
|
||||
|
||||
/*
|
||||
The DTGetComment function gets a file or directory's Finder comment
|
||||
field (if any) from the Desktop Manager or if the Desktop Manager is
|
||||
not available, from the Finder's Desktop file.
|
||||
|
||||
IMPORTANT NOTE: Inside Macintosh says that comments are up to
|
||||
200 characters. While that may be correct for the HFS file system's
|
||||
Desktop Manager, other file systems (such as Apple Photo Access) return
|
||||
up to 255 characters. Make sure the comment buffer is a Str255 or you'll
|
||||
regret it.
|
||||
|
||||
vRefNum input: Volume specification.
|
||||
dirID input: Directory ID.
|
||||
name input: Pointer to object name, or nil when dirID
|
||||
specifies a directory that's the object.
|
||||
comment output: A Str255 where the comment is to be returned.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
fnfErr -43 File not found
|
||||
paramErr -50 Volume doesn't support this function
|
||||
rfNumErr <20>51 Reference number invalid
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call.
|
||||
desktopDamagedErr -1305 The desktop database has become corrupted -
|
||||
the Finder will fix this, but if your
|
||||
application is not running with the
|
||||
Finder, use PBDTReset or PBDTDelete
|
||||
afpItemNotFound -5012 Information not found
|
||||
|
||||
__________
|
||||
|
||||
Also see: DTCopyComment, FSpDTCopyComment, DTSetComment, FSpDTSetComment,
|
||||
FSpDTGetComment
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
FSpDTGetComment(
|
||||
const FSSpec * spec,
|
||||
Str255 comment);
|
||||
|
||||
|
||||
/*
|
||||
The FSpDTGetComment function gets a file or directory's Finder comment
|
||||
field (if any) from the Desktop Manager or if the Desktop Manager is
|
||||
not available, from the Finder's Desktop file.
|
||||
|
||||
IMPORTANT NOTE: Inside Macintosh says that comments are up to
|
||||
200 characters. While that may be correct for the HFS file system's
|
||||
Desktop Manager, other file systems (such as Apple Photo Access) return
|
||||
up to 255 characters. Make sure the comment buffer is a Str255 or you'll
|
||||
regret it.
|
||||
|
||||
spec input: An FSSpec record specifying the file or directory.
|
||||
comment output: A Str255 where the comment is to be returned.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
fnfErr -43 File not found
|
||||
paramErr -50 Volume doesn't support this function
|
||||
rfNumErr <20>51 Reference number invalid
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call.
|
||||
desktopDamagedErr -1305 The desktop database has become corrupted -
|
||||
the Finder will fix this, but if your
|
||||
application is not running with the
|
||||
Finder, use PBDTReset or PBDTDelete
|
||||
afpItemNotFound -5012 Information not found
|
||||
|
||||
__________
|
||||
|
||||
Also see: DTCopyComment, FSpDTCopyComment, DTSetComment, FSpDTSetComment,
|
||||
DTGetComment
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
DTCopyComment(
|
||||
short srcVRefNum,
|
||||
long srcDirID,
|
||||
ConstStr255Param srcName,
|
||||
short dstVRefNum,
|
||||
long dstDirID,
|
||||
ConstStr255Param dstName);
|
||||
|
||||
|
||||
/*
|
||||
The DTCopyComment function copies the file or folder comment from the
|
||||
source to the destination object. The destination volume must support
|
||||
the Desktop Manager because you only have read access to the Desktop file.
|
||||
|
||||
srcVRefNum input: Source volume specification.
|
||||
srcDirID input: Source directory ID.
|
||||
srcName input: Pointer to source object name, or nil when srcDirID
|
||||
specifies a directory that's the object.
|
||||
dstVRefNum input: Destination volume specification.
|
||||
dstDirID input: Destination directory ID.
|
||||
dstName input: Pointer to destination object name, or nil when
|
||||
dstDirID specifies a directory that's the object.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
fnfErr <20>43 File or directory doesn<73>t exist
|
||||
wPrErr <20>44 Volume is locked through hardware
|
||||
vLckdErr <20>46 Volume is locked through software
|
||||
paramErr -50 Volume doesn't support this function
|
||||
rfNumErr <20>51 Reference number invalid
|
||||
paramErr -50 Volume doesn't support this function
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call.
|
||||
desktopDamagedErr -1305 The desktop database has become corrupted -
|
||||
the Finder will fix this, but if your
|
||||
application is not running with the
|
||||
Finder, use PBDTReset or PBDTDelete
|
||||
afpItemNotFound -5012 Information not found
|
||||
|
||||
__________
|
||||
|
||||
Also see: FSpDTCopyComment, DTSetComment, FSpDTSetComment, DTGetComment,
|
||||
FSpDTGetComment
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
FSpDTCopyComment(
|
||||
const FSSpec * srcSpec,
|
||||
const FSSpec * dstSpec);
|
||||
|
||||
|
||||
/*
|
||||
The FSpDTCopyComment function copies the desktop database comment from
|
||||
the source to the destination object. Both the source and the
|
||||
destination volumes must support the Desktop Manager.
|
||||
|
||||
srcSpec input: An FSSpec record specifying the source object.
|
||||
dstSpec input: An FSSpec record specifying the destination object.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
fnfErr <20>43 File or directory doesn<73>t exist
|
||||
wPrErr <20>44 Volume is locked through hardware
|
||||
vLckdErr <20>46 Volume is locked through software
|
||||
paramErr -50 Volume doesn't support this function
|
||||
rfNumErr <20>51 Reference number invalid
|
||||
paramErr -50 Volume doesn't support this function
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call.
|
||||
desktopDamagedErr -1305 The desktop database has become corrupted -
|
||||
the Finder will fix this, but if your
|
||||
application is not running with the
|
||||
Finder, use PBDTReset or PBDTDelete
|
||||
afpItemNotFound -5012 Information not found
|
||||
|
||||
__________
|
||||
|
||||
Also see: DTCopyComment, DTSetComment, FSpDTSetComment, DTGetComment,
|
||||
FSpDTGetComment
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "OptimizationEnd.h"
|
||||
|
||||
#if PRAGMA_STRUCT_ALIGN
|
||||
#pragma options align=reset
|
||||
#elif PRAGMA_STRUCT_PACKPUSH
|
||||
#pragma pack(pop)
|
||||
#elif PRAGMA_STRUCT_PACK
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef PRAGMA_IMPORT_OFF
|
||||
#pragma import off
|
||||
#elif PRAGMA_IMPORT
|
||||
#pragma import reset
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __MOREDESKTOPMGR__ */
|
||||
|
@@ -1,643 +0,0 @@
|
||||
/*
|
||||
File: MoreFiles.c
|
||||
|
||||
Contains: The long lost high-level and FSSpec File Manager functions.
|
||||
|
||||
Version: MoreFiles
|
||||
|
||||
Copyright: <09> 1992-2001 by Apple Computer, Inc., all rights reserved.
|
||||
|
||||
You may incorporate this sample code into your applications without
|
||||
restriction, though the sample code has been provided "AS IS" and the
|
||||
responsibility for its operation is 100% yours. However, what you are
|
||||
not permitted to do is to redistribute the source as "DSC Sample Code"
|
||||
after having made changes. If you're going to re-distribute the source,
|
||||
we require that you make it clear in the source that the code was
|
||||
descended from Apple Sample Code, but that you've made changes.
|
||||
|
||||
File Ownership:
|
||||
|
||||
DRI: Apple Macintosh Developer Technical Support
|
||||
|
||||
Other Contact: Apple Macintosh Developer Technical Support
|
||||
<http://developer.apple.com/bugreporter/>
|
||||
|
||||
Technology: DTS Sample Code
|
||||
|
||||
Writers:
|
||||
|
||||
(JL) Jim Luther
|
||||
|
||||
Change History (most recent first):
|
||||
|
||||
<2> 2/7/01 JL Added standard header. Updated names of includes.
|
||||
<1> 12/06/99 JL MoreFiles 1.5.
|
||||
*/
|
||||
|
||||
#include <MacTypes.h>
|
||||
#include <MacErrors.h>
|
||||
#include <Files.h>
|
||||
|
||||
#define __COMPILINGMOREFILES
|
||||
|
||||
#include "MoreFiles.h"
|
||||
#include "MoreFilesExtras.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr HGetVolParms(ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
GetVolParmsInfoBuffer *volParmsInfo,
|
||||
long *infoSize)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
OSErr error;
|
||||
|
||||
pb.ioParam.ioNamePtr = (StringPtr)volName;
|
||||
pb.ioParam.ioVRefNum = vRefNum;
|
||||
pb.ioParam.ioBuffer = (Ptr)volParmsInfo;
|
||||
pb.ioParam.ioReqCount = *infoSize;
|
||||
error = PBHGetVolParmsSync(&pb);
|
||||
if ( error == noErr )
|
||||
{
|
||||
*infoSize = pb.ioParam.ioActCount;
|
||||
}
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr HCreateMinimum(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param fileName)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.fileParam.ioNamePtr = (StringPtr)fileName;
|
||||
pb.fileParam.ioVRefNum = vRefNum;
|
||||
pb.ioParam.ioVersNum = 0;
|
||||
pb.fileParam.ioDirID = dirID;
|
||||
return ( PBHCreateSync(&pb) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpCreateMinimum(const FSSpec *spec)
|
||||
{
|
||||
return ( HCreateMinimum(spec->vRefNum, spec->parID, spec->name) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr ExchangeFiles(short vRefNum,
|
||||
long srcDirID,
|
||||
ConstStr255Param srcName,
|
||||
long dstDirID,
|
||||
ConstStr255Param dstName)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.fidParam.ioVRefNum = vRefNum;
|
||||
pb.fidParam.ioSrcDirID = srcDirID;
|
||||
pb.fidParam.ioNamePtr = (StringPtr)srcName;
|
||||
pb.fidParam.ioDestDirID = dstDirID;
|
||||
pb.fidParam.ioDestNamePtr = (StringPtr)dstName;
|
||||
return ( PBExchangeFilesSync(&pb) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr ResolveFileIDRef(ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
long fileID,
|
||||
long *parID,
|
||||
StringPtr fileName)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
OSErr error;
|
||||
Str255 tempStr;
|
||||
|
||||
tempStr[0] = 0;
|
||||
if ( volName != NULL )
|
||||
{
|
||||
BlockMoveData(volName, tempStr, volName[0] + 1);
|
||||
}
|
||||
pb.fidParam.ioNamePtr = (StringPtr)tempStr;
|
||||
pb.fidParam.ioVRefNum = vRefNum;
|
||||
pb.fidParam.ioFileID = fileID;
|
||||
error = PBResolveFileIDRefSync(&pb);
|
||||
if ( error == noErr )
|
||||
{
|
||||
*parID = pb.fidParam.ioSrcDirID;
|
||||
if ( fileName != NULL )
|
||||
{
|
||||
BlockMoveData(tempStr, fileName, tempStr[0] + 1);
|
||||
}
|
||||
}
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpResolveFileIDRef(ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
long fileID,
|
||||
FSSpec *spec)
|
||||
{
|
||||
OSErr error;
|
||||
|
||||
error = DetermineVRefNum(volName, vRefNum, &(spec->vRefNum));
|
||||
if ( error == noErr )
|
||||
{
|
||||
error = ResolveFileIDRef(volName, vRefNum, fileID, &(spec->parID), spec->name);
|
||||
}
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr CreateFileIDRef(short vRefNum,
|
||||
long parID,
|
||||
ConstStr255Param fileName,
|
||||
long *fileID)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
OSErr error;
|
||||
|
||||
pb.fidParam.ioNamePtr = (StringPtr)fileName;
|
||||
pb.fidParam.ioVRefNum = vRefNum;
|
||||
pb.fidParam.ioSrcDirID = parID;
|
||||
error = PBCreateFileIDRefSync(&pb);
|
||||
if ( (error == noErr) || (error == fidExists) || (error == afpIDExists) )
|
||||
{
|
||||
*fileID = pb.fidParam.ioFileID;
|
||||
}
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpCreateFileIDRef(const FSSpec *spec,
|
||||
long *fileID)
|
||||
{
|
||||
return ( CreateFileIDRef(spec->vRefNum, spec->parID, spec->name, fileID) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr DeleteFileIDRef(ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
long fileID)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.fidParam.ioNamePtr = (StringPtr)volName;
|
||||
pb.fidParam.ioVRefNum = vRefNum;
|
||||
pb.fidParam.ioFileID = fileID;
|
||||
return ( PBDeleteFileIDRefSync(&pb) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FlushFile(short refNum)
|
||||
{
|
||||
ParamBlockRec pb;
|
||||
|
||||
pb.ioParam.ioRefNum = refNum;
|
||||
return ( PBFlushFileSync(&pb) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr LockRange(short refNum,
|
||||
long rangeLength,
|
||||
long rangeStart)
|
||||
{
|
||||
ParamBlockRec pb;
|
||||
|
||||
pb.ioParam.ioRefNum = refNum;
|
||||
pb.ioParam.ioReqCount = rangeLength;
|
||||
pb.ioParam.ioPosMode = fsFromStart;
|
||||
pb.ioParam.ioPosOffset = rangeStart;
|
||||
return ( PBLockRangeSync(&pb) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr UnlockRange(short refNum,
|
||||
long rangeLength,
|
||||
long rangeStart)
|
||||
{
|
||||
ParamBlockRec pb;
|
||||
|
||||
pb.ioParam.ioRefNum = refNum;
|
||||
pb.ioParam.ioReqCount = rangeLength;
|
||||
pb.ioParam.ioPosMode = fsFromStart;
|
||||
pb.ioParam.ioPosOffset = rangeStart;
|
||||
return ( PBUnlockRangeSync(&pb) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr GetForeignPrivs(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name,
|
||||
void *foreignPrivBuffer,
|
||||
long *foreignPrivSize,
|
||||
long *foreignPrivInfo1,
|
||||
long *foreignPrivInfo2,
|
||||
long *foreignPrivInfo3,
|
||||
long *foreignPrivInfo4)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
OSErr error;
|
||||
|
||||
pb.foreignPrivParam.ioNamePtr = (StringPtr)name;
|
||||
pb.foreignPrivParam.ioVRefNum = vRefNum;
|
||||
pb.foreignPrivParam.ioForeignPrivDirID = dirID;
|
||||
pb.foreignPrivParam.ioForeignPrivBuffer = (Ptr)foreignPrivBuffer;
|
||||
pb.foreignPrivParam.ioForeignPrivReqCount = *foreignPrivSize;
|
||||
error = PBGetForeignPrivsSync(&pb);
|
||||
*foreignPrivSize = pb.foreignPrivParam.ioForeignPrivActCount;
|
||||
*foreignPrivInfo1 = pb.foreignPrivParam.ioForeignPrivInfo1;
|
||||
*foreignPrivInfo2 = pb.foreignPrivParam.ioForeignPrivInfo2;
|
||||
*foreignPrivInfo3 = pb.foreignPrivParam.ioForeignPrivInfo3;
|
||||
*foreignPrivInfo4 = pb.foreignPrivParam.ioForeignPrivInfo4;
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpGetForeignPrivs(const FSSpec *spec,
|
||||
void *foreignPrivBuffer,
|
||||
long *foreignPrivSize,
|
||||
long *foreignPrivInfo1,
|
||||
long *foreignPrivInfo2,
|
||||
long *foreignPrivInfo3,
|
||||
long *foreignPrivInfo4)
|
||||
{
|
||||
return ( GetForeignPrivs(spec->vRefNum, spec->parID, spec->name,
|
||||
foreignPrivBuffer, foreignPrivSize,
|
||||
foreignPrivInfo1, foreignPrivInfo2,
|
||||
foreignPrivInfo3, foreignPrivInfo4) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr SetForeignPrivs(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name,
|
||||
const void *foreignPrivBuffer,
|
||||
long *foreignPrivSize,
|
||||
long foreignPrivInfo1,
|
||||
long foreignPrivInfo2,
|
||||
long foreignPrivInfo3,
|
||||
long foreignPrivInfo4)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
OSErr error;
|
||||
|
||||
pb.foreignPrivParam.ioNamePtr = (StringPtr)name;
|
||||
pb.foreignPrivParam.ioVRefNum = vRefNum;
|
||||
pb.foreignPrivParam.ioForeignPrivDirID = dirID;
|
||||
pb.foreignPrivParam.ioForeignPrivBuffer = (Ptr)foreignPrivBuffer;
|
||||
pb.foreignPrivParam.ioForeignPrivReqCount = *foreignPrivSize;
|
||||
pb.foreignPrivParam.ioForeignPrivInfo1 = foreignPrivInfo1;
|
||||
pb.foreignPrivParam.ioForeignPrivInfo2 = foreignPrivInfo2;
|
||||
pb.foreignPrivParam.ioForeignPrivInfo3 = foreignPrivInfo3;
|
||||
pb.foreignPrivParam.ioForeignPrivInfo4 = foreignPrivInfo4;
|
||||
error = PBSetForeignPrivsSync(&pb);
|
||||
if ( error == noErr )
|
||||
{
|
||||
*foreignPrivSize = pb.foreignPrivParam.ioForeignPrivActCount;
|
||||
}
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpSetForeignPrivs(const FSSpec *spec,
|
||||
const void *foreignPrivBuffer,
|
||||
long *foreignPrivSize,
|
||||
long foreignPrivInfo1,
|
||||
long foreignPrivInfo2,
|
||||
long foreignPrivInfo3,
|
||||
long foreignPrivInfo4)
|
||||
{
|
||||
return ( SetForeignPrivs(spec->vRefNum, spec->parID, spec->name,
|
||||
foreignPrivBuffer, foreignPrivSize,
|
||||
foreignPrivInfo1, foreignPrivInfo2,
|
||||
foreignPrivInfo3, foreignPrivInfo4) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr HGetLogInInfo(ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
short *loginMethod,
|
||||
StringPtr userName)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
OSErr error;
|
||||
|
||||
pb.objParam.ioNamePtr = (StringPtr)volName;
|
||||
pb.objParam.ioVRefNum = vRefNum;
|
||||
pb.objParam.ioObjNamePtr = userName;
|
||||
error = PBHGetLogInInfoSync(&pb);
|
||||
if ( error == noErr )
|
||||
{
|
||||
*loginMethod = pb.objParam.ioObjType;
|
||||
}
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr HGetDirAccess(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name,
|
||||
long *ownerID,
|
||||
long *groupID,
|
||||
long *accessRights)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
OSErr error;
|
||||
|
||||
pb.accessParam.ioNamePtr = (StringPtr)name;
|
||||
pb.accessParam.ioVRefNum = vRefNum;
|
||||
pb.fileParam.ioDirID = dirID;
|
||||
error = PBHGetDirAccessSync(&pb);
|
||||
if ( error == noErr )
|
||||
{
|
||||
*ownerID = pb.accessParam.ioACOwnerID;
|
||||
*groupID = pb.accessParam.ioACGroupID;
|
||||
*accessRights = pb.accessParam.ioACAccess;
|
||||
}
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpGetDirAccess(const FSSpec *spec,
|
||||
long *ownerID,
|
||||
long *groupID,
|
||||
long *accessRights)
|
||||
{
|
||||
return ( HGetDirAccess(spec->vRefNum, spec->parID, spec->name,
|
||||
ownerID, groupID, accessRights) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr HSetDirAccess(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name,
|
||||
long ownerID,
|
||||
long groupID,
|
||||
long accessRights)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.accessParam.ioNamePtr = (StringPtr)name;
|
||||
pb.accessParam.ioVRefNum = vRefNum;
|
||||
pb.fileParam.ioDirID = dirID;
|
||||
pb.accessParam.ioACOwnerID = ownerID;
|
||||
pb.accessParam.ioACGroupID = groupID;
|
||||
pb.accessParam.ioACAccess = accessRights;
|
||||
return ( PBHSetDirAccessSync(&pb) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpSetDirAccess(const FSSpec *spec,
|
||||
long ownerID,
|
||||
long groupID,
|
||||
long accessRights)
|
||||
{
|
||||
return ( HSetDirAccess(spec->vRefNum, spec->parID, spec->name,
|
||||
ownerID, groupID, accessRights) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr HMapID(ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
long ugID,
|
||||
short objType,
|
||||
StringPtr name)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.objParam.ioNamePtr = (StringPtr)volName;
|
||||
pb.objParam.ioVRefNum = vRefNum;
|
||||
pb.objParam.ioObjType = objType;
|
||||
pb.objParam.ioObjNamePtr = name;
|
||||
pb.objParam.ioObjID = ugID;
|
||||
return ( PBHMapIDSync(&pb) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr HMapName(ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
ConstStr255Param name,
|
||||
short objType,
|
||||
long *ugID)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
OSErr error;
|
||||
|
||||
pb.objParam.ioNamePtr = (StringPtr)volName;
|
||||
pb.objParam.ioVRefNum = vRefNum;
|
||||
pb.objParam.ioObjType = objType;
|
||||
pb.objParam.ioObjNamePtr = (StringPtr)name;
|
||||
error = PBHMapNameSync(&pb);
|
||||
if ( error == noErr )
|
||||
{
|
||||
*ugID = pb.objParam.ioObjID;
|
||||
}
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr HCopyFile(short srcVRefNum,
|
||||
long srcDirID,
|
||||
ConstStr255Param srcName,
|
||||
short dstVRefNum,
|
||||
long dstDirID,
|
||||
ConstStr255Param dstPathname,
|
||||
ConstStr255Param copyName)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.copyParam.ioVRefNum = srcVRefNum;
|
||||
pb.copyParam.ioDirID = srcDirID;
|
||||
pb.copyParam.ioNamePtr = (StringPtr)srcName;
|
||||
pb.copyParam.ioDstVRefNum = dstVRefNum;
|
||||
pb.copyParam.ioNewDirID = dstDirID;
|
||||
pb.copyParam.ioNewName = (StringPtr)dstPathname;
|
||||
pb.copyParam.ioCopyName = (StringPtr)copyName;
|
||||
return ( PBHCopyFileSync(&pb) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpCopyFile(const FSSpec *srcSpec,
|
||||
const FSSpec *dstSpec,
|
||||
ConstStr255Param copyName)
|
||||
{
|
||||
return ( HCopyFile(srcSpec->vRefNum, srcSpec->parID, srcSpec->name,
|
||||
dstSpec->vRefNum, dstSpec->parID,
|
||||
dstSpec->name, copyName) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr HMoveRename(short vRefNum,
|
||||
long srcDirID,
|
||||
ConstStr255Param srcName,
|
||||
long dstDirID,
|
||||
ConstStr255Param dstpathName,
|
||||
ConstStr255Param copyName)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.copyParam.ioVRefNum = vRefNum;
|
||||
pb.copyParam.ioDirID = srcDirID;
|
||||
pb.copyParam.ioNamePtr = (StringPtr)srcName;
|
||||
pb.copyParam.ioNewDirID = dstDirID;
|
||||
pb.copyParam.ioNewName = (StringPtr)dstpathName;
|
||||
pb.copyParam.ioCopyName = (StringPtr)copyName;
|
||||
return ( PBHMoveRenameSync(&pb) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpMoveRename(const FSSpec *srcSpec,
|
||||
const FSSpec *dstSpec,
|
||||
ConstStr255Param copyName)
|
||||
{
|
||||
OSErr error;
|
||||
|
||||
/* make sure the FSSpecs refer to the same volume */
|
||||
if ( srcSpec->vRefNum != dstSpec->vRefNum )
|
||||
{
|
||||
error = diffVolErr;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = HMoveRename(srcSpec->vRefNum, srcSpec->parID, srcSpec->name,
|
||||
dstSpec->parID, dstSpec->name, copyName);
|
||||
}
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr GetVolMountInfoSize(ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
short *size)
|
||||
{
|
||||
ParamBlockRec pb;
|
||||
|
||||
pb.ioParam.ioNamePtr = (StringPtr)volName;
|
||||
pb.ioParam.ioVRefNum = vRefNum;
|
||||
pb.ioParam.ioBuffer = (Ptr)size;
|
||||
return ( PBGetVolMountInfoSize(&pb) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr GetVolMountInfo(ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
void *volMountInfo)
|
||||
{
|
||||
ParamBlockRec pb;
|
||||
|
||||
pb.ioParam.ioNamePtr = (StringPtr)volName;
|
||||
pb.ioParam.ioVRefNum = vRefNum;
|
||||
pb.ioParam.ioBuffer = (Ptr)volMountInfo;
|
||||
return ( PBGetVolMountInfo(&pb) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr VolumeMount(const void *volMountInfo,
|
||||
short *vRefNum)
|
||||
{
|
||||
ParamBlockRec pb;
|
||||
OSErr error;
|
||||
|
||||
pb.ioParam.ioBuffer = (Ptr)volMountInfo;
|
||||
error = PBVolumeMount(&pb);
|
||||
if ( error == noErr )
|
||||
{
|
||||
*vRefNum = pb.ioParam.ioVRefNum;
|
||||
}
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr Share(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.fileParam.ioNamePtr = (StringPtr)name;
|
||||
pb.fileParam.ioVRefNum = vRefNum;
|
||||
pb.fileParam.ioDirID = dirID;
|
||||
return ( PBShareSync(&pb) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpShare(const FSSpec *spec)
|
||||
{
|
||||
return ( Share(spec->vRefNum, spec->parID, spec->name) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr Unshare(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param name)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
|
||||
pb.fileParam.ioNamePtr = (StringPtr)name;
|
||||
pb.fileParam.ioVRefNum = vRefNum;
|
||||
pb.fileParam.ioDirID = dirID;
|
||||
return ( PBUnshareSync(&pb) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr FSpUnshare(const FSSpec *spec)
|
||||
{
|
||||
return ( Unshare(spec->vRefNum, spec->parID, spec->name) );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pascal OSErr GetUGEntry(short objType,
|
||||
StringPtr objName,
|
||||
long *objID)
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
OSErr error;
|
||||
|
||||
pb.objParam.ioObjType = objType;
|
||||
pb.objParam.ioObjNamePtr = objName;
|
||||
pb.objParam.ioObjID = *objID;
|
||||
error = PBGetUGEntrySync(&pb);
|
||||
if ( error == noErr )
|
||||
{
|
||||
*objID = pb.objParam.ioObjID;
|
||||
}
|
||||
return ( error );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
File: Optimization.h
|
||||
|
||||
Contains: Defines that let you make MoreFiles code more efficient.
|
||||
|
||||
Version: MoreFiles
|
||||
|
||||
Copyright: <09> 1992-2001 by Apple Computer, Inc., all rights reserved.
|
||||
|
||||
You may incorporate this sample code into your applications without
|
||||
restriction, though the sample code has been provided "AS IS" and the
|
||||
responsibility for its operation is 100% yours. However, what you are
|
||||
not permitted to do is to redistribute the source as "DSC Sample Code"
|
||||
after having made changes. If you're going to re-distribute the source,
|
||||
we require that you make it clear in the source that the code was
|
||||
descended from Apple Sample Code, but that you've made changes.
|
||||
|
||||
File Ownership:
|
||||
|
||||
DRI: Apple Macintosh Developer Technical Support
|
||||
|
||||
Other Contact: Apple Macintosh Developer Technical Support
|
||||
<http://developer.apple.com/bugreporter/>
|
||||
|
||||
Technology: DTS Sample Code
|
||||
|
||||
Writers:
|
||||
|
||||
(JL) Jim Luther
|
||||
|
||||
Change History (most recent first):
|
||||
|
||||
<1> 2/7/01 JL first checked in
|
||||
*/
|
||||
|
||||
/*
|
||||
The Optimization changes to MoreFiles source and header files, along with
|
||||
this file and OptimizationEnd.h, let you optimize the code produced
|
||||
by MoreFiles in several ways.
|
||||
|
||||
1 -- MoreFiles contains extra code so that many routines can run under
|
||||
Mac OS systems back to System 6. If your program requires a specific
|
||||
version of Mac OS and your program checks for that version before
|
||||
calling MoreFiles routines, then you can remove a lot of compatibility
|
||||
code by defining one of the following to 1:
|
||||
|
||||
__MACOSSEVENFIVEONEORLATER // assume Mac OS 7.5.1 or later
|
||||
__MACOSSEVENFIVEORLATER // assume Mac OS 7.5 or later
|
||||
__MACOSSEVENORLATER // assume Mac OS 7.0 or later
|
||||
|
||||
If you're compiling 68K code, the default is to include all compatibility code.
|
||||
If you're compiling PowerPC code (TARGET_RT_MAC_CFM), the default is __MACOSSEVENORLATER
|
||||
If you're compiling for Carbon code (TARGET_API_MAC_CARBON), the default is __MACOSSEVENFIVEONEORLATER
|
||||
|
||||
2 -- You may disable Pascal calling conventions in all MoreFiles routines
|
||||
except for system callbacks that require Pascal calling conventions.
|
||||
This will make 68K C programs both smaller and faster.
|
||||
(PowerPC compilers ignore pascal calling conventions.)
|
||||
Just define __WANTPASCALELIMINATION to be 1 to turn this optimization on
|
||||
when building MoreFiles for use from C programs (you'll need to keep
|
||||
Pascal calling conventions when linking MoreFiles routines with Pascal
|
||||
programs).
|
||||
|
||||
3 -- If Metrowerks compiler is used, "#pragma internal on" may help produce
|
||||
better code. However, this option can also cause problems if you're
|
||||
trying to build MoreFiles as a shared library, so it is by default not used.
|
||||
Just define __USEPRAGMAINTERNAL to be 1 to turn this optimization on.
|
||||
|
||||
Original changes supplied by Fabrizio Oddone
|
||||
*/
|
||||
|
||||
#include <ConditionalMacros.h>
|
||||
|
||||
// if we're compiling for Carbon, then we're running on Mac OS 8.1 or later
|
||||
#ifndef __MACOSSEVENFIVEONEORLATER
|
||||
#define __MACOSSEVENFIVEONEORLATER TARGET_API_MAC_CARBON
|
||||
#endif
|
||||
|
||||
#ifndef __MACOSSEVENFIVEORLATER
|
||||
#define __MACOSSEVENFIVEORLATER __MACOSSEVENFIVEONEORLATER
|
||||
#endif
|
||||
|
||||
#ifndef __MACOSSEVENORLATER
|
||||
#if TARGET_RT_MAC_CFM
|
||||
#define __MACOSSEVENORLATER 1
|
||||
#else
|
||||
#define __MACOSSEVENORLATER __MACOSSEVENFIVEORLATER
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __WANTPASCALELIMINATION
|
||||
#define __WANTPASCALELIMINATION 0
|
||||
#endif
|
||||
|
||||
#if __WANTPASCALELIMINATION
|
||||
#define pascal
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __USEPRAGMAINTERNAL
|
||||
#define __USEPRAGMAINTERNAL 0
|
||||
#endif
|
||||
|
||||
#if __USEPRAGMAINTERNAL
|
||||
#if defined(__MWERKS__)
|
||||
#pragma internal on
|
||||
#endif
|
||||
#endif
|
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
File: OptimizationEnd.h
|
||||
|
||||
Contains: Defines that let you make MoreFiles code more efficient.
|
||||
|
||||
Version: MoreFiles
|
||||
|
||||
Copyright: <09> 1992-2001 by Apple Computer, Inc., all rights reserved.
|
||||
|
||||
You may incorporate this sample code into your applications without
|
||||
restriction, though the sample code has been provided "AS IS" and the
|
||||
responsibility for its operation is 100% yours. However, what you are
|
||||
not permitted to do is to redistribute the source as "DSC Sample Code"
|
||||
after having made changes. If you're going to re-distribute the source,
|
||||
we require that you make it clear in the source that the code was
|
||||
descended from Apple Sample Code, but that you've made changes.
|
||||
|
||||
File Ownership:
|
||||
|
||||
DRI: Apple Macintosh Developer Technical Support
|
||||
|
||||
Other Contact: Apple Macintosh Developer Technical Support
|
||||
<http://developer.apple.com/bugreporter/>
|
||||
|
||||
Technology: DTS Sample Code
|
||||
|
||||
Writers:
|
||||
|
||||
(JL) Jim Luther
|
||||
|
||||
Change History (most recent first):
|
||||
|
||||
<1> 2/7/01 JL first checked in
|
||||
*/
|
||||
|
||||
/*
|
||||
The Optimization changes to MoreFiles source and header files, along with
|
||||
this file and Optimization.h, let you optimize the code produced by MoreFiles
|
||||
in several ways.
|
||||
|
||||
Original changes supplied by Fabrizio Oddone
|
||||
*/
|
||||
|
||||
|
||||
#if __USEPRAGMAINTERNAL
|
||||
#if defined(__MWERKS__)
|
||||
#pragma internal reset
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#if __WANTPASCALELIMINATION
|
||||
#ifndef __COMPILINGMOREFILES
|
||||
#undef pascal
|
||||
#endif
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@@ -1,304 +0,0 @@
|
||||
/*
|
||||
File: Search.h
|
||||
|
||||
Contains: IndexedSearch and the PBCatSearch compatibility function.
|
||||
|
||||
Version: Technology: MoreFiles
|
||||
Release: 1.5.2
|
||||
|
||||
Copyright: <20> 1992-2001 by Apple Computer, Inc., all rights reserved.
|
||||
|
||||
Bugs?: For bug reports, consult the following page on
|
||||
the World Wide Web:
|
||||
|
||||
http://developer.apple.com/bugreporter/
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
You may incorporate this sample code into your applications without
|
||||
restriction, though the sample code has been provided "AS IS" and the
|
||||
responsibility for its operation is 100% yours. However, what you are
|
||||
not permitted to do is to redistribute the source as "DSC Sample Code"
|
||||
after having made changes. If you're going to re-distribute the source,
|
||||
we require that you make it clear in the source that the code was
|
||||
descended from Apple Sample Code, but that you've made changes.
|
||||
*/
|
||||
|
||||
#ifndef __SEARCH__
|
||||
#define __SEARCH__
|
||||
|
||||
#ifndef __MACTYPES__
|
||||
#include <MacTypes.h>
|
||||
#endif
|
||||
|
||||
#ifndef __FILES__
|
||||
#include <Files.h>
|
||||
#endif
|
||||
|
||||
#include "Optimization.h"
|
||||
|
||||
|
||||
#if PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if PRAGMA_IMPORT
|
||||
#pragma import on
|
||||
#endif
|
||||
|
||||
#if PRAGMA_STRUCT_ALIGN
|
||||
#pragma options align=mac68k
|
||||
#elif PRAGMA_STRUCT_PACKPUSH
|
||||
#pragma pack(push, 2)
|
||||
#elif PRAGMA_STRUCT_PACK
|
||||
#pragma pack(2)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
IndexedSearch(
|
||||
CSParamPtr pb,
|
||||
long dirID);
|
||||
|
||||
|
||||
/*
|
||||
The IndexedSearch function performs an indexed search in and below the
|
||||
specified directory using the same parameters (in pb) as is passed to
|
||||
PBCatSearch. See Inside Macintosh: Files for a description of the
|
||||
parameter block.
|
||||
|
||||
pb input: A CSParamPtr record specifying the volume to search
|
||||
and the search criteria.
|
||||
output: Fields in the parameter block are returned indicating
|
||||
the number of matches found, the matches, and if the
|
||||
search ended with noErr, the CatPosition record that
|
||||
lets you resume a search where the last search left
|
||||
off.
|
||||
dirID input: The directory to search. If fsRtDirID is passed,
|
||||
the entire volume is searched.
|
||||
|
||||
Note: If you use a high-level debugger and use ioSearchTime to limit
|
||||
the length of time to run the search, you'll want to step over
|
||||
calls to IndexedSearch because it installs a Time Manager task.
|
||||
Most high-level debuggers don't deal gracefully with interrupt
|
||||
driven code.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
eofErr -39 End of catalog found (this is normal!)
|
||||
paramErr -50 Parameter block has invalid parameters
|
||||
(see source for VerifyUserPB) or
|
||||
invalid catPosition record was passed
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call.
|
||||
memFullErr -108 Memory could not be allocated in heap
|
||||
catChangedErr -1304 Catalog has changed and catalog position
|
||||
record may be invalid
|
||||
|
||||
__________
|
||||
|
||||
See also: PBCatSearch, PBCatSearchSyncCompat
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
PBCatSearchSyncCompat(CSParamPtr paramBlock);
|
||||
|
||||
|
||||
/*
|
||||
The PBCatSearchSyncCompat function uses PBCatSearch (if available) or
|
||||
IndexedSearch (if PBCatSearch is not available) to search a volume
|
||||
using a set of search criteria that you specify. It builds a list of all
|
||||
files or directories that meet your specifications.
|
||||
|
||||
pb input: A CSParamPtr record specifying the volume to search
|
||||
and the search criteria.
|
||||
output: Fields in the parameter block are returned indicating
|
||||
the number of matches found, the matches, and if the
|
||||
search ended with noErr, the CatPosition record that
|
||||
lets you resume a search where the last search left
|
||||
off.
|
||||
|
||||
Note: If you use a high-level debugger and use ioSearchTime to limit
|
||||
the length of time to run the search, you'll want to step over
|
||||
calls to PBCatSearchSyncCompat because it calls IndexedSearch
|
||||
which installs a Time Manager task. Most high-level debuggers
|
||||
don't deal gracefully with interrupt driven code.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
eofErr -39 End of catalog found (this is normal!)
|
||||
paramErr -50 Parameter block has invalid parameters
|
||||
(see source for VerifyUserPB) or
|
||||
invalid catPosition record was passed
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call.
|
||||
memFullErr -108 Memory could not be allocated in heap
|
||||
catChangedErr -1304 Catalog has changed and catalog position
|
||||
record may be invalid
|
||||
afpCatalogChanged -5037 Catalog has changed and search cannot
|
||||
be resumed
|
||||
|
||||
__________
|
||||
|
||||
See also: PBCatSearch, IndexedSearch
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
NameFileSearch(
|
||||
ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
ConstStr255Param fileName,
|
||||
FSSpecPtr matches,
|
||||
long reqMatchCount,
|
||||
long * actMatchCount,
|
||||
Boolean newSearch,
|
||||
Boolean partial);
|
||||
|
||||
|
||||
/*
|
||||
The NameFileSearch function searches for files with a specific file
|
||||
name on a volume that supports PBCatSearch.
|
||||
Note: A result of catChangedErr means the catalog has changed between
|
||||
searches, but the search can be continued with the possiblity that you
|
||||
may miss some matches or get duplicate matches. For all other results
|
||||
(except for noErr), the search cannot be continued.
|
||||
|
||||
volName input: A pointer to the name of a mounted volume
|
||||
or nil.
|
||||
vRefNum input: Volume specification.
|
||||
fileName input: The name of the file to search for.
|
||||
matches input: Pointer to array of FSSpec where the match list is
|
||||
returned.
|
||||
reqMatchCount input: Maximum number of matches to return (the number of
|
||||
elements in the matches array).
|
||||
actMatchCount output: The number of matches actually returned.
|
||||
newSearch input: If true, start a new search. If false and if
|
||||
vRefNum is the same as the last call to
|
||||
NameFileSearch, then start searching at the
|
||||
position where the last search left off.
|
||||
partial input: If the partial parameter is false, then only files
|
||||
that exactly match fileName will be found. If the
|
||||
partial parameter is true, then all file names that
|
||||
contain fileName will be found.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
eofErr -39 End of catalog found (this is normal!)
|
||||
paramErr -50 Parameter block has invalid parameters
|
||||
(see source for VerifyUserPB) or
|
||||
invalid catPosition record was passed
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call.
|
||||
memFullErr -108 Memory could not be allocated in heap
|
||||
catChangedErr -1304 Catalog has changed and catalog position
|
||||
record may be invalid
|
||||
afpCatalogChanged -5037 Catalog has changed and search cannot
|
||||
be resumed
|
||||
|
||||
__________
|
||||
|
||||
Also see: CreatorTypeFileSearch
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
EXTERN_API( OSErr )
|
||||
CreatorTypeFileSearch(
|
||||
ConstStr255Param volName,
|
||||
short vRefNum,
|
||||
OSType creator,
|
||||
OSType fileType,
|
||||
FSSpecPtr matches,
|
||||
long reqMatchCount,
|
||||
long * actMatchCount,
|
||||
Boolean newSearch);
|
||||
|
||||
|
||||
/*
|
||||
The CreatorTypeFileSearch function searches for files with a specific
|
||||
creator or fileType on a volume that supports PBCatSearch.
|
||||
Note: A result of catChangedErr means the catalog has changed between
|
||||
searches, but the search can be continued with the possiblity that you
|
||||
may miss some matches or get duplicate matches. For all other results
|
||||
(except for noErr), the search cannot be continued.
|
||||
|
||||
volName input: A pointer to the name of a mounted volume
|
||||
or nil.
|
||||
vRefNum input: Volume specification.
|
||||
creator input: The creator type of the file to search for.
|
||||
To ignore the creator type, pass 0x00000000 in
|
||||
this field.
|
||||
fileType input: The file type of the file to search for.
|
||||
To ignore the file type, pass 0x00000000 in
|
||||
this field.
|
||||
matches input: Pointer to array of FSSpec where the match list is
|
||||
returned.
|
||||
reqMatchCount input: Maximum number of matches to return (the number of
|
||||
elements in the matches array).
|
||||
actMatchCount output: The number of matches actually returned.
|
||||
newSearch input: If true, start a new search. If false and if
|
||||
vRefNum is the same as the last call to
|
||||
CreatorTypeFileSearch, then start searching at the
|
||||
position where the last search left off.
|
||||
|
||||
Result Codes
|
||||
noErr 0 No error
|
||||
nsvErr -35 Volume not found
|
||||
ioErr -36 I/O error
|
||||
eofErr -39 End of catalog found (this is normal!)
|
||||
paramErr -50 Parameter block has invalid parameters
|
||||
(see source for VerifyUserPB) or
|
||||
invalid catPosition record was passed
|
||||
extFSErr -58 External file system error - no file
|
||||
system claimed this call.
|
||||
memFullErr -108 Memory could not be allocated in heap
|
||||
catChangedErr -1304 Catalog has changed and catalog position
|
||||
record may be invalid
|
||||
afpCatalogChanged -5037 Catalog has changed and search cannot
|
||||
be resumed
|
||||
|
||||
__________
|
||||
|
||||
Also see: NameFileSearch
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "OptimizationEnd.h"
|
||||
|
||||
#if PRAGMA_STRUCT_ALIGN
|
||||
#pragma options align=reset
|
||||
#elif PRAGMA_STRUCT_PACKPUSH
|
||||
#pragma pack(pop)
|
||||
#elif PRAGMA_STRUCT_PACK
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef PRAGMA_IMPORT_OFF
|
||||
#pragma import off
|
||||
#elif PRAGMA_IMPORT
|
||||
#pragma import reset
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SEARCH__ */
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,125 +0,0 @@
|
||||
MoreFilesX
|
||||
|
||||
Copyright (c) 1992-2002 Apple Computer, Inc.
|
||||
All rights reserved.
|
||||
|
||||
________________________________________________________________________________
|
||||
|
||||
About MoreFilesX
|
||||
|
||||
MoreFilesX is a collection of useful high-level File Manager routines that use the HFS Plus APIs introduced in Mac OS 9.0 wherever possible.
|
||||
|
||||
While many of the routines in MoreFilesX are based on the older MoreFiles sample code (which used the older File Manager APIs), by using the HFS Plus APIs, the routines in MoreFilesX have several advantages over the older MoreFiles code:
|
||||
|
||||
<EFBFBD> The routines are simpler to understand because the high-level HFS Plus APIs are more powerful.
|
||||
|
||||
<EFBFBD> The routines support the features of the HFS Plus volume format such as long Unicode filenames and files larger than 2GB.
|
||||
|
||||
<EFBFBD> In many cases, the routines execute more efficiently than code that uses the older File Manager APIs -- especially on non-HFS volumes.
|
||||
|
||||
<EFBFBD> The routines use Apple's standard exception and assertion macros (the require, check, and verify macros) which improves readability and error handling, and which provides easy debug builds -- just add #define DEBUG 1 and every exception causes an assertion.
|
||||
|
||||
<EFBFBD> The routines are thread safe. There are no global or static variables so multiple program threads can use MoreFilesX routines safely.
|
||||
|
||||
If you are writing new Carbon applications for Mac OS X that call the File Manager, you should use MoreFilesX -- not MoreFiles. If you're porting existing applications to Mac OS X and those applications use routines from MoreFiles, you should consider switching to the routines in MoreFilesX.
|
||||
|
||||
The routines were designed for applications running in the Mac OS X Carbon environment. All of the routines will work under Mac OS 9 if you define BuildingMoreFilesXForMacOS9 to 1. Doing that removes code that calls Mac OS X only APIs. MoreFilesX cannot be used in pre-Mac OS 9 system releases.
|
||||
|
||||
The routines in MoreFilesX have been tested (but not stress-tested) and are fully documented.
|
||||
|
||||
________________________________________________________________________________
|
||||
|
||||
Files in the MoreFilesX Package
|
||||
|
||||
MoreFilesX.c - the source code for MoreFilesX.
|
||||
|
||||
MoreFilesX.h - the header files and complete documentation for the routines included in MoreFilesX.
|
||||
|
||||
________________________________________________________________________________
|
||||
|
||||
How to use MoreFilesX
|
||||
|
||||
You can compile the code and link it into your programs. You can cut and paste portions of it into your programs. You can use it as an example. Since MoreFilesX is sample code, many routines are there simply to show you how to use the File Manager APIs. If a routine does more or less than what you want, you can have the source so you can modify it to do exactly you want it to do. Feel free to rip MoreFilesX off and modify its code in whatever ways you find work best for you.
|
||||
|
||||
You'll also notice that all routines that make other File Manager calls return an OSErr or OSStatus result. I always check for error results and you should too.
|
||||
|
||||
________________________________________________________________________________
|
||||
|
||||
Documentation
|
||||
|
||||
The documentation for the routines can be found in the header files. There, you'll find function prototypes, and a description of each call that includes a complete listing of all input and output parameters. For example, here's the function prototype and documentation for one of the routines, FSPathMakeFSSpec.
|
||||
|
||||
OSStatus
|
||||
FSPathMakeFSSpec(
|
||||
UInt8 *path,
|
||||
FSSpec *spec,
|
||||
Boolean *isDirectory); /* can be NULL */
|
||||
|
||||
/*
|
||||
The FSPathMakeFSSpec function converts a pathname to an FSSpec.
|
||||
|
||||
path --> A pointer to a C String that is the pathname. The
|
||||
format of the pathname you must supply can be
|
||||
determined with the Gestalt selector gestaltFSAttr's
|
||||
gestaltFSUsesPOSIXPathsForConversion bit.
|
||||
If the gestaltFSUsesPOSIXPathsForConversion bit is
|
||||
clear, the pathname must be a Mac OS File Manager
|
||||
full pathname in a C string. If the
|
||||
gestaltFSUsesPOSIXPathsForConversion bit is set,
|
||||
the pathname must be a UTF8 encoded POSIX absolute
|
||||
pathname in a C string. In either case, the pathname
|
||||
returned by FSMakePath can be passed to
|
||||
FSPathMakeFSSpec.
|
||||
spec <-- The FSSpec.
|
||||
isDirectory <** An optional pointer to a Boolean.
|
||||
If not NULL, true will be returned in the Boolean
|
||||
if the specified path is a directory or false will
|
||||
be returned in the Boolean if the specified path is
|
||||
a file.
|
||||
*/
|
||||
|
||||
What do those arrows in the documentation for each routine mean?
|
||||
|
||||
--> The parameter is an input
|
||||
|
||||
<-- The parameter is an output. The pointer to the variable
|
||||
where the output will be returned (must not be NULL).
|
||||
|
||||
<** The parameter is an optional output. If it is not a
|
||||
NULL pointer, it points to the variable where the output
|
||||
will be returned. If it is a NULL pointer, the output will
|
||||
not be returned and will possibly let the routine and the
|
||||
File Manager do less work. If you don't need an optional output,
|
||||
don't ask for it.
|
||||
**> The parameter is an optional input. If it is not a
|
||||
NULL pointer, it points to the variable containing the
|
||||
input data. If it is a NULL pointer, the input is not used
|
||||
and will possibly let the routine and the File Manager
|
||||
do less work.
|
||||
|
||||
While most of the routines in MoreFilesX have plenty of comments to clarify what the code is doing, a few have very few comments in their code because they simply make a single File Manager call. For those routines, the routine description is the comment. If something isn't clear, take a look at File Manager documentation online at <http://developer.apple.com/techpubs/macosx/Carbon/Files/FileManager/File_Manager/index.html>.
|
||||
|
||||
The methodology behind Apple's standard exception and assertion macros is clearly explained in Sean Parent's article "Living in an Exceptional World" develop, The Apple Technical Journal, August 1992 <http://developer.apple.com/dev/techsupport/develop/issue11toc.shtml>. Don't let the fact that this article is 10 years old fool you -- this is highly recommended reading.
|
||||
|
||||
________________________________________________________________________________
|
||||
|
||||
Release Notes
|
||||
|
||||
v1.0 Jan 25, 2002
|
||||
First Release.
|
||||
|
||||
v1.0.1 Aug 23, 2002
|
||||
[2850624] Fixed C++ compile errors and Project Builder warnings.
|
||||
[2853901] Updated standard disclaimer.
|
||||
[2853905] Fixed #if test around header includes.
|
||||
[3016251] Changed FSMoveRenameObjectUnicode to not use the Temporary folder because it isn't available on NFS volumes.
|
||||
|
||||
________________________________________________________________________________
|
||||
|
||||
Bug Reports and Enhancement Requests
|
||||
|
||||
To file bug reports and enhancement requests, please go to <http://developer.apple.com/bugreporter/> and include "MoreFilesX Sample Code" in the title of your message.
|
||||
|
||||
Yes, we know that some of the routines available in MoreFiles still aren't in MoreFilesX. They were omitted due to time constraints.
|
||||
|
||||
________________________________________________________________________________
|
@@ -134,270 +134,6 @@ void wxCriticalSection::Leave()
|
||||
#define wxUSE_MAC_CRITICAL_REGION_MUTEX 1
|
||||
#define wxUSE_MAC_PTHREADS_MUTEX 0
|
||||
|
||||
#if wxUSE_MAC_PTHREADS_MUTEX
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
class wxMutexInternal
|
||||
{
|
||||
public:
|
||||
wxMutexInternal( wxMutexType mutexType );
|
||||
~wxMutexInternal();
|
||||
|
||||
wxMutexError Lock();
|
||||
wxMutexError TryLock();
|
||||
wxMutexError Unlock();
|
||||
|
||||
bool IsOk() const
|
||||
{ return m_isOk; }
|
||||
|
||||
private:
|
||||
pthread_mutex_t m_mutex;
|
||||
bool m_isOk;
|
||||
|
||||
// wxConditionInternal uses our m_mutex
|
||||
friend class wxConditionInternal;
|
||||
};
|
||||
|
||||
#ifdef HAVE_PTHREAD_MUTEXATTR_T
|
||||
// on some systems pthread_mutexattr_settype() is not in the headers (but it is
|
||||
// in the library, otherwise we wouldn't compile this code at all)
|
||||
extern "C" int pthread_mutexattr_settype( pthread_mutexattr_t *, int );
|
||||
#endif
|
||||
|
||||
wxMutexInternal::wxMutexInternal( wxMutexType mutexType )
|
||||
{
|
||||
int err;
|
||||
switch ( mutexType )
|
||||
{
|
||||
case wxMUTEX_RECURSIVE:
|
||||
// support recursive locks like Win32, i.e. a thread can lock a
|
||||
// mutex which it had itself already locked
|
||||
//
|
||||
// unfortunately initialization of recursive mutexes is non
|
||||
// portable, so try several methods
|
||||
#ifdef HAVE_PTHREAD_MUTEXATTR_T
|
||||
{
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init( &attr );
|
||||
pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE );
|
||||
|
||||
err = pthread_mutex_init( &m_mutex, &attr );
|
||||
}
|
||||
#elif defined(HAVE_PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
|
||||
// we can use this only as initializer so we have to assign it
|
||||
// first to a temp var - assigning directly to m_mutex wouldn't
|
||||
// even compile
|
||||
{
|
||||
pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
|
||||
m_mutex = mutex;
|
||||
}
|
||||
#else // no recursive mutexes
|
||||
err = EINVAL;
|
||||
#endif // HAVE_PTHREAD_MUTEXATTR_T/...
|
||||
break;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( wxT("unknown mutex type") );
|
||||
// fall through
|
||||
|
||||
case wxMUTEX_DEFAULT:
|
||||
err = pthread_mutex_init( &m_mutex, NULL );
|
||||
break;
|
||||
}
|
||||
|
||||
m_isOk = err == 0;
|
||||
if ( !m_isOk )
|
||||
{
|
||||
wxLogApiError( wxT("pthread_mutex_init()"), err );
|
||||
}
|
||||
}
|
||||
|
||||
wxMutexInternal::~wxMutexInternal()
|
||||
{
|
||||
if ( m_isOk )
|
||||
{
|
||||
int err = pthread_mutex_destroy( &m_mutex );
|
||||
if ( err != 0 )
|
||||
{
|
||||
wxLogApiError( wxT("pthread_mutex_destroy()"), err );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wxMutexError wxMutexInternal::Lock()
|
||||
{
|
||||
int err = pthread_mutex_lock( &m_mutex );
|
||||
switch ( err )
|
||||
{
|
||||
case EDEADLK:
|
||||
// only error checking mutexes return this value and so it's an
|
||||
// unexpected situation -- hence use assert, not wxLogDebug
|
||||
wxFAIL_MSG( wxT("mutex deadlock prevented") );
|
||||
return wxMUTEX_DEAD_LOCK;
|
||||
|
||||
case EINVAL:
|
||||
wxLogDebug( wxT("pthread_mutex_lock(): mutex not initialized.") );
|
||||
break;
|
||||
|
||||
case 0:
|
||||
return wxMUTEX_NO_ERROR;
|
||||
|
||||
default:
|
||||
wxLogApiError( wxT("pthread_mutex_lock()"), err );
|
||||
}
|
||||
|
||||
return wxMUTEX_MISC_ERROR;
|
||||
}
|
||||
|
||||
wxMutexError wxMutexInternal::TryLock()
|
||||
{
|
||||
int err = pthread_mutex_trylock( &m_mutex );
|
||||
switch ( err )
|
||||
{
|
||||
case EBUSY:
|
||||
// not an error: mutex is already locked, but we're prepared for this case
|
||||
return wxMUTEX_BUSY;
|
||||
|
||||
case EINVAL:
|
||||
wxLogDebug( wxT("pthread_mutex_trylock(): mutex not initialized.") );
|
||||
break;
|
||||
|
||||
case 0:
|
||||
return wxMUTEX_NO_ERROR;
|
||||
|
||||
default:
|
||||
wxLogApiError( wxT("pthread_mutex_trylock()"), err );
|
||||
}
|
||||
|
||||
return wxMUTEX_MISC_ERROR;
|
||||
}
|
||||
|
||||
wxMutexError wxMutexInternal::Unlock()
|
||||
{
|
||||
int err = pthread_mutex_unlock( &m_mutex );
|
||||
switch ( err )
|
||||
{
|
||||
case EPERM:
|
||||
// we don't own the mutex
|
||||
return wxMUTEX_UNLOCKED;
|
||||
|
||||
case EINVAL:
|
||||
wxLogDebug( wxT("pthread_mutex_unlock(): mutex not initialized.") );
|
||||
break;
|
||||
|
||||
case 0:
|
||||
return wxMUTEX_NO_ERROR;
|
||||
|
||||
default:
|
||||
wxLogApiError( wxT("pthread_mutex_unlock()"), err );
|
||||
}
|
||||
|
||||
return wxMUTEX_MISC_ERROR;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if wxUSE_MAC_SEMAPHORE_MUTEX
|
||||
|
||||
class wxMutexInternal
|
||||
{
|
||||
public:
|
||||
wxMutexInternal( wxMutexType mutexType );
|
||||
virtual ~wxMutexInternal();
|
||||
|
||||
bool IsOk() const
|
||||
{ return m_isOk; }
|
||||
|
||||
wxMutexError Lock();
|
||||
wxMutexError TryLock();
|
||||
wxMutexError Unlock();
|
||||
|
||||
private:
|
||||
MPSemaphoreID m_semaphore;
|
||||
bool m_isOk;
|
||||
};
|
||||
|
||||
wxMutexInternal::wxMutexInternal(wxMutexType mutexType )
|
||||
{
|
||||
m_isOk = false;
|
||||
m_semaphore = kInvalidID;
|
||||
OSStatus err = noErr;
|
||||
|
||||
switch ( mutexType )
|
||||
{
|
||||
case wxMUTEX_DEFAULT :
|
||||
verify_noerr( MPCreateBinarySemaphore( &m_semaphore ) );
|
||||
m_isOk = ( m_semaphore != kInvalidID );
|
||||
break;
|
||||
|
||||
case wxMUTEX_RECURSIVE :
|
||||
wxFAIL_MSG( wxT("Recursive Mutex not supported yet") );
|
||||
break;
|
||||
|
||||
default :
|
||||
wxFAIL_MSG( wxT("Unknown mutex type") );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wxMutexInternal::~wxMutexInternal()
|
||||
{
|
||||
if ( m_semaphore != kInvalidID )
|
||||
MPDeleteSemaphore( m_semaphore );
|
||||
|
||||
MPYield();
|
||||
}
|
||||
|
||||
wxMutexError wxMutexInternal::Lock()
|
||||
{
|
||||
wxCHECK_MSG( m_isOk, wxMUTEX_MISC_ERROR, wxT("Invalid Mutex") );
|
||||
OSStatus err = MPWaitOnSemaphore( m_semaphore, kDurationForever );
|
||||
if (err != noErr)
|
||||
{
|
||||
wxLogSysError( wxT("Could not lock mutex") );
|
||||
|
||||
return wxMUTEX_MISC_ERROR;
|
||||
}
|
||||
|
||||
return wxMUTEX_NO_ERROR;
|
||||
}
|
||||
|
||||
wxMutexError wxMutexInternal::TryLock()
|
||||
{
|
||||
wxCHECK_MSG( m_isOk, wxMUTEX_MISC_ERROR, wxT("Invalid Mutex") );
|
||||
OSStatus err = MPWaitOnSemaphore( m_semaphore, kDurationImmediate );
|
||||
if (err != noErr)
|
||||
{
|
||||
if (err == kMPTimeoutErr)
|
||||
return wxMUTEX_BUSY;
|
||||
|
||||
wxLogSysError( wxT("Could not try lock mutex") );
|
||||
|
||||
return wxMUTEX_MISC_ERROR;
|
||||
}
|
||||
|
||||
return wxMUTEX_NO_ERROR;
|
||||
}
|
||||
|
||||
wxMutexError wxMutexInternal::Unlock()
|
||||
{
|
||||
wxCHECK_MSG( m_isOk, wxMUTEX_MISC_ERROR, wxT("Invalid Mutex") );
|
||||
OSStatus err = MPSignalSemaphore( m_semaphore );
|
||||
|
||||
MPYield();
|
||||
if (err != noErr)
|
||||
{
|
||||
wxLogSysError( wxT("Could not unlock mutex") );
|
||||
return wxMUTEX_MISC_ERROR;
|
||||
}
|
||||
|
||||
return wxMUTEX_NO_ERROR;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if wxUSE_MAC_CRITICAL_REGION_MUTEX
|
||||
|
||||
class wxMutexInternal
|
||||
@@ -583,177 +319,6 @@ wxSemaError wxSemaphoreInternal::Post()
|
||||
// wxCondition implementation
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#if 0
|
||||
|
||||
class wxConditionInternal
|
||||
{
|
||||
public:
|
||||
wxConditionInternal( wxMutex& mutex )
|
||||
:
|
||||
m_mutex( mutex ),
|
||||
m_semaphore( 0, 1 ),
|
||||
m_gate( 1, 1 )
|
||||
{
|
||||
m_waiters = 0;
|
||||
m_signals = 0;
|
||||
m_canceled = 0;
|
||||
}
|
||||
|
||||
virtual ~wxConditionInternal() {}
|
||||
|
||||
bool IsOk() const
|
||||
{ return m_mutex.IsOk(); }
|
||||
|
||||
wxCondError Wait()
|
||||
{ return WaitTimeout( kDurationForever ); }
|
||||
|
||||
wxCondError WaitTimeout( unsigned long msectimeout );
|
||||
|
||||
wxCondError Signal()
|
||||
{ return DoSignal( false); }
|
||||
|
||||
wxCondError Broadcast()
|
||||
{ return DoSignal( true ); }
|
||||
|
||||
private:
|
||||
wxCondError DoSignal( bool signalAll );
|
||||
|
||||
wxMutex& m_mutex;
|
||||
wxSemaphoreInternal m_semaphore; // Signals the waiting threads.
|
||||
wxSemaphoreInternal m_gate;
|
||||
wxCriticalSection m_varSection;
|
||||
size_t m_waiters; // Number of threads waiting for a signal.
|
||||
size_t m_signals; // Number of signals to send.
|
||||
size_t m_canceled; // Number of canceled waiters in m_waiters.
|
||||
};
|
||||
|
||||
wxCondError wxConditionInternal::WaitTimeout( unsigned long msectimeout )
|
||||
{
|
||||
m_gate.Wait();
|
||||
|
||||
if ( ++ m_waiters == INT_MAX )
|
||||
{
|
||||
m_varSection.Enter();
|
||||
|
||||
m_waiters -= m_canceled;
|
||||
m_signals -= m_canceled;
|
||||
m_canceled = 0;
|
||||
|
||||
m_varSection.Leave();
|
||||
}
|
||||
|
||||
m_gate.Post();
|
||||
m_mutex.Unlock();
|
||||
|
||||
wxSemaError err = m_semaphore.WaitTimeout( msectimeout);
|
||||
wxASSERT( err == wxSEMA_NO_ERROR || err == wxSEMA_TIMEOUT);
|
||||
|
||||
m_varSection.Enter();
|
||||
|
||||
if ( err != wxSEMA_NO_ERROR )
|
||||
{
|
||||
if ( m_signals > m_canceled )
|
||||
{
|
||||
// A signal is being sent after we timed out.
|
||||
if ( m_waiters == m_signals )
|
||||
{
|
||||
// There are no excess waiters to catch the signal, so
|
||||
// we must throw it away.
|
||||
wxSemaError err2 = m_semaphore.Wait();
|
||||
if ( err2 != wxSEMA_NO_ERROR )
|
||||
{
|
||||
wxLogSysError( wx("Error while waiting on semaphore") );
|
||||
}
|
||||
|
||||
wxASSERT( err2 == wxSEMA_NO_ERROR);
|
||||
|
||||
--m_waiters;
|
||||
if ( --m_signals == m_canceled )
|
||||
{
|
||||
// This was the last signal. open the gate.
|
||||
wxASSERT( m_waiters == m_canceled );
|
||||
m_gate.Post();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// There are excess waiters to catch the signal, leave it be.
|
||||
--m_waiters;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No signals is being sent:
|
||||
// the gate may be open or closed, so we can't touch m_waiters.
|
||||
++m_canceled;
|
||||
++m_signals;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We caught a signal.
|
||||
wxASSERT( m_signals > m_canceled );
|
||||
|
||||
--m_waiters;
|
||||
|
||||
if ( --m_signals == m_canceled)
|
||||
{
|
||||
// This was the last signal. open the gate.
|
||||
wxASSERT( m_waiters == m_canceled );
|
||||
|
||||
m_gate.Post();
|
||||
}
|
||||
}
|
||||
|
||||
m_varSection.Leave();
|
||||
m_mutex.Lock();
|
||||
|
||||
if (err != noErr)
|
||||
return err == wxSEMA_TIMEOUT ? wxCOND_TIMEOUT : wxCOND_MISC_ERROR;
|
||||
|
||||
return wxCOND_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
wxCondError wxConditionInternal::DoSignal( bool signalAll)
|
||||
{
|
||||
m_gate.Wait();
|
||||
m_varSection.Enter();
|
||||
|
||||
wxASSERT( m_signals == m_canceled );
|
||||
|
||||
if ( m_waiters == m_canceled)
|
||||
{
|
||||
m_varSection.Leave();
|
||||
m_gate.Post();
|
||||
return wxCOND_NO_ERROR;
|
||||
}
|
||||
|
||||
if ( m_canceled > 0)
|
||||
{
|
||||
m_waiters -= m_canceled;
|
||||
m_signals = 0;
|
||||
m_canceled = 0;
|
||||
}
|
||||
|
||||
m_signals = signalAll ? m_waiters : 1;
|
||||
size_t n = m_signals;
|
||||
|
||||
m_varSection.Leave();
|
||||
|
||||
// Let the waiters inherit the gate lock.
|
||||
|
||||
do
|
||||
{
|
||||
wxSemaError err = m_semaphore.Post();
|
||||
wxASSERT( err == wxSEMA_NO_ERROR );
|
||||
}
|
||||
while ( --n );
|
||||
|
||||
return wxCOND_NO_ERROR;
|
||||
}
|
||||
|
||||
#else
|
||||
class wxConditionInternal
|
||||
{
|
||||
public:
|
||||
@@ -884,7 +449,6 @@ wxCondError wxConditionInternal::Broadcast()
|
||||
|
||||
return wxCOND_NO_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxCriticalSection implementation
|
||||
|
Reference in New Issue
Block a user