#include #include #include #include #include #include #include #include //Cab file headers // #include //Main program header file //////////////////////////// //Cabbing Context Variables //////////////////////////// ERF erf; client_state cs; //Global Definations for some static setting // Set these to override the defaults char g_szCabFileLocation[_MAX_PATH] = {""}; //This is the fully qualified path, must have a \ at the end char g_szCabFileName[_MAX_PATH] = {""}; //this is the file name for the cab.. Suggest that it has a .cab for telling its a cab extern void Log(char *szString); extern void Log2(char *szString, char *szString2); /* /////////////////////////////// // Cabbing API Helper Functions /////////////////////.///////// */ /* * Memory allocation function */ FNFCIALLOC(mem_alloc) { return malloc(cb); } /* * Memory free function */ FNFCIFREE(mem_free) { free(memory); } /* * File i/o functions */ FNFCIOPEN(fci_open) { int result; result = _open(pszFile, oflag, pmode); if (result == -1) *err = errno; return result; } FNFCIREAD(fci_read) { unsigned int result; result = (unsigned int) _read(hf, memory, cb); if (result != cb) *err = errno; return result; } FNFCIWRITE(fci_write) { unsigned int result; result = (unsigned int) _write(hf, memory, cb); if (result != cb) *err = errno; return result; } FNFCICLOSE(fci_close) { int result; result = _close(hf); if (result != 0) *err = errno; return result; } FNFCISEEK(fci_seek) { long result; result = _lseek(hf, dist, seektype); if (result == -1) *err = errno; return result; } FNFCIDELETE(fci_delete) { int result; result = remove(pszFile); if (result != 0) *err = errno; return result; } /* * File placed function called when a file has been committed to a cabinet */ FNFCIFILEPLACED(file_placed) { if (fContinuation) Log(" (Above file is a later segment of a continued file)\n"); return 0; } /* * Function to obtain temporary files */ FNFCIGETTEMPFILE(get_temp_file) { char *psz; psz = _tempnam("","xx"); // Get a name if ((psz != NULL) && (strlen(psz) < (unsigned)cbTempName)) { strcpy(pszTempName,psz); // Copy to caller's buffer free(psz); // Free temporary name buffer return TRUE; // Success } //** if Failed if (psz) { free(psz); } return FALSE; } /* * Progress function */ FNFCISTATUS(progress) { client_state *cs; cs = (client_state *) pv; if (typeStatus == statusFile) { cs->total_compressed_size += cb1; cs->total_uncompressed_size += cb2; /* * Compressing a block into a folder * cb2 = uncompressed size of block */ //printf( // "Compressing: %9ld -> %9ld \r", // cs->total_uncompressed_size, // cs->total_compressed_size //); fflush(stdout); } else if (typeStatus == statusFolder) { int percentage; /* * Adding a folder to a cabinet * cb1 = amount of folder copied to cabinet so far * cb2 = total size of folder */ percentage = get_percentage(cb1, cb2); //printf("Copying folder to cabinet: %d%% \r", percentage); fflush(stdout); } return 0; } FNFCIGETNEXTCABINET(get_next_cabinet) { char lpBuffer[_MAX_PATH]; /* * Cabinet counter has been incremented already by FCI * Store next cabinet name */ strGenerateCabFileName(lpBuffer, MAX_COMPUTERNAME_LENGTH +1); //BUGBUG I am just glueing this together, should check for error strcpy(pccab->szCab, lpBuffer); /* * You could change the disk name here too, if you wanted */ return TRUE; } FNFCIGETOPENINFO(get_open_info) { BY_HANDLE_FILE_INFORMATION finfo; FILETIME filetime; HANDLE handle; DWORD attrs; int hf; //* //* Need a Win32 type handle to get file date/time //* using the Win32 APIs, even though the handle we //* will be returning is of the type compatible with //* _open //* handle = CreateFileA( pszName, //BUGBUG ARG What should this be??? GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, //OPEN_EXISTING FILE_ATTRIBUTE_NORMAL, //FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN NULL ); if (INVALID_HANDLE_VALUE == handle) { printf("DEBUG: Invalid Handle for CreateFile\n"); printf("DEBUG: %ld\n", GetLastError()); return -1; } if (GetFileInformationByHandle(handle, &finfo) == FALSE) { printf("DEBUG: GetFileInformation Failed\n"); CloseHandle(handle); return -1; } FileTimeToLocalFileTime( &finfo.ftLastWriteTime, &filetime ); FileTimeToDosDateTime( &filetime, pdate, ptime ); attrs = GetFileAttributes((const LPCTSTR)pszName); if (attrs == 0xFFFFFFFF) { // failure *pattribs = 0; } else { //* //* Mask out all other bits except these four, since other //* bits are used by the cabinet format to indicate a //* special meaning. //* *pattribs = (int) (attrs & (_A_RDONLY | _A_SYSTEM | _A_HIDDEN | _A_ARCH)); } CloseHandle(handle); //* //* Return handle using _open //* hf = _open( pszName, _O_RDONLY | _O_BINARY ); if (hf == -1) return -1; // abort on error return hf; } void set_cab_parameters(PCCAB cab_parms) { const char *szCabStorePath=""; char lpBuffer[_MAX_PATH]; memset(cab_parms, 0, sizeof(CCAB)); cab_parms->cb = MEDIA_SIZE; cab_parms->cbFolderThresh = FOLDER_THRESHOLD; /* * Don't reserve space for any extensions */ cab_parms->cbReserveCFHeader = 0; cab_parms->cbReserveCFFolder = 0; cab_parms->cbReserveCFData = 0; /* * We use this to create the cabinet name */ cab_parms->iCab = 1; /* * If you want to use disk names, use this to * count disks */ cab_parms->iDisk = 0; /* * Choose your own number */ cab_parms->setID = 12345; /* * Only important if CABs are spanning multiple * disks, in which case you will want to use a * real disk name. * * Can be left as an empty string. */ strcpy(cab_parms->szDisk, "MyDisk"); /* where to store the created CAB files */ if( NULL != *g_szCabFileLocation) { //make sure that we have a \\ on the end of the path to the cab. if( '\\' != g_szCabFileLocation[strlen(g_szCabFileLocation)] ) strcat(g_szCabFileLocation, "\\"); strcpy(cab_parms->szCabPath, g_szCabFileLocation); } else { szCabStorePath = getenv("TEMP"); strcpy(cab_parms->szCabPath, szCabStorePath); strcat(cab_parms->szCabPath, "\\"); } //** //check if last char in path is "\" // len = strlen(g_szCurrDir); // if ('\' != g_szCurrDir[len-1]) // strcat(cab_parms->szCabPath, "\\"); //Not the root: Append "\"at end of path /* store name of first CAB file */ strGenerateCabFileName(lpBuffer, _MAX_PATH); //BUGBUG I am just glueing this together, should check for error strcpy(cab_parms->szCab, lpBuffer); sprintf(lpBuffer, "Cab location = %s%s\n", cab_parms->szCabPath, cab_parms->szCab); Log(lpBuffer); } /* ************************************************************************ * * Function: create_cab() * * Initializes the Context to create a CAB File. * Returns hcfi if successful (context to a Cab file). * ************************************************************************ */ HFCI create_cab() { // Initialize our internal state HFCI hfci; CCAB cab_parameters; cs.total_compressed_size = 0; cs.total_uncompressed_size = 0; set_cab_parameters(&cab_parameters); hfci = FCICreate( &erf, file_placed, mem_alloc, mem_free, fci_open, fci_read, fci_write, fci_close, fci_seek, fci_delete, get_temp_file, &cab_parameters, &cs ); if (hfci == NULL) { Log2("FCICreate() failed: ",return_fci_error_string((FCIERROR)erf.erfOper)); printf("FCICreate() failed: code %d [%s]\n", erf.erfOper, return_fci_error_string((FCIERROR)erf.erfOper) ); return hfci; } else return hfci; } /* ******************************************************************************** * * Function: flush_cab * * Forces the Cabinet under construction to be completed and written to disk. * Returns TRUE if successful * ******************************************************************************** */ BOOL flush_cab(HFCI hfci) { // This will automatically flush the folder first if (FALSE == FCIFlushCabinet( hfci, FALSE, get_next_cabinet, progress)) { Log2("FCIFlushCabinet() failed: ",return_fci_error_string((FCIERROR)erf.erfOper)); printf("FCIFlushCabinet() failed: code %d [%s]\n", erf.erfOper, return_fci_error_string((FCIERROR)erf.erfOper) ); (void) FCIDestroy(hfci); return FALSE; } if (FCIDestroy(hfci) != TRUE) { Log2("FCIDestroy() failed: ",return_fci_error_string((FCIERROR)erf.erfOper)); printf("FCIDestroy() failed: code %d [%s]\n", erf.erfOper, return_fci_error_string((FCIERROR)erf.erfOper) ); return FALSE; } return TRUE; } /* ************************************************************************************** * * Function: test_fci * * Adds Files to HFCI Context, Cabs them and flushes the folder (generates Cab file). * Returns TRUE if successfull * *************************************************************************************** */ bool test_fci(HFCI hfci, int num_files, char *file_list[], char *currdir) { int i; // Add files in the Array passed in file_list[] for (i = 0; (i < num_files)&&(strlen(file_list[i])); i++) { char stripped_name[256]; char *szAux;//added =""; Log("--------------------------------------------------"); Log2("Processing File = ",file_list[i]); szAux = (char *) malloc(strlen(file_list[i])+strlen(currdir)+1); if (NULL!= szAux) { if (NULL == currdir) // if currdir is empty, then just pass element[i] in argv[] strcpy(szAux,file_list[i]); else { strcpy(szAux,currdir); // else append filename to currdir strcat(szAux,file_list[i]); } if( -1 != (_access(szAux, 0 )) ) { // Don't store the path name in the cabinet file! strip_path(szAux, stripped_name); if (FALSE == FCIAddFile( hfci, //This was hfci szAux, /* file to add */ stripped_name, /* file name in cabinet file */ FALSE, /* file is not executable */ get_next_cabinet, progress, get_open_info, COMPRESSION_TYPE)) { Log2("FCIAddFile() failed: ",return_fci_error_string((FCIERROR)erf.erfOper)); printf("FCIAddFile() failed: code %d [%s]\n", erf.erfOper, return_fci_error_string((FCIERROR)erf.erfOper) ); // I need to continue if file can't be added.... // (void) FCIDestroy(hfci); // return false; } else Log("File Was Added!"); } else Log("File does not exist! Continuing... "); free (szAux); } else Log("Could not allocate enough memory to Cab\n"); } // End for // Done Adding Files Log("--------------------------------------------------"); //By here then everything is successful.. If not then you need to uncomment the previous failure return. return true; } int get_percentage(unsigned long a, unsigned long b) { while (a > 10000000) { a >>= 3; b >>= 3; } if (b == 0) return 0; return ((a*100)/b); } /* ******************************************************************************** * * Function: strip_path * * Returns the file name of a full path. * ******************************************************************************** */ void strip_path(char *filename, char *stripped_name) { char *p; p = strrchr(filename, '\\'); //printf ("Path + Filename= %s\n",filename); if (p == NULL) strcpy(stripped_name, filename); else strcpy(stripped_name, p+1); } char *return_fci_error_string(FCIERROR err) { switch (err) { case FCIERR_NONE: return "No error"; case FCIERR_OPEN_SRC: return "Failure opening file to be stored in cabinet"; case FCIERR_READ_SRC: return "Failure reading file to be stored in cabinet"; case FCIERR_ALLOC_FAIL: return "Insufficient memory in FCI"; case FCIERR_TEMP_FILE: return "Could not create a temporary file"; case FCIERR_BAD_COMPR_TYPE: return "Unknown compression type"; case FCIERR_CAB_FILE: return "Could not create cabinet file"; case FCIERR_USER_ABORT: return "Client requested abort"; case FCIERR_MCI_FAIL: return "Failure compressing data"; default: return "Unknown error"; } } /* ************************************************************** * * Function: Generate Cab File name * * Output: Global String containing a filename * szCabFileName = ComputerName + ddmmyy + hhmmss * ************************************************************** */ DWORD strGenerateCabFileName(char *lpBuffer, DWORD dSize) { time_t ltime; struct tm *now; char tmpbuf[128]; //Check to see if we have an override for the cabname, if so use it. if( NULL != *g_szCabFileName) { strcpy(lpBuffer, g_szCabFileName); return 0; } // // Copy Computer Name to CabFileName // strcpy(lpBuffer, getenv("COMPUTERNAME")); //GetComputerName((LPTSTR) lpBuffer, &dSize); // // Append Undescore character to CabFileName // strcat(lpBuffer, "_"); // // Get System Time and Date // time( <ime ); now = localtime( <ime ); // // Convert time/date to mmddyyhhmmss format (24hr) // if (strftime( tmpbuf, 128,"%m%d%y_%H%M%S", now)) // Append Timestamp to CabFileName strcat(lpBuffer, tmpbuf); else { Log ("Could not convert system time to mmddyy_hhmmss format\n"); return -1; } //Now append on the extension and now we are set. strcat(lpBuffer, ".cab"); return 0; }