Darwin-Streaming-Server/QTFileLib/QTAtom_dref.cpp

382 lines
11 KiB
C++
Raw Permalink Normal View History

/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
//
// QTAtom_dref:
// The 'dref' QTAtom class.
// -------------------------------------
// Includes
//
#include <stdio.h>
#include <stdlib.h>
#include "SafeStdLib.h"
#include <string.h>
#ifndef __Win32__
#include <sys/types.h>
#include <netinet/in.h>
#endif
#include "QTFile.h"
#include "QTAtom.h"
#include "QTAtom_dref.h"
#include "OSMemory.h"
// -------------------------------------
// Macros
//
#define DEBUG_PRINT(s) if(fDebug) qtss_printf s
#define DEEP_DEBUG_PRINT(s) if(fDeepDebug) qtss_printf s
// -------------------------------------
// Constants
//
const int drefPos_VersionFlags = 0;
const int drefPos_NumRefs = 4;
const int drefPos_RefTable = 8;
const int drefRefPos_Size = 0;
const int drefRefPos_Type = 4;
const int drefRefPos_VersionFlags = 8;
const int drefRefPos_Data = 12;
// -------------------------------------
// Mac alias constants and typedefs
//
enum {
kEndMark =-1, /* -1 end of variable info */
kAbsPath = 2, /* 2 absolute path name */
kMaxMark = 10 /* End Marker */
};
typedef struct
{
short what; /* what kind of information */
short len; /* length of variable data */
char data[1]; /* actual data */
} varInfo;
typedef struct
{
char private1[130];
short nlvlFrom; /* # of levels from fromFile/toFile until a common */
short nlvlTo; /* ancestor directory is found */
char private2[16];
varInfo vdata[1]; /* variable length info */
} AliasRecordPriv;
// -------------------------------------
// Constructors and destructors
//
QTAtom_dref::QTAtom_dref(QTFile * File, QTFile::AtomTOCEntry * TOCEntry, Bool16 Debug, Bool16 DeepDebug)
: QTAtom(File, TOCEntry, Debug, DeepDebug),
fNumRefs(0), fRefs(NULL)
{
}
QTAtom_dref::~QTAtom_dref(void)
{
//+ 6.16.1999 rt fix memory leak
for( UInt32 curRef = 0; curRef < fNumRefs; curRef++ )
{
delete [] fRefs[curRef].Data;
delete fRefs[curRef].FCB;
}
//-end
//
// Free our variables.
delete[] fRefs;
}
// -------------------------------------
// Initialization functions
//
Bool16 QTAtom_dref::Initialize(void)
{
// Temporary vars
UInt32 tempInt32;
// General vars
UInt64 refPos;
//
// Parse this atom's fields.
ReadInt32(drefPos_VersionFlags, &tempInt32);
fVersion = (UInt8)((tempInt32 >> 24) & 0x000000ff);
fFlags = tempInt32 & 0x00ffffff;
ReadInt32(drefPos_NumRefs, &fNumRefs);
//
// Read in all of the refs.
if( fNumRefs > 0 ) {
//
// Allocate our ref table.
fRefs = NEW DataRefEntry[fNumRefs];
if( fRefs == NULL )
return false;
//
// Read them all in..
refPos = drefPos_RefTable;
for( UInt32 CurRef = 0; CurRef < fNumRefs; CurRef++ ) {
//
// Set up the entry.
fRefs[CurRef].Flags = 0x0;
fRefs[CurRef].ReferenceType = FOUR_CHARS_TO_INT('N', 'U', 'L', 'L'); // NULL
fRefs[CurRef].DataLength = 0;
fRefs[CurRef].Data = NULL;
fRefs[CurRef].IsEntryInitialized = false;
fRefs[CurRef].IsFileOpen = false;
fRefs[CurRef].FCB = NULL;
//
// Get the flags and type.
ReadInt32(refPos + drefRefPos_VersionFlags, &tempInt32);
fRefs[CurRef].Flags = tempInt32 & 0x00ffffff;
ReadInt32(refPos + drefRefPos_Type, &tempInt32);
fRefs[CurRef].ReferenceType = tempInt32;
//
// We're done if this is a self-referencing atom.
if( fRefs[CurRef].Flags & flagSelfRef ) {
fRefs[CurRef].IsEntryInitialized = true;
continue;
}
//
// Get all of the data.
ReadInt32(refPos + drefRefPos_Size, &tempInt32);
fRefs[CurRef].DataLength = tempInt32 - 12 /* skip the header */;
fRefs[CurRef].Data = NEW char[fRefs[CurRef].DataLength];
if( fRefs[CurRef].Data == NULL ) {
//
// De-initialize this entry.
fRefs[CurRef].DataLength = 0;
fRefs[CurRef].IsEntryInitialized = false;
} else {
//
// Read the entry data.
ReadBytes(refPos + drefRefPos_Data, fRefs[CurRef].Data, fRefs[CurRef].DataLength);
//
// Configure the rest of the entry.
fRefs[CurRef].FCB = NEW QTFile_FileControlBlock();
if( fRefs[CurRef].FCB == NULL )
fRefs[CurRef].IsEntryInitialized = false;
else
fRefs[CurRef].IsEntryInitialized = true;
fRefs[CurRef].IsFileOpen = false;
}
//
// Skip over this mini-atom.
refPos += fRefs[CurRef].DataLength + 12 /* account for the header */;
}
}
//
// This atom has been successfully read in.
return true;
}
// -------------------------------------
// Read functions.
//
Bool16 QTAtom_dref::Read(UInt32 RefID, UInt64 Offset, char * const Buffer, UInt32 Length, QTFile_FileControlBlock * FCB)
{
// General vars
DataRefEntry *Entry;
//
// Validate that this ref exists.
if( (RefID == 0) || (RefID > fNumRefs) )
return false;
// qtss_printf("QTAtom_dref::Read Offset = %qd, Length = %"_S32BITARG_" \n", Offset, Length);
//
// If this data reference is in the movie file itself, then we can forward
// the request directly to QTFile.
if( IsRefInThisFile(RefID) )
return fFile->Read(Offset, Buffer, Length, FCB);
//
// The ref is not in this file; see if we have already opened an FCB for
// the file and use that, otherwise we need to process the ref.
Entry = &fRefs[RefID - 1];
//
// Abort if the entry was not initialized.
if( !Entry->IsEntryInitialized )
return false;
//
// Open the file (after parsing the data reference) if it is not open
// already.
if( !Entry->IsFileOpen ) {
// General vars
char *AliasPath;
//
// We only support parsing alias types.
if( Entry->ReferenceType != FOUR_CHARS_TO_INT('a', 'l', 'i', 's') ) //alis
return false;
//
// Parse the alias.
if( (AliasPath = ResolveAlias(Entry->Data, Entry->DataLength)) == NULL )
return false;
//
// Create a path which does *not* contain the current movie's name.
char * p;
char * MoviePath = fFile->GetMoviePath();
char * NewPath = NEW char[strlen(MoviePath) + strlen(AliasPath) + 1];
//char * NewPath = (char *)calloc(1, strlen(MoviePath) + strlen(AliasPath));
if( (p = strrchr(MoviePath, QT_PATH_SEPARATOR)) == NULL ) {
memcpy(NewPath, AliasPath, strlen(AliasPath) + 1);
} else {
int MoviePathClippedLength = (p - MoviePath) + 1;
memcpy(NewPath, MoviePath, MoviePathClippedLength);
memcpy(NewPath + MoviePathClippedLength, AliasPath, strlen(AliasPath) + 1);
}
//
// Do the open.
Entry->FCB->Set(NewPath);
if(!Entry->FCB->IsValid()) {
delete [] NewPath;
//free(NewPath);
return false;
}
Entry->IsFileOpen = true;
delete [] NewPath;
//free(NewPath);
}
//
// Do the read.
return fFile->Read(Offset, Buffer, Length, Entry->FCB);
}
// -------------------------------------
// Debugging functions
//
void QTAtom_dref::DumpAtom(void)
{
DEBUG_PRINT(("QTAtom_dref::DumpAtom - Dumping atom.\n"));
for( UInt32 CurRef = 1; CurRef <= fNumRefs; CurRef++ )
DEBUG_PRINT(("QTAtom_dref::DumpAtom - ..Ref #%"_U32BITARG_" is in file: %s\n", CurRef, IsRefInThisFile(CurRef) ? "yes" : "no"));
}
// -------------------------------------
// Protected member functions.
//
char * QTAtom_dref::ResolveAlias(char * const AliasData, UInt32 /* AliasDataLength */)
{
// General vars
AliasRecordPriv *Alias = (AliasRecordPriv *)AliasData;
varInfo *AliasVarInfo;
char *path, *pathStart;
int pathLength;
//
// Verify that we have a relative path.
if( (Alias->nlvlTo == -1) || (Alias->nlvlFrom == -1) )
return NULL;
//
// Search for the absolute pathname in this alias.
AliasVarInfo = Alias->vdata;
for( int loopCount = kMaxMark - 1; loopCount >= 0; loopCount--) {
//
// Break out of the loop if this is a match/the end of the alias.
if( ((short)ntohs(AliasVarInfo->what) == kAbsPath) || ((short)ntohs(AliasVarInfo->what) == kEndMark) )
break;
//
// Otherwise we need to move to the next data unit.
AliasVarInfo = (varInfo *)((char *)AliasVarInfo + ((ntohs(AliasVarInfo->len) + 1) & ~1) + 4 /* header size */);
}
//
// Now that we have the path, we need to strip off the absolute portions
// of it so that we can get at it from our current (relative) root.
AliasVarInfo->data[ntohs(AliasVarInfo->len)] = '\0';
pathStart = path = AliasVarInfo->data;
path += ntohs(AliasVarInfo->len);
int i = ntohs(Alias->nlvlTo);
pathLength = -1;
while( i && (path > pathStart) ) {
if( *path-- == ':' )
i--;
pathLength++;
}
if( i == 1 )
pathLength += 2; // fell out of loop; we're relative to root
else
path += 2; // points past separator character
//
// Return the alias.
return path;
}