mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 22:02:58 +00:00
- Add a function MatchFileNamePattern for matching a file against a pattern (imported from Busybox under GPL2 or later license, heavily modified for our purposes, more information in the function comments)
- Add support for multiple search criterias, which are actually checked. This makes it possible to pass parameters like "*.rbuild *.txt" to the cabman command line for adding, displaying and extracting files in a cabinet. - Overhaul CreateSimpleCabinet, make it able to add multiple files to the cabinet using the new search criteria functions. - Fix some comments and indentation here and there. svn path=/trunk/; revision=32127
This commit is contained in:
parent
38c6c12999
commit
7356090407
5 changed files with 401 additions and 82 deletions
|
@ -18,6 +18,9 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#if !defined(WIN32)
|
||||||
|
# include <dirent.h>
|
||||||
|
#endif
|
||||||
#if defined(__FreeBSD__) || defined(__APPLE__)
|
#if defined(__FreeBSD__) || defined(__APPLE__)
|
||||||
# include <sys/stat.h>
|
# include <sys/stat.h>
|
||||||
#endif // __FreeBSD__
|
#endif // __FreeBSD__
|
||||||
|
@ -315,10 +318,12 @@ CCabinet::CCabinet()
|
||||||
CabinetReservedFileBuffer = NULL;
|
CabinetReservedFileBuffer = NULL;
|
||||||
CabinetReservedFileSize = 0;
|
CabinetReservedFileSize = 0;
|
||||||
|
|
||||||
FolderListHead = NULL;
|
FolderListHead = NULL;
|
||||||
FolderListTail = NULL;
|
FolderListTail = NULL;
|
||||||
FileListHead = NULL;
|
FileListHead = NULL;
|
||||||
FileListTail = NULL;
|
FileListTail = NULL;
|
||||||
|
CriteriaListHead = NULL;
|
||||||
|
CriteriaListTail = NULL;
|
||||||
|
|
||||||
Codec = NULL;
|
Codec = NULL;
|
||||||
CodecId = -1;
|
CodecId = -1;
|
||||||
|
@ -511,6 +516,82 @@ void CCabinet::SetDestinationPath(char* DestinationPath)
|
||||||
NormalizePath(DestPath, MAX_PATH);
|
NormalizePath(DestPath, MAX_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ULONG CCabinet::AddSearchCriteria(char* SearchCriteria)
|
||||||
|
/*
|
||||||
|
* FUNCTION: Adds a criteria to the search criteria list
|
||||||
|
* ARGUMENTS:
|
||||||
|
* SearchCriteria = String with the search criteria to add
|
||||||
|
* RETURNS:
|
||||||
|
* Status of operation
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
PSEARCH_CRITERIA Criteria;
|
||||||
|
|
||||||
|
// Add the criteria to the list of search criteria
|
||||||
|
Criteria = (PSEARCH_CRITERIA)AllocateMemory(sizeof(SEARCH_CRITERIA));
|
||||||
|
if(!Criteria)
|
||||||
|
{
|
||||||
|
DPRINT(MIN_TRACE, ("Insufficient memory.\n"));
|
||||||
|
return CAB_STATUS_NOMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
Criteria->Prev = CriteriaListTail;
|
||||||
|
Criteria->Next = NULL;
|
||||||
|
|
||||||
|
if(CriteriaListTail)
|
||||||
|
CriteriaListTail->Next = Criteria;
|
||||||
|
else
|
||||||
|
CriteriaListHead = Criteria;
|
||||||
|
|
||||||
|
CriteriaListTail = Criteria;
|
||||||
|
|
||||||
|
// Set the actual criteria string
|
||||||
|
Criteria->Search = (char*)AllocateMemory(strlen(SearchCriteria) + 1);
|
||||||
|
if (!Criteria->Search)
|
||||||
|
{
|
||||||
|
DPRINT(MIN_TRACE, ("Insufficient memory.\n"));
|
||||||
|
return CAB_STATUS_NOMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(Criteria->Search, SearchCriteria);
|
||||||
|
|
||||||
|
return CAB_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCabinet::DestroySearchCriteria()
|
||||||
|
/*
|
||||||
|
* FUNCTION: Destroys the list with the search criteria
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
PSEARCH_CRITERIA Criteria;
|
||||||
|
PSEARCH_CRITERIA NextCriteria;
|
||||||
|
|
||||||
|
Criteria = CriteriaListHead;
|
||||||
|
|
||||||
|
while(Criteria)
|
||||||
|
{
|
||||||
|
NextCriteria = Criteria->Next;
|
||||||
|
|
||||||
|
FreeMemory(Criteria->Search);
|
||||||
|
FreeMemory(Criteria);
|
||||||
|
|
||||||
|
Criteria = NextCriteria;
|
||||||
|
}
|
||||||
|
|
||||||
|
CriteriaListHead = NULL;
|
||||||
|
CriteriaListTail = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCabinet::HasSearchCriteria()
|
||||||
|
/*
|
||||||
|
* FUNCTION: Returns whether we have search criteria
|
||||||
|
* RETURNS:
|
||||||
|
* Whether we have search criteria or not.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
return (CriteriaListHead != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
bool CCabinet::SetCompressionCodec(char* CodecName)
|
bool CCabinet::SetCompressionCodec(char* CodecName)
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Selects the codec to use for compression
|
* FUNCTION: Selects the codec to use for compression
|
||||||
|
@ -821,19 +902,16 @@ void CCabinet::Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ULONG CCabinet::FindFirst(char* FileName,
|
ULONG CCabinet::FindFirst(PCAB_SEARCH Search)
|
||||||
PCAB_SEARCH Search)
|
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Finds the first file in the cabinet that matches a search criteria
|
* FUNCTION: Finds the first file in the cabinet that matches a search criteria
|
||||||
* ARGUMENTS:
|
* ARGUMENTS:
|
||||||
* FileName = Pointer to search criteria
|
|
||||||
* Search = Pointer to search structure
|
* Search = Pointer to search structure
|
||||||
* RETURNS:
|
* RETURNS:
|
||||||
* Status of operation
|
* Status of operation
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
RestartSearch = false;
|
RestartSearch = false;
|
||||||
strncpy(Search->Search, FileName, MAX_PATH);
|
|
||||||
Search->Next = FileListHead;
|
Search->Next = FileListHead;
|
||||||
return FindNext(Search);
|
return FindNext(Search);
|
||||||
}
|
}
|
||||||
|
@ -848,6 +926,8 @@ ULONG CCabinet::FindNext(PCAB_SEARCH Search)
|
||||||
* Status of operation
|
* Status of operation
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
|
bool bFound = false;
|
||||||
|
PSEARCH_CRITERIA Criteria;
|
||||||
ULONG Status;
|
ULONG Status;
|
||||||
|
|
||||||
if (RestartSearch)
|
if (RestartSearch)
|
||||||
|
@ -867,7 +947,32 @@ ULONG CCabinet::FindNext(PCAB_SEARCH Search)
|
||||||
RestartSearch = false;
|
RestartSearch = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Check search criteria */
|
/* Check each search criteria against each file */
|
||||||
|
while(Search->Next)
|
||||||
|
{
|
||||||
|
// Some features (like displaying cabinets) don't require search criteria, so we can just break here.
|
||||||
|
// If a feature requires it, handle this in the ParseCmdline() function in "main.cxx".
|
||||||
|
if(!CriteriaListHead)
|
||||||
|
break;
|
||||||
|
|
||||||
|
Criteria = CriteriaListHead;
|
||||||
|
|
||||||
|
while(Criteria)
|
||||||
|
{
|
||||||
|
if(MatchFileNamePattern(Search->Next->FileName, Criteria->Search))
|
||||||
|
{
|
||||||
|
bFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Criteria = Criteria->Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bFound)
|
||||||
|
break;
|
||||||
|
|
||||||
|
Search->Next = Search->Next->Next;
|
||||||
|
}
|
||||||
|
|
||||||
if (!Search->Next)
|
if (!Search->Next)
|
||||||
{
|
{
|
||||||
|
@ -1960,6 +2065,151 @@ ULONG CCabinet::AddFile(char* FileName)
|
||||||
return CAB_STATUS_SUCCESS;
|
return CAB_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CCabinet::CreateSimpleCabinet()
|
||||||
|
/*
|
||||||
|
* FUNCTION: Create a simple cabinet based on the files in the criteria list
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
bool bRet = false;
|
||||||
|
char* pszFile;
|
||||||
|
char szFilePath[MAX_PATH];
|
||||||
|
char szFile[MAX_PATH];
|
||||||
|
PSEARCH_CRITERIA Criteria;
|
||||||
|
ULONG Status;
|
||||||
|
|
||||||
|
#if defined(WIN32)
|
||||||
|
HANDLE hFind;
|
||||||
|
WIN32_FIND_DATA FindFileData;
|
||||||
|
#else
|
||||||
|
DIR* dirp;
|
||||||
|
struct dirent* dp;
|
||||||
|
struct stat stbuf;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Initialize a new cabinet
|
||||||
|
Status = NewCabinet();
|
||||||
|
if (Status != CAB_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
DPRINT(MIN_TRACE, ("Cannot create cabinet (%u).\n", (UINT)Status));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add each file in the criteria list
|
||||||
|
Criteria = CriteriaListHead;
|
||||||
|
|
||||||
|
while(Criteria)
|
||||||
|
{
|
||||||
|
// Store the file path with a trailing slash in szFilePath
|
||||||
|
pszFile = strrchr(Criteria->Search, '/');
|
||||||
|
if(!pszFile)
|
||||||
|
pszFile = strrchr(Criteria->Search, '\\');
|
||||||
|
|
||||||
|
if(pszFile)
|
||||||
|
{
|
||||||
|
strncpy(szFilePath, Criteria->Search, pszFile - Criteria->Search + 1);
|
||||||
|
szFilePath[pszFile - Criteria->Search + 1] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
szFilePath[0] = 0;
|
||||||
|
|
||||||
|
#if defined(WIN32)
|
||||||
|
// Windows: Use the easy FindFirstFile/FindNextFile API for getting all files and checking them against the pattern
|
||||||
|
hFind = FindFirstFile(Criteria->Search, &FindFileData);
|
||||||
|
|
||||||
|
// Don't stop if a search criteria is not found
|
||||||
|
if(hFind == INVALID_HANDLE_VALUE && GetLastError() != ERROR_FILE_NOT_FOUND)
|
||||||
|
{
|
||||||
|
DPRINT(MIN_TRACE, ("FindFirstFile failed, Criteria: %s, error code is %u\n", Criteria->Search, (UINT)GetLastError()));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if(!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
||||||
|
{
|
||||||
|
strcpy(szFile, szFilePath);
|
||||||
|
strcat(szFile, FindFileData.cFileName);
|
||||||
|
|
||||||
|
Status = AddFile(szFile);
|
||||||
|
|
||||||
|
if(Status != CAB_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
DPRINT(MIN_TRACE, ("Cannot add file to cabinet (%u).\n", (UINT)Status));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(FindNextFile(hFind, &FindFileData));
|
||||||
|
|
||||||
|
FindClose(hFind);
|
||||||
|
#else
|
||||||
|
// Unix: Use opendir/readdir to loop through all entries, stat to check if it's a file and MatchFileNamePattern to match the file against the pattern
|
||||||
|
if(szFilePath[0] == 0)
|
||||||
|
strcpy(szFilePath, "./");
|
||||||
|
|
||||||
|
dirp = opendir(szFilePath);
|
||||||
|
|
||||||
|
if(dirp)
|
||||||
|
{
|
||||||
|
while( (dp = readdir(dirp)) )
|
||||||
|
{
|
||||||
|
strcpy(szFile, szFilePath);
|
||||||
|
strcat(szFile, dp->d_name);
|
||||||
|
|
||||||
|
if(stat(szFile, &stbuf) == 0)
|
||||||
|
{
|
||||||
|
if(stbuf.st_mode != S_IFDIR)
|
||||||
|
{
|
||||||
|
// As we added "./" to szFilePath above, szFile might contain "./test.txt" now and Criteria->Search "test.txt".
|
||||||
|
// Therefore they won't match using MatchFileNamePattern. By using pszFile here, we can avoid this problem.
|
||||||
|
if(szFile[0] == '.' && szFile[1] == '/')
|
||||||
|
pszFile = szFile + 2;
|
||||||
|
else
|
||||||
|
pszFile = szFile;
|
||||||
|
|
||||||
|
if(MatchFileNamePattern(pszFile, Criteria->Search))
|
||||||
|
{
|
||||||
|
Status = AddFile(szFile);
|
||||||
|
|
||||||
|
if(Status != CAB_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
DPRINT(MIN_TRACE, ("Cannot add file to cabinet (%u).\n", (UINT)Status));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINT(MIN_TRACE, ("stat failed, error code is %i\n", errno));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dirp);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Criteria = Criteria->Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = WriteDisk(false);
|
||||||
|
if (Status == CAB_STATUS_SUCCESS)
|
||||||
|
Status = CloseDisk();
|
||||||
|
if (Status != CAB_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
DPRINT(MIN_TRACE, ("Cannot write disk (%u).\n", (UINT)Status));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseCabinet();
|
||||||
|
bRet = true;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
DestroySearchCriteria();
|
||||||
|
return bRet;
|
||||||
|
}
|
||||||
|
|
||||||
void CCabinet::SetMaxDiskSize(ULONG Size)
|
void CCabinet::SetMaxDiskSize(ULONG Size)
|
||||||
/*
|
/*
|
||||||
|
@ -2509,8 +2759,6 @@ void CCabinet::DestroyDataNodes(PCFFOLDER_NODE FolderNode)
|
||||||
void CCabinet::DestroyFileNodes()
|
void CCabinet::DestroyFileNodes()
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Destroys file nodes
|
* FUNCTION: Destroys file nodes
|
||||||
* ARGUMENTS:
|
|
||||||
* FolderNode = Pointer to folder node
|
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
PCFFILE_NODE PrevNode;
|
PCFFILE_NODE PrevNode;
|
||||||
|
@ -2641,8 +2889,8 @@ void CCabinet::DestroyDeletedFolderNodes()
|
||||||
|
|
||||||
|
|
||||||
ULONG CCabinet::ComputeChecksum(void* Buffer,
|
ULONG CCabinet::ComputeChecksum(void* Buffer,
|
||||||
ULONG Size,
|
ULONG Size,
|
||||||
ULONG Seed)
|
ULONG Seed)
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Computes checksum for data block
|
* FUNCTION: Computes checksum for data block
|
||||||
* ARGUMENTS:
|
* ARGUMENTS:
|
||||||
|
@ -2700,8 +2948,8 @@ ULONG CCabinet::ComputeChecksum(void* Buffer,
|
||||||
|
|
||||||
|
|
||||||
ULONG CCabinet::ReadBlock(void* Buffer,
|
ULONG CCabinet::ReadBlock(void* Buffer,
|
||||||
ULONG Size,
|
ULONG Size,
|
||||||
PULONG BytesRead)
|
PULONG BytesRead)
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Read a block of data from file
|
* FUNCTION: Read a block of data from file
|
||||||
* ARGUMENTS:
|
* ARGUMENTS:
|
||||||
|
@ -2718,6 +2966,67 @@ ULONG CCabinet::ReadBlock(void* Buffer,
|
||||||
return CAB_STATUS_SUCCESS;
|
return CAB_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CCabinet::MatchFileNamePattern(char* FileName, char* Pattern)
|
||||||
|
/*
|
||||||
|
* FUNCTION: Matches a wildcard character pattern against a file
|
||||||
|
* ARGUMENTS:
|
||||||
|
* FileName = The file name to check
|
||||||
|
* Pattern = The pattern
|
||||||
|
* RETURNS:
|
||||||
|
* Whether the pattern matches the file
|
||||||
|
*
|
||||||
|
* COPYRIGHT:
|
||||||
|
* This function is based on Busybox code, Copyright (C) 1998 by Erik Andersen, released under GPL2 or any later version.
|
||||||
|
* Adapted from code written by Ingo Wilken.
|
||||||
|
* Original location: http://www.busybox.net/cgi-bin/viewcvs.cgi/trunk/busybox/utility.c?rev=5&view=markup
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
char* retryPattern = NULL;
|
||||||
|
char* retryFileName = NULL;
|
||||||
|
char ch;
|
||||||
|
|
||||||
|
while (*FileName || *Pattern)
|
||||||
|
{
|
||||||
|
ch = *Pattern++;
|
||||||
|
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case '*':
|
||||||
|
retryPattern = Pattern;
|
||||||
|
retryFileName = FileName;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '?':
|
||||||
|
if (*FileName++ == '\0')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (*FileName == ch)
|
||||||
|
{
|
||||||
|
if (*FileName)
|
||||||
|
FileName++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*FileName)
|
||||||
|
{
|
||||||
|
Pattern = retryPattern;
|
||||||
|
FileName = ++retryFileName;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Pattern)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef CAB_READ_ONLY
|
#ifndef CAB_READ_ONLY
|
||||||
|
|
||||||
ULONG CCabinet::InitCabinetHeader()
|
ULONG CCabinet::InitCabinetHeader()
|
||||||
|
|
|
@ -224,13 +224,18 @@ typedef struct _CFFILE_NODE
|
||||||
PCFFOLDER_NODE FolderNode; // Folder this file belong to
|
PCFFOLDER_NODE FolderNode; // Folder this file belong to
|
||||||
} CFFILE_NODE, *PCFFILE_NODE;
|
} CFFILE_NODE, *PCFFILE_NODE;
|
||||||
|
|
||||||
|
typedef struct _SEARCH_CRITERIA
|
||||||
|
{
|
||||||
|
struct _SEARCH_CRITERIA *Next; // Pointer to next search criteria
|
||||||
|
struct _SEARCH_CRITERIA *Prev; // Pointer to previous search criteria
|
||||||
|
char* Search; // The actual search criteria
|
||||||
|
} SEARCH_CRITERIA, *PSEARCH_CRITERIA;
|
||||||
|
|
||||||
typedef struct _CAB_SEARCH
|
typedef struct _CAB_SEARCH
|
||||||
{
|
{
|
||||||
char Search[MAX_PATH]; // Search criteria
|
PCFFILE_NODE Next; // Pointer to next node
|
||||||
PCFFILE_NODE Next; // Pointer to next node
|
PCFFILE File; // Pointer to current CFFILE
|
||||||
PCFFILE File; // Pointer to current CFFILE
|
char* FileName; // Current filename
|
||||||
char* FileName; // Current filename
|
|
||||||
} CAB_SEARCH, *PCAB_SEARCH;
|
} CAB_SEARCH, *PCAB_SEARCH;
|
||||||
|
|
||||||
|
|
||||||
|
@ -345,16 +350,25 @@ public:
|
||||||
/* Closes the current open cabinet file */
|
/* Closes the current open cabinet file */
|
||||||
void Close();
|
void Close();
|
||||||
/* Locates the first file in the current cabinet file that matches a search criteria */
|
/* Locates the first file in the current cabinet file that matches a search criteria */
|
||||||
ULONG FindFirst(char* FileName, PCAB_SEARCH Search);
|
ULONG FindFirst(PCAB_SEARCH Search);
|
||||||
/* Locates the next file in the current cabinet file */
|
/* Locates the next file in the current cabinet file */
|
||||||
ULONG FindNext(PCAB_SEARCH Search);
|
ULONG FindNext(PCAB_SEARCH Search);
|
||||||
/* Extracts a file from the current cabinet file */
|
/* Extracts a file from the current cabinet file */
|
||||||
ULONG ExtractFile(char* FileName);
|
ULONG ExtractFile(char* FileName);
|
||||||
/* Select codec engine to use */
|
/* Select codec engine to use */
|
||||||
void SelectCodec(LONG Id);
|
void SelectCodec(LONG Id);
|
||||||
/* Returns if a codec engine is selected */
|
/* Returns whether a codec engine is selected */
|
||||||
bool IsCodecSelected();
|
bool IsCodecSelected();
|
||||||
|
/* Adds a search criteria for adding files to a simple cabinet, displaying files in a cabinet or extracting them */
|
||||||
|
ULONG AddSearchCriteria(char* SearchCriteria);
|
||||||
|
/* Destroys the search criteria list */
|
||||||
|
void DestroySearchCriteria();
|
||||||
|
/* Returns whether we have search criteria */
|
||||||
|
bool HasSearchCriteria();
|
||||||
|
|
||||||
#ifndef CAB_READ_ONLY
|
#ifndef CAB_READ_ONLY
|
||||||
|
/* Creates a simple cabinet based on the search criteria data */
|
||||||
|
bool CreateSimpleCabinet();
|
||||||
/* Sets the codec to use for compression (based on a string value) */
|
/* Sets the codec to use for compression (based on a string value) */
|
||||||
bool SetCompressionCodec(char* CodecName);
|
bool SetCompressionCodec(char* CodecName);
|
||||||
/* Creates a new cabinet file */
|
/* Creates a new cabinet file */
|
||||||
|
@ -412,6 +426,7 @@ private:
|
||||||
void DestroyDeletedFolderNodes();
|
void DestroyDeletedFolderNodes();
|
||||||
ULONG ComputeChecksum(void* Buffer, ULONG Size, ULONG Seed);
|
ULONG ComputeChecksum(void* Buffer, ULONG Size, ULONG Seed);
|
||||||
ULONG ReadBlock(void* Buffer, ULONG Size, PULONG BytesRead);
|
ULONG ReadBlock(void* Buffer, ULONG Size, PULONG BytesRead);
|
||||||
|
bool MatchFileNamePattern(char* FileName, char* Pattern);
|
||||||
#ifndef CAB_READ_ONLY
|
#ifndef CAB_READ_ONLY
|
||||||
ULONG InitCabinetHeader();
|
ULONG InitCabinetHeader();
|
||||||
ULONG WriteCabinetHeader(bool MoreDisks);
|
ULONG WriteCabinetHeader(bool MoreDisks);
|
||||||
|
@ -455,6 +470,8 @@ private:
|
||||||
PCFDATA_NODE CurrentDataNode;
|
PCFDATA_NODE CurrentDataNode;
|
||||||
PCFFILE_NODE FileListHead;
|
PCFFILE_NODE FileListHead;
|
||||||
PCFFILE_NODE FileListTail;
|
PCFFILE_NODE FileListTail;
|
||||||
|
PSEARCH_CRITERIA CriteriaListHead;
|
||||||
|
PSEARCH_CRITERIA CriteriaListTail;
|
||||||
CCABCodec *Codec;
|
CCABCodec *Codec;
|
||||||
LONG CodecId;
|
LONG CodecId;
|
||||||
bool CodecSelected;
|
bool CodecSelected;
|
||||||
|
|
|
@ -27,7 +27,6 @@ public:
|
||||||
private:
|
private:
|
||||||
void Usage();
|
void Usage();
|
||||||
bool CreateCabinet();
|
bool CreateCabinet();
|
||||||
bool CreateSimpleCabinet();
|
|
||||||
bool DisplayCabinet();
|
bool DisplayCabinet();
|
||||||
bool ExtractFromCabinet();
|
bool ExtractFromCabinet();
|
||||||
/* Event handlers */
|
/* Event handlers */
|
||||||
|
@ -39,7 +38,6 @@ private:
|
||||||
bool ProcessAll;
|
bool ProcessAll;
|
||||||
ULONG Mode;
|
ULONG Mode;
|
||||||
bool PromptOnOverwrite;
|
bool PromptOnOverwrite;
|
||||||
char Location[MAX_PATH];
|
|
||||||
char FileName[MAX_PATH];
|
char FileName[MAX_PATH];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -391,7 +391,7 @@ ULONG CDFParser::Parse()
|
||||||
|
|
||||||
if (!InfFileOnly)
|
if (!InfFileOnly)
|
||||||
{
|
{
|
||||||
printf("\nWriting cabinet. This may take a while...\n\n");
|
printf("\nWriting cabinet. This may take a while...\n\n");
|
||||||
|
|
||||||
if (DiskCreated)
|
if (DiskCreated)
|
||||||
{
|
{
|
||||||
|
|
|
@ -172,6 +172,7 @@ CCABManager::CCABManager()
|
||||||
ProcessAll = false;
|
ProcessAll = false;
|
||||||
InfFileOnly = false;
|
InfFileOnly = false;
|
||||||
Mode = CM_MODE_DISPLAY;
|
Mode = CM_MODE_DISPLAY;
|
||||||
|
FileName[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -190,8 +191,8 @@ void CCABManager::Usage()
|
||||||
{
|
{
|
||||||
printf("ReactOS Cabinet Manager\n\n");
|
printf("ReactOS Cabinet Manager\n\n");
|
||||||
printf("CABMAN [-D | -E] [-A] [-L dir] cabinet [filename ...]\n");
|
printf("CABMAN [-D | -E] [-A] [-L dir] cabinet [filename ...]\n");
|
||||||
printf("CABMAN -C dirfile [-I] [-RC file] [-P dir]\n");
|
printf("CABMAN [-M mode] -C dirfile [-I] [-RC file] [-P dir]\n");
|
||||||
printf("CABMAN -S cabinet filename\n");
|
printf("CABMAN [-M mode] -S cabinet filename ...\n");
|
||||||
printf(" cabinet Cabinet file.\n");
|
printf(" cabinet Cabinet file.\n");
|
||||||
printf(" filename Name of the file to extract from the cabinet.\n");
|
printf(" filename Name of the file to extract from the cabinet.\n");
|
||||||
printf(" Wild cards and multiple filenames\n");
|
printf(" Wild cards and multiple filenames\n");
|
||||||
|
@ -207,7 +208,7 @@ void CCABManager::Usage()
|
||||||
printf(" -I Don't create the cabinet, only the .inf file.\n");
|
printf(" -I Don't create the cabinet, only the .inf file.\n");
|
||||||
printf(" -L dir Location to place extracted or generated files\n");
|
printf(" -L dir Location to place extracted or generated files\n");
|
||||||
printf(" (default is current directory).\n");
|
printf(" (default is current directory).\n");
|
||||||
printf(" -M Specify the compression method to use\n");
|
printf(" -M mode Specify the compression method to use:\n");
|
||||||
printf(" raw - No compression\n");
|
printf(" raw - No compression\n");
|
||||||
printf(" mszip - MsZip compression (default)\n");
|
printf(" mszip - MsZip compression (default)\n");
|
||||||
printf(" -N Don't create the .inf file, only the cabinet.\n");
|
printf(" -N Don't create the .inf file, only the cabinet.\n");
|
||||||
|
@ -351,10 +352,23 @@ bool CCABManager::ParseCmdline(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((FoundCabinet) || (Mode == CM_MODE_CREATE))
|
if(Mode == CM_MODE_CREATE)
|
||||||
{
|
{
|
||||||
/* FIXME: There may be many of these if Mode != CM_MODE_CREATE */
|
if(FileName[0])
|
||||||
strcpy(FileName, argv[i]);
|
{
|
||||||
|
printf("You may only specify one directive file!\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// For creating cabinets, this argument is the path to the directive file
|
||||||
|
strcpy(FileName, argv[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(FoundCabinet)
|
||||||
|
{
|
||||||
|
// For creating simple cabinets, displaying or extracting them, add the argument as a search criteria
|
||||||
|
AddSearchCriteria(argv[i]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -366,14 +380,21 @@ bool CCABManager::ParseCmdline(int argc, char* argv[])
|
||||||
|
|
||||||
if (ShowUsage)
|
if (ShowUsage)
|
||||||
{
|
{
|
||||||
Usage();
|
Usage();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select MsZip by default for creating cabinets
|
// Select MsZip by default for creating cabinets
|
||||||
if( (Mode == CM_MODE_CREATE || Mode == CM_MODE_CREATE_SIMPLE) && !IsCodecSelected() )
|
if( (Mode == CM_MODE_CREATE || Mode == CM_MODE_CREATE_SIMPLE) && !IsCodecSelected() )
|
||||||
SelectCodec(CAB_CODEC_MSZIP);
|
SelectCodec(CAB_CODEC_MSZIP);
|
||||||
|
|
||||||
|
// Search criteria (= the filename argument) is necessary for creating a simple cabinet
|
||||||
|
if( Mode == CM_MODE_CREATE_SIMPLE && !HasSearchCriteria())
|
||||||
|
{
|
||||||
|
printf("You have to enter input file names!\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,43 +418,6 @@ bool CCABManager::CreateCabinet()
|
||||||
return (Status == CAB_STATUS_SUCCESS ? true : false);
|
return (Status == CAB_STATUS_SUCCESS ? true : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CCABManager::CreateSimpleCabinet()
|
|
||||||
/*
|
|
||||||
* FUNCTION: Create cabinet
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
ULONG Status;
|
|
||||||
|
|
||||||
Status = NewCabinet();
|
|
||||||
if (Status != CAB_STATUS_SUCCESS)
|
|
||||||
{
|
|
||||||
DPRINT(MIN_TRACE, ("Cannot create cabinet (%u).\n", (UINT)Status));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = AddFile(FileName);
|
|
||||||
if (Status != CAB_STATUS_SUCCESS)
|
|
||||||
{
|
|
||||||
DPRINT(MIN_TRACE, ("Cannot add file to cabinet (%u).\n", (UINT)Status));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = WriteDisk(false);
|
|
||||||
if (Status == CAB_STATUS_SUCCESS)
|
|
||||||
Status = CloseDisk();
|
|
||||||
if (Status != CAB_STATUS_SUCCESS)
|
|
||||||
{
|
|
||||||
DPRINT(MIN_TRACE, ("Cannot write disk (%u).\n", (UINT)Status));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
CloseCabinet();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool CCABManager::DisplayCabinet()
|
bool CCABManager::DisplayCabinet()
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Display cabinet contents
|
* FUNCTION: Display cabinet contents
|
||||||
|
@ -448,7 +432,7 @@ bool CCABManager::DisplayCabinet()
|
||||||
{
|
{
|
||||||
printf("Cabinet %s\n\n", GetCabinetName());
|
printf("Cabinet %s\n\n", GetCabinetName());
|
||||||
|
|
||||||
if (FindFirst("", &Search) == CAB_STATUS_SUCCESS)
|
if (FindFirst(&Search) == CAB_STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -467,6 +451,8 @@ bool CCABManager::DisplayCabinet()
|
||||||
} while (FindNext(&Search) == CAB_STATUS_SUCCESS);
|
} while (FindNext(&Search) == CAB_STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DestroySearchCriteria();
|
||||||
|
|
||||||
if (FileCount > 0) {
|
if (FileCount > 0) {
|
||||||
if (FileCount == 1)
|
if (FileCount == 1)
|
||||||
printf(" 1 file ");
|
printf(" 1 file ");
|
||||||
|
@ -503,6 +489,7 @@ bool CCABManager::ExtractFromCabinet()
|
||||||
* FUNCTION: Extract file(s) from cabinet
|
* FUNCTION: Extract file(s) from cabinet
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
|
bool bRet = true;
|
||||||
CAB_SEARCH Search;
|
CAB_SEARCH Search;
|
||||||
ULONG Status;
|
ULONG Status;
|
||||||
|
|
||||||
|
@ -510,34 +497,46 @@ bool CCABManager::ExtractFromCabinet()
|
||||||
{
|
{
|
||||||
printf("Cabinet %s\n\n", GetCabinetName());
|
printf("Cabinet %s\n\n", GetCabinetName());
|
||||||
|
|
||||||
if (FindFirst("", &Search) == CAB_STATUS_SUCCESS)
|
if (FindFirst(&Search) == CAB_STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
switch (Status = ExtractFile(Search.FileName)) {
|
switch (Status = ExtractFile(Search.FileName))
|
||||||
|
{
|
||||||
case CAB_STATUS_SUCCESS:
|
case CAB_STATUS_SUCCESS:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CAB_STATUS_INVALID_CAB:
|
case CAB_STATUS_INVALID_CAB:
|
||||||
printf("Cabinet contains errors.\n");
|
printf("Cabinet contains errors.\n");
|
||||||
return false;
|
bRet = false;
|
||||||
|
break;
|
||||||
|
|
||||||
case CAB_STATUS_UNSUPPCOMP:
|
case CAB_STATUS_UNSUPPCOMP:
|
||||||
printf("Cabinet uses unsupported compression type.\n");
|
printf("Cabinet uses unsupported compression type.\n");
|
||||||
return false;
|
bRet = false;
|
||||||
|
break;
|
||||||
|
|
||||||
case CAB_STATUS_CANNOT_WRITE:
|
case CAB_STATUS_CANNOT_WRITE:
|
||||||
printf("You've run out of free space on the destination volume or the volume is damaged.\n");
|
printf("You've run out of free space on the destination volume or the volume is damaged.\n");
|
||||||
return false;
|
bRet = false;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf("Unspecified error code (%u).\n", (UINT)Status);
|
printf("Unspecified error code (%u).\n", (UINT)Status);
|
||||||
return false;
|
bRet = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!bRet)
|
||||||
|
break;
|
||||||
} while (FindNext(&Search) == CAB_STATUS_SUCCESS);
|
} while (FindNext(&Search) == CAB_STATUS_SUCCESS);
|
||||||
|
|
||||||
|
DestroySearchCriteria();
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
} else
|
return bRet;
|
||||||
|
}
|
||||||
|
else
|
||||||
printf("Cannot open file: %s.\n", GetCabinetName());
|
printf("Cannot open file: %s.\n", GetCabinetName());
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -555,19 +554,15 @@ bool CCABManager::Run()
|
||||||
{
|
{
|
||||||
case CM_MODE_CREATE:
|
case CM_MODE_CREATE:
|
||||||
return CreateCabinet();
|
return CreateCabinet();
|
||||||
break;
|
|
||||||
|
|
||||||
case CM_MODE_DISPLAY:
|
case CM_MODE_DISPLAY:
|
||||||
return DisplayCabinet();
|
return DisplayCabinet();
|
||||||
break;
|
|
||||||
|
|
||||||
case CM_MODE_EXTRACT:
|
case CM_MODE_EXTRACT:
|
||||||
return ExtractFromCabinet();
|
return ExtractFromCabinet();
|
||||||
break;
|
|
||||||
|
|
||||||
case CM_MODE_CREATE_SIMPLE:
|
case CM_MODE_CREATE_SIMPLE:
|
||||||
return CreateSimpleCabinet();
|
return CreateSimpleCabinet();
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue