Errors EntryList_appendCString(EntryList *entryList, EntryTypes type, const char *pattern, PatternTypes patternType ) { EntryNode *entryNode; #if defined(PLATFORM_LINUX) #elif defined(PLATFORM_WINDOWS) String string; #endif /* PLATFORM_... */ Errors error; assert(entryList != NULL); assert(pattern != NULL); // allocate entry node entryNode = LIST_NEW_NODE(EntryNode); if (entryNode == NULL) { HALT_INSUFFICIENT_MEMORY(); } entryNode->type = type; entryNode->string = String_newCString(pattern); // init pattern #if defined(PLATFORM_LINUX) error = Pattern_initCString(&entryNode->pattern, pattern, patternType, PATTERN_FLAG_NONE ); #elif defined(PLATFORM_WINDOWS) // escape all '\' by '\\' string = String_newCString(pattern); String_replaceAllCString(string,STRING_BEGIN,"\\","\\\\"); error = Pattern_init(&entryNode->pattern, string, patternType, PATTERN_FLAG_IGNORE_CASE ); // free resources String_delete(string); #endif /* PLATFORM_... */ if (error != ERROR_NONE) { String_delete(entryNode->string); LIST_DELETE_NODE(entryNode); return error; } // add to list List_append(entryList,entryNode); return ERROR_NONE; }
LOCAL EntryNode *copyEntryNode(EntryNode *entryNode, void *userData ) { EntryNode *newEntryNode; #if defined(PLATFORM_LINUX) #elif defined(PLATFORM_WINDOWS) String string; #endif /* PLATFORM_... */ Errors error; assert(entryNode != NULL); UNUSED_VARIABLE(userData); // allocate entry node newEntryNode = LIST_NEW_NODE(EntryNode); if (newEntryNode == NULL) { HALT_INSUFFICIENT_MEMORY(); } // create entry newEntryNode->type = entryNode->type; newEntryNode->string = String_duplicate(entryNode->string); #if defined(PLATFORM_LINUX) error = Pattern_init(&newEntryNode->pattern, entryNode->string, entryNode->pattern.type, PATTERN_FLAG_NONE ); #elif defined(PLATFORM_WINDOWS) // escape all '\' by '\\' string = String_duplicate(entryNode->string); String_replaceAllCString(string,STRING_BEGIN,"\\","\\\\"); error = Pattern_init(&newEntryNode->pattern, string, entryNode->pattern.type|, PATTERN_FLAG_IGNORE_CASE ); // free resources String_delete(string); #endif /* PLATFORM_... */ if (error != ERROR_NONE) { String_delete(newEntryNode->string); LIST_DELETE_NODE(newEntryNode); return NULL; } return newEntryNode; }
LOCAL PatternNode *copyPatternNode(PatternNode *patternNode, void *userData ) { PatternNode *newPatternNode; Errors error; assert(patternNode != NULL); UNUSED_VARIABLE(userData); // allocate pattern node newPatternNode = LIST_NEW_NODE(PatternNode); if (newPatternNode == NULL) { HALT_INSUFFICIENT_MEMORY(); } newPatternNode->string = String_duplicate(patternNode->string); // create pattern error = Pattern_init(&newPatternNode->pattern, patternNode->string, patternNode->pattern.type, patternNode->pattern.flags ); if (error != ERROR_NONE) { String_delete(newPatternNode->string); LIST_DELETE_NODE(newPatternNode); return NULL; } return newPatternNode; }
void PathName_setSeparator(String* sep) { if (NULL != _separator) { String_delete(_separator); } _separator = sep; }
LOCAL void freeStringNode(StringNode *stringNode, void *userData) { assert(stringNode != NULL); UNUSED_VARIABLE(userData); String_delete(stringNode->string); }
LOCAL void freeFileFragmentNode(FileFragmentNode *fileFragmentNode, void *userData) { assert(fileFragmentNode != NULL); UNUSED_VARIABLE(userData); List_done(&fileFragmentNode->fragmentList,NULL,NULL); String_delete(fileFragmentNode->fileName); }
void PathName_delete(PathName* self) { smug_assert(_invariant(self)); if (self->root) { String_delete(self->root); } if (self->bareName) { String_delete(self->bareName); if (self->extension) { String_delete(self->extension); } } LinkedList_deleteContents(self->path, String_deleteVoid); LinkedList_delete(self->path); free(self); }
Errors File_close(FileHandle *fileHandle) { assert(fileHandle != NULL); assert(fileHandle->file != NULL); assert(fileHandle->name != NULL); fclose(fileHandle->file); fileHandle->file = NULL; String_delete(fileHandle->name); return ERROR_NONE; }
Errors Device_close(DeviceHandle *deviceHandle) { assert(deviceHandle != NULL); assert(deviceHandle->file != NULL); assert(deviceHandle->name != NULL); fclose(deviceHandle->file); deviceHandle->file = NULL; String_delete(deviceHandle->name); return ERROR_NONE; }
LOCAL void freeEntryNode(EntryNode *entryNode, void *userData ) { assert(entryNode != NULL); assert(entryNode->string != NULL); UNUSED_VARIABLE(userData); Pattern_done(&entryNode->pattern); String_delete(entryNode->string); }
LOCAL void freePatternNode(PatternNode *patternNode, void *userData ) { assert(patternNode != NULL); assert(patternNode->string != NULL); UNUSED_VARIABLE(userData); Pattern_done(&patternNode->pattern); String_delete(patternNode->string); }
Errors File_printLine(FileHandle *fileHandle, const char *format, ... ) { String line; va_list arguments; Errors error; assert(fileHandle != NULL); assert(fileHandle->file != NULL); assert(format != NULL); /* initialise variables */ line = String_new(); /* format line */ va_start(arguments,format); String_vformat(line,format,arguments); va_end(arguments); /* write line */ error = File_write(fileHandle,String_cString(line),String_length(line)); if (error != ERROR_NONE) { String_delete(line); return error; } error = File_write(fileHandle,"\n",1); if (error != ERROR_NONE) { String_delete(line); return error; } /* free resources */ String_delete(line); return ERROR_NONE; }
LOCAL void freeFragmentNode(FragmentNode *fragmentNode, void *userData) { assert(fragmentNode != NULL); UNUSED_VARIABLE(userData); List_done(&fragmentNode->fragmentEntryList,NULL,NULL); if (fragmentNode->userData != NULL) { free(fragmentNode->userData); } String_delete(fragmentNode->name); }
LOCAL String getDestinationFileName(String destinationFileName, String fileName, const String directory, uint directoryStripCount ) { String pathName,baseName,name; StringTokenizer fileNameTokenizer; int z; assert(destinationFileName != NULL); assert(fileName != NULL); if (directory != NULL) { File_setFileName(destinationFileName,directory); } else { String_clear(destinationFileName); } File_splitFileName(fileName,&pathName,&baseName); File_initSplitFileName(&fileNameTokenizer,pathName); z = 0; while ((z< directoryStripCount) && File_getNextSplitFileName(&fileNameTokenizer,&name)) { z++; } while (File_getNextSplitFileName(&fileNameTokenizer,&name)) { File_appendFileName(destinationFileName,name); } File_doneSplitFileName(&fileNameTokenizer); File_appendFileName(destinationFileName,baseName); String_delete(pathName); String_delete(baseName); return destinationFileName; }
String* PathName_getAsString(PathName* self) { smug_assert(_invariant(self)); String* path; String* fullPath; path = String_newJoin(self->path, _getSeparator()); if (self->root != NULL) { fullPath = String_newConcat(self->root, path); String_delete(path); } else { fullPath = path; } return fullPath; }
/*---------------------------------------------------------------------*/ void StringList_init(StringList *stringList) { assert(stringList != NULL); List_init(stringList); } void StringList_done(StringList *stringList) { assert(stringList != NULL); List_done(stringList,(ListNodeFreeFunction)freeStringNode,NULL); } StringList *StringList_new(void) { return (StringList*)List_new(); } StringList *StringList_duplicate(const StringList *stringList) { StringList *newStringList; assert(stringList != NULL); newStringList = StringList_new(); if (newStringList == NULL) { return NULL; } StringList_copy(newStringList,stringList); return newStringList; } void StringList_copy(StringList *stringList, const StringList *fromStringList) { StringNode *stringNode; assert(stringList != NULL); assert(fromStringList != NULL); stringNode = fromStringList->head; while (stringNode != NULL) { StringList_append(stringList,stringNode->string); stringNode = stringNode->next; } } void StringList_delete(StringList *stringList) { assert(stringList != NULL); List_delete(stringList,(ListNodeFreeFunction)freeStringNode,NULL); } void StringList_clear(StringList *stringList) { assert(stringList != NULL); List_clear(stringList,(ListNodeFreeFunction)freeStringNode,NULL); } void StringList_move(StringList *fromStringList, StringList *toStringList) { assert(fromStringList != NULL); assert(toStringList != NULL); List_move(fromStringList,toStringList,NULL,NULL,NULL); } #ifdef NDEBUG void StringList_insert(StringList *stringList, const String string, StringNode *nextStringNode) #else /* not NDEBUG */ void __StringList_insert(const char *__fileName__, ulong __lineNb__, StringList *stringList, const String string, StringNode *nextStringNode) #endif /* NDEBUG */ { #ifdef NDEBUG insertString(stringList,String_duplicate(string),nextStringNode); #else /* not NDEBUG */ insertString(__fileName__,__lineNb__,stringList,__String_duplicate(__fileName__,__lineNb__,string),nextStringNode); #endif /* NDEBUG */ } #ifdef NDEBUG void StringList_insertCString(StringList *stringList, const char *s, StringNode *nextStringNode) #else /* not NDEBUG */ void __StringList_insertCString(const char *__fileName__, ulong __lineNb__, StringList *stringList, const char *s, StringNode *nextStringNode) #endif /* NDEBUG */ { #ifdef NDEBUG insertString(stringList,String_newCString(s),nextStringNode); #else /* not NDEBUG */ insertString(__fileName__,__lineNb__,stringList,__String_newCString(__fileName__,__lineNb__,s),nextStringNode); #endif /* NDEBUG */ } #ifdef NDEBUG void StringList_insertChar(StringList *stringList, char ch, StringNode *nextStringNode) #else /* not NDEBUG */ void __StringList_insertChar(const char *__fileName__, ulong __lineNb__, StringList *stringList, char ch, StringNode *nextStringNode) #endif /* NDEBUG */ { #ifdef NDEBUG insertString(stringList,String_newChar(ch),nextStringNode); #else /* not NDEBUG */ insertString(__fileName__,__lineNb__,stringList,__String_newChar(__fileName__,__lineNb__,ch),nextStringNode); #endif /* NDEBUG */ } #ifdef NDEBUG void StringList_insertBuffer(StringList *stringList, char *buffer, ulong bufferLength, StringNode *nextStringNode) #else /* not NDEBUG */ void __StringList_insertBuffer(const char *__fileName__, ulong __lineNb__, StringList *stringList, char *buffer, ulong bufferLength, StringNode *nextStringNode) #endif /* NDEBUG */ { #ifdef NDEBUG insertString(stringList,String_newBuffer(buffer,bufferLength),nextStringNode); #else /* not NDEBUG */ insertString(__fileName__,__lineNb__,stringList,__String_newBuffer(__fileName__,__lineNb__,buffer,bufferLength),nextStringNode); #endif /* NDEBUG */ } #ifdef NDEBUG void StringList_append(StringList *stringList, const String string) #else /* not NDEBUG */ void __StringList_append(const char *__fileName__, ulong __lineNb__, StringList *stringList, const String string) #endif /* NDEBUG */ { #ifdef NDEBUG insertString(stringList,String_duplicate(string),NULL); #else /* not NDEBUG */ insertString(__fileName__,__lineNb__,stringList,__String_duplicate(__fileName__,__lineNb__,string),NULL); #endif /* NDEBUG */ } #ifdef NDEBUG void StringList_appendCString(StringList *stringList, const char *s) #else /* not NDEBUG */ void __StringList_appendCString(const char *__fileName__, ulong __lineNb__, StringList *stringList, const char *s) #endif /* NDEBUG */ { #ifdef NDEBUG insertString(stringList,String_newCString(s),NULL); #else /* not NDEBUG */ insertString(__fileName__,__lineNb__,stringList,__String_newCString(__fileName__,__lineNb__,s),NULL); #endif /* NDEBUG */ } #ifdef NDEBUG void StringList_appendChar(StringList *stringList, char ch) #else /* not NDEBUG */ void __StringList_appendChar(const char *__fileName__, ulong __lineNb__, StringList *stringList, char ch) #endif /* NDEBUG */ { #ifdef NDEBUG insertString(stringList,String_newChar(ch),NULL); #else /* not NDEBUG */ insertString(__fileName__,__lineNb__,stringList,__String_newChar(__fileName__,__lineNb__,ch),NULL); #endif /* NDEBUG */ } #ifdef NDEBUG void StringList_appendBuffer(StringList *stringList, char *buffer, ulong bufferLength) #else /* not NDEBUG */ void __StringList_appendBuffer(const char *__fileName__, ulong __lineNb__, StringList *stringList, char *buffer, ulong bufferLength) #endif /* NDEBUG */ { #ifdef NDEBUG insertString(stringList,String_newBuffer(buffer,bufferLength),NULL); #else /* not NDEBUG */ insertString(__fileName__,__lineNb__,stringList,__String_newBuffer(__fileName__,__lineNb__,buffer,bufferLength),NULL); #endif /* NDEBUG */ } #ifdef NDEBUG StringNode *StringList_remove(StringList *stringList, StringNode *stringNode) #else /* not NDEBUG */ StringNode *__StringList_remove(const char *__fileName__, ulong __lineNb__, StringList *stringList, StringNode *stringNode) #endif /* NDEBUG */ { StringNode *nextStringNode; assert(stringList != NULL); assert(stringNode != NULL); nextStringNode = (StringNode*)List_remove(stringList,stringNode); String_delete(stringNode->string); #ifdef NDEBUG stringNode = (StringNode*)LIST_DELETE_NODE(stringNode); #else /* not NDEBUG */ stringNode = (StringNode*)__LIST_DELETE_NODE(__fileName__,__lineNb__,stringNode); #endif /* NDEBUG */ return nextStringNode; }
String* PathName_getFileName(PathName* self) { String* ret; String* temp; smug_assert(_invariant(self)); if (NULL == self->bareName) return NULL; if (NULL == self->extension || String_isEmpty(self->extension)) { ret = String_newCopy(self->bareName); } else { temp = String_newConcat(self->bareName, _getDot()); ret = String_newConcat(temp, self->extension); String_delete(temp); } return ret; }
/*---------------------------------------------------------------------*/ void StringList_init(StringList *stringList) { assert(stringList != NULL); List_init(stringList); } void StringList_done(StringList *stringList) { assert(stringList != NULL); List_done(stringList,(ListNodeFreeFunction)freeStringNode,NULL); } StringList *StringList_new(void) { return (StringList*)List_new(); } StringList *StringList_duplicate(const StringList *stringList) { StringList *newStringList; assert(stringList != NULL); newStringList = StringList_new(); if (newStringList == NULL) { return NULL; } StringList_copy(newStringList,stringList); return newStringList; } void StringList_copy(StringList *stringList, const StringList *fromStringList) { StringNode *stringNode; assert(stringList != NULL); assert(fromStringList != NULL); stringNode = fromStringList->head; while (stringNode != NULL) { StringList_append(stringList,stringNode->string); stringNode = stringNode->next; } } void StringList_delete(StringList *stringList) { assert(stringList != NULL); List_delete(stringList,(ListNodeFreeFunction)freeStringNode,NULL); } void StringList_clear(StringList *stringList) { assert(stringList != NULL); List_clear(stringList,(ListNodeFreeFunction)freeStringNode,NULL); } void StringList_move(StringList *fromStringList, StringList *toStringList) { assert(fromStringList != NULL); assert(toStringList != NULL); List_move(fromStringList,toStringList,NULL,NULL,NULL); } #ifdef NDEBUG void StringList_insert(StringList *stringList, const String string, StringNode *nextStringNode) #else /* not NDEBUG */ void __StringList_insert(const char *__fileName__, ulong __lineNb__, StringList *stringList, const String string, StringNode *nextStringNode) #endif /* NDEBUG */ { #ifdef NDEBUG insertString(stringList,String_duplicate(string),nextStringNode); #else /* not NDEBUG */ insertString(__fileName__,__lineNb__,stringList,__String_duplicate(__fileName__,__lineNb__,string),nextStringNode); #endif /* NDEBUG */ } #ifdef NDEBUG void StringList_insertCString(StringList *stringList, const char *s, StringNode *nextStringNode) #else /* not NDEBUG */ void __StringList_insertCString(const char *__fileName__, ulong __lineNb__, StringList *stringList, const char *s, StringNode *nextStringNode) #endif /* NDEBUG */ { #ifdef NDEBUG insertString(stringList,String_newCString(s),nextStringNode); #else /* not NDEBUG */ insertString(__fileName__,__lineNb__,stringList,__String_newCString(__fileName__,__lineNb__,s),nextStringNode); #endif /* NDEBUG */ } #ifdef NDEBUG void StringList_insertChar(StringList *stringList, char ch, StringNode *nextStringNode) #else /* not NDEBUG */ void __StringList_insertChar(const char *__fileName__, ulong __lineNb__, StringList *stringList, char ch, StringNode *nextStringNode) #endif /* NDEBUG */ { #ifdef NDEBUG insertString(stringList,String_newChar(ch),nextStringNode); #else /* not NDEBUG */ insertString(__fileName__,__lineNb__,stringList,__String_newChar(__fileName__,__lineNb__,ch),nextStringNode); #endif /* NDEBUG */ } #ifdef NDEBUG void StringList_insertBuffer(StringList *stringList, char *buffer, ulong bufferLength, StringNode *nextStringNode) #else /* not NDEBUG */ void __StringList_insertBuffer(const char *__fileName__, ulong __lineNb__, StringList *stringList, char *buffer, ulong bufferLength, StringNode *nextStringNode) #endif /* NDEBUG */ { #ifdef NDEBUG insertString(stringList,String_newBuffer(buffer,bufferLength),nextStringNode); #else /* not NDEBUG */ insertString(__fileName__,__lineNb__,stringList,__String_newBuffer(__fileName__,__lineNb__,buffer,bufferLength),nextStringNode); #endif /* NDEBUG */ } #ifdef NDEBUG void StringList_append(StringList *stringList, const String string) #else /* not NDEBUG */ void __StringList_append(const char *__fileName__, ulong __lineNb__, StringList *stringList, const String string) #endif /* NDEBUG */ { #ifdef NDEBUG insertString(stringList,String_duplicate(string),NULL); #else /* not NDEBUG */ insertString(__fileName__,__lineNb__,stringList,__String_duplicate(__fileName__,__lineNb__,string),NULL); #endif /* NDEBUG */ } #ifdef NDEBUG void StringList_appendCString(StringList *stringList, const char *s) #else /* not NDEBUG */ void __StringList_appendCString(const char *__fileName__, ulong __lineNb__, StringList *stringList, const char *s) #endif /* NDEBUG */ { #ifdef NDEBUG insertString(stringList,String_newCString(s),NULL); #else /* not NDEBUG */ insertString(__fileName__,__lineNb__,stringList,__String_newCString(__fileName__,__lineNb__,s),NULL); #endif /* NDEBUG */ } #ifdef NDEBUG void StringList_appendChar(StringList *stringList, char ch) #else /* not NDEBUG */ void __StringList_appendChar(const char *__fileName__, ulong __lineNb__, StringList *stringList, char ch) #endif /* NDEBUG */ { #ifdef NDEBUG insertString(stringList,String_newChar(ch),NULL); #else /* not NDEBUG */ insertString(__fileName__,__lineNb__,stringList,__String_newChar(__fileName__,__lineNb__,ch),NULL); #endif /* NDEBUG */ } #ifdef NDEBUG void StringList_appendBuffer(StringList *stringList, char *buffer, ulong bufferLength) #else /* not NDEBUG */ void __StringList_appendBuffer(const char *__fileName__, ulong __lineNb__, StringList *stringList, char *buffer, ulong bufferLength) #endif /* NDEBUG */ { #ifdef NDEBUG insertString(stringList,String_newBuffer(buffer,bufferLength),NULL); #else /* not NDEBUG */ insertString(__fileName__,__lineNb__,stringList,__String_newBuffer(__fileName__,__lineNb__,buffer,bufferLength),NULL); #endif /* NDEBUG */ } #ifdef NDEBUG StringNode *StringList_remove(StringList *stringList, StringNode *stringNode) #else /* not NDEBUG */ StringNode *__StringList_remove(const char *__fileName__, ulong __lineNb__, StringList *stringList, StringNode *stringNode) #endif /* NDEBUG */ { StringNode *nextStringNode; assert(stringList != NULL); assert(stringNode != NULL); nextStringNode = (StringNode*)List_remove(stringList,stringNode); String_delete(stringNode->string); #ifdef NDEBUG stringNode = (StringNode*)LIST_DELETE_NODE(stringNode); #else /* not NDEBUG */ stringNode = (StringNode*)__LIST_DELETE_NODE(__fileName__,__lineNb__,stringNode); #endif /* NDEBUG */ return nextStringNode; } #ifdef NDEBUG String StringList_getFirst(StringList *stringList, String string) #else /* not NDEBUG */ String __StringList_getFirst(const char *fileName, ulong lineNb, StringList *stringList, String string) #endif /* NDEBUG */ { StringNode *stringNode; assert(stringList != NULL); stringNode = (StringNode*)List_getFirst(stringList); if (stringNode != NULL) { if (string != NULL) { String_set(string,stringNode->string); String_delete(stringNode->string); } else { string = stringNode->string; } #ifdef NDEBUG LIST_DELETE_NODE(stringNode); #else /* not NDEBUG */ __LIST_DELETE_NODE(fileName,lineNb,stringNode); #endif /* NDEBUG */ return string; } else { if (string != NULL) { String_clear(string); } return NULL; } } #ifdef NDEBUG String StringList_getLast(StringList *stringList, String string) #else /* not NDEBUG */ String __StringList_getLast(const char *fileName, ulong lineNb, StringList *stringList, String string) #endif /* NDEBUG */ { StringNode *stringNode; assert(stringList != NULL); stringNode = (StringNode*)List_getLast(stringList); if (stringNode != NULL) { if (string != NULL) { String_set(string,stringNode->string); String_delete(stringNode->string); } else { string = stringNode->string; } #ifdef NDEBUG LIST_DELETE_NODE(stringNode); #else /* not NDEBUG */ __LIST_DELETE_NODE(fileName,lineNb,stringNode); #endif /* NDEBUG */ return string; } else { if (string != NULL) { String_clear(string); } return NULL; } }
Errors PatternList_appendCString(PatternList *patternList, const char *pattern, PatternTypes patternType ) { PatternNode *patternNode; Errors error; assert(patternList != NULL); assert(pattern != NULL); // allocate pattern node patternNode = LIST_NEW_NODE(PatternNode); if (patternNode == NULL) { HALT_INSUFFICIENT_MEMORY(); } patternNode->string = String_newCString(pattern); // init pattern error = Pattern_initCString(&patternNode->pattern, pattern, patternType, PATTERN_FLAG_IGNORE_CASE ); if (error != ERROR_NONE) { String_delete(patternNode->string); LIST_DELETE_NODE(patternNode); return error; } // add to list List_append(patternList,patternNode); return ERROR_NONE; }
Errors Command_restore(StringList *archiveFileNameList, PatternList *includePatternList, PatternList *excludePatternList, JobOptions *jobOptions, ArchiveGetCryptPasswordFunction archiveGetCryptPasswordFunction, void *archiveGetCryptPasswordUserData, RestoreStatusInfoFunction restoreStatusInfoFunction, void *restoreStatusInfoUserData, bool *pauseFlag, bool *requestedAbortFlag ) { RestoreInfo restoreInfo; byte *buffer; FileFragmentList fileFragmentList; String archiveFileName; Errors error; ArchiveInfo archiveInfo; ArchiveFileInfo archiveFileInfo; FileTypes fileType; FileFragmentNode *fileFragmentNode; assert(archiveFileNameList != NULL); assert(includePatternList != NULL); assert(excludePatternList != NULL); assert(jobOptions != NULL); /* initialize variables */ restoreInfo.includePatternList = includePatternList; restoreInfo.excludePatternList = excludePatternList; restoreInfo.jobOptions = jobOptions; restoreInfo.pauseFlag = pauseFlag; restoreInfo.requestedAbortFlag = requestedAbortFlag; restoreInfo.error = ERROR_NONE; restoreInfo.statusInfoFunction = restoreStatusInfoFunction; restoreInfo.statusInfoUserData = restoreStatusInfoUserData; restoreInfo.statusInfo.doneFiles = 0L; restoreInfo.statusInfo.doneBytes = 0LL; restoreInfo.statusInfo.skippedFiles = 0L; restoreInfo.statusInfo.skippedBytes = 0LL; restoreInfo.statusInfo.errorFiles = 0L; restoreInfo.statusInfo.errorBytes = 0LL; restoreInfo.statusInfo.fileName = String_new(); restoreInfo.statusInfo.fileDoneBytes = 0LL; restoreInfo.statusInfo.fileTotalBytes = 0LL; restoreInfo.statusInfo.storageName = String_new(); restoreInfo.statusInfo.storageDoneBytes = 0LL; restoreInfo.statusInfo.storageTotalBytes = 0LL; /* allocate resources */ buffer = malloc(BUFFER_SIZE); if (buffer == NULL) { HALT_INSUFFICIENT_MEMORY(); } FileFragmentList_init(&fileFragmentList); archiveFileName = String_new(); while ( ((restoreInfo.requestedAbortFlag == NULL) || !(*restoreInfo.requestedAbortFlag)) && !StringList_empty(archiveFileNameList) && (restoreInfo.error == ERROR_NONE) ) { /* pause */ while ((restoreInfo.pauseFlag != NULL) && (*restoreInfo.pauseFlag)) { Misc_udelay(500*1000); } StringList_getFirst(archiveFileNameList,archiveFileName); printInfo(0,"Restore archive '%s':\n",String_cString(archiveFileName)); /* open archive */ error = Archive_open(&archiveInfo, archiveFileName, jobOptions, archiveGetCryptPasswordFunction, archiveGetCryptPasswordUserData ); if (error != ERROR_NONE) { printError("Cannot open archive file '%s' (error: %s)!\n", String_cString(archiveFileName), Errors_getText(error) ); if (restoreInfo.error == ERROR_NONE) restoreInfo.error = error; continue; } String_set(restoreInfo.statusInfo.storageName,archiveFileName); updateStatusInfo(&restoreInfo); /* read files */ while ( ((restoreInfo.requestedAbortFlag == NULL) || !(*restoreInfo.requestedAbortFlag)) && !Archive_eof(&archiveInfo) && (restoreInfo.error == ERROR_NONE) ) { /* pause */ while ((restoreInfo.pauseFlag != NULL) && (*restoreInfo.pauseFlag)) { Misc_udelay(500*1000); } /* get next file type */ error = Archive_getNextFileType(&archiveInfo, &archiveFileInfo, &fileType ); if (error != ERROR_NONE) { printError("Cannot not read next entry in archive '%s' (error: %s)!\n", String_cString(archiveFileName), Errors_getText(error) ); if (restoreInfo.error == ERROR_NONE) restoreInfo.error = error; break; } switch (fileType) { case FILE_TYPE_FILE: { String fileName; FileInfo fileInfo; uint64 fragmentOffset,fragmentSize; FileFragmentNode *fileFragmentNode; String destinationFileName; String directoryName; // FileInfo localFileInfo; FileHandle fileHandle; uint64 length; ulong n; /* read file */ fileName = String_new(); error = Archive_readFileEntry(&archiveInfo, &archiveFileInfo, NULL, NULL, NULL, fileName, &fileInfo, &fragmentOffset, &fragmentSize ); if (error != ERROR_NONE) { printError("Cannot not read 'file' content of archive '%s' (error: %s)!\n", String_cString(archiveFileName), Errors_getText(error) ); String_delete(fileName); if (restoreInfo.error == ERROR_NONE) restoreInfo.error = error; continue; } if ( (List_empty(includePatternList) || PatternList_match(includePatternList,fileName,PATTERN_MATCH_MODE_EXACT)) && !PatternList_match(excludePatternList,fileName,PATTERN_MATCH_MODE_EXACT) ) { String_set(restoreInfo.statusInfo.fileName,fileName); restoreInfo.statusInfo.fileDoneBytes = 0LL; restoreInfo.statusInfo.fileTotalBytes = fragmentSize; updateStatusInfo(&restoreInfo); /* get destination filename */ destinationFileName = getDestinationFileName(String_new(), fileName, jobOptions->directory, jobOptions->directoryStripCount ); /* check if file fragment exists */ fileFragmentNode = FileFragmentList_findFile(&fileFragmentList,fileName); if (fileFragmentNode != NULL) { if (!jobOptions->overwriteFilesFlag && FileFragmentList_checkExists(fileFragmentNode,fragmentOffset,fragmentSize)) { printInfo(1," Restore file '%s'...skipped (file part %ll..%ll exists)\n", String_cString(destinationFileName), fragmentOffset, (fragmentSize > 0)?fragmentOffset+fragmentSize-1:fragmentOffset ); String_delete(destinationFileName); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); continue; } } else { if (!jobOptions->overwriteFilesFlag && File_exists(destinationFileName)) { printInfo(1," Restore file '%s'...skipped (file exists)\n",String_cString(destinationFileName)); String_delete(destinationFileName); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); continue; } fileFragmentNode = FileFragmentList_addFile(&fileFragmentList,fileName,fileInfo.size); } printInfo(2," Restore file '%s'...",String_cString(destinationFileName)); /* create directory if not existing */ directoryName = File_getFilePathName(String_new(),destinationFileName); if (!File_exists(directoryName)) { /* create directory */ error = File_makeDirectory(directoryName, FILE_DEFAULT_USER_ID, FILE_DEFAULT_GROUP_ID, fileInfo.permission ); if (error != ERROR_NONE) { printInfo(2,"FAIL!\n"); printError("Cannot create directory '%s' (error: %s)\n", String_cString(directoryName), Errors_getText(error) ); String_delete(directoryName); String_delete(destinationFileName); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); if (restoreInfo.error == ERROR_NONE) restoreInfo.error = error; continue; } /* set owner ship */ error = File_setOwner(directoryName, (jobOptions->owner.userId != FILE_DEFAULT_USER_ID )?jobOptions->owner.userId:fileInfo.userId, (jobOptions->owner.groupId != FILE_DEFAULT_GROUP_ID)?jobOptions->owner.groupId:fileInfo.groupId ); if (error != ERROR_NONE) { if (jobOptions->stopOnErrorFlag) { printInfo(2,"FAIL!\n"); printError("Cannot set owner ship of directory '%s' (error: %s)\n", String_cString(directoryName), Errors_getText(error) ); String_delete(directoryName); String_delete(destinationFileName); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); if (restoreInfo.error == ERROR_NONE) restoreInfo.error = error; continue; } else { printWarning("Cannot set owner ship of directory '%s' (error: %s)\n", String_cString(directoryName), Errors_getText(error) ); } } } String_delete(directoryName); /* write file data */ //if (fileFragmentNode == NULL) File_delete(destinationFileName,TRUE); error = File_open(&fileHandle,destinationFileName,FILE_OPENMODE_WRITE); if (error != ERROR_NONE) { printInfo(2,"FAIL!\n"); printError("Cannot create/write to file '%s' (error: %s)\n", String_cString(destinationFileName), Errors_getText(error) ); String_delete(destinationFileName); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); if (jobOptions->stopOnErrorFlag) { restoreInfo.error = error; } continue; } error = File_seek(&fileHandle,fragmentOffset); if (error != ERROR_NONE) { printInfo(2,"FAIL!\n"); printError("Cannot write file '%s' (error: %s)\n", String_cString(destinationFileName), Errors_getText(error) ); File_close(&fileHandle); String_delete(destinationFileName); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); if (jobOptions->stopOnErrorFlag) { restoreInfo.error = error; } continue; } length = 0; while ( ((restoreInfo.requestedAbortFlag == NULL) || !(*restoreInfo.requestedAbortFlag)) && (length < fragmentSize) ) { /* pause */ while ((restoreInfo.pauseFlag != NULL) && (*restoreInfo.pauseFlag)) { Misc_udelay(500*1000); } n = MIN(fragmentSize-length,BUFFER_SIZE); error = Archive_readFileData(&archiveFileInfo,buffer,n); if (error != ERROR_NONE) { printInfo(2,"FAIL!\n"); printError("Cannot not read content of archive '%s' (error: %s)!\n", String_cString(archiveFileName), Errors_getText(error) ); if (restoreInfo.error == ERROR_NONE) restoreInfo.error = error; break; } error = File_write(&fileHandle,buffer,n); if (error != ERROR_NONE) { printInfo(2,"FAIL!\n"); printError("Cannot write file '%s' (error: %s)\n", String_cString(destinationFileName), Errors_getText(error) ); if (jobOptions->stopOnErrorFlag) { restoreInfo.error = error; } break; } restoreInfo.statusInfo.fileDoneBytes += n; updateStatusInfo(&restoreInfo); length += n; } if (File_getSize(&fileHandle) > fileInfo.size) { File_truncate(&fileHandle,fileInfo.size); } File_close(&fileHandle); if ((restoreInfo.requestedAbortFlag != NULL) && (*restoreInfo.requestedAbortFlag)) { printInfo(2,"ABORTED\n"); String_delete(destinationFileName); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); continue; } #if 0 if (restoreInfo.error != ERROR_NONE) { String_delete(destinationFileName); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); continue; } #endif /* 0 */ /* set file time, file owner/group */ if (jobOptions->owner.userId != FILE_DEFAULT_USER_ID ) fileInfo.userId = jobOptions->owner.userId; if (jobOptions->owner.groupId != FILE_DEFAULT_GROUP_ID) fileInfo.groupId = jobOptions->owner.groupId; error = File_setFileInfo(destinationFileName,&fileInfo); if (error != ERROR_NONE) { if (jobOptions->stopOnErrorFlag) { printInfo(2,"FAIL!\n"); printError("Cannot set file info of '%s' (error: %s)\n", String_cString(destinationFileName), Errors_getText(error) ); String_delete(destinationFileName); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); restoreInfo.error = error; continue; } else { printWarning("Cannot set file info of '%s' (error: %s)\n", String_cString(destinationFileName), Errors_getText(error) ); } } /* add fragment to file fragment list */ FileFragmentList_add(fileFragmentNode,fragmentOffset,fragmentSize); //FileFragmentList_print(fileFragmentNode,String_cString(fileName)); /* discard fragment list if file is complete */ if (FileFragmentList_checkComplete(fileFragmentNode)) { FileFragmentList_removeFile(&fileFragmentList,fileFragmentNode); } /* free resources */ String_delete(destinationFileName); printInfo(2,"ok\n"); } else { /* skip */ printInfo(3," Restore '%s'...skipped\n",String_cString(fileName)); } /* close archive file, free resources */ Archive_closeEntry(&archiveFileInfo); String_delete(fileName); } break; case FILE_TYPE_DIRECTORY: { String directoryName; FileInfo fileInfo; String destinationFileName; // FileInfo localFileInfo; /* read directory */ directoryName = String_new(); error = Archive_readDirectoryEntry(&archiveInfo, &archiveFileInfo, NULL, NULL, directoryName, &fileInfo ); if (error != ERROR_NONE) { printError("Cannot not read 'directory' content of archive '%s' (error: %s)!\n", String_cString(archiveFileName), Errors_getText(error) ); String_delete(directoryName); if (restoreInfo.error == ERROR_NONE) restoreInfo.error = error; break; } if ( (List_empty(includePatternList) || PatternList_match(includePatternList,directoryName,PATTERN_MATCH_MODE_EXACT)) && !PatternList_match(excludePatternList,directoryName,PATTERN_MATCH_MODE_EXACT) ) { String_set(restoreInfo.statusInfo.fileName,directoryName); restoreInfo.statusInfo.fileDoneBytes = 0LL; restoreInfo.statusInfo.fileTotalBytes = 00L; updateStatusInfo(&restoreInfo); /* get destination filename */ destinationFileName = getDestinationFileName(String_new(), directoryName, jobOptions->directory, jobOptions->directoryStripCount ); /* check if directory already exists */ if (!jobOptions->overwriteFilesFlag && File_exists(destinationFileName)) { printInfo(1, " Restore directory '%s'...skipped (file exists)\n", String_cString(destinationFileName) ); String_delete(destinationFileName); Archive_closeEntry(&archiveFileInfo); String_delete(directoryName); continue; } printInfo(2," Restore directory '%s'...",String_cString(destinationFileName)); /* create directory */ error = File_makeDirectory(destinationFileName, FILE_DEFAULT_USER_ID, FILE_DEFAULT_GROUP_ID, fileInfo.permission ); if (error != ERROR_NONE) { printInfo(2,"FAIL!\n"); printError("Cannot create directory '%s' (error: %s)\n", String_cString(destinationFileName), Errors_getText(error) ); String_delete(destinationFileName); Archive_closeEntry(&archiveFileInfo); String_delete(directoryName); if (jobOptions->stopOnErrorFlag) { restoreInfo.error = error; } continue; } /* set file time, file owner/group */ if (jobOptions->owner.userId != FILE_DEFAULT_USER_ID ) fileInfo.userId = jobOptions->owner.userId; if (jobOptions->owner.groupId != FILE_DEFAULT_GROUP_ID) fileInfo.groupId = jobOptions->owner.groupId; error = File_setFileInfo(destinationFileName,&fileInfo); if (error != ERROR_NONE) { if (jobOptions->stopOnErrorFlag) { printInfo(2,"FAIL!\n"); printError("Cannot set directory info of '%s' (error: %s)\n", String_cString(destinationFileName), Errors_getText(error) ); String_delete(destinationFileName); Archive_closeEntry(&archiveFileInfo); String_delete(directoryName); if (jobOptions->stopOnErrorFlag) { restoreInfo.error = error; } continue; } else { printWarning("Cannot set directory info of '%s' (error: %s)\n", String_cString(destinationFileName), Errors_getText(error) ); } } /* free resources */ String_delete(destinationFileName); printInfo(2,"ok\n"); } else { /* skip */ printInfo(3," Restore '%s'...skipped\n",String_cString(directoryName)); } /* close archive file */ Archive_closeEntry(&archiveFileInfo); String_delete(directoryName); } break; case FILE_TYPE_LINK: { String linkName; String fileName; FileInfo fileInfo; String destinationFileName; // FileInfo localFileInfo; /* read link */ linkName = String_new(); fileName = String_new(); error = Archive_readLinkEntry(&archiveInfo, &archiveFileInfo, NULL, NULL, linkName, fileName, &fileInfo ); if (error != ERROR_NONE) { printError("Cannot not read 'link' content of archive '%s' (error: %s)!\n", String_cString(archiveFileName), Errors_getText(error) ); String_delete(fileName); String_delete(linkName); if (restoreInfo.error == ERROR_NONE) restoreInfo.error = error; break; } if ( (List_empty(includePatternList) || PatternList_match(includePatternList,linkName,PATTERN_MATCH_MODE_EXACT)) && !PatternList_match(excludePatternList,linkName,PATTERN_MATCH_MODE_EXACT) ) { String_set(restoreInfo.statusInfo.fileName,linkName); restoreInfo.statusInfo.fileDoneBytes = 0LL; restoreInfo.statusInfo.fileTotalBytes = 00L; updateStatusInfo(&restoreInfo); /* get destination filename */ destinationFileName = getDestinationFileName(String_new(), linkName, jobOptions->directory, jobOptions->directoryStripCount ); /* create link */ if (!jobOptions->overwriteFilesFlag && File_exists(destinationFileName)) { printInfo(1, " Restore link '%s'...skipped (file exists)\n", String_cString(destinationFileName) ); String_delete(destinationFileName); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); String_delete(linkName); if (jobOptions->stopOnErrorFlag) { restoreInfo.error = ERROR_FILE_EXITS; } continue; } printInfo(2," Restore link '%s'...",String_cString(destinationFileName)); error = File_makeLink(destinationFileName,fileName); if (error != ERROR_NONE) { printInfo(2,"FAIL!\n"); printError("Cannot create link '%s' -> '%s' (error: %s)\n", String_cString(destinationFileName), String_cString(fileName), Errors_getText(error) ); String_delete(destinationFileName); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); String_delete(linkName); if (jobOptions->stopOnErrorFlag) { restoreInfo.error = error; } continue; } /* set file time, file owner/group */ if (jobOptions->owner.userId != FILE_DEFAULT_USER_ID ) fileInfo.userId = jobOptions->owner.userId; if (jobOptions->owner.groupId != FILE_DEFAULT_GROUP_ID) fileInfo.groupId = jobOptions->owner.groupId; error = File_setFileInfo(destinationFileName,&fileInfo); if (error != ERROR_NONE) { if (jobOptions->stopOnErrorFlag) { printInfo(2,"FAIL!\n"); printError("Cannot set file info of '%s' (error: %s)\n", String_cString(destinationFileName), Errors_getText(error) ); String_delete(destinationFileName); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); String_delete(linkName); if (jobOptions->stopOnErrorFlag) { restoreInfo.error = error; } continue; } else { printWarning("Cannot set file info of '%s' (error: %s)\n", String_cString(destinationFileName), Errors_getText(error) ); } } /* free resources */ String_delete(destinationFileName); printInfo(2,"ok\n"); } else { /* skip */ printInfo(3," Restore '%s'...skipped\n",String_cString(linkName)); } /* close archive file */ Archive_closeEntry(&archiveFileInfo); String_delete(fileName); String_delete(linkName); } break; case FILE_TYPE_SPECIAL: { String fileName; FileInfo fileInfo; String destinationFileName; // FileInfo localFileInfo; /* read special device */ fileName = String_new(); error = Archive_readSpecialEntry(&archiveInfo, &archiveFileInfo, NULL, NULL, fileName, &fileInfo ); if (error != ERROR_NONE) { printError("Cannot not read 'special' content of archive '%s' (error: %s)!\n", String_cString(archiveFileName), Errors_getText(error) ); String_delete(fileName); if (restoreInfo.error == ERROR_NONE) restoreInfo.error = error; break; } if ( (List_empty(includePatternList) || PatternList_match(includePatternList,fileName,PATTERN_MATCH_MODE_EXACT)) && !PatternList_match(excludePatternList,fileName,PATTERN_MATCH_MODE_EXACT) ) { String_set(restoreInfo.statusInfo.fileName,fileName); restoreInfo.statusInfo.fileDoneBytes = 0LL; restoreInfo.statusInfo.fileTotalBytes = 00L; updateStatusInfo(&restoreInfo); /* get destination filename */ destinationFileName = getDestinationFileName(String_new(), fileName, jobOptions->directory, jobOptions->directoryStripCount ); /* create special device */ if (!jobOptions->overwriteFilesFlag && File_exists(destinationFileName)) { printInfo(1, " Restore special device '%s'...skipped (file exists)\n", String_cString(destinationFileName) ); String_delete(destinationFileName); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); if (jobOptions->stopOnErrorFlag) { restoreInfo.error = ERROR_FILE_EXITS; } continue; } printInfo(2," Restore special device '%s'...",String_cString(destinationFileName)); error = File_makeSpecial(destinationFileName, fileInfo.specialType, fileInfo.major, fileInfo.minor ); if (error != ERROR_NONE) { printInfo(2,"FAIL!\n"); printError("Cannot create special device '%s' (error: %s)\n", String_cString(fileName), Errors_getText(error) ); String_delete(destinationFileName); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); if (jobOptions->stopOnErrorFlag) { restoreInfo.error = error; } continue; } /* set file time, file owner/group */ if (jobOptions->owner.userId != FILE_DEFAULT_USER_ID ) fileInfo.userId = jobOptions->owner.userId; if (jobOptions->owner.groupId != FILE_DEFAULT_GROUP_ID) fileInfo.groupId = jobOptions->owner.groupId; error = File_setFileInfo(destinationFileName,&fileInfo); if (error != ERROR_NONE) { if (jobOptions->stopOnErrorFlag) { printInfo(2,"FAIL!\n"); printError("Cannot set file info of '%s' (error: %s)\n", String_cString(destinationFileName), Errors_getText(error) ); String_delete(destinationFileName); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); if (jobOptions->stopOnErrorFlag) { restoreInfo.error = error; } continue; } else { printWarning("Cannot set file info of '%s' (error: %s)\n", String_cString(destinationFileName), Errors_getText(error) ); } } /* free resources */ String_delete(destinationFileName); printInfo(2,"ok\n"); } else { /* skip */ printInfo(3," Restore '%s'...skipped\n",String_cString(fileName)); } /* close archive file */ Archive_closeEntry(&archiveFileInfo); String_delete(fileName); } break; default: #ifndef NDEBUG HALT_INTERNAL_ERROR_UNHANDLED_SWITCH_CASE(); #endif /* NDEBUG */ break; /* not reached */ } } /* close archive */ Archive_close(&archiveInfo); } /* check fragment lists */ if ((restoreInfo.requestedAbortFlag == NULL) || !(*restoreInfo.requestedAbortFlag)) { for (fileFragmentNode = fileFragmentList.head; fileFragmentNode != NULL; fileFragmentNode = fileFragmentNode->next) { if (!FileFragmentList_checkComplete(fileFragmentNode)) { printInfo(0,"Warning: incomplete file '%s'\n",String_cString(fileFragmentNode->fileName)); if (restoreInfo.error == ERROR_NONE) restoreInfo.error = ERROR_FILE_INCOMPLETE; } } } /* free resources */ String_delete(archiveFileName); FileFragmentList_done(&fileFragmentList); free(buffer); String_delete(restoreInfo.statusInfo.fileName); String_delete(restoreInfo.statusInfo.storageName); if ((restoreInfo.requestedAbortFlag == NULL) || !(*restoreInfo.requestedAbortFlag)) { return restoreInfo.error; } else { return ERROR_ABORTED; } }
Errors Misc_executeCommand(const char *commandTemplate, const TextMacro macros[], uint macroCount, ExecuteIOFunction stdoutExecuteIOFunction, ExecuteIOFunction stderrExecuteIOFunction, void *executeIOUserData ) { Errors error; String commandLine; StringTokenizer stringTokenizer; String token; String command; StringList argumentList; const char *path; String fileName; bool foundFlag; char const **arguments; int pipeStdin[2],pipeStdout[2],pipeStderr[2]; int pid; StringNode *stringNode; uint n,z; int status; bool sleepFlag; String stdoutLine,stderrLine; int exitcode; int terminateSignal; error = ERROR_NONE; if (commandTemplate != NULL) { commandLine = String_new(); command = File_newFileName(); StringList_init(&argumentList); // expand command line Misc_expandMacros(commandLine,commandTemplate,macros,macroCount); printInfo(3,"Execute command '%s'...",String_cString(commandLine)); // parse command String_initTokenizer(&stringTokenizer,commandLine,STRING_BEGIN,STRING_WHITE_SPACES,STRING_QUOTES,FALSE); if (!String_getNextToken(&stringTokenizer,&token,NULL)) { String_doneTokenizer(&stringTokenizer); StringList_done(&argumentList); String_delete(command); String_delete(commandLine); return ERRORX_(PARSE_COMMAND,0,String_cString(commandLine)); } File_setFileName(command,token); // parse arguments while (String_getNextToken(&stringTokenizer,&token,NULL)) { StringList_append(&argumentList,token); } String_doneTokenizer(&stringTokenizer); // find command in PATH path = getenv("PATH"); if (path != NULL) { fileName = File_newFileName(); foundFlag = FALSE; String_initTokenizerCString(&stringTokenizer,path,":","",FALSE); while (String_getNextToken(&stringTokenizer,&token,NULL) && !foundFlag) { File_setFileName(fileName,token); File_appendFileName(fileName,command); if (File_exists(fileName)) { File_setFileName(command,fileName); foundFlag = TRUE; } } String_doneTokenizer(&stringTokenizer); File_deleteFileName(fileName); } #if 0 fprintf(stderr,"%s,%d: command %s\n",__FILE__,__LINE__,String_cString(command)); stringNode = argumentList.head; while (stringNode != NULL) { fprintf(stderr,"%s,%d: argument %s\n",__FILE__,__LINE__,String_cString(stringNode->string)); stringNode = stringNode->next; } #endif /* 0 */ #if defined(HAVE_PIPE) && defined(HAVE_FORK) && defined(HAVE_WAITPID) #if 1 // create i/o pipes if (pipe(pipeStdin) != 0) { error = ERRORX_(IO_REDIRECT_FAIL,errno,String_cString(commandLine)); StringList_done(&argumentList); String_delete(command); String_delete(commandLine); return error; } if (pipe(pipeStdout) != 0) { error = ERRORX_(IO_REDIRECT_FAIL,errno,String_cString(commandLine)); close(pipeStdin[0]); close(pipeStdin[1]); StringList_done(&argumentList); String_delete(command); String_delete(commandLine); return error; } if (pipe(pipeStderr) != 0) { error = ERRORX_(IO_REDIRECT_FAIL,errno,String_cString(commandLine)); close(pipeStdout[0]); close(pipeStdout[1]); close(pipeStdin[0]); close(pipeStdin[1]); StringList_done(&argumentList); String_delete(command); String_delete(commandLine); return error; } // do fork to start separated process pid = fork(); if (pid == 0) { // close stdin, stdout, and stderr and reassign them to the pipes close(STDERR_FILENO); close(STDOUT_FILENO); close(STDIN_FILENO); // redirect stdin/stdout/stderr to pipe dup2(pipeStdin[0],STDIN_FILENO); dup2(pipeStdout[1],STDOUT_FILENO); dup2(pipeStderr[1],STDERR_FILENO); /* close unused pipe handles (the pipes are duplicated by fork(), thus there are two open ends of the pipes) */ close(pipeStderr[0]); close(pipeStdout[0]); close(pipeStdin[1]); // execute of external program n = 1+StringList_count(&argumentList)+1; arguments = (char const**)malloc(n*sizeof(char*)); if (arguments == NULL) { HALT_INSUFFICIENT_MEMORY(); } z = 0; arguments[z] = String_cString(command); z++; stringNode = argumentList.head; while (stringNode != NULL) { assert(z < n); arguments[z] = String_cString(stringNode->string); z++; stringNode = stringNode->next; } assert(z < n); arguments[z] = NULL; z++; execvp(String_cString(command),(char**)arguments); // in case exec() fail, return a default exitcode HALT_INTERNAL_ERROR("execvp() returned"); } else if (pid < 0) { error = ERRORX_(EXEC_FAIL,errno,String_cString(commandLine)); printInfo(3,"FAIL!\n"); close(pipeStderr[0]); close(pipeStderr[1]); close(pipeStdout[0]); close(pipeStdout[1]); close(pipeStdin[0]); close(pipeStdin[1]); StringList_done(&argumentList); String_delete(command); String_delete(commandLine); return error; } // close unused pipe handles (the pipe is duplicated by fork(), thus there are two open ends of the pipe) close(pipeStderr[1]); close(pipeStdout[1]); close(pipeStdin[0]); #else /* 0 */ error = ERROR_NONE; #endif /* 0 */ // wait until process terminate and read stdout/stderr stdoutLine = String_new(); stderrLine = String_new(); status = 0; while ((waitpid(pid,&status,WNOHANG) == 0) || (!WIFEXITED(status) && !WIFSIGNALED(status))) { sleepFlag = TRUE; if (readProcessIO(pipeStdout[0],stdoutLine)) { if (stdoutExecuteIOFunction != NULL) stdoutExecuteIOFunction(executeIOUserData,stdoutLine); String_clear(stdoutLine); sleepFlag = FALSE; } if (readProcessIO(pipeStderr[0],stderrLine)) { if (stderrExecuteIOFunction != NULL) stderrExecuteIOFunction(executeIOUserData,stderrLine); String_clear(stderrLine); sleepFlag = FALSE; } if (sleepFlag) { Misc_udelay(500LL*1000LL); } } while (readProcessIO(pipeStdout[0],stdoutLine)) { if (stdoutExecuteIOFunction != NULL) stdoutExecuteIOFunction(executeIOUserData,stdoutLine); String_clear(stdoutLine); } while (readProcessIO(pipeStderr[0],stderrLine)) { if (stderrExecuteIOFunction != NULL) stderrExecuteIOFunction(executeIOUserData,stderrLine); String_clear(stderrLine); } String_delete(stderrLine); String_delete(stdoutLine); // close i/o close(pipeStderr[0]); close(pipeStdout[0]); close(pipeStdin[1]); // check exit code exitcode = -1; if (WIFEXITED(status)) { exitcode = WEXITSTATUS(status); printInfo(3,"ok (exitcode %d)\n",exitcode); if (exitcode != 0) { error = ERRORX_(EXEC_FAIL,exitcode,String_cString(commandLine)); StringList_done(&argumentList); String_delete(command); String_delete(commandLine); return error; } } else if (WIFSIGNALED(status)) { terminateSignal = WTERMSIG(status); error = ERRORX_(EXEC_FAIL,terminateSignal,String_cString(commandLine)); printInfo(3,"FAIL (signal %d)\n",terminateSignal); StringList_done(&argumentList); String_delete(command); String_delete(commandLine); return error; } else { printInfo(3,"ok (unknown exit)\n"); } #elif defined(WIN32) #if 0 HANDLE hOutputReadTmp,hOutputRead,hOutputWrite; HANDLE hInputWriteTmp,hInputRead,hInputWrite; HANDLE hErrorWrite; HANDLE hThread; DWORD ThreadId; SECURITY_ATTRIBUTES sa; // Set up the security attributes struct. sa.nLength= sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; // Create the child output pipe. if (!CreatePipe(&hOutputReadTmp,&hOutputWrite,&sa,0)) DisplayError("CreatePipe"); // Create a duplicate of the output write handle for the std error // write handle. This is necessary in case the child application // closes one of its std output handles. if (!DuplicateHandle(GetCurrentProcess(),hOutputWrite, GetCurrentProcess(),&hErrorWrite,0, TRUE,DUPLICATE_SAME_ACCESS)) DisplayError("DuplicateHandle"); // Create the child input pipe. if (!CreatePipe(&hInputRead,&hInputWriteTmp,&sa,0)) DisplayError("CreatePipe"); // Create new output read handle and the input write handles. Set // the Properties to FALSE. Otherwise, the child inherits the // properties and, as a result, non-closeable handles to the pipes // are created. if (!DuplicateHandle(GetCurrentProcess(),hOutputReadTmp, GetCurrentProcess(), &hOutputRead, // Address of new handle. 0,FALSE, // Make it uninheritable. DUPLICATE_SAME_ACCESS)) DisplayError("DupliateHandle"); if (!DuplicateHandle(GetCurrentProcess(),hInputWriteTmp, GetCurrentProcess(), &hInputWrite, // Address of new handle. 0,FALSE, // Make it uninheritable. DUPLICATE_SAME_ACCESS)) DisplayError("DupliateHandle"); // Close inheritable copies of the handles you do not want to be // inherited. if (!CloseHandle(hOutputReadTmp)) DisplayError("CloseHandle"); if (!CloseHandle(hInputWriteTmp)) DisplayError("CloseHandle"); // Get std input handle so you can close it and force the ReadFile to // fail when you want the input thread to exit. if ( (hStdIn = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE ) DisplayError("GetStdHandle"); PrepAndLaunchRedirectedChild(hOutputWrite,hInputRead,hErrorWrite); // Close pipe handles (do not continue to modify the parent). // You need to make sure that no handles to the write end of the // output pipe are maintained in this process or else the pipe will // not close when the child process exits and the ReadFile will hang. if (!CloseHandle(hOutputWrite)) DisplayError("CloseHandle"); if (!CloseHandle(hInputRead )) DisplayError("CloseHandle"); if (!CloseHandle(hErrorWrite)) DisplayError("CloseHandle"); // Launch the thread that gets the input and sends it to the child. hThread = CreateThread(NULL,0,GetAndSendInputThread, (LPVOID)hInputWrite,0,&ThreadId); if (hThread == NULL) DisplayError("CreateThread"); // Read the child's output. ReadAndHandleOutput(hOutputRead); // Redirection is complete // Force the read on the input to return by closing the stdin handle. if (!CloseHandle(hStdIn)) DisplayError("CloseHandle"); // Tell the thread to exit and wait for thread to die. bRunThread = FALSE; if (WaitForSingleObject(hThread,INFINITE) == WAIT_FAILED) DisplayError("WaitForSingleObject"); if (!CloseHandle(hOutputRead)) DisplayError("CloseHandle"); if (!CloseHandle(hInputWrite)) DisplayError("CloseHandle"); #endif #else /* not defined(HAVE_PIPE) && defined(HAVE_FORK) && defined(HAVE_WAITPID) || WIN32 */ #error pipe()/fork()/waitpid() not available nor Win32 system! #endif /* defined(HAVE_PIPE) && defined(HAVE_FORK) && defined(HAVE_WAITPID) || WIN32 */ // free resources StringList_done(&argumentList); String_delete(command); String_delete(commandLine); } return error; }
LOCAL bool parseDefinition(const char *s, Definition *definition, uint64 maxPosition) { StringTokenizer stringTokenizer; String t; String w; uint length; char buffer[1024]; assert(definition != NULL); t = String_newCString(s); String_initTokenizer(&stringTokenizer,t,STRING_BEGIN,":",NULL,FALSE); /* get type */ if (String_getNextToken(&stringTokenizer,&w,NULL)) { if (String_equalsCString(w,"m")) definition->type = DEFINITION_TYPE_MODIFY; else if (String_equalsCString(w,"r")) definition->type = DEFINITION_TYPE_RANDOMIZE; else if (String_equalsCString(w,"i")) definition->type = DEFINITION_TYPE_INSERT; else if (String_equalsCString(w,"d")) definition->type = DEFINITION_TYPE_DELETE; else { String_doneTokenizer(&stringTokenizer); String_delete(t); fprintf(stderr,"ERROR: Invalid definition '%s': expected m,i,d!\n",s); return FALSE; } } else { String_doneTokenizer(&stringTokenizer); String_delete(t); fprintf(stderr,"ERROR: Invalid definition '%s'!\n",s); return FALSE; } /* get position */ if (String_getNextToken(&stringTokenizer,&w,NULL)) { if (!String_scan(w,STRING_BEGIN,"%llu",&definition->position)) { String_doneTokenizer(&stringTokenizer); String_delete(t); fprintf(stderr,"ERROR: Invalid position in definition '%s'!\n",s); return FALSE; } } else { definition->position = getRandomInteger64(maxPosition); } /* get value/length */ if (String_getNextToken(&stringTokenizer,&w,NULL)) { switch (definition->type) { case DEFINITION_TYPE_MODIFY: definition->value = String_new(); if (!String_scan(w,STRING_BEGIN,"%S",definition->value)) { String_delete(definition->value); String_doneTokenizer(&stringTokenizer); String_delete(t); fprintf(stderr,"ERROR: Invalid length in definition '%s'!\n",s); return FALSE; } break; case DEFINITION_TYPE_RANDOMIZE: if (!String_scan(w,STRING_BEGIN,"%u",&length)) { String_doneTokenizer(&stringTokenizer); String_delete(t); fprintf(stderr,"ERROR: Invalid length in definition '%s'!\n",s); return FALSE; } if (length > sizeof(buffer)) length = sizeof(buffer); getRandomBuffer(buffer,length); definition->value = String_newBuffer(buffer,length); break; case DEFINITION_TYPE_INSERT: definition->value = String_new(); if (!String_scan(w,STRING_BEGIN,"%S",definition->value)) { String_delete(definition->value); String_doneTokenizer(&stringTokenizer); String_delete(t); fprintf(stderr,"ERROR: Invalid value in definition '%s'!\n",s); return FALSE; } break; case DEFINITION_TYPE_DELETE: if (!String_scan(w,STRING_BEGIN,"%u",&definition->length)) { String_doneTokenizer(&stringTokenizer); String_delete(t); fprintf(stderr,"ERROR: Invalid length in definition '%s'!\n",s); return FALSE; } break; } } else { switch (definition->type) { case DEFINITION_TYPE_MODIFY: definition->value = String_newChar((char)getRandomByte(256)); break; case DEFINITION_TYPE_RANDOMIZE: getRandomBuffer(buffer,sizeof(buffer)); definition->value = String_newBuffer(buffer,getRandomInteger(sizeof(buffer))); break; case DEFINITION_TYPE_INSERT: definition->value = String_new(); if (!String_scan(w,STRING_BEGIN,"%S",&definition->value)) { String_delete(definition->value); String_doneTokenizer(&stringTokenizer); String_delete(t); fprintf(stderr,"ERROR: Invalid value in definition '%s'!\n",s); return FALSE; } break; case DEFINITION_TYPE_DELETE: if (!String_scan(w,STRING_BEGIN,"%u",&definition->length)) { String_doneTokenizer(&stringTokenizer); String_delete(t); fprintf(stderr,"ERROR: Invalid length in definition '%s'!\n",s); return FALSE; } break; } } if (String_getNextToken(&stringTokenizer,&w,NULL)) { String_doneTokenizer(&stringTokenizer); String_delete(t); fprintf(stderr,"ERROR: Invalid definition '%s'!\n",s); return FALSE; } String_doneTokenizer(&stringTokenizer); String_delete(t); return TRUE; }
Errors Command_compare(StringList *archiveFileNameList, EntryList *includeEntryList, PatternList *excludePatternList, JobOptions *jobOptions, ArchiveGetCryptPasswordFunction archiveGetCryptPasswordFunction, void *archiveGetCryptPasswordUserData ) { byte *archiveBuffer,*buffer; FragmentList fragmentList; String archiveFileName; Errors failError; Errors error; ArchiveInfo archiveInfo; ArchiveFileInfo archiveFileInfo; ArchiveEntryTypes archiveEntryType; FragmentNode *fragmentNode; assert(archiveFileNameList != NULL); assert(includeEntryList != NULL); assert(excludePatternList != NULL); assert(jobOptions != NULL); /* allocate resources */ archiveBuffer = (byte*)malloc(BUFFER_SIZE); if (archiveBuffer == NULL) { HALT_INSUFFICIENT_MEMORY(); } buffer = malloc(BUFFER_SIZE); if (buffer == NULL) { free(archiveBuffer); HALT_INSUFFICIENT_MEMORY(); } FragmentList_init(&fragmentList); archiveFileName = String_new(); failError = ERROR_NONE; while ( !StringList_empty(archiveFileNameList) && (failError == ERROR_NONE) ) { StringList_getFirst(archiveFileNameList,archiveFileName); printInfo(1,"Comparing archive '%s':\n",String_cString(archiveFileName)); /* open archive */ error = Archive_open(&archiveInfo, archiveFileName, jobOptions, archiveGetCryptPasswordFunction, archiveGetCryptPasswordUserData ); if (error != ERROR_NONE) { printError("Cannot open archive file '%s' (error: %s)!\n", String_cString(archiveFileName), Errors_getText(error) ); if (failError == ERROR_NONE) failError = error; continue; } /* read files */ while ( !Archive_eof(&archiveInfo) && (failError == ERROR_NONE) ) { /* get next archive entry type */ error = Archive_getNextArchiveEntryType(&archiveInfo, &archiveFileInfo, &archiveEntryType ); if (error != ERROR_NONE) { printError("Cannot not read next entry in archive '%s' (error: %s)!\n", String_cString(archiveFileName), Errors_getText(error) ); if (failError == ERROR_NONE) failError = error; break; } switch (archiveEntryType) { case ARCHIVE_ENTRY_TYPE_FILE: { String fileName; FileInfo fileInfo; uint64 fragmentOffset,fragmentSize; FragmentNode *fragmentNode; // FileInfo localFileInfo; FileHandle fileHandle; bool equalFlag; uint64 length; ulong n; ulong diffIndex; /* read file */ fileName = String_new(); error = Archive_readFileEntry(&archiveInfo, &archiveFileInfo, NULL, NULL, NULL, fileName, &fileInfo, &fragmentOffset, &fragmentSize ); if (error != ERROR_NONE) { printError("Cannot not read 'file' content of archive '%s' (error: %s)!\n", String_cString(archiveFileName), Errors_getText(error) ); String_delete(fileName); if (failError == ERROR_NONE) failError = error; break; } if ( (List_empty(includeEntryList) || EntryList_match(includeEntryList,fileName,PATTERN_MATCH_MODE_EXACT)) && !PatternList_match(excludePatternList,fileName,PATTERN_MATCH_MODE_EXACT) ) { printInfo(2," Compare file '%s'...",String_cString(fileName)); /* check file */ if (!File_exists(fileName)) { printInfo(2,"FAIL!\n"); printError("File '%s' not found!\n",String_cString(fileName)); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); if (jobOptions->stopOnErrorFlag) { failError = ERROR_FILE_NOT_FOUND; } break; } if (File_getType(fileName) != FILE_TYPE_FILE) { printInfo(2,"FAIL!\n"); printError("'%s' is not a file!\n",String_cString(fileName)); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); if (jobOptions->stopOnErrorFlag) { failError = ERROR_WRONG_FILE_TYPE; } break; } /* get file fragment list */ fragmentNode = FragmentList_find(&fragmentList,fileName); if (fragmentNode == NULL) { fragmentNode = FragmentList_add(&fragmentList,fileName,fileInfo.size); } //FragmentList_print(fragmentNode,String_cString(fileName)); /* open file */ error = File_open(&fileHandle,fileName,FILE_OPENMODE_READ); if (error != ERROR_NONE) { printInfo(2,"FAIL!\n"); printError("Cannot open file '%s' (error: %s)\n", String_cString(fileName), Errors_getText(error) ); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); if (jobOptions->stopOnErrorFlag) { failError = error; } continue; } /* check file size */ if (fileInfo.size != File_getSize(&fileHandle)) { printInfo(2,"FAIL!\n"); printError("'%s' differ in size: expected %lld bytes, found %lld bytes\n", String_cString(fileName), fileInfo.size, File_getSize(&fileHandle) ); File_close(&fileHandle); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); if (jobOptions->stopOnErrorFlag) { failError = ERROR_FILES_DIFFER; } continue; } /* check file content */ error = File_seek(&fileHandle,fragmentOffset); if (error != ERROR_NONE) { printInfo(2,"FAIL!\n"); printError("Cannot read file '%s' (error: %s)\n", String_cString(fileName), Errors_getText(error) ); File_close(&fileHandle); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); if (jobOptions->stopOnErrorFlag) { failError = error; } continue; } length = 0; equalFlag = TRUE; diffIndex = 0; while ((length < fragmentSize) && equalFlag) { n = MIN(fragmentSize-length,BUFFER_SIZE); /* read archive, file */ error = Archive_readData(&archiveFileInfo,archiveBuffer,n); if (error != ERROR_NONE) { printInfo(2,"FAIL!\n"); printError("Cannot not read content of archive '%s' (error: %s)!\n", String_cString(archiveFileName), Errors_getText(error) ); if (failError == ERROR_NONE) failError = error; break; } error = File_read(&fileHandle,buffer,n,NULL); if (error != ERROR_NONE) { printInfo(2,"FAIL!\n"); printError("Cannot read file '%s' (error: %s)\n", String_cString(fileName), Errors_getText(error) ); if (jobOptions->stopOnErrorFlag) { failError = error; } break; } /* compare */ diffIndex = compare(archiveBuffer,buffer,n); equalFlag = (diffIndex >= n); if (!equalFlag) { printInfo(2,"FAIL!\n"); printError("'%s' differ at offset %llu\n", String_cString(fileName), fragmentOffset+length+(uint64)diffIndex ); if (jobOptions->stopOnErrorFlag) { failError = ERROR_FILES_DIFFER; } break; } length += n; } File_close(&fileHandle); if (failError != ERROR_NONE) { Archive_closeEntry(&archiveFileInfo); String_delete(fileName); continue; } #if 0 /* get local file info */ /* check file time, permissions, file owner/group */ #endif /* 0 */ printInfo(2,"ok\n"); /* add fragment to file fragment list */ FragmentList_addEntry(fragmentNode,fragmentOffset,fragmentSize); /* discard fragment list if file is complete */ if (FragmentList_checkEntryComplete(fragmentNode)) { FragmentList_remove(&fragmentList,fragmentNode); } /* free resources */ } else { /* skip */ printInfo(3," Compare '%s'...skipped\n",String_cString(fileName)); } /* close archive file, free resources */ Archive_closeEntry(&archiveFileInfo); String_delete(fileName); } break; case ARCHIVE_ENTRY_TYPE_IMAGE: { String imageName; DeviceInfo deviceInfo; uint64 blockOffset,blockCount; FragmentNode *fragmentNode; DeviceHandle deviceHandle; bool equalFlag; uint64 block; ulong bufferBlockCount; ulong diffIndex; /* read image */ imageName = String_new(); error = Archive_readImageEntry(&archiveInfo, &archiveFileInfo, NULL, NULL, NULL, imageName, &deviceInfo, &blockOffset, &blockCount ); if (error != ERROR_NONE) { printError("Cannot not read 'image' content of archive '%s' (error: %s)!\n", String_cString(archiveFileName), Errors_getText(error) ); String_delete(imageName); if (failError == ERROR_NONE) failError = error; break; } if ( (List_empty(includeEntryList) || EntryList_match(includeEntryList,imageName,PATTERN_MATCH_MODE_EXACT)) && !PatternList_match(excludePatternList,imageName,PATTERN_MATCH_MODE_EXACT) ) { printInfo(2," Compare image '%s'...",String_cString(imageName)); /* check if device exists */ if (!File_exists(imageName)) { printInfo(2,"FAIL!\n"); printError("Device '%s' not found!\n",String_cString(imageName)); Archive_closeEntry(&archiveFileInfo); String_delete(imageName); if (jobOptions->stopOnErrorFlag) { failError = ERROR_FILE_NOT_FOUND; } break; } /* get image fragment list */ fragmentNode = FragmentList_find(&fragmentList,imageName); if (fragmentNode == NULL) { fragmentNode = FragmentList_add(&fragmentList,imageName,deviceInfo.size); } /* open device */ error = Device_open(&deviceHandle,imageName,DEVICE_OPENMODE_READ); if (error != ERROR_NONE) { printInfo(2,"FAIL!\n"); printError("Cannot open file '%s' (error: %s)\n", String_cString(imageName), Errors_getText(error) ); Archive_closeEntry(&archiveFileInfo); String_delete(imageName); if (jobOptions->stopOnErrorFlag) { failError = error; } continue; } /* check image size */ if (deviceInfo.size != Device_getSize(&deviceHandle)) { printInfo(2,"FAIL!\n"); printError("'%s' differ in size: expected %lld bytes, found %lld bytes\n", String_cString(imageName), deviceInfo.size, Device_getSize(&deviceHandle) ); Device_close(&deviceHandle); Archive_closeEntry(&archiveFileInfo); String_delete(imageName); if (jobOptions->stopOnErrorFlag) { failError = ERROR_FILES_DIFFER; } continue; } /* check image content */ error = Device_seek(&deviceHandle,blockOffset*(uint64)deviceInfo.blockSize); if (error != ERROR_NONE) { printInfo(2,"FAIL!\n"); printError("Cannot read file '%s' (error: %s)\n", String_cString(imageName), Errors_getText(error) ); Device_close(&deviceHandle); Archive_closeEntry(&archiveFileInfo); String_delete(imageName); if (jobOptions->stopOnErrorFlag) { failError = error; } continue; } block = 0LL; equalFlag = TRUE; diffIndex = 0; while ((block < blockCount) && equalFlag) { assert(deviceInfo.blockSize > 0); bufferBlockCount = MIN(blockCount-block,BUFFER_SIZE/deviceInfo.blockSize); /* read archive, file */ error = Archive_readData(&archiveFileInfo,archiveBuffer,bufferBlockCount*deviceInfo.blockSize); if (error != ERROR_NONE) { printInfo(2,"FAIL!\n"); printError("Cannot not read content of archive '%s' (error: %s)!\n", String_cString(archiveFileName), Errors_getText(error) ); if (failError == ERROR_NONE) failError = error; break; } error = Device_read(&deviceHandle,buffer,bufferBlockCount*deviceInfo.blockSize,NULL); if (error != ERROR_NONE) { printInfo(2,"FAIL!\n"); printError("Cannot read file '%s' (error: %s)\n", String_cString(imageName), Errors_getText(error) ); if (jobOptions->stopOnErrorFlag) { failError = error; } break; } /* compare */ diffIndex = compare(archiveBuffer,buffer,bufferBlockCount*deviceInfo.blockSize); equalFlag = (diffIndex >= bufferBlockCount*deviceInfo.blockSize); if (!equalFlag) { printInfo(2,"FAIL!\n"); printError("'%s' differ at offset %llu\n", String_cString(imageName), blockOffset*(uint64)deviceInfo.blockSize+block*(uint64)deviceInfo.blockSize+(uint64)diffIndex ); if (jobOptions->stopOnErrorFlag) { failError = ERROR_FILES_DIFFER; } break; } block += (uint64)bufferBlockCount; } Device_close(&deviceHandle); if (failError != ERROR_NONE) { Archive_closeEntry(&archiveFileInfo); String_delete(imageName); continue; } #if 0 /* get local file info */ /* check file time, permissions, file owner/group */ #endif /* 0 */ printInfo(2,"ok\n"); /* add fragment to file fragment list */ FragmentList_addEntry(fragmentNode,blockOffset*(uint64)deviceInfo.blockSize,blockCount*(uint64)deviceInfo.blockSize); /* discard fragment list if file is complete */ if (FragmentList_checkEntryComplete(fragmentNode)) { FragmentList_remove(&fragmentList,fragmentNode); } /* free resources */ } else { /* skip */ printInfo(3," Compare '%s'...skipped\n",String_cString(imageName)); } /* close archive file, free resources */ Archive_closeEntry(&archiveFileInfo); String_delete(imageName); } break; case ARCHIVE_ENTRY_TYPE_DIRECTORY: { String directoryName; FileInfo fileInfo; // String localFileName; // FileInfo localFileInfo; /* read directory */ directoryName = String_new(); error = Archive_readDirectoryEntry(&archiveInfo, &archiveFileInfo, NULL, NULL, directoryName, &fileInfo ); if (error != ERROR_NONE) { printError("Cannot not read 'directory' content of archive '%s' (error: %s)!\n", String_cString(archiveFileName), Errors_getText(error) ); String_delete(directoryName); if (failError == ERROR_NONE) failError = error; break; } if ( (List_empty(includeEntryList) || EntryList_match(includeEntryList,directoryName,PATTERN_MATCH_MODE_EXACT)) && !PatternList_match(excludePatternList,directoryName,PATTERN_MATCH_MODE_EXACT) ) { printInfo(2," Compare directory '%s'...",String_cString(directoryName)); /* check directory */ if (!File_exists(directoryName)) { printInfo(2,"FAIL!\n"); printError("Directory '%s' does not exists!\n",String_cString(directoryName)); Archive_closeEntry(&archiveFileInfo); String_delete(directoryName); if (jobOptions->stopOnErrorFlag) { failError = ERROR_FILE_NOT_FOUND; } break; } if (File_getType(directoryName) != FILE_TYPE_DIRECTORY) { printInfo(2,"FAIL!\n"); printError("'%s' is not a directory!\n", String_cString(directoryName) ); Archive_closeEntry(&archiveFileInfo); String_delete(directoryName); if (jobOptions->stopOnErrorFlag) { failError = ERROR_WRONG_FILE_TYPE; } break; } #if 0 /* get local file info */ error = File_getFileInfo(directoryName,&localFileInfo); if (error != ERROR_NONE) { printError("Cannot not read local directory '%s' (error: %s)!\n", String_cString(directoryName), Errors_getText(error) ); Archive_closeEntry(&archiveFileInfo); String_delete(directoryName); if (failError == ERROR_NONE) failError = error; break; } /* check file time, permissions, file owner/group */ #endif /* 0 */ printInfo(2,"ok\n"); /* free resources */ } else { /* skip */ printInfo(3," Compare '%s'...skipped\n",String_cString(directoryName)); } /* close archive file */ Archive_closeEntry(&archiveFileInfo); String_delete(directoryName); } break; case ARCHIVE_ENTRY_TYPE_LINK: { String linkName; String fileName; FileInfo fileInfo; String localFileName; // FileInfo localFileInfo; /* read link */ linkName = String_new(); fileName = String_new(); error = Archive_readLinkEntry(&archiveInfo, &archiveFileInfo, NULL, NULL, linkName, fileName, &fileInfo ); if (error != ERROR_NONE) { printError("Cannot not read 'link' content of archive '%s' (error: %s)!\n", String_cString(archiveFileName), Errors_getText(error) ); String_delete(fileName); String_delete(linkName); if (failError == ERROR_NONE) failError = error; break; } if ( (List_empty(includeEntryList) || EntryList_match(includeEntryList,linkName,PATTERN_MATCH_MODE_EXACT)) && !PatternList_match(excludePatternList,linkName,PATTERN_MATCH_MODE_EXACT) ) { printInfo(2," Compare link '%s'...",String_cString(linkName)); /* check link */ if (!File_exists(linkName)) { printInfo(2,"FAIL!\n"); printError("Link '%s' -> '%s' does not exists!\n", String_cString(linkName), String_cString(fileName) ); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); String_delete(linkName); if (jobOptions->stopOnErrorFlag) { failError = ERROR_FILE_NOT_FOUND; } break; } if (File_getType(linkName) != FILE_TYPE_LINK) { printInfo(2,"FAIL!\n"); printError("'%s' is not a link!\n", String_cString(linkName) ); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); String_delete(linkName); if (jobOptions->stopOnErrorFlag) { failError = ERROR_WRONG_FILE_TYPE; } break; } /* check link content */ localFileName = String_new(); error = File_readLink(linkName,localFileName); if (error != ERROR_NONE) { printError("Cannot not read local file '%s' (error: %s)!\n", String_cString(linkName), Errors_getText(error) ); String_delete(localFileName); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); String_delete(linkName); if (jobOptions->stopOnErrorFlag) { failError = error; } break; } if (!String_equals(fileName,localFileName)) { printInfo(2,"FAIL!\n"); printError("Link '%s' does not contain file '%s'!\n", String_cString(linkName), String_cString(fileName) ); String_delete(localFileName); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); String_delete(linkName); if (jobOptions->stopOnErrorFlag) { failError = ERROR_FILES_DIFFER; } break; } String_delete(localFileName); #if 0 /* get local file info */ error = File_getFileInfo(linkName,&localFileInfo); if (error != ERROR_NONE) { printError("Cannot not read local file '%s' (error: %s)!\n", String_cString(linkName), Errors_getText(error) ); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); String_delete(linkName); if (failError == ERROR_NONE) failError = error; break; } /* check file time, permissions, file owner/group */ #endif /* 0 */ printInfo(2,"ok\n"); /* free resources */ } else { /* skip */ printInfo(3," Compare '%s'...skipped\n",String_cString(linkName)); } /* close archive file */ Archive_closeEntry(&archiveFileInfo); String_delete(fileName); String_delete(linkName); } break; case ARCHIVE_ENTRY_TYPE_SPECIAL: { String fileName; FileInfo fileInfo; FileInfo localFileInfo; /* read special */ fileName = String_new(); error = Archive_readSpecialEntry(&archiveInfo, &archiveFileInfo, NULL, NULL, fileName, &fileInfo ); if (error != ERROR_NONE) { printError("Cannot not read 'special' content of archive '%s' (error: %s)!\n", String_cString(archiveFileName), Errors_getText(error) ); String_delete(fileName); if (failError == ERROR_NONE) failError = error; break; } if ( (List_empty(includeEntryList) || EntryList_match(includeEntryList,fileName,PATTERN_MATCH_MODE_EXACT)) && !PatternList_match(excludePatternList,fileName,PATTERN_MATCH_MODE_EXACT) ) { printInfo(2," Compare special device '%s'...",String_cString(fileName)); /* check special device */ if (!File_exists(fileName)) { printInfo(2,"FAIL!\n"); printError("Special device '%s' does not exists!\n", String_cString(fileName) ); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); if (jobOptions->stopOnErrorFlag) { failError = ERROR_FILE_NOT_FOUND; } break; } if (File_getType(fileName) != FILE_TYPE_SPECIAL) { printInfo(2,"FAIL!\n"); printError("'%s' is not a special device!\n", String_cString(fileName) ); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); if (jobOptions->stopOnErrorFlag) { failError = ERROR_WRONG_FILE_TYPE; } break; } /* check special settings */ error = File_getFileInfo(fileName,&localFileInfo); if (error != ERROR_NONE) { printError("Cannot not read local file '%s' (error: %s)!\n", String_cString(fileName), Errors_getText(error) ); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); if (jobOptions->stopOnErrorFlag) { failError = error; } break; } if (fileInfo.specialType != localFileInfo.specialType) { printError("Different types of special device '%s'!\n", String_cString(fileName) ); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); if (jobOptions->stopOnErrorFlag) { failError = error; } break; } if ( (fileInfo.specialType == FILE_SPECIAL_TYPE_CHARACTER_DEVICE) || (fileInfo.specialType == FILE_SPECIAL_TYPE_BLOCK_DEVICE) ) { if (fileInfo.major != localFileInfo.major) { printError("Different major numbers of special device '%s'!\n", String_cString(fileName) ); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); if (jobOptions->stopOnErrorFlag) { failError = error; } break; } if (fileInfo.minor != localFileInfo.minor) { printError("Different minor numbers of special device '%s'!\n", String_cString(fileName) ); Archive_closeEntry(&archiveFileInfo); String_delete(fileName); if (jobOptions->stopOnErrorFlag) { failError = error; } break; } } #if 0 /* check file time, permissions, file owner/group */ #endif /* 0 */ printInfo(2,"ok\n"); /* free resources */ } else { /* skip */ printInfo(3," Compare '%s'...skipped\n",String_cString(fileName)); } /* close archive file */ Archive_closeEntry(&archiveFileInfo); String_delete(fileName); } break; default: #ifndef NDEBUG HALT_INTERNAL_ERROR_UNHANDLED_SWITCH_CASE(); #endif /* NDEBUG */ break; /* not reached */ } } /* close archive */ Archive_close(&archiveInfo); } /* check fragment lists */ for (fragmentNode = fragmentList.head; fragmentNode != NULL; fragmentNode = fragmentNode->next) { if (!FragmentList_checkEntryComplete(fragmentNode)) { printInfo(0,"Warning: incomplete entry '%s'\n",String_cString(fragmentNode->name)); if (failError == ERROR_NONE) failError = ERROR_FILE_INCOMPLETE; } } /* free resources */ String_delete(archiveFileName); FragmentList_done(&fragmentList); free(buffer); free(archiveBuffer); return failError; }
bool Password_input(Password *password, const char *title, uint modes ) { bool okFlag; assert(password != NULL); Password_clear(password); okFlag = FALSE; /* input via SSH_ASKPASS program */ if (((modes & PASSWORD_INPUT_MODE_GUI) != 0) && !okFlag) { const char *sshAskPassword; String command; FILE *file; bool eolFlag; int ch; sshAskPassword = getenv("SSH_ASKPASS"); if ((sshAskPassword != NULL) && (strcmp(sshAskPassword,"") != 0)) { /* open pipe to external password program */ command = String_newCString(sshAskPassword); if (title != NULL) { String_format(command," %\"s:",title); } file = popen(String_cString(command),"r"); if (file == NULL) { String_delete(command); return FALSE; } String_delete(command); /* read password, discard last LF */ printInfo(2,"Wait for password..."); eolFlag = FALSE; do { ch = getc(file); if (ch != EOF) { switch ((char)ch) { case '\n': case '\r': eolFlag = TRUE; break; default: Password_appendChar(password,(char)ch); break; } } else { eolFlag = TRUE; } } while (!eolFlag); printInfo(2,"ok\n"); /* close pipe */ pclose(file); okFlag = TRUE; } } /* input via console */ if (((modes & PASSWORD_INPUT_MODE_CONSOLE) != 0) && !okFlag) { int n; struct termios oldTermioSettings; struct termios termioSettings; bool eolFlag; char ch; if (isatty(STDIN_FILENO) == 1) { /* read data from interactive input */ if (title != NULL) { fprintf(stderr,"%s: ",title);fflush(stderr); } /* save current console settings */ if (tcgetattr(STDIN_FILENO,&oldTermioSettings) != 0) { return FALSE; } /* disable echo */ memcpy(&termioSettings,&oldTermioSettings,sizeof(struct termios)); termioSettings.c_lflag &= ~ECHO; if (tcsetattr(STDIN_FILENO,TCSANOW,&termioSettings) != 0) { return FALSE; } /* input password */ eolFlag = FALSE; do { if (read(STDIN_FILENO,&ch,1) == 1) { switch (ch) { case '\r': break; case '\n': eolFlag = TRUE; break; default: Password_appendChar(password,ch); break; } } else { eolFlag = TRUE; } } while (!eolFlag); /* restore console settings */ tcsetattr(STDIN_FILENO,TCSANOW,&oldTermioSettings); if (title != NULL) { fprintf(stderr,"\n"); } } else { /* read data from non-interactive input */ eolFlag = FALSE; do { ioctl(STDIN_FILENO,FIONREAD,(char*)&n); if (n > 0) { if (read(STDIN_FILENO,&ch,1) == 1) { switch (ch) { case '\r': break; case '\n': eolFlag = TRUE; break; default: Password_appendChar(password,ch); break; } } else { eolFlag = TRUE; } } } while (!eolFlag && (n > 0)); } okFlag = TRUE; } return okFlag; }
static BOOL _validPath(String* inputString) { int state; int pos; char* str; String* inputCopy; String* validDriveLetters; String* invalidDirNameChars; validDriveLetters = String_new("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); invalidDirNameChars = String_new("/\\:*?\"<>|"); state = 0; pos = 0; inputCopy = String_newCopy(inputString); String_toUppercase(inputCopy); str = inputCopy->mString; while (pos < inputString->mLength) { switch (state) { case 0: // Just starting out. if (str[pos] == '/' || str[pos] == '\\') { state = 1; //We have an absolute path on a unix system (accept backslash too, because we're lenient.). } else if (String_findChar(invalidDirNameChars, str[pos]) != -1) { state = 666; // Invalid path. } else if (String_findChar(validDriveLetters, str[pos]) != -1) { state = 2; // We have a windows drive letter, OR beginning of relative path. } else { state = 3; //Valid dirname character, but not letter. Beginning of relative path. } break; case 1: //Beginning of dir name. if (String_findChar(invalidDirNameChars, str[pos]) != -1) { state = 666; // Invalid path. } else { state = 3; //Valid dirname character. } break; case 2: //First char was letter. Either drive letter or beginning of dir name. if (str[pos] == ':' && (str[pos+1] == '/' || str[pos+1] == '\\')) { state = 1; pos++; // Absolute windows path. } else if (String_findChar(invalidDirNameChars, str[pos]) != -1) { state = 666; // Invalid path. } else { state = 3; // Relative path. } break; case 3: //Middle of dirname. if (str[pos] == '/' || str[pos] == '\\') { state = 1; // Found separator, new dirname. } else if (String_findChar(invalidDirNameChars, str[pos]) != -1) { state = 666; // Invalid path. } else { state = 3; // Name continues. } break; default: smug_assert(FALSE); break; } pos++; } String_delete(inputCopy); String_delete(validDriveLetters); String_delete(invalidDirNameChars); return (state != 666); }
char * tree2string (struct Tree *tree) { String s; s = String_new(); if (tree != NULL) { if (tree->child[0] != NULL) { if (tree->child[1] == NULL) { if (tree->child[0]->left != NULL && tree->child[0]->right != NULL) { String_appendChar(s, '('); tree2string_node(tree->child[0]->left, s); String_appendChar(s, ','); tree2string_node(tree->child[0]->right, s); String_appendCString(s, ");"); } else { if (tree->child[0]->clust->clustersize == 1) { String_appendCString(s, "0;"); } else { unsigned int i; for (i=0; i<tree->child[0]->clust->clustersize-1; i++) { String_appendChar(s, '('); distance2text(s, tree->child[0]->clust->members[i]->name, 0.0); } distance2text(s, tree->child[0]->clust->members[i]->name, 0.0); for (i=0; i<tree->child[0]->clust->clustersize-2; i++) { String_appendCString(s, "):0.0)"); } String_appendCString(s, ");"); } } } } } // unsigned int strlen = String_length(s); char *buffer = NULL; // buffer = malloc(sizeof(char) * (strlen+1)); // strncpy(buffer, String_cString(s), strlen); char *position; const char *cString = String_cString(s); // fprintf(stderr, "[TREE]: ### %s ###\n", cString); position = strchr(cString, ';'); if (position == NULL) { fprintf(stderr, "Error in trees\n"); exit(-1); } int index = cString - position; if (index < 0) { index = -index; } // fprintf(stderr, "\tindex: %d\n", index); buffer = malloc(sizeof(char) * (index+2)); strncpy(buffer, cString, index+1); buffer[index+1] = '\0'; // fprintf(stderr, "\tbuffer: %s\n", buffer); String_delete(s); return buffer; }
void File_deleteFileName(String fileName) { String_delete(fileName); }
PathName* PathName_new(String* string, BOOL isFile) { PathName* newPn; int pos; String* pathWoRoot; String* separators; String* fileName; // Validate the path. if (!_validPath(string)) return NULL; separators = String_new("\\/"); newPn = (PathName*)malloc(sizeof(PathName)); // Check the root. pos = String_findChar(string, ':'); if (1 == pos) { // This is a Windows absolute path. newPn->root = String_newSubString(string, 0, 3); pos = 3; } else if (String_findChar(string, '/') == 0 || String_findChar(string, '\\') == 0) { // This is a Unix absolute path. newPn->root = String_new("/"); pos = 1; } else { // This is a relative path. newPn->root = NULL; pos = 0; } // Parse the rest of the path. pathWoRoot = String_newSubString(string, pos, -1); newPn->path = String_splitMultiSep(pathWoRoot, separators); String_delete(pathWoRoot); if (isFile) { // Get the file name. if (String_isEmpty((String*)newPn->path->last->item)) { // This was supposed to be a file, but the path ended in '/' or '\' String_delete(separators); PathName_delete(newPn); return NULL; } fileName = (String*)newPn->path->last->item; LinkedList_remove(newPn->path, newPn->path->last); // Find the extension, if there is one. pos = String_findCharReverse(fileName, '.'); if (-1 == pos) { // No extension (no '.' in file name). newPn->bareName = fileName; newPn->extension = NULL; } else { // At least one '.' in file name. Separate out extension. newPn->bareName = String_newSubString(fileName, 0, pos); newPn->extension = String_newSubString(fileName, pos + 1, -1); String_delete(fileName); } } else { // No file name. newPn->bareName = NULL; newPn->extension = NULL; if (String_isEmpty((String*)newPn->path->last->item)) { // The string ended in '/' or '\'. Last path element is empty, so remove it. String_delete((String*)newPn->path->last->item); LinkedList_remove(newPn->path, newPn->path->last); } } String_delete(separators); smug_assert(_invariant(newPn)); return newPn; }