| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409 |
- #include "BurnCore.h"
- #include "FindFile.h"
- //---------------------------------------------------------------------------------
- void StoreFileName (char (& shortFilename) [252], char * psLongFilename, LPCSTR psFilename)
- {
- // If filename can fit in the old field, store it there
- // to prevent unnecessary allocation. If not, allocate
- // a sufficient buffer to hold the string.
- //
- int iLen = strlen (psFilename);
- if (iLen < sizeof (shortFilename))
- {
- strcpy (shortFilename, psFilename);
- }
- else
- {
- psLongFilename = new char [iLen + 1];
- if (psLongFilename != NULL)
- {
- strcpy (psLongFilename, psFilename);
- }
- }
- }
- inline LPCSTR GetFilename (const NERO_ISO_ITEM * pItem)
- {
- return (pItem->longFileName != NULL)? pItem->longFileName: pItem->fileName;
- }
- //---------------------------------------------------------------------------------
- void DeleteIsoItemTree (NERO_ISO_ITEM * pItem)
- {
- // First free our own long filename strings, then free the whole tree.
- //
- FreeOurOwnResources (pItem);
- NeroFreeIsoItemTree (pItem);
- }
- //---------------------------------------------------------------------------------
- void FreeOurOwnResources (NERO_ISO_ITEM * pItem)
- {
- // Step through the tree until the
- // ISO item tree pointer becomes NULL
- while (NULL != pItem)
- {
- NERO_ISO_ITEM* pNextItem = pItem->nextItem;
- if (pItem->isDirectory)
- {
- // We have encountered another ISO item tree;
- // recurse another level.
- FreeOurOwnResources (pItem->subDirFirstItem);
- }
- // It the item is not a reference, free its associated long
- // filenames, if any.
- //
- if (!pItem->isReference)
- {
- delete pItem->longFileName;
- delete (char *) pItem->longSourceFilePath;
- }
- pItem = pNextItem;
- }
- }
- //---------------------------------------------------------------------------------
- EXITCODE GetIsoTrack (string s_VolumeName,const CFileList *fList,CNeroIsoTrack** ppIsoTrack, NERO_ISO_ITEM** ppItem)
- {
- *ppIsoTrack = NULL;
- // Iterate through the file list and it each one to the tree.
- // If directory is stumbled upon, recurse it and it all of
- // its contents.
- for (CFileList::const_iterator it=fList->begin();
- it!=fList->end();it++)
- {
- NERO_ISO_ITEM* pItem=NULL;
- EXITCODE code;
- // Create a tree from the filename supplied.
- code = CreateIsoTree ((*it)->Recursive, (*it)->szLocalPath.c_str(), &pItem);
- // If there was a problem creating the tree then delete
- // the whole tree that has been created so far and
- // return the error code.
- if (code != EXITCODE_OK)
- {
- DeleteIsoItemTree (*ppItem);
- *ppItem=NULL;
- return code;
- }
- // Merge the new track with the existing one. The user could
- // specify similar paths/content on the command line. We must make
- // sure the duplicates are weeded out. If return value is false,
- // we need to quit.
- //
- if (!MergeIsoTrack (ppItem, pItem))
- {
- return EXITCODE_FAILED_TO_CREATE_ISO_TRACK;
- }
- }
- if (NULL != *ppItem)
- {
-
- // This is used only for debugging purposese. Never allow this
- // call to take place in Release code.
- //
- // DebugPrintIsoTrack (*ppItem);
- DWORD dwFlags=NCITEF_USE_JOLIET|NCITEF_CREATE_ISO_FS;
- NERO_CITE_ARGS citeArgs;
- memset (&citeArgs, 0, sizeof (citeArgs));
- citeArgs.dwBurnOptions = dwFlags;
- citeArgs.name = s_VolumeName.c_str();
- citeArgs.firstRootItem = *ppItem;
- /*
- citeArgs.abstract = params.GetAbstract ();
- citeArgs.application = params.GetApplication ();
- citeArgs.bibliographic = params.GetBibliographic ();
- citeArgs.copyright = params.GetCopyright ();
- citeArgs.dataPreparer = params.GetDataPreparer ();
- citeArgs.publisher = params.GetPublisher ();
- citeArgs.systemIdentifier = params.GetSystemIdentifier ();
- citeArgs.volumeSet = params.GetVolumeSet ();
- */
- // Finally, create the ISO track.
- *ppIsoTrack = NeroCreateIsoTrackEx (NULL,
- (const char *) &citeArgs,
- NCITEF_USE_STRUCT);
- // If the ISO track could not be created then delete the
- // ISO item tree and return with an error
- if (NULL == *ppIsoTrack)
- {
- DeleteIsoItemTree (*ppItem);
- return EXITCODE_FAILED_TO_CREATE_ISO_TRACK;
- }
- }
- return EXITCODE_OK;
- }
- //---------------------------------------------------------------
- EXITCODE CreateIsoTree (bool Recursive, LPCSTR psFilename, NERO_ISO_ITEM ** ppItem, int iLevel)
- {
- // CFindFiles is a helper class for file and subdirectory handling
- CFindFiles ff (psFilename);
- *ppItem = NULL;
- if (!ff.IsValidEntry())
- {
- if (0 == iLevel)
- {
- // If we haven't found any entries and we are on the
- // first level of recursion then this should be
- // reported as an error.
- return EXITCODE_FILE_NOT_FOUND;
- }
- else
- {
- // If we are on a level other than first, it is ok
- // not to find any entries. This simply means we
- // stumbled upon an empty directory somewhere in a tree.
- return EXITCODE_OK;
- }
- }
- char sPath[MAX_PATH];
- // Make sure that we have no relative path names, but only absolute paths
- if (NULL == _fullpath (sPath, psFilename, sizeof (sPath)))
- {
- // Our path buffer is too small. Bail out!
- return EXITCODE_INTERNAL_ERROR;
- }
- // Find the last blackslash and remove it if found.
- // This will leave us with a root directory.
- LPSTR psBackslash = strrchr (sPath, '\\');
- if (NULL != psBackslash)
- {
- *psBackslash = '\0';
- }
- do
- {
- std::string sNewPath;
- sNewPath = sPath;
- sNewPath += "\\";
- sNewPath += ff.GetName ();
- if (ff.IsSubDir())
- {
- // Here we handle subdirectories
- // strcmp returns 0 on equal strings.
- // Proceed if name contains none of "." or ".."
- if ((0 != strcmp (ff.GetName (), ".")) && (0 != strcmp (ff.GetName (), "..")))
- {
- // Append a wildcard to the path and do a recursive search.
- sNewPath += "\\";
- sNewPath += ff.GetWildcard ();
- NERO_ISO_ITEM * pNewItem = NeroCreateIsoItem ();
- if (NULL == pNewItem)
- {
- DeleteIsoItemTree (*ppItem);
- return EXITCODE_OUT_OF_MEMORY;
- }
- // Attach this item to the beginning of the list.
- if (*ppItem != NULL)
- {
- pNewItem->nextItem = *ppItem;
- }
- *ppItem = pNewItem;
- pNewItem->isDirectory = TRUE;
- time_t t = ff.GetCreateTime ();
- pNewItem->entryTime = *localtime (&t);
- StoreFileName (pNewItem->fileName, pNewItem->longFileName, ff.GetName ());
- // If we the user wants recursive search, only then do we
- // actually recurse at deeper levels otherwise ignore directories
- // alltogether.
- //
- if (Recursive)
- {
- // Create an ISO item tree at a deeper level
- EXITCODE code = CreateIsoTree (Recursive, sNewPath.c_str (), &pNewItem->subDirFirstItem, iLevel + 1);
- if (EXITCODE_OK != code)
- {
- DeleteIsoItemTree (*ppItem);
- return code;
- }
- // We don't allow empty directories. This should probably
- // be regulated by a command line switch.
- //
- if (pNewItem->subDirFirstItem == NULL)
- {
- // If the newly added directory is empty, remove it!
- // We first detach it from the list and then
- // deallocate it.
- //
- *ppItem = pNewItem->nextItem;
- pNewItem->nextItem = NULL;
- DeleteIsoItemTree (pNewItem);
- }
- }
- }
- }
- else
- {
- // Here we handle regular files
- NERO_ISO_ITEM * pNewItem = NeroCreateIsoItem ();
- if (NULL == pNewItem)
- {
- DeleteIsoItemTree (*ppItem);
- return EXITCODE_OUT_OF_MEMORY;
- }
- StoreFileName (pNewItem->sourceFilePath, (char *) pNewItem->longSourceFilePath, sNewPath.c_str ());
- pNewItem->isDirectory = FALSE;
- time_t t = ff.GetCreateTime ();
- pNewItem->entryTime = *localtime (&t);
- StoreFileName (pNewItem->fileName, pNewItem->longFileName, ff.GetName ());
- // Attach this item to the beginning of the list.
- if (*ppItem != NULL)
- {
- pNewItem->nextItem = *ppItem;
- }
- *ppItem = pNewItem;
- }
- ff.FindNext ();
- }
- while (ff.IsValidEntry ());
- return EXITCODE_OK;
- }
- bool MergeIsoTrack (NERO_ISO_ITEM ** ppItemFirst, NERO_ISO_ITEM * pItemToAdd)
- {
- bool bSuccess = true;
- // Two loops. Outter loops the first tree, the inner loops the second
- // tree.
- //
- for (; bSuccess && *ppItemFirst != NULL; ppItemFirst = &(*ppItemFirst)->nextItem)
- {
- for (NERO_ISO_ITEM ** ppItemSecond = &pItemToAdd; *ppItemSecond != NULL; )
- {
- // Compare entry names...
- //
- if ((*ppItemFirst)->isDirectory == (*ppItemSecond)->isDirectory &&
- 0 == stricmp (GetFilename (*ppItemFirst), GetFilename (*ppItemSecond)))
- {
- bool bReplace = true;
- // The items point to the same file/directory. We need
- // to remove one of them. Which one is removed depends
- // on whether "--backup" is specified on command line.
- // If it is a directory, make sure to recurse anyway
- // because the trees below may not be identical.
- //
- if ((*ppItemFirst)->isDirectory)
- {
- bSuccess = MergeIsoTrack (&(*ppItemFirst)->subDirFirstItem, (*ppItemSecond)->subDirFirstItem);
- (*ppItemSecond)->subDirFirstItem = NULL;
- if (!bSuccess)
- {
- break;
- }
- // Since the item is a directory, we won't replace
- // the old one as it doesn't matter which one we
- // keep. Directory is just a name. It has no file
- // access time stamp.
- //
- bReplace = false;
- }
- else
- {
- // If there is a file name conflict between iso items
- // that don't belong to imported sessions, ask the user
- // what to do.
- //
- if (!(*ppItemFirst)->isReference)
- {
- time_t timeOld = mktime (&(*ppItemFirst)->entryTime);
- time_t timeNew = mktime (&(*ppItemSecond)->entryTime);
- bReplace = timeOld < timeNew;
- }
- }
- if (bReplace)
- {
- // We will now switch places of items in the first and
- // second tree. Since one of the items has to be deleted
- // eventually, this operation will essentially keep
- // the item from the second tree and delete the item
- // from the first tree.
- //
- NERO_ISO_ITEM * pTempItem = *ppItemSecond;
- *ppItemSecond = *ppItemFirst;
- *ppItemFirst = pTempItem;
- pTempItem = (*ppItemSecond)->nextItem;
- (*ppItemSecond)->nextItem = (*ppItemFirst)->nextItem;
- (*ppItemFirst)->nextItem = pTempItem;
- }
- // Remove the item from the second tree.
- //
- NERO_ISO_ITEM * pTempItem = *ppItemSecond;
- *ppItemSecond = pTempItem->nextItem;
- pTempItem->nextItem = NULL;
- DeleteIsoItemTree (pTempItem);
- }
- else
- {
- // No match, advance to the next item.
- //
- ppItemSecond = &(*ppItemSecond)->nextItem;
- }
- }
- }
- // Attach whatever is left of the new tree to the main tree.
- //
- *ppItemFirst = pItemToAdd;
- // Returning true means, everything is fine, continue.
- //
- return bSuccess;
- }
|