hxdir.cpp

来自「symbian 下的helix player源代码」· C++ 代码 · 共 928 行 · 第 1/2 页

CPP
928
字号
	    	    	    int nSpecPos = nextFSpec.name[0] - nCompareLen + 1;
	    	    	    if (0 != strncasecmp((char*)&nextFSpec.name[nSpecPos], &m_pPattern[patternOffset+1], nCompareLen))
	    	    	    	bContinue = FALSE;
	    	    	}
	    	    }
	    	    else
	    	    {
	    	    	if ((patlen != nextFSpec.name[0]) ||
	    	    		(0 != strncasecmp((char*)&nextFSpec.name[1], szPattern, patlen)))
	    	    	    bContinue = FALSE;
	    	    }
	    	}
	    }
	    if (bContinue)
	    {
	    	strncpy(m_pNextFileName, (char*)&nextFSpec.name[1], len); /* Flawfinder: ignore */
	    	m_pNextFileName[len] = 0;
	    	tempStr = m_strPath;
	    	if (m_strPath.GetLength())
	    	{
	    	    if (tempStr[tempStr.GetLength()-1] != ':')
	    	    	tempStr += ":";
	    	}
	    	tempStr += m_pNextFileName;
	    	SafeStrCpy(szPath, (const char*)tempStr, nSize);

	    	if (IsFolder(&nextFSpec))
	    	    return FSOBJ_DIRECTORY;
	    	else
	    	    return FSOBJ_FILE;
	    }
	}
        RetVal = FindNext(szPath, nSize);
    }
    return RetVal;
}

/* Continues enumeration process. */
CHXDirectory::FSOBJ 
CHXDirectory::FindNext(char* szPath, UINT16 nSize)
{
    FSOBJ RetVal = FSOBJ_NOTVALID;
    CHXString tempStr;
    FSSpec nextFSpec;
    BOOL bContinue;

    if (m_pNextFileName)
    {
	SafeStrCpy(m_pCurrentFileName, m_pNextFileName, nSize);
    }
    else
    {
	if (m_pCurrentFileName)
	{
	    delete [] m_pCurrentFileName;
	    m_pCurrentFileName = NULL;
	}
    }
/*
    tempStr = szPath;
    ::FSMakeFSSpec(0,0,*((Str255*)tempStr),&nextFSpec);

    if (IsFolder(&nextFSpec, 1))
    {
	strcpy(szPath, (const char*)tempStr);
	return FSOBJ_DIRECTORY;
    }
*/    
    if (m_pNextFileName)
    {
	INT16 len = 0;
	char* patternStart;

	CInfoPBRec		pb;
	OSErr			err=noErr;

	memset(&pb,0,sizeof(pb));
				
	pb.hFileInfo.ioVRefNum=m_fileSpec.vRefNum;
	pb.hFileInfo.ioFDirIndex=0;
	pb.hFileInfo.ioNamePtr=m_fileSpec.name;
	pb.hFileInfo.ioDirID=m_fileSpec.parID;

	err = PBGetCatInfoSync(&pb);
	
	UINT16 dirItems = pb.dirInfo.ioDrNmFls;
	if (dirItems < m_nDirItems) // items have been deleted
	{
	    m_nIndex -= (m_nDirItems - dirItems);
	    m_nDirItems = dirItems;
	}

	while (::FSpIterateDirectory(&m_fileSpec, ++m_nIndex, &nextFSpec))
	{
	    bContinue = TRUE;
	    if (m_pPattern)
	    {
	    	INT16 patlen = strlen(m_pPattern);
	    	if ( 0 == strcmp("*.*", m_pPattern) || // *.*
	    	    	((m_pPattern[0] == '*') && (strlen(m_pPattern) == 1)) ) // *
	    	    bContinue = TRUE;
	    	else
	    	{
	    	    if (m_pPattern[0] == '*') //eg. *.dll
	    	    {
	    	    	if (0 != strncasecmp((char*)&nextFSpec.name[len-2], &m_pPattern[strlen(m_pPattern)-3], 3))
	    	    	    bContinue = FALSE;
	    	    }
	    	    else if ((patternStart = strchr(m_pPattern, '*')) != 0) //eg. pncrt*.dll
	    	    {
	    	    	INT16 patternOffset = patternStart-m_pPattern;
	    	    	if (0 != strncasecmp((char*)&nextFSpec.name[1], m_pPattern, patternOffset))
	    	    	    bContinue = FALSE;
	    	    	if (bContinue && (patternOffset < patlen))
	    	    	{
	    	    	    int nCompareLen = (patlen > nextFSpec.name[0]) ? nextFSpec.name[0] - patternOffset
	    	    	    						   : patlen - patternOffset - 1;
	    	    	    int nSpecPos = nextFSpec.name[0] - nCompareLen + 1;
	    	    	    if (0 != strncasecmp((char*)&nextFSpec.name[nSpecPos], &m_pPattern[patternOffset+1], nCompareLen))
	    	    	    	bContinue = FALSE;
	    	    	}
	    	    }
	    	    else // eg. pncrtd.dll
	    	    {
	    	    	if (0 != strncasecmp((char*)&nextFSpec.name[1], m_pPattern, patlen))
	    	    	    bContinue = FALSE;
	    	    }
	    	}
	    }
	    
	    
	    if (bContinue)
	    {
		len = nextFSpec.name[0];
		strncpy(m_pNextFileName, (char*)&nextFSpec.name[1], len); /* Flawfinder: ignore */
		m_pNextFileName[len] = 0;
	    	tempStr = m_strPath;
	    	if (m_strPath.GetLength())
	    	{
	    	    if (tempStr[tempStr.GetLength()-1] != ':')
	    	    	tempStr += ":";
	    	}
		tempStr += m_pNextFileName;
		SafeStrCpy(szPath, (const char*)tempStr, nSize);
	    	if (IsFolder(&nextFSpec))
	    	    return FSOBJ_DIRECTORY;
	    	else
	    	    return FSOBJ_FILE;
	    }
	}
	if (RetVal != FSOBJ_FILE)
	{
	    delete [] m_pNextFileName;
	    m_pNextFileName = 0;
	}
    }
    return RetVal;
}

OSErr 
CHXDirectory::GetDirID(long& dirID)
{
	FSSpec		dirSpec;
	CInfoPBRec	cinfo;
	OSErr		err;
	Boolean		dirFlag;
	
	if (EnsureValidPathSpec())
	{
		dirSpec = m_dirSpec;
		
		// call GetCatInfo to get it's dirID
		
		cinfo.dirInfo.ioNamePtr = dirSpec.name;
		cinfo.dirInfo.ioVRefNum = dirSpec.vRefNum;
		cinfo.dirInfo.ioDrDirID = dirSpec.parID;
		cinfo.dirInfo.ioFDirIndex = 0;	// use name and dirID
		
		err = PBGetCatInfoSync(&cinfo);
		
		// be sure it's really a directory
		if (err == noErr)
		{
			dirFlag = ((cinfo.dirInfo.ioFlAttrib & ioDirMask) != 0);
			if (!dirFlag) err = dirNFErr;
		}
		
		if (err == noErr)
		{
			dirID = cinfo.dirInfo.ioDrDirID;
		}
	}	
	else
	{
		// invalid path
		err = fnfErr;
	}
	return err;
}

BOOL 
CHXDirectory::DeleteFile(const char* szRelPath)
{
	CHXString	relativeStr(szRelPath);
	CHXString 	fullFileStr;
	FSSpec		fileSpec;
	OSErr		err;
	

	// make a full pathname to the file if we don't have a 
	// directory set (since some callers use a null dir
	// just to delete files)
	
	if (IsPartialMacPath(relativeStr) && (m_strPath.GetLength() > 0))
	{
		// we're deleting for a partial path from the current obj directory

		fullFileStr = m_strPath;
		// add seperator if needed
		if ((fullFileStr.GetLength() > 0) && (fullFileStr[fullFileStr.GetLength()-1] != ':'))
		    fullFileStr += ':';
		fullFileStr += relativeStr;
	}
	else
	{
		HX_ASSERT(IsFullMacPath(relativeStr));  // object's dir not set, so this works only for full paths
		
		fullFileStr = relativeStr;
	}
	
	// delete the file
	fileSpec = fullFileStr;
	err = FSpDelete(&fileSpec);
	// we really should return an error
	// this gets called frequently if the file doesn't exist - not an error 
	// so return error only if file is busy
	return (err != fBsyErr);
}

/* Sets itself to current directory. */
BOOL 
CHXDirectory::SetCurrentDir()
{
	// This was never implemented, doesn't work reliably on
	// Macs, and since it's a bad idea, it's not worth implementing.
	
    long 	dirID;
    short	vRefNum;
    OSErr err = ::HGetVol(NULL, &vRefNum, &dirID);
    err = ::FSMakeFSSpec(vRefNum, dirID, "\p", &m_dirSpec);
    if (noErr == err)
    {
    	m_strPath = m_dirSpec;
    	m_strPath = m_strPath.Left(m_strPath.GetLength()-1);
    	return TRUE;
    }
    return FALSE;
}

/* Makes itself a current directory. */
BOOL 
CHXDirectory::MakeCurrentDir()
{
	// Relying on a global current default directory is a bad
	// idea, so never call this.
	//
	// Also beware that calling GetVol() won't work properly
	// after this, anyway.  See ch. 2 of Inside Mac: Files
	// (under Manipulating the Default Volume and Directory)
	// for an explanation of why.
	//
	// SetVol, GetVol, and everything using
	// WDRefNums has been obsolete since 1987.
	// Use FSSpecs (or full pathnames, if necessary) instead.
	
	OSErr	err;
	long 	dirID;
	
	err = GetDirID(dirID);
	if (err == noErr)
	{
		err = HSetVol(NULL, m_dirSpec.vRefNum, dirID);
	}
	
	return (err == noErr);
}

UINT32 
CHXDirectory::Rename(const char* szOldName, const char* szNewName)
{
	UINT32		err;
	
	// Unfortunately, the semantics of the parameters for this call aren't clear
	//
	// presumably, szOldName is a full path, or a partial path in the current directory
	// presumably, szNewName is a full path, or just a name
	
	CHXString	oldFileStr(szOldName);
	CHXString	newFileStr(szNewName);
	StringPtr	newNamePtr;
	
	FSSpec		oldFileSpec;
	FSSpec		newFileSpec;
	FSSpec		destDirSpec;
	
	(void) EnsureValidPathSpec();
	
	oldFileSpec.vRefNum = 0;
	if (oldFileStr.Find(':') >= 0)
	{
		// the old name has a colon; convert it to a file spec
		oldFileSpec = oldFileStr;
	}
	
	if (oldFileSpec.vRefNum == 0)
	{
		// we couldn't get a valid FSSpec for the old name,
		// so assume it's relative to the current directory,
		// and make a file spec for it
		
		oldFileStr = m_dirSpec;
		oldFileStr += ":";
		oldFileStr += szOldName;
		oldFileSpec = oldFileStr;
	}
	require_action(oldFileSpec.vRefNum != 0, CantGetSourceForRename, err = fnfErr);
	
	newFileSpec.vRefNum = 0;
	if (newFileStr.Find(':') >= 0)
	{
		// the new name has a colon; try to convert it to a file spec
		newFileSpec = newFileStr;
	}
	
	// make a filespec for the destination folder
	//
	// use the directory of the new file if it was specified, otherwise use
	//   the directory of the old file
	
	err = FSMakeFSSpec(newFileSpec.vRefNum, 
			(newFileSpec.vRefNum == 0 ? oldFileSpec.parID : newFileSpec.parID), 
			"\p", &destDirSpec);
	check_noerr(err);
	
	// make sure we're not trying to move to another volume
	require_action(destDirSpec.vRefNum == oldFileSpec.vRefNum, CantChangeVolumes, err = HXR_FAILED);

	// they're on the same drive; possibly in different folders

	// use the name from the new file spec, if we have one, or else from the parameter
	newNamePtr = (newFileSpec.vRefNum ? newFileSpec.name : newFileStr);
	
	// use morefiles' Move/Rename call
	err = FSpMoveRenameCompat(&oldFileSpec, &destDirSpec, newNamePtr);
	if (err == dupFNErr)
	{
		err = FSpDelete(&newFileSpec);
		if (err == noErr)
		{
			err = FSpMoveRenameCompat(&oldFileSpec, &destDirSpec, newNamePtr);
		}
	}
		
CantChangeVolumes:
CantGetSourceForRename:

	if (err == noErr) 	err = HXR_OK;
	else				err = HXR_FAILED;
	
	
	return err;
}

// this moves or copies and renames a file
BOOL
CHXDirectory::MoveRename(const char* szSrcName, const char* szDestName, BOOL bMove)
{
    OSErr err;

    FSSpec srcSpec, destSpec, deleteSpec;
    CHXString strSourcePath(szSrcName);
    srcSpec = strSourcePath;
    
    CHXString strDestFilePath(szDestName);
    CHXString strDestFile;
    strDestFile = (strrchr(szDestName, OS_SEPARATOR_CHAR)+1);
    CHXString strDestPath(szDestName);
    strDestPath = strDestPath.Left(strDestPath.ReverseFind(OS_SEPARATOR_CHAR));
    destSpec = strDestPath;
    
    if (noErr == FSSpecFromPathName(strDestFilePath, &deleteSpec))
    {
	err = ::FSpDelete(&deleteSpec); //delete existing file
    }
    // Note, FSpMoveRenameCompat doesn't move across volumes, 
    // so copy, then delete original (below) if a move has to be done??
    
    if (bMove)
    {
    	err = FSpMoveRenameCompat(&srcSpec, &destSpec, *((Str255*)strDestFile));
    }
    if (!bMove || (diffVolErr == err))
    {
    	char* buffer = new char[0x40000];
	err = FSpFileCopy(&srcSpec,&destSpec, (ConstStr255Param)strDestFile, buffer, 0x40000, FALSE);
	delete buffer;
    }


    return (err == noErr);	
}

/* Checks if directory is on CD or removable drive. */    
BOOL 
CHXDirectory::IsRemovable()
{
#ifdef _CARBON

	if (EnsureValidPathSpec())
	{
		return CHXFileSpecUtils::IsDiskEjectable(m_dirSpec);
	}
	return FALSE;

#else
	OSErr				err;
	HParamBlockRec		hpb;

	
	DrvQElPtr	queueElPtr;
    QHdrPtr     queueHeader;
    Ptr         p;

	if (EnsureValidPathSpec())
	{	
		hpb.volumeParam.ioVRefNum = m_dirSpec.vRefNum;
		hpb.volumeParam.ioNamePtr = NULL;
		hpb.volumeParam.ioVolIndex = 0;					// use vRefNum only

		err = PBHGetVInfoSync(&hpb);
		check_noerr(err);
		
		if (err != noErr) return false;

		// check the flag bits in the drive queue (from Technote FL 530)
	    queueHeader = GetDrvQHdr();
	    queueElPtr = (DrvQElPtr) queueHeader->qHead;

	    while (queueElPtr != nil)
	    {
	        if (queueElPtr->dQDrive == hpb.volumeParam.ioVDrvInfo) 
	        {
	            p = (Ptr) queueElPtr;
	            p -= 3; /* to get to the byte with eject info */
	            if ((*p) & 8) return false;		// non-ejectable
	            else return true;				// ejectable
	        }
	        queueElPtr = (DrvQElPtr) queueElPtr->qLink;
	    }
	}	
	return false;	// we can't find this drive
#endif
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?