Initialize issues branch

This commit is contained in:
2025-05-11 20:04:37 +02:00
parent ae2fb89d82
commit b8ed4ffeea
31 changed files with 0 additions and 3636 deletions

View File

@@ -1,65 +0,0 @@
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: true
AlignEscapedNewlinesLeft: false
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AlwaysBreakAfterDefinitionReturnType: false
AlwaysBreakTemplateDeclarations: false
AlwaysBreakBeforeMultilineStrings: false
BreakBeforeBinaryOperators: None
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BinPackParameters: true
BinPackArguments: true
ColumnLimit: 80
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
DerivePointerAlignment: false
ExperimentalAutoDetectBinPacking: false
IndentCaseLabels: false
IndentWrappedFunctionNames: false
IndentFunctionDeclarationAfterType: false
MaxEmptyLinesToKeep: 1
KeepEmptyLinesAtTheStartOfBlocks: true
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakString: 1000
PenaltyBreakFirstLessLess: 120
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
SpacesBeforeTrailingComments: 1
Cpp11BracedListStyle: true
Standard: Cpp11
IndentWidth: 4
TabWidth: 4
UseTab: true
BreakBeforeBraces: Attach
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpacesInAngles: false
SpaceInEmptyParentheses: false
SpacesInCStyleCastParentheses: false
SpaceAfterCStyleCast: false
SpacesInContainerLiterals: true
SpaceBeforeAssignmentOperators: true
ContinuationIndentWidth: 4
CommentPragmas: '^ IWYU pragma:'
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
SpaceBeforeParens: ControlStatements
DisableFormat: false
...

23
.gitignore vendored
View File

@@ -1,23 +0,0 @@
*.o
*.d
*.exe
build
*/.vs/*
*.opensdf
*.sdf
VisualStudio/Debug
VisualStudio/filesync/Debug
VisualStudio/Release
VisualStudio/filesync/Release
MonoDevelop/FileSync/bin
*.user
/filesync.exe
/filesync
VisualStudio/filesync/x64/*
*.pdb
*.ilk
*.VC.db
*.VC.opendb
tests/*
.vs

View File

@@ -1,50 +0,0 @@
{
"configurations": [
{
"name": "Mac",
"includePath": [
"/usr/include",
"${workspaceFolder}",
"${workspaceFolder}/src/"
],
"intelliSenseMode": "clang-x64",
"macFrameworkPath": [
"/System/Library/Frameworks",
"/Library/Frameworks"
]
},
{
"name": "Linux",
"includePath": [
"/usr/include",
"${workspaceFolder}",
"${workspaceFolder}/src/"
],
"intelliSenseMode": "linux-gcc-x64",
"compilerPath": "/usr/bin/gcc",
"cStandard": "c17",
"cppStandard": "c++17"
},
{
"name": "Win32",
"includePath": [
"C:/msys64/mingw64/include",
"C:/msys64/mingw64/x86_64-w64-mingw32/include",
"${workspaceFolder}",
"${workspaceFolder}/src/"
],
"defines": [
"WIN32",
"_DEBUG",
"UNICODE",
"_UNICODE"
],
"windowsSdkVersion": "10.0.18362.0",
"compilerPath": "C:/msys64/mingw64/bin/g++.exe",
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "windows-gcc-x64"
}
],
"version": 4
}

25
.vscode/launch.json vendored
View File

@@ -1,25 +0,0 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceRoot}/filesync.exe",
"args": ["copy","D:\\source","F:\\source"],
"stopAtEntry": false,
"cwd": "${workspaceRoot}",
"environment": [],
"externalConsole": true,
"MIMode": "gdb",
"miDebuggerPath": "C:\\msys64\\mingw64\\bin\\gdb.exe",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}

View File

@@ -1,5 +0,0 @@
{
"files.associations": {
"*.h": "c"
}
}

View File

@@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2014-2021 Valeriano Alfonso Rodriguez
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

102
Makefile
View File

@@ -1,102 +0,0 @@
# SPDX-License-Identifier: MIT
# Copyright (c) 2014-2021 Valeriano Alfonso Rodriguez
IsMinGW := $(findstring MSYS,$(shell uname -s))$(findstring MINGW,$(shell uname -s))
ifneq (,$(IsMinGW))
RES_APP := filesync.exe
BUILDDIR := build-$(shell gcc -dumpmachine)
else
RES_APP := filesync
BUILDDIR := build-$(shell gcc -dumpmachine)
endif
VERBOSE_BUILD=false
CC := gcc
RM := rm -f
ECHO := echo
MKDIR := mkdir
HEADS := \
src/util.h \
src/crc.h \
src/fileutil.h \
src/parameteroperation.h \
src/filenode.h \
src/actionfilenode.h \
src/actionfilenodesync.h \
src/actionfilenodecopy.h
OBJS_BASE := \
$(BUILDDIR)/util.o \
$(BUILDDIR)/crc.o \
$(BUILDDIR)/fileutil.o \
$(BUILDDIR)/parameteroperation.o \
$(BUILDDIR)/filenode.o \
$(BUILDDIR)/actionfilenode.o \
$(BUILDDIR)/actionfilenodesync.o \
$(BUILDDIR)/actionfilenodecopy.o
OBJS_APP := \
$(OBJS_BASE) \
$(BUILDDIR)/main.o
CFLAGS := -g
LIBS := -lm
ifeq ($(VERBOSE_BUILD),true)
DO_CC=$(CC) $(CFLAGS) -o $@ -c $<
DO_CXX=$(CXX) $(CFLAGS) -o $@ -c $<
else
DO_CC=@$(ECHO) "CC: $@" ;\
$(CC) $(CFLAGS) -o $@ -c $<
DO_CXX=@$(ECHO) "CXX: $@" ;\
$(CXX) $(CFLAGS) -o $@ -c $<
endif
all: $(RES_APP)
clean:
$(RM) $(RES_APP)
$(RM) $(OBJS_APP)
$(BUILDDIR):
@-$(MKDIR) $(BUILDDIR)
$(BUILDDIR)/util.o: src/util.c $(HEADS)
$(DO_CC)
$(BUILDDIR)/crc.o: src/crc.c $(HEADS)
$(DO_CC)
$(BUILDDIR)/fileutil.o: src/fileutil.c $(HEADS)
$(DO_CC)
$(BUILDDIR)/parameteroperation.o: src/parameteroperation.c $(HEADS)
$(DO_CC)
$(BUILDDIR)/filenode.o: src/filenode.c $(HEADS)
$(DO_CC)
$(BUILDDIR)/actionfilenode.o: src/actionfilenode.c $(HEADS)
$(DO_CC)
$(BUILDDIR)/actionfilenodesync.o: src/actionfilenodesync.c $(HEADS)
$(DO_CC)
$(BUILDDIR)/actionfilenodecopy.o: src/actionfilenodecopy.c $(HEADS)
$(DO_CC)
$(BUILDDIR)/main.o: src/main.c $(HEADS)
$(DO_CC)
$(RES_APP): $(BUILDDIR) $(OBJS_APP)
@$(ECHO) "LINK: $@"
@$(CC) $(OBJS_APP) \
-o $(RES_APP) $(LIBS)

View File

@@ -1,72 +0,0 @@
# FileSync
Simple local filesystem file synchronization. For use with external devices (usbdisk) and SneakerNet like usage.
## Installation
Copy the resulting executable to the desired location.
The executable is completelly portable, there are no dependencies.
## Usage
Basic usage to syncronize two directories, dirA and dirB:
filesync -sync -dir dirA -dir dirB
To make a efficient copy from dirA to dirB:
filesync -copy -dir dirA -dir dirB
The rest of options are listed with no parameters:
```
$ filesync
Parameters:
-dir [Item]: Specify a directory.
-nocheck: Do not check for changes on directories.
-dummy: Do not perform operations.
-copy: Copy first directory to second directory.
-sync: Synchronize between two directories.
-log [Item]: Log actions to file.
-scan [Item] [Item]: Scan directory and save to filenode file.
-rescan [Item] [Item]: Rescan directory and save to filenode file.
-read [Item]: Read filenode file.
-check [Item]: Check changes on a directory.
```
## Building
There is a GNU Make compatible Makefile usable on Linux and MingGW.
make
## Contributing
1. Fork it!
2. Create your feature branch: `git checkout -b my-new-feature`
3. Commit your changes: `git commit -am 'Add some feature'`
4. Push to the branch: `git push origin my-new-feature`
5. Submit a pull request :D
## Credits
* Valeriano Alfonso Rodriguez.
## License
The MIT License (MIT)
Copyright (c) 2014-2021 Valeriano Alfonso Rodriguez
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

0
issues/.keep Normal file
View File

View File

@@ -1,469 +0,0 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2014-2021 Valeriano Alfonso Rodriguez
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "actionfilenode.h"
#include "crc.h"
#include "filenode.h"
#include "fileutil.h"
#include "util.h"
ActionFileNode _actionFileNodeFree = NULL;
#define AccionFileNode_Block 1024
ActionFileNode ActionFileNode_Create() {
ActionFileNode actionFileNode;
if (_actionFileNodeFree == NULL) {
ActionFileNode actionFileNodeFreeAux;
int i;
// Allocate block
actionFileNodeFreeAux =
malloc(sizeof(TActionFileNode) * AccionFileNode_Block);
if (actionFileNodeFreeAux == NULL) {
return NULL;
}
for (i = 0; i < AccionFileNode_Block - 1; i++) {
actionFileNodeFreeAux[i].next = &actionFileNodeFreeAux[i + 1];
}
actionFileNodeFreeAux[AccionFileNode_Block - 1].next = NULL;
_actionFileNodeFree = &actionFileNodeFreeAux[0];
}
// Get the first free
actionFileNode = _actionFileNodeFree;
_actionFileNodeFree = actionFileNode->next;
// Initialize
actionFileNode->action = ActionFileCmp_Nothing;
actionFileNode->left = NULL;
actionFileNode->right = NULL;
actionFileNode->result = ActionFileNodeResult_Nothing;
actionFileNode->next = NULL;
return (actionFileNode);
}
void AccionFileNode_Destroy(ActionFileNode actionFileNode) {
actionFileNode->next = _actionFileNodeFree;
_actionFileNodeFree = actionFileNode;
}
ActionFileNode ActionFileNode_CreateNormal(FileNode fileNodeLeft,
FileNode fileNodeRight) {
ActionFileNode actionFileNode;
actionFileNode = ActionFileNode_Create();
actionFileNode->action = ActionFileCmp_Nothing;
actionFileNode->left = fileNodeLeft;
actionFileNode->right = fileNodeRight;
return actionFileNode;
}
void AccionFileNode_CompareChilds(
ActionFileNode actionFileNodeRoot, ActionFileNode *actionFileNodeQueue,
void (*CheckPair)(FileNode fileNodeLeft, FileNode fileNodeRight,
ActionFileNode *actionFileNodeQueue)) {
FileNode fileNodeLeft;
FileNode fileNodeRight;
FileNode fileNodeRightQueue;
FileNode fileNodeRightProcessed;
FileNode fileNodeRightPrevious;
// Check if there is something to do
if (!actionFileNodeRoot->left && !actionFileNodeRoot->right) {
return;
}
// There is no left part
if (!actionFileNodeRoot->left) {
fileNodeRight = actionFileNodeRoot->right->child;
while (fileNodeRight) {
CheckPair(NULL, fileNodeRight, actionFileNodeQueue);
fileNodeRight = fileNodeRight->next;
}
return;
}
// There is no right part
if (!actionFileNodeRoot->right) {
fileNodeLeft = actionFileNodeRoot->left->child;
while (fileNodeLeft) {
CheckPair(fileNodeLeft, NULL, actionFileNodeQueue);
fileNodeLeft = fileNodeLeft->next;
}
return;
}
// Prepare chains
fileNodeRightQueue = actionFileNodeRoot->right->child;
fileNodeRightProcessed = NULL;
// Iterate left child FileNodes
fileNodeLeft = actionFileNodeRoot->left->child;
while (fileNodeLeft) {
fileNodeRightPrevious = NULL;
fileNodeRight = fileNodeRightQueue;
while (fileNodeRight) {
if (!strcmp(fileNodeLeft->name, fileNodeRight->name)) {
// Match, extract right child FileNode to the processed chain
if (fileNodeRightPrevious) {
fileNodeRightPrevious->next = fileNodeRight->next;
} else {
fileNodeRightQueue = fileNodeRight->next;
}
fileNodeRight->next = fileNodeRightProcessed;
fileNodeRightProcessed = fileNodeRight;
CheckPair(fileNodeLeft, fileNodeRight, actionFileNodeQueue);
break;
} else {
// Next right child
fileNodeRightPrevious = fileNodeRight;
fileNodeRight = fileNodeRight->next;
}
}
if (!fileNodeRight) {
CheckPair(fileNodeLeft, NULL, actionFileNodeQueue);
}
fileNodeLeft = fileNodeLeft->next;
}
// Iterate unprocessed right childs
fileNodeRight = fileNodeRightQueue;
while (fileNodeRight) {
CheckPair(NULL, fileNodeRight, actionFileNodeQueue);
fileNodeRightPrevious = fileNodeRight;
fileNodeRight = fileNodeRight->next;
fileNodeRightPrevious->next = fileNodeRightProcessed;
fileNodeRightProcessed = fileNodeRightPrevious;
}
actionFileNodeRoot->right->child = fileNodeRightProcessed;
}
int ActionFileNode_Statistics(ActionFileNode actionFileNode,
ActionQueueStatistics *statistics,
ActionFileNodeResult result) {
statistics->readLeft = 0;
statistics->writeLeft = 0;
statistics->readRight = 0;
statistics->writeRight = 0;
statistics->deleteLeft = 0;
statistics->deleteRight = 0;
statistics->fullCopyCount = 0;
statistics->dateCopyCount = 0;
statistics->directoryCount = 0;
statistics->deleteCount = 0;
while (actionFileNode != NULL) {
if (actionFileNode->result != result) {
actionFileNode = actionFileNode->next;
continue;
}
switch (actionFileNode->action) {
case ActionFileCmp_Nothing:
break;
case ActionFileCmp_LeftToRight:
statistics->fullCopyCount++;
statistics->readLeft += actionFileNode->left->size;
statistics->writeRight += actionFileNode->left->size;
break;
case ActionFileCmp_RightToLeft:
statistics->fullCopyCount++;
statistics->writeLeft += actionFileNode->right->size;
statistics->readRight += actionFileNode->right->size;
break;
case ActionFileCmp_DeleteLeft:
statistics->deleteCount++;
statistics->deleteLeft += actionFileNode->left->size;
break;
case ActionFileCmp_DeleteRight:
statistics->deleteCount++;
statistics->deleteRight += actionFileNode->right->size;
break;
case ActionFileCmp_DateLeftToRight:
statistics->dateCopyCount++;
break;
case ActionFileCmp_DateRightToLeft:
statistics->dateCopyCount++;
break;
case ActionFileCmp_MakeRightDirectory:
statistics->directoryCount++;
break;
case ActionFileCmp_MakeLeftDirectory:
statistics->directoryCount++;
break;
}
actionFileNode = actionFileNode->next;
}
return (statistics->fullCopyCount + statistics->dateCopyCount +
statistics->directoryCount + statistics->deleteCount);
}
void ActionFileNode_Print(ActionFileNode actionFileNode) {
char showPath[MaxPath];
while (actionFileNode != NULL) {
if (actionFileNode->left) {
FileNode_GetFullPath(actionFileNode->left, "", showPath);
} else {
FileNode_GetFullPath(actionFileNode->right, "", showPath);
}
switch (actionFileNode->action) {
case ActionFileCmp_Nothing:
// printff("%s == %s\n",pathIzq,pathDer);
break;
case ActionFileCmp_LeftToRight:
Print(". => %s\n", showPath);
break;
case ActionFileCmp_RightToLeft:
Print(". <= %s\n", showPath);
break;
case ActionFileCmp_DeleteLeft:
Print(". *- %s\n", showPath);
break;
case ActionFileCmp_DeleteRight:
Print(". -* %s\n", showPath);
break;
case ActionFileCmp_DateLeftToRight:
Print(". -> %s\n", showPath);
break;
case ActionFileCmp_DateRightToLeft:
Print(". <- %s\n", showPath);
break;
case ActionFileCmp_MakeRightDirectory:
Print(". -D %s\n", showPath);
break;
case ActionFileCmp_MakeLeftDirectory:
Print(". D- %s\n", showPath);
break;
}
actionFileNode = actionFileNode->next;
}
Print("End\n");
}
bool AccionFileNodeAux_CopyDate(char *pathOrig, char *pathDest) {
FileTime ft = FileTime_Get(pathOrig);
FileTime_Set(pathDest, ft);
return true;
}
bool AccionFileNodeAux_Copy(char *pathOrig, char *pathDest) {
if (File_Copy(pathOrig, pathDest)) {
return AccionFileNodeAux_CopyDate(pathOrig, pathDest);
} else {
File_Delete(pathDest);
Print("Error Copying to: %s, %s\n", pathDest, GetError());
return false;
}
}
bool AccionFileNodeAux_Delete(char *pathOrig, char *pathDest) {
if (File_IsDirectory(pathDest)) {
if (File_DeleteDirectory(pathDest) == 0) {
Print("Error Deleting Directory: %s, %s\n", pathDest, GetError());
return false;
}
} else {
if (File_Delete(pathDest) == 0) {
Print("Error Deleting File: %s, %s\n", pathDest, GetError());
return false;
}
}
return true;
}
bool AccionFileNodeAux_MakeDir(char *pathOrig, char *pathDest) {
if (File_MakeDirectory(pathDest) == 0) {
Print("Error Making Directory: %s, %s\n", pathDest, GetError());
return false;
}
}
int ActionFileNode_RunList(ActionFileNode actionFileNode, char *pathLeft,
char *pathRight) {
int numActions = 0;
char fullPathLeft[MaxPath], fullPathRight[MaxPath], showPath[MaxPath];
while (actionFileNode != NULL) {
if (actionFileNode->left) {
FileNode_GetFullPath(actionFileNode->left, pathLeft, fullPathLeft);
FileNode_GetFullPath(actionFileNode->left, "", showPath);
} else {
FileNode_GetFullPath(actionFileNode->right, pathLeft, fullPathLeft);
FileNode_GetFullPath(actionFileNode->right, "", showPath);
}
if (actionFileNode->right) {
FileNode_GetFullPath(actionFileNode->right, pathRight,
fullPathRight);
} else {
FileNode_GetFullPath(actionFileNode->left, pathRight,
fullPathRight);
}
switch (actionFileNode->action) {
case ActionFileCmp_Nothing:
// printff("%s == %s\n",pathIzq,pathDer);
break;
case ActionFileCmp_LeftToRight:
Print(" => %s\n", showPath);
if (AccionFileNodeAux_Copy(fullPathLeft, fullPathRight)) {
actionFileNode->result = ActionFileNodeResult_Ok;
} else {
actionFileNode->result = ActionFileNodeResult_Error;
}
numActions++;
break;
case ActionFileCmp_RightToLeft:
Print(" <= %s\n", showPath);
if (AccionFileNodeAux_Copy(fullPathRight, fullPathLeft)) {
actionFileNode->result = ActionFileNodeResult_Ok;
} else {
actionFileNode->result = ActionFileNodeResult_Error;
}
numActions++;
break;
case ActionFileCmp_DeleteLeft:
Print(" *- %s\n", showPath);
if (AccionFileNodeAux_Delete(fullPathRight, fullPathLeft)) {
actionFileNode->result = ActionFileNodeResult_Ok;
} else {
actionFileNode->result = ActionFileNodeResult_Error;
}
numActions++;
break;
case ActionFileCmp_DeleteRight:
Print(" -* %s\n", showPath);
if (AccionFileNodeAux_Delete(fullPathLeft, fullPathRight)) {
actionFileNode->result = ActionFileNodeResult_Ok;
} else {
actionFileNode->result = ActionFileNodeResult_Error;
}
numActions++;
break;
case ActionFileCmp_DateLeftToRight:
Print(" -> %s\n", showPath);
if (AccionFileNodeAux_CopyDate(fullPathLeft, fullPathRight)) {
actionFileNode->result = ActionFileNodeResult_Ok;
} else {
actionFileNode->result = ActionFileNodeResult_Error;
}
numActions++;
break;
case ActionFileCmp_DateRightToLeft:
Print(" <- %s\n", showPath);
if (AccionFileNodeAux_CopyDate(fullPathRight, fullPathLeft)) {
actionFileNode->result = ActionFileNodeResult_Ok;
} else {
actionFileNode->result = ActionFileNodeResult_Error;
}
numActions++;
break;
case ActionFileCmp_MakeRightDirectory:
Print(" -D %s\n", showPath);
if (AccionFileNodeAux_MakeDir(fullPathLeft, fullPathRight)) {
actionFileNode->result = ActionFileNodeResult_Ok;
} else {
actionFileNode->result = ActionFileNodeResult_Error;
}
numActions++;
break;
case ActionFileCmp_MakeLeftDirectory:
Print(" D- %s\n", showPath);
if (AccionFileNodeAux_MakeDir(fullPathRight, fullPathLeft)) {
actionFileNode->result = ActionFileNodeResult_Ok;
} else {
actionFileNode->result = ActionFileNodeResult_Error;
}
numActions++;
break;
}
actionFileNode = actionFileNode->next;
}
Print("End\n");
return numActions;
}
// ----------------------------------------------------------------------------
// Common utilities
#define QueueNode(queue, node) \
(queue)->next = (node); \
(queue) = (node);
void AccionFileNode_DeletePair(FileNode fileNodeLeft, FileNode fileNodeRight,
ActionFileNode *actionFileNodeQueue) {
ActionFileNode actionFileNodeNew =
ActionFileNode_CreateNormal(fileNodeLeft, fileNodeRight);
if (!fileNodeLeft && !fileNodeRight) {
AccionFileNode_Destroy(actionFileNodeNew);
return;
}
if (!fileNodeLeft && fileNodeRight) {
if (fileNodeRight->flags & FileFlag_Directory) {
// Iterate childs for deletion
AccionFileNode_CompareChilds(actionFileNodeNew, actionFileNodeQueue,
AccionFileNode_DeletePair);
}
if (fileNodeRight->status != FileStatus_Deleted) {
// Node delete action
actionFileNodeNew->action = ActionFileCmp_DeleteRight;
QueueNode(*actionFileNodeQueue, actionFileNodeNew);
} else {
AccionFileNode_Destroy(actionFileNodeNew);
}
}
if (fileNodeLeft && !fileNodeRight) {
if (fileNodeLeft->flags & FileFlag_Directory) {
// Iterate childs for deletion
AccionFileNode_CompareChilds(actionFileNodeNew, actionFileNodeQueue,
AccionFileNode_DeletePair);
}
if (fileNodeLeft->status != FileStatus_Deleted) {
// Node delete action
actionFileNodeNew->action = ActionFileCmp_DeleteLeft;
QueueNode(*actionFileNodeQueue, actionFileNodeNew);
} else {
AccionFileNode_Destroy(actionFileNodeNew);
}
}
if (fileNodeLeft && fileNodeRight) {
if ((fileNodeLeft->flags & FileFlag_Directory) ||
(fileNodeRight->flags & FileFlag_Directory)) {
// One is Directory
// Iterate childs for deletion
AccionFileNode_CompareChilds(actionFileNodeNew, actionFileNodeQueue,
AccionFileNode_DeletePair);
}
if (fileNodeLeft->status != FileStatus_Deleted) {
// Left node delete action
actionFileNodeNew->action = ActionFileCmp_DeleteLeft;
QueueNode(*actionFileNodeQueue, actionFileNodeNew);
actionFileNodeNew = NULL;
}
if (fileNodeRight->status != FileStatus_Deleted) {
if (!actionFileNodeNew) {
actionFileNodeNew =
ActionFileNode_CreateNormal(fileNodeLeft, fileNodeRight);
}
// Right node delete action
actionFileNodeNew->action = ActionFileCmp_DeleteRight;
QueueNode(*actionFileNodeQueue, actionFileNodeNew);
actionFileNodeNew = NULL;
}
if (actionFileNodeNew) {
AccionFileNode_Destroy(actionFileNodeNew);
}
}
}

View File

@@ -1,75 +0,0 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2014-2021 Valeriano Alfonso Rodriguez
#ifndef _ACTIONFILENODE_H_
#define _ACTIONFILENODE_H_
#include "filenode.h"
typedef enum EActionFileCmp {
ActionFileCmp_Nothing,
ActionFileCmp_LeftToRight,
ActionFileCmp_RightToLeft,
ActionFileCmp_DeleteLeft,
ActionFileCmp_DeleteRight,
ActionFileCmp_DateLeftToRight,
ActionFileCmp_DateRightToLeft,
ActionFileCmp_MakeRightDirectory,
ActionFileCmp_MakeLeftDirectory
} ActionFileCmp;
typedef enum EActionFileNodeResult {
ActionFileNodeResult_Nothing,
ActionFileNodeResult_Ok,
ActionFileNodeResult_Error
} ActionFileNodeResult;
typedef struct SActionFileNode TActionFileNode, *ActionFileNode;
struct SActionFileNode {
ActionFileCmp action;
FileNode left;
FileNode right;
ActionFileNodeResult result;
ActionFileNode next;
};
ActionFileNode ActionFileNode_Create();
void AccionFileNode_Destroy(ActionFileNode actionFileNode);
ActionFileNode ActionFileNode_CreateNormal(FileNode fileNodeLeft,
FileNode fileNodeRight);
void AccionFileNode_CompareChilds(
ActionFileNode actionFileNodeRoot, ActionFileNode *actionFileNodeQueue,
void (*CheckPair)(FileNode fileNodeLeft, FileNode fileNodeRight,
ActionFileNode *actionFileNodeQueue));
typedef struct SActionQueueStatistics {
long long readLeft;
long long writeLeft;
long long readRight;
long long writeRight;
int fullCopyCount;
int dateCopyCount;
int directoryCount;
int deleteCount;
long long deleteLeft;
long long deleteRight;
} ActionQueueStatistics;
int ActionFileNode_Statistics(ActionFileNode actionFileNode,
ActionQueueStatistics *statistics,
ActionFileNodeResult result);
void ActionFileNode_Print(ActionFileNode actionFileNode);
int ActionFileNode_RunList(ActionFileNode actionFileNode, char *pathLeft,
char *pathRight);
// Common utilities
void AccionFileNode_DeletePair(FileNode fileNodeLeft, FileNode fileNodeRight,
ActionFileNode *actionFileNodeQueue);
#endif

View File

@@ -1,117 +0,0 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2014-2021 Valeriano Alfonso Rodriguez
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "actionfilenode.h"
#include "actionfilenodecopy.h"
#include "crc.h"
#include "filenode.h"
#include "fileutil.h"
#include "util.h"
#define MaxDeltaTime 0
#define QueueNode(queue, node) \
(queue)->next = (node); \
(queue) = (node);
void AccionFileNode_CopyPair(FileNode fileNodeLeft, FileNode fileNodeRight,
ActionFileNode *actionFileNodeQueue) {
ActionFileNode actionFileNodeNew =
ActionFileNode_CreateNormal(fileNodeLeft, fileNodeRight);
if (!fileNodeLeft && !fileNodeRight) {
AccionFileNode_Destroy(actionFileNodeNew);
return;
}
if (!fileNodeLeft && fileNodeRight) {
if (fileNodeRight->flags & FileFlag_Directory) {
AccionFileNode_CompareChilds(actionFileNodeNew, actionFileNodeQueue,
AccionFileNode_DeletePair);
}
if (fileNodeRight->status != FileStatus_Deleted) {
actionFileNodeNew->action = ActionFileCmp_DeleteRight;
} else {
actionFileNodeNew->action = ActionFileCmp_Nothing;
}
QueueNode(*actionFileNodeQueue, actionFileNodeNew);
}
if (fileNodeLeft && !fileNodeRight) {
if (fileNodeLeft->status != FileStatus_Deleted) {
if (fileNodeLeft->flags & FileFlag_Directory) {
actionFileNodeNew->action = ActionFileCmp_MakeRightDirectory;
QueueNode(*actionFileNodeQueue, actionFileNodeNew);
AccionFileNode_CompareChilds(actionFileNodeNew,
actionFileNodeQueue,
AccionFileNode_CopyPair);
actionFileNodeNew =
ActionFileNode_CreateNormal(fileNodeLeft, fileNodeRight);
actionFileNodeNew->action = ActionFileCmp_DateLeftToRight;
} else {
actionFileNodeNew->action = ActionFileCmp_LeftToRight;
}
} else {
actionFileNodeNew->action = ActionFileCmp_Nothing;
}
QueueNode(*actionFileNodeQueue, actionFileNodeNew);
}
if (fileNodeLeft && fileNodeRight) {
if ((fileNodeLeft->flags & FileFlag_Directory) ||
(fileNodeRight->flags & FileFlag_Directory)) {
if (fileNodeLeft->status != FileStatus_Deleted) {
if (fileNodeRight->status == FileStatus_Deleted) {
actionFileNodeNew->action =
ActionFileCmp_MakeRightDirectory;
QueueNode(*actionFileNodeQueue, actionFileNodeNew);
actionFileNodeNew = ActionFileNode_CreateNormal(
fileNodeLeft, fileNodeRight);
}
AccionFileNode_CompareChilds(actionFileNodeNew,
actionFileNodeQueue,
AccionFileNode_CopyPair);
if (abs((int)(fileNodeLeft->fileTime -
fileNodeRight->fileTime)) <=
MaxDeltaTime) { // appox. equal
actionFileNodeNew->action = ActionFileCmp_Nothing;
} else {
actionFileNodeNew->action = ActionFileCmp_DateLeftToRight;
}
} else {
AccionFileNode_CompareChilds(actionFileNodeNew,
actionFileNodeQueue,
AccionFileNode_DeletePair);
if (fileNodeRight->status != FileStatus_Deleted) {
actionFileNodeNew->action = ActionFileCmp_DeleteRight;
}
}
} else {
if (fileNodeLeft->status != FileStatus_Deleted) {
if (abs((int)(fileNodeLeft->fileTime -
fileNodeRight->fileTime)) <= MaxDeltaTime) {
actionFileNodeNew->action = ActionFileCmp_Nothing;
} else {
actionFileNodeNew->action = ActionFileCmp_LeftToRight;
}
} else {
if (fileNodeRight->status != FileStatus_Deleted) {
actionFileNodeNew->action = ActionFileCmp_DeleteRight;
}
}
}
QueueNode(*actionFileNodeQueue, actionFileNodeNew);
}
}
ActionFileNode ActionFileNode_BuildCopy(FileNode fileNodeLeft,
FileNode fileNodeRight) {
ActionFileNode actionFileNodeRoot =
ActionFileNode_CreateNormal(fileNodeLeft, fileNodeRight);
ActionFileNode actionFileNodeQueue = actionFileNodeRoot;
AccionFileNode_CompareChilds(actionFileNodeRoot, &actionFileNodeQueue,
AccionFileNode_CopyPair);
return actionFileNodeRoot;
}

View File

@@ -1,13 +0,0 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2014-2021 Valeriano Alfonso Rodriguez
#ifndef _ACTIONFILENODECOPY_H_
#define _ACTIONFILENODECOPY_H_
#include "actionfilenode.h"
#include "filenode.h"
ActionFileNode ActionFileNode_BuildCopy(FileNode fileNodeLeft,
FileNode fileNodeRight);
#endif

View File

@@ -1,220 +0,0 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2014-2021 Valeriano Alfonso Rodriguez
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "actionfilenode.h"
#include "actionfilenodesync.h"
#include "crc.h"
#include "filenode.h"
#include "fileutil.h"
#include "util.h"
#define MaxDeltaTime 0
#define QueueNode(queue, node) \
(queue)->next = (node); \
(queue) = (node);
void AccionFileNode_SyncPair(FileNode fileNodeLeft, FileNode fileNodeRight,
ActionFileNode *actionFileNodeQueue) {
if (!fileNodeLeft && !fileNodeRight) {
return;
}
ActionFileNode actionFileNodeNew =
ActionFileNode_CreateNormal(fileNodeLeft, fileNodeRight);
if (!fileNodeLeft && fileNodeRight) {
if (fileNodeRight->flags & FileFlag_Directory) {
// Directory
if (fileNodeRight->status == FileStatus_Deleted) {
actionFileNodeNew->action = ActionFileCmp_Nothing;
QueueNode(*actionFileNodeQueue, actionFileNodeNew);
} else {
actionFileNodeNew->action = ActionFileCmp_MakeLeftDirectory;
QueueNode(*actionFileNodeQueue, actionFileNodeNew);
// Iterate childs
AccionFileNode_CompareChilds(actionFileNodeNew,
actionFileNodeQueue,
AccionFileNode_SyncPair);
// Create new action for date copy
actionFileNodeNew =
ActionFileNode_CreateNormal(fileNodeLeft, fileNodeRight);
actionFileNodeNew->action = ActionFileCmp_DateRightToLeft;
QueueNode(*actionFileNodeQueue, actionFileNodeNew);
}
} else {
// File
if (fileNodeRight->status == FileStatus_Deleted) {
actionFileNodeNew->action = ActionFileCmp_Nothing;
} else {
actionFileNodeNew->action = ActionFileCmp_RightToLeft;
}
QueueNode(*actionFileNodeQueue, actionFileNodeNew);
}
}
if (fileNodeLeft && !fileNodeRight) {
if (fileNodeLeft->flags & FileFlag_Directory) {
// Directory
if (fileNodeLeft->status == FileStatus_Deleted) {
actionFileNodeNew->action = ActionFileCmp_Nothing;
QueueNode(*actionFileNodeQueue, actionFileNodeNew);
} else {
actionFileNodeNew->action = ActionFileCmp_MakeRightDirectory;
QueueNode(*actionFileNodeQueue, actionFileNodeNew);
// Iterate childs
AccionFileNode_CompareChilds(actionFileNodeNew,
actionFileNodeQueue,
AccionFileNode_SyncPair);
// Create new action for date copy
actionFileNodeNew =
ActionFileNode_CreateNormal(fileNodeLeft, fileNodeRight);
actionFileNodeNew->action = ActionFileCmp_DateLeftToRight;
QueueNode(*actionFileNodeQueue, actionFileNodeNew);
}
} else {
// File
if (fileNodeLeft->status == FileStatus_Deleted) {
actionFileNodeNew->action = ActionFileCmp_Nothing;
} else {
actionFileNodeNew->action = ActionFileCmp_LeftToRight;
}
QueueNode(*actionFileNodeQueue, actionFileNodeNew);
}
}
if (fileNodeLeft && fileNodeRight) {
if ((fileNodeLeft->flags & FileFlag_Directory) &&
(fileNodeRight->flags & FileFlag_Directory)) {
// Directory
// Prepare action for directory pair
if (abs((int)(fileNodeLeft->fileTime - fileNodeRight->fileTime)) <=
MaxDeltaTime) { // aprox. equal
if (fileNodeRight->status == FileStatus_Deleted &&
fileNodeLeft->status == FileStatus_Deleted) {
actionFileNodeNew->action = ActionFileCmp_Nothing;
} else if (fileNodeLeft->status == FileStatus_Undeleted &&
fileNodeRight->status == FileStatus_Deleted) {
actionFileNodeNew->action = ActionFileCmp_LeftToRight;
} else if (fileNodeLeft->status == FileStatus_Deleted &&
fileNodeRight->status == FileStatus_Undeleted) {
actionFileNodeNew->action = ActionFileCmp_RightToLeft;
} else if (fileNodeRight->status == FileStatus_Deleted) {
actionFileNodeNew->action = ActionFileCmp_DeleteLeft;
} else if (fileNodeLeft->status == FileStatus_Deleted) {
actionFileNodeNew->action = ActionFileCmp_DeleteRight;
} else {
actionFileNodeNew->action = ActionFileCmp_Nothing;
}
} else if (fileNodeLeft->fileTime < fileNodeRight->fileTime) {
if (fileNodeRight->status == FileStatus_Deleted) {
actionFileNodeNew->action = ActionFileCmp_DeleteLeft;
if (fileNodeLeft->status == FileStatus_Deleted) {
actionFileNodeNew->action = ActionFileCmp_Nothing;
}
} else {
if (fileNodeLeft->status == FileStatus_Deleted) {
actionFileNodeNew->action =
ActionFileCmp_MakeLeftDirectory;
QueueNode(*actionFileNodeQueue, actionFileNodeNew);
actionFileNodeNew = ActionFileNode_CreateNormal(
fileNodeLeft, fileNodeRight);
}
actionFileNodeNew->action = ActionFileCmp_DateRightToLeft;
}
} else if (fileNodeLeft->fileTime > fileNodeRight->fileTime) {
if (fileNodeLeft->status == FileStatus_Deleted) {
actionFileNodeNew->action = ActionFileCmp_DeleteRight;
if (fileNodeRight->status == FileStatus_Deleted) {
actionFileNodeNew->action = ActionFileCmp_Nothing;
}
} else {
if (fileNodeRight->status == FileStatus_Deleted) {
actionFileNodeNew->action =
ActionFileCmp_MakeRightDirectory;
QueueNode(*actionFileNodeQueue, actionFileNodeNew);
actionFileNodeNew = ActionFileNode_CreateNormal(
fileNodeLeft, fileNodeRight);
}
actionFileNodeNew->action = ActionFileCmp_DateLeftToRight;
}
}
// Process child nodes
if (actionFileNodeNew->action == ActionFileCmp_DeleteRight ||
actionFileNodeNew->action == ActionFileCmp_DeleteLeft) {
// Iterate child nodes for deletion
AccionFileNode_CompareChilds(actionFileNodeNew,
actionFileNodeQueue,
AccionFileNode_DeletePair);
} else {
AccionFileNode_CompareChilds(actionFileNodeNew,
actionFileNodeQueue,
AccionFileNode_SyncPair);
}
QueueNode(*actionFileNodeQueue, actionFileNodeNew);
} else if ((fileNodeLeft->flags & FileFlag_Normal) &&
(fileNodeRight->flags & FileFlag_Normal)) {
// Files
// Prepare action for file pair
if (abs((int)(fileNodeLeft->fileTime - fileNodeRight->fileTime)) <=
MaxDeltaTime) { // aprox. equal
if (fileNodeRight->status == FileStatus_Deleted &&
fileNodeLeft->status == FileStatus_Deleted) {
actionFileNodeNew->action = ActionFileCmp_Nothing;
} else if (fileNodeLeft->status == FileStatus_Undeleted &&
fileNodeRight->status == FileStatus_Deleted) {
actionFileNodeNew->action = ActionFileCmp_LeftToRight;
} else if (fileNodeLeft->status == FileStatus_Deleted &&
fileNodeRight->status == FileStatus_Undeleted) {
actionFileNodeNew->action = ActionFileCmp_RightToLeft;
} else if (fileNodeRight->status == FileStatus_Deleted) {
actionFileNodeNew->action = ActionFileCmp_DeleteLeft;
} else if (fileNodeLeft->status == FileStatus_Deleted) {
actionFileNodeNew->action = ActionFileCmp_DeleteRight;
} else {
actionFileNodeNew->action = ActionFileCmp_Nothing;
}
} else if (fileNodeLeft->fileTime < fileNodeRight->fileTime) {
// FIXME: Check size to determine y further checks are necessary
actionFileNodeNew->action = ActionFileCmp_RightToLeft;
if (fileNodeRight->status == FileStatus_Deleted) {
actionFileNodeNew->action = ActionFileCmp_DeleteLeft;
if (fileNodeLeft->status == FileStatus_Deleted) {
actionFileNodeNew->action = ActionFileCmp_Nothing;
}
}
} else if (fileNodeLeft->fileTime > fileNodeRight->fileTime) {
// FIXME: Check size to determine y further checks are necessary
actionFileNodeNew->action = ActionFileCmp_LeftToRight;
if (fileNodeLeft->status == FileStatus_Deleted) {
actionFileNodeNew->action = ActionFileCmp_DeleteRight;
if (fileNodeRight->status == FileStatus_Deleted) {
actionFileNodeNew->action = ActionFileCmp_Nothing;
}
}
}
QueueNode(*actionFileNodeQueue, actionFileNodeNew);
} else {
// FIXME: !!!!!
// Directory vs File
}
}
}
ActionFileNode ActionFileNode_BuildSync(FileNode izquierda, FileNode derecha) {
ActionFileNode actionFileNodeRoot =
ActionFileNode_CreateNormal(izquierda, derecha);
ActionFileNode actionFileNodeQueue = actionFileNodeRoot;
AccionFileNode_CompareChilds(actionFileNodeRoot, &actionFileNodeQueue,
AccionFileNode_SyncPair);
return actionFileNodeRoot;
}

View File

@@ -1,13 +0,0 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2014-2021 Valeriano Alfonso Rodriguez
#ifndef _ACTIONFILENODESYNC_H_
#define _ACTIONFILENODESYNC_H_
#include "actionfilenode.h"
#include "filenode.h"
ActionFileNode ActionFileNode_BuildSync(FileNode fileNodeLeft,
FileNode fileNodeRight);
#endif

View File

@@ -1,70 +0,0 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2014-2021 Valeriano Alfonso Rodriguez
#include <stdio.h>
unsigned long _crcTable[256];
int _crcTableInitialized = 0;
#define CRC32_POLYNOMIAL 0xEDB88320L
void CRCTable_Init() {
int i;
int j;
unsigned long crc;
if (_crcTableInitialized) {
return;
}
_crcTableInitialized = 1;
for (i = 0; i < 256; i++) {
crc = i;
for (j = 8; j > 0; j--) {
if (crc & 1)
crc = (crc >> 1) ^ CRC32_POLYNOMIAL;
else
crc >>= 1;
}
_crcTable[i] = crc;
}
}
unsigned long CRC_BufferInternal(unsigned char *buffer, unsigned long len,
unsigned long crc) {
unsigned char *p;
// Calculate CRC from buffer
p = (unsigned char *)buffer;
while (len-- != 0) {
unsigned long termA = (crc >> 8) & 0x00FFFFFFL;
unsigned long termB = _crcTable[((int)crc ^ *p++) & 0xff];
crc = termA ^ termB;
}
return (crc);
}
unsigned long CRC_Buffer(unsigned char *buffer, unsigned long len,
unsigned long crc) {
CRCTable_Init();
return (CRC_BufferInternal(buffer, len, crc));
}
unsigned long CRC_File(FILE *file) {
unsigned long crc;
unsigned char buffer[512];
CRCTable_Init();
crc = 0xFFFFFFFFL;
for (;;) {
// Fill buffer
size_t count = fread(buffer, 1, 512, file);
if (count == 0)
break;
crc = CRC_BufferInternal(buffer, (int)count, crc);
}
return (crc ^= 0xFFFFFFFFL);
}

View File

@@ -1,13 +0,0 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2014-2021 Valeriano Alfonso Rodriguez
#ifndef _CRC_
#define _CRC_
#include <stdio.h>
unsigned long CRC_Buffer(unsigned char *buffer, unsigned long len,
unsigned long crc);
unsigned long CRC_File(FILE *file);
#endif

View File

@@ -1,596 +0,0 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2014-2021 Valeriano Alfonso Rodriguez
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "crc.h"
#include "filenode.h"
#include "fileutil.h"
#include "util.h"
FileNode _freeFileNode = NULL;
int _n_filenode = 0;
#define FileNode_Block 1024
FileNode FileNode_Create() {
FileNode fileNode;
if (_freeFileNode == NULL) {
FileNode nodes;
int i;
// Allocate a block
nodes = (FileNode)malloc(sizeof(TFileNode) * FileNode_Block);
if (nodes == NULL) {
return NULL;
}
for (i = 0; i < FileNode_Block - 1; i++) {
nodes[i].next = &nodes[i + 1];
}
nodes[FileNode_Block - 1].next = NULL;
_freeFileNode = &nodes[0];
}
// Get first free
fileNode = _freeFileNode;
_freeFileNode = fileNode->next;
fileNode->next = NULL;
_n_filenode++;
// Initialize
fileNode->name[0] = 0;
fileNode->flags = 0;
fileNode->status = FileStatus_None;
fileNode->size = 0;
fileNode->crc = 0;
fileNode->fileTime = 0;
fileNode->child = NULL;
fileNode->childCount = 0;
fileNode->next = NULL;
fileNode->parent = NULL;
return (fileNode);
}
FileNode FileNode_Copy(FileNode fileNode) {
FileNode fileNodeNew;
fileNodeNew = FileNode_Create();
// Copy
strcpy(fileNodeNew->name, fileNode->name);
fileNodeNew->flags = fileNode->flags;
fileNodeNew->status = fileNode->status;
fileNodeNew->size = fileNode->size;
fileNodeNew->crc = fileNode->crc;
fileNodeNew->fileTime = fileNode->fileTime;
return fileNodeNew;
}
void FileNode_Delete(FileNode fn) {
// Delete childs
FileNode fileNodeChildAux = fn->child;
FileNode fileNodeChild = fn->child;
while (fileNodeChild) {
fn->childCount--;
fileNodeChildAux = fileNodeChild;
fileNodeChild = fileNodeChild->next;
fileNodeChildAux->next = NULL;
if (fileNodeChildAux->parent == fn) {
fileNodeChildAux->parent = NULL;
FileNode_Delete(fileNodeChildAux);
}
}
// Queue freed node
fn->next = _freeFileNode;
_freeFileNode = fn;
_n_filenode--;
}
void FileNode_AddChild(FileNode fileNode, FileNode fileNodeChild) {
if (fileNodeChild == NULL || fileNode == NULL) { return; }
fileNodeChild->next = fileNode->child;
fileNode->child = fileNodeChild;
fileNode->childCount++;
fileNodeChild->parent = fileNode;
}
FileNode FileNode_GetRoot(FileNode fileNode) {
FileNode fileNodeParent = fileNode->parent;
while (fileNodeParent != NULL && fileNodeParent->parent != NULL) {
fileNodeParent = fileNodeParent->parent;
}
return fileNodeParent;
}
void FileNode_SetStatusRec(FileNode fileNode, FileStatus status) {
FileNode fileNodeChild;
if (fileNode == NULL) { return; }
fileNode->status = status;
fileNodeChild = fileNode->child;
while (fileNodeChild) {
FileNode_SetStatusRec(fileNodeChild, status);
fileNodeChild = fileNodeChild->next;
}
}
void FileNode_GetPath_Rec(FileNode fileNode, char **pathNode) {
if (fileNode->parent) {
pathNode[0] = fileNode->parent->name;
FileNode_GetPath_Rec(fileNode->parent, pathNode + 1);
} else {
pathNode[0] = NULL;
}
}
char tempPath[MaxPath];
char *FileNode_GetPath(FileNode fileNode, char *path) {
char *pathNodes[MaxPathNodes];
int levels, i;
char *pathPtr = tempPath;
if (path) {
pathPtr = path;
}
FileNode_GetPath_Rec(fileNode, pathNodes);
levels = 0;
while (pathNodes[levels]) {
levels++;
}
strcpy(pathPtr, "");
for (i = levels - 1; i >= 0; i--) {
strcat(pathPtr, pathNodes[i]);
strcat(pathPtr, "/");
}
strcat(pathPtr, fileNode->name);
return tempPath;
}
char *FileNode_GetFullPath(FileNode fileNode, char *basePath, char *path) {
char *pathNodes[MaxPath];
int levels, i;
char *pathPtr = tempPath;
if (path)
pathPtr = path;
FileNode_GetPath_Rec(fileNode, pathNodes);
levels = 0;
while (pathNodes[levels]) {
levels++;
}
strcpy(pathPtr, basePath);
strcat(pathPtr, "/");
for (i = levels - 2; i >= 0; i--) {
strcat(pathPtr, pathNodes[i]);
strcat(pathPtr, "/");
}
strcat(pathPtr, fileNode->name);
return tempPath;
}
void FileNode_LoadSize(FileNode fileNode, char *file) {
fileNode->flags |= FileFlag_HasSize;
fileNode->size = File_GetSize(file);
}
void FileNode_LoadTime(FileNode fileNode, char *file) {
fileNode->flags |= FileFlag_HasTime;
fileNode->fileTime = FileTime_Get(file);
}
void FileNode_LoadSizeAndTime(FileNode fileNode, char *file) {
fileNode->flags |= FileFlag_HasSize | FileFlag_HasTime;
File_GetSizeAndTime(file, &fileNode->size, &fileNode->fileTime);
}
void FileNode_LoadCRC(FileNode fileNode, char *filePath) {
FILE *file;
file = fopen(filePath, "rb");
if (!file) {
return;
}
fileNode->flags |= FileFlag_HasCRC;
fileNode->crc = CRC_File(file);
fclose(file);
}
void FileNode_SaveNode(FileNode fileNode, FILE *file) {
short nameLen;
// Write name
nameLen = (short)strlen(fileNode->name);
fwrite((void *)&nameLen, sizeof(nameLen), 1, file);
if (nameLen > 0 && nameLen < MaxFilename) {
fputs(fileNode->name, file);
} else {
return;
}
// Write flags
fwrite((void *)&fileNode->flags, sizeof(fileNode->flags), 1, file);
// Write status
fputc((char)fileNode->status, file);
// Write size
if (fileNode->flags & FileFlag_HasSize) {
fwrite((void *)&fileNode->size, sizeof(fileNode->size), 1, file);
}
// Write date
if (fileNode->flags & FileFlag_HasTime) {
fwrite((void *)&fileNode->fileTime, sizeof(fileNode->fileTime), 1,
file);
}
// Write CRC
if (fileNode->flags & FileFlag_HasCRC) {
fwrite((void *)&fileNode->crc, sizeof(fileNode->crc), 1, file);
}
// Write files of directory
if (fileNode->flags & FileFlag_Directory) {
FileNode fileNodeChild;
fwrite((void *)&fileNode->childCount, sizeof(fileNode->childCount), 1,
file);
fileNodeChild = fileNode->child;
int cnt = 0;
while (fileNodeChild) {
FileNode_SaveNode(fileNodeChild, file);
fileNodeChild = fileNodeChild->next;
cnt++;
}
if (fileNode->childCount != cnt) {
return;
}
}
}
void FileNode_Save(FileNode fileNode, char *filePath) {
FILE *file;
char mark[5];
int version;
if (!fileNode)
return;
file = fopen(filePath, "wb+");
if (!file)
return;
// Write mark and version
strcpy(mark, "sYnC");
fwrite((void *)mark, sizeof(char), 4, file);
version = FileNode_Version;
fwrite((void *)&version, sizeof(int), 1, file);
FileNode_SaveNode(fileNode, file);
fclose(file);
}
FileNode FileNode_LoadNode(FILE *file) {
short nameLen;
FileNode fileNode;
int i;
fileNode = FileNode_Create();
// Read name
fread((void *)&nameLen, sizeof(nameLen), 1, file);
fileNode->name[0] = 0;
if (nameLen < 0 || nameLen > MaxFilename) {
FileNode_Delete(fileNode);
return NULL;
}
if (nameLen > 0) {
fread((void *)fileNode->name, sizeof(char), nameLen, file);
fileNode->name[nameLen] = 0;
}
// Read flags
fread((void *)&fileNode->flags, sizeof(fileNode->flags), 1, file);
// Read status
fileNode->status = (FileStatus)fgetc(file);
// Read status
if (fileNode->flags & FileFlag_HasSize) {
fread((void *)&fileNode->size, sizeof(fileNode->size), 1, file);
}
// Read date
if (fileNode->flags & FileFlag_HasTime) {
fread((void *)&fileNode->fileTime, sizeof(fileNode->fileTime), 1, file);
if (fileNode->fileTime < 0) {
fileNode->fileTime = Time_GetCurrentTime();
}
}
// Read CRC
if (fileNode->flags & FileFlag_HasCRC) {
fread((void *)&fileNode->crc, sizeof(fileNode->crc), 1, file);
}
// Read files on directory
if (fileNode->flags & FileFlag_Directory) {
FileNode fileNodeChildAux = NULL;
FileNode fileNodeChild;
fread((void *)&fileNode->childCount, sizeof(fileNode->childCount), 1,
file);
for (i = 0; i < fileNode->childCount; i++) {
fileNodeChild = FileNode_LoadNode(file);
if (fileNodeChild == NULL) {
FileNode_Delete(fileNode);
return NULL;
}
fileNodeChild->parent = fileNode;
if (!fileNodeChildAux) {
fileNode->child = fileNodeChild;
} else {
fileNodeChildAux->next = fileNodeChild;
}
fileNodeChildAux = fileNodeChild;
}
}
return (fileNode);
}
FileNode FileNode_Load(char *filePath) {
FILE *file;
FileNode fileNode;
char mark[5];
int version;
file = fopen(filePath, "rb");
if (!file)
return (NULL);
// Read mark and version
fread((void *)mark, sizeof(char), 4, file);
mark[4] = 0;
if (strcmp(mark, "sYnC")) {
// Incorrect mark
fclose(file);
return (NULL);
}
fread((void *)&version, sizeof(int), 1, file);
if (version != FileNode_Version) {
// Incorrect version
fclose(file);
return (NULL);
}
fileNode = FileNode_LoadNode(file);
fclose(file);
return (fileNode);
}
void FileNode_PrintNode(FileNode fileNode) {
Print(FileNode_GetPath(fileNode, NULL));
if (fileNode->flags & FileFlag_Normal) {
Print(" File");
} else {
Print(" Dir");
}
if (fileNode->status == FileStatus_New) {
Print(" New");
}
if (fileNode->status == FileStatus_Modified) {
Print(" Modified");
}
if (fileNode->status == FileStatus_Deleted) {
Print(" Deleted");
}
if (fileNode->status == FileStatus_Undeleted) {
Print(" Undeleted");
}
Print("\n");
if (fileNode->flags & FileFlag_HasSize) {
Print("\\-Size : %lld\n", fileNode->size);
}
if (fileNode->flags & FileFlag_HasTime) {
Print("\\-Date : ");
FileTime_Print(fileNode->fileTime);
Print("\n");
}
if (fileNode->flags & FileFlag_HasCRC) {
Print("\\-CRC : [%08X]\n", fileNode->crc);
}
}
void FileNode_Print(FileNode fileNode) {
FileNode fileNodeAux = fileNode;
int end = 0;
while (fileNodeAux != NULL && !end) {
if (fileNodeAux->parent != NULL) {
FileNode_PrintNode(fileNodeAux);
}
if (fileNodeAux->child) {
fileNodeAux = fileNodeAux->child;
} else {
while (fileNodeAux->next == NULL) {
fileNodeAux = fileNodeAux->parent;
if (fileNodeAux == fileNode || fileNodeAux == NULL) {
Print("End\n");
end = 1;
break;
}
}
if (!end) {
fileNodeAux = fileNodeAux->next;
}
}
}
}
int FileNode_Build_Iterate(char *path, char *name, void *d);
FileNode FileNode_Build(char *path) {
FileNode fileNode;
if (!File_ExistsPath(path))
return (NULL);
// Create node
fileNode = FileNode_Create();
File_GetName(path, fileNode->name);
fileNode->fileTime = Time_GetCurrentTime();
fileNode->flags |= FileFlag_HasTime;
if (File_IsDirectory(path)) {
// Get information data from directories, and child files
fileNode->flags |= FileFlag_Directory;
FileNode_LoadTime(fileNode, path);
File_IterateDir(path, FileNode_Build_Iterate, fileNode);
} else {
// Get information data from files
fileNode->flags |= FileFlag_Normal;
FileNode_LoadSizeAndTime(fileNode, path);
}
return (fileNode);
}
int FileNode_Build_Iterate(char *path, char *name, void *d) {
FileNode fileNode;
FileNode fileNodeParent = (FileNode)d;
if (!strcmp(name, FileNode_Filename)) {
return (0);
}
fileNode = FileNode_Build(path);
FileNode_AddChild(fileNodeParent, fileNode);
return (0);
}
int FileNode_Refresh_Iterate(char *path, char *name, void *d);
FileNode FileNode_Refresh(FileNode fileNode, char *filePath) {
if (!fileNode) {
Print("FileNode_Refresh: Error NULL FileNode\n");
return NULL;
}
if (!File_ExistsPath(filePath)) {
// The file/directory has been deleted
FileNode_SetStatusRec(fileNode, FileStatus_Deleted);
return (fileNode);
}
// Check modification
FileTime fileTime;
long long size;
// Remove mark
fileNode->flags &= ~FileFlag_MarkerForReview;
if (File_IsDirectory(filePath)) {
FileNode fileNodeChild;
// Check directory data
fileTime = FileTime_Get(filePath);
if (fileNode->status == FileStatus_Deleted) {
fileNode->status = FileStatus_Undeleted;
fileNode->fileTime = fileTime;
}
if (!(fileNode->flags & FileFlag_Directory)) {
fileNode->status = FileStatus_Modified;
fileNode->flags |= FileFlag_Directory;
fileNode->flags &= ~FileFlag_Normal;
}
if (fileTime != fileNode->fileTime) {
fileNode->status = FileStatus_Modified;
fileNode->fileTime = fileTime;
}
// Mark childs for review
fileNodeChild = fileNode->child;
while (fileNodeChild) {
fileNodeChild->flags |= FileFlag_MarkerForReview;
fileNodeChild = fileNodeChild->next;
}
// Scan subdirectories
File_IterateDir(filePath, FileNode_Refresh_Iterate, fileNode);
// Mark as deleted remaining files marked for review
fileNodeChild = fileNode->child;
while (fileNodeChild) {
if (fileNodeChild->flags & FileFlag_MarkerForReview) {
fileNodeChild->flags &= ~FileFlag_MarkerForReview;
FileNode_SetStatusRec(fileNodeChild, FileStatus_Deleted);
}
fileNodeChild = fileNodeChild->next;
}
} else {
// Comprar datos de los ficheros
File_GetSizeAndTime(filePath, &size, &fileTime);
if (fileNode->status == FileStatus_Deleted) {
fileNode->status = FileStatus_Undeleted;
fileNode->fileTime = fileTime;
}
if (!(fileNode->flags & FileFlag_Normal)) {
fileNode->status = FileStatus_Modified;
fileNode->flags |= FileFlag_Normal;
fileNode->flags &= ~FileFlag_Directory;
}
if (size != fileNode->size) {
fileNode->status = FileStatus_Modified;
fileNode->size = size;
}
if (fileTime != fileNode->fileTime) {
fileNode->status = FileStatus_Modified;
fileNode->fileTime = fileTime;
}
if (fileNode->status == FileStatus_Modified) {
fileNode->flags &= ~FileFlag_HasCRC;
}
}
// Save update time on root FileNode
if (fileNode->parent == NULL) {
fileNode->fileTime = Time_GetCurrentTime();
fileNode->flags |= FileFlag_HasTime;
}
return (fileNode);
}
int FileNode_Refresh_Iterate(char *path, char *name, void *d) {
FileNode fileNode = (FileNode)d;
FileNode fileNodeChild;
if (!strcmp(name, FileNode_Filename)) {
return (0);
}
// Search the file on childs
fileNodeChild = fileNode->child;
while (fileNodeChild) {
if (!strcmp(fileNodeChild->name, name)) {
break;
}
fileNodeChild = fileNodeChild->next;
}
if (fileNodeChild) {
// Exists, Refresh
FileNode_Refresh(fileNodeChild, path);
} else {
// New, Build
fileNodeChild = FileNode_Build(path);
FileNode_SetStatusRec(fileNodeChild, FileStatus_New);
FileNode_AddChild(fileNode, fileNodeChild);
}
return (0);
}

View File

@@ -1,70 +0,0 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2014-2021 Valeriano Alfonso Rodriguez
#ifndef _FILENODE_H_
#define _FILENODE_H_
#include "fileutil.h"
#define FileNode_Filename "nodesFile.fs"
#define FileNode_Version 5
#define FileFlag_Root 1
#define FileFlag_Normal 2
#define FileFlag_Directory 4
#define FileFlag_HasSize 8
#define FileFlag_HasTime 16
#define FileFlag_HasCRC 32
#define FileFlag_PlaceHolder 512
#define FileFlag_MarkerForReview 1024
typedef enum EFileStatus {
FileStatus_None,
FileStatus_New,
FileStatus_Modified,
FileStatus_Deleted,
FileStatus_Undeleted
} FileStatus;
typedef struct TFileNode TFileNode, *FileNode;
struct TFileNode {
char name[MaxFilename];
int flags;
FileStatus status;
long long size;
unsigned long crc;
FileTime fileTime;
FileNode child;
int childCount;
FileNode next;
FileNode parent;
};
FileNode FileNode_Create();
FileNode FileNode_Copy(FileNode fileNode);
void FileNode_Delete(FileNode fileNode);
void FileNode_AddChild(FileNode file, FileNode file2);
FileNode FileNode_GetRoot(FileNode fileNode);
char *FileNode_GetFullPath(FileNode fileNode, char *basePath, char *path);
void FileNode_LoadSize(FileNode fileNode, char *file);
void FileNode_LoadTime(FileNode fileNode, char *file);
void FileNode_LoadSizeAndTime(FileNode fileNode, char *file);
void FileNode_LoadCRC(FileNode fileNode, char *file);
void FileNode_Save(FileNode fileNode, char *fichero);
FileNode FileNode_Load(char *fichero);
void FileNode_PrintNode(FileNode fileNode);
void FileNode_Print(FileNode fileNode);
FileNode FileNode_Build(char *path);
FileNode FileNode_Refresh(FileNode file, char *path);
#endif

View File

@@ -1,422 +0,0 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2014-2021 Valeriano Alfonso Rodriguez
#ifdef WIN32
#define _WIN32_WINNT 0x0501
#include <direct.h>
#include <errno.h>
#include <fcntl.h>
#include <io.h>
#include <signal.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <windows.h>
#else
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <utime.h>
#endif
#include "fileutil.h"
#include "util.h"
#ifdef WIN32
long long FileTime_to_POSIX(FILETIME fileTime) {
LARGE_INTEGER date, adjust;
// takes the last modified date
date.HighPart = fileTime.dwHighDateTime;
date.LowPart = fileTime.dwLowDateTime;
// 100-nanoseconds = milliseconds * 10000
adjust.QuadPart = 11644473600000ll * 10000;
// removes the diff between 1970 and 1601
date.QuadPart -= adjust.QuadPart;
// converts back from 100-nanoseconds to seconds
return date.QuadPart / 10000000ll;
}
FILETIME POSIX_to_FileTime(FileTime fileTime) {
LARGE_INTEGER date, adjust;
FILETIME fileTimeOut;
// converts to 100-nanoseconds from seconds
date.QuadPart = fileTime * 10000000ll;
// 100-nanoseconds = milliseconds * 10000
adjust.QuadPart = 11644473600000ll * 10000ll;
// removes the diff between 1970 and 1601
date.QuadPart += adjust.QuadPart;
// asigns to filetime
fileTimeOut.dwHighDateTime = date.HighPart;
fileTimeOut.dwLowDateTime = date.LowPart;
return fileTimeOut;
}
/////////////////////////////
// FileTime_Get
//
// Gets the current time in POSIX.
FileTime FileTime_Get(char *fileName) {
HANDLE hFile;
FILETIME ftCreate, ftAccess, ftWrite;
hFile = CreateFile(fileName, READ_CONTROL, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite);
CloseHandle(hFile);
return (FileTime_to_POSIX(ftWrite));
}
/////////////////////////////
// FileTime_Set
//
// Sets the current time in POSIX.
void FileTime_Set(char *fileName, FileTime fileTime) {
HANDLE hFile;
FILETIME ftWrite;
hFile = CreateFile(fileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
ftWrite = POSIX_to_FileTime(fileTime);
SetFileTime(hFile, NULL, NULL, &ftWrite);
CloseHandle(hFile);
}
#else
/////////////////////////////
// FileTime_Get
//
// Gets the current time in POSIX.
FileTime FileTime_Get(char *fileName) {
struct stat fs;
lstat(fileName, &fs);
return (fs.st_mtime);
}
/////////////////////////////
// FileTime_Set
//
// Sets the current time in POSIX.
void FileTime_Set(char *fileName, FileTime t) {
struct utimbuf utb;
utb.actime = t;
utb.modtime = t;
utime(fileName, &utb);
}
#endif
/////////////////////////////
// FileTime_Print
//
// Prints the filetime
void FileTime_Print(FileTime fileTime) {
struct tm *tms;
tms = localtime((time_t *)&fileTime);
Print("%04d-%02d-%02d %02d:%02d:%02d", tms->tm_year + 1900, tms->tm_mon + 1,
tms->tm_mday, tms->tm_hour, tms->tm_min, tms->tm_sec);
}
#ifdef WIN32
long long File_GetSize(char *fileName) {
HANDLE hFile;
DWORD fSize;
hFile = CreateFile(fileName, READ_CONTROL, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
fSize = GetFileSize(hFile, NULL);
CloseHandle(hFile);
return (fSize);
}
#else
long long File_GetSize(char *fileName) {
struct stat fs;
lstat(fileName, &fs);
return (fs.st_size);
}
#endif
#ifdef WIN32
void File_GetSizeAndTime(char *fileName, long long *size, FileTime *time) {
HANDLE hFile;
DWORD fSize;
FILETIME ftCreate, ftAccess, ftWrite;
hFile = CreateFile(fileName, READ_CONTROL, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
fSize = GetFileSize(hFile, NULL);
GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite);
CloseHandle(hFile);
*size = fSize;
*time = FileTime_to_POSIX(ftWrite);
}
#else
void File_GetSizeAndTime(char *fileName, long long *size, FileTime *time) {
struct stat fs;
lstat(fileName, &fs);
*size = fs.st_size;
*time = fs.st_mtime;
}
#endif
void File_GetName(char *path, char *name) {
size_t i, j;
i = strlen(path) - 1;
while (i >= 0) {
if (path[i] == '/' || path[i] == '\\') {
i++;
break;
} else {
i--;
}
}
if (i < 0)
i++;
j = 0;
while (path[i]) {
name[j] = path[i];
i++;
j++;
}
name[j] = 0;
}
#ifdef WIN32
int File_ExistsPath(char *path) {
unsigned rc;
rc = GetFileAttributes(path);
if (rc == INVALID_FILE_ATTRIBUTES) {
SetError(strerror(errno));
return (0);
}
return (1);
}
int File_IsDirectory(char *fileName) {
unsigned rc;
rc = GetFileAttributes(fileName);
if (rc == INVALID_FILE_ATTRIBUTES) {
SetError(strerror(errno));
return (0);
}
if (rc & FILE_ATTRIBUTE_DIRECTORY) {
return (1);
}
return (0);
}
int File_IsFile(char *fileName) {
unsigned rc;
rc = GetFileAttributes(fileName);
if (rc == INVALID_FILE_ATTRIBUTES) {
SetError(strerror(errno));
return (0);
}
if (rc & FILE_ATTRIBUTE_DIRECTORY) {
return (0);
}
return (1);
}
#else
int File_ExistsPath(char *path) {
struct stat info;
if (lstat(path, &info) == -1) {
return (0);
}
return (1);
}
int File_IsDirectory(char *fileName) {
struct stat info;
if (lstat(fileName, &info) == -1) {
SetError(strerror(errno));
return (0);
}
if (S_ISDIR(info.st_mode)) {
return (1);
}
return (0);
}
int File_IsFile(char *fileName) {
struct stat info;
if (lstat(fileName, &info) == -1) {
SetError(strerror(errno));
return (0);
}
if (S_ISDIR(info.st_mode)) {
return (0);
}
return (1);
}
#endif
#ifdef WIN32
int File_MakeDirectory(char *path) { return (CreateDirectory(path, NULL)); }
#else
int File_MakeDirectory(char *path) {
int rc = mkdir(path, 0777);
if (rc != 0) {
SetError(strerror(errno));
return 0;
}
return 1;
}
#endif
#ifdef WIN32
void File_IterateDir(char *path,
int (*func)(char *path, char *name, void *data),
void *data) {
intptr_t handle;
struct _finddata_t fileinfo;
char f_path[MaxPath];
int fin = 0;
int findnext_rc;
char path_aux[MaxPath];
snprintf(path_aux, MaxPath, "%s/*", path);
handle = _findfirst(path_aux, &fileinfo);
if (handle == -1)
return;
// Iterate directory
do {
if (strcmp(fileinfo.name, ".") && strcmp(fileinfo.name, "..")) {
// Each item
snprintf(f_path, 512, "%s/%s", path, fileinfo.name);
fin = func(f_path, fileinfo.name, data);
}
findnext_rc = _findnext(handle, &fileinfo);
} while (findnext_rc != -1 && !fin);
_findclose(handle);
}
#else
void File_IterateDir(char *path,
int (*func)(char *path, char *name, void *data),
void *data) {
DIR *directorio;
struct dirent *entidad_dir;
char f_path[MaxPath];
int fin = 0;
char *ptr;
directorio = opendir(path);
if (directorio == NULL)
return;
// Iterate directory
do {
entidad_dir = readdir(directorio);
if (entidad_dir != NULL) {
if (strcmp(entidad_dir->d_name, ".") &&
strcmp(entidad_dir->d_name, "..")) {
// Each item
snprintf(f_path, MaxPath, "%s/%s", path, entidad_dir->d_name);
fin = func(f_path, entidad_dir->d_name, data);
}
}
} while (entidad_dir != NULL && !fin);
closedir(directorio);
}
#endif
int File_Delete(char *path) {
#ifdef WIN32
int rc = remove(path);
#else
int rc = unlink(path);
#endif
if (rc != 0) {
SetError(strerror(errno));
return 0;
}
return 1;
}
int File_DeleteDirectory(char *path) {
#ifndef WIN32
int rc = rmdir(path);
#else
int rc = _rmdir(path);
#endif
if (rc != 0) {
SetError(strerror(errno));
return 0;
}
return 1;
}
#define MaxBuffer 16384
int File_Copy(const char *pathOrig, const char *pathDest) {
FILE *fOrig = NULL;
FILE *fDest = NULL;
char *buffer = NULL;
size_t readLen = 0;
size_t writeLen = 0;
int status = 0;
if ((fOrig = fopen(pathOrig, "rb")) == NULL) {
SetError(strerror(errno));
goto cleanup;
}
if ((fDest = fopen(pathDest, "wb")) == NULL) {
SetError(strerror(errno));
goto cleanup;
}
buffer = (char *)malloc(sizeof(char) * MaxBuffer);
if (buffer == NULL) {
goto cleanup;
}
do {
readLen = fread(buffer, 1, MaxBuffer, fOrig);
if (readLen > 0) {
writeLen = fwrite(buffer, 1, readLen, fDest);
if (writeLen != readLen) {
SetError("Write error");
goto cleanup;
}
}
} while (readLen == MaxBuffer);
if (feof(fOrig)) {
status = 1;
}
cleanup:
if (fOrig != NULL) {
fclose(fOrig);
}
if (fDest != NULL) {
fclose(fDest);
}
if (buffer != NULL) {
free(buffer);
}
return status;
}

View File

@@ -1,59 +0,0 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2014-2021 Valeriano Alfonso Rodriguez
#ifndef _FILEUTIL_
#define _FILEUTIL_
////////////////////////////////////////////////
// FileTime
typedef long long FileTime;
/////////////////////////////
// FileTime_Get
//
// Gets the current time in POSIX.
FileTime FileTime_Get(char *filename);
/////////////////////////////
// FileTime_Set
//
// Sets the current time in POSIX.
void FileTime_Set(char *filename, FileTime t);
/////////////////////////////
// FileTime_Print
//
// Prints the filetime
void FileTime_Print(FileTime t);
///////////////////////////////////////////////
// File
#define MaxFilename 2048
#define MaxPath 4096
#define MaxPathNodes 512
long long File_GetSize(char *fileName);
void File_GetSizeAndTime(char *fileName, long long *size, FileTime *time);
void File_GetName(char *path, char *name);
int File_ExistsPath(char *path);
int File_IsDirectory(char *path);
int File_IsFile(char *path);
int File_MakeDirectory(char *path);
void File_IterateDir(char *path,
int (*func)(char *path, char *name, void *data),
void *data);
int File_Delete(char *path);
int File_DeleteDirectory(char *path);
int File_Copy(const char *pathOrig, const char *pathDest);
#endif

View File

@@ -1,376 +0,0 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2014-2021 Valeriano Alfonso Rodriguez
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "actionfilenode.h"
#include "actionfilenodecopy.h"
#include "actionfilenodesync.h"
#include "crc.h"
#include "filenode.h"
#include "fileutil.h"
#include "parameteroperation.h"
#include "util.h"
FileNode CheckDir(char *path, int recheck) {
char dirNodesFile[MaxPath];
FileNode fileNode;
// Check directory
snprintf(dirNodesFile, MaxPath, "%s/" FileNode_Filename, path);
if (recheck) {
Print("Checking Directory.. %s\n", path);
long long tScan = Time_GetTime();
fileNode = FileNode_Load(dirNodesFile);
if (fileNode) {
fileNode = FileNode_Refresh(fileNode, path);
} else {
fileNode = FileNode_Build(path);
}
tScan = Time_GetTime() - tScan;
Print("\ttScan :");
PrintElapsedTime(tScan);
Print("\n");
long long tSave = Time_GetTime();
FileNode_Save(fileNode, dirNodesFile);
tSave = Time_GetTime() - tSave;
Print("\ttSave :");
PrintElapsedTime(tSave);
Print("\n");
} else {
Print("Loading Directory.. %s\n", path);
fileNode = FileNode_Load(dirNodesFile);
if (!fileNode) {
Print("Error, no nodesFile.fs\n");
return NULL;
}
}
return fileNode;
}
void PrintStatistics(ActionFileNode actionFileNode,
ActionFileNodeResult result) {
ActionQueueStatistics statistics;
if (ActionFileNode_Statistics(actionFileNode, &statistics, result) == 0) {
Print("Noting to do.\n");
return;
}
Print("Statistics\n");
Print(" % 8s % 8s % 8s\n", "Read", "Write", "Delete");
Print("Left :");
PrintDataSize(statistics.readLeft);
PrintDataSize(statistics.writeLeft);
PrintDataSize(statistics.deleteLeft);
Print("\n");
Print("Right:");
PrintDataSize(statistics.readRight);
PrintDataSize(statistics.writeRight);
PrintDataSize(statistics.deleteRight);
Print("\n");
Print("\n");
Print("Copy count : % 10d\n", statistics.fullCopyCount);
Print("Date copy count: % 10d\n", statistics.dateCopyCount);
Print("Directory count: % 10d\n", statistics.directoryCount);
Print("Delete count : % 10d\n", statistics.deleteCount);
}
int Sync(char *pathLeft, char *pathRight, int reCheck, int dryRun) {
FileNode fileNodeLeft;
FileNode fileNodeRight;
// Check and load directories
if (!File_ExistsPath(pathLeft) || !File_IsDirectory(pathLeft)) {
Print("Error, directory does not exist: %s\n", pathLeft);
return 0;
}
if (!File_ExistsPath(pathRight) || !File_IsDirectory(pathRight)) {
Print("Error, directory does not exist: %s\n", pathRight);
return 0;
}
fileNodeLeft = CheckDir(pathLeft, reCheck);
if (!fileNodeLeft) {
return 0;
}
fileNodeRight = CheckDir(pathRight, reCheck);
if (!fileNodeRight) {
return 0;
}
// Build actions
long long tBuild = Time_GetTime();
Print("Building action list.. \n");
ActionFileNode actionFileNode = NULL;
actionFileNode = ActionFileNode_BuildSync(fileNodeLeft, fileNodeRight);
tBuild = Time_GetTime() - tBuild;
Print("\ttBuild:");
PrintElapsedTime(tBuild);
Print("\n");
int postCheckDir = 0;
long long tRun = Time_GetTime();
if (dryRun) {
// Show action list
ActionFileNode_Print(actionFileNode);
PrintStatistics(actionFileNode, ActionFileNodeResult_Nothing);
} else {
// Run action list
if (ActionFileNode_RunList(actionFileNode, pathLeft, pathRight)) {
PrintStatistics(actionFileNode, ActionFileNodeResult_Ok);
postCheckDir = 1;
}
}
tRun = Time_GetTime() - tRun;
Print("\ttRun:");
PrintElapsedTime(tRun);
Print("\n");
if (postCheckDir) {
CheckDir(pathLeft, reCheck);
CheckDir(pathRight, reCheck);
}
return (1);
}
int Copy(char *pathLeft, char *pathRight, int reCheck, int dryRun) {
FileNode fileNodeLeft;
FileNode fileNodeRight;
// Check and load directories
if (!File_ExistsPath(pathLeft) || !File_IsDirectory(pathLeft)) {
Print("Error, directory does not exist: %s\n", pathLeft);
return 0;
}
if (!File_ExistsPath(pathRight) || !File_IsDirectory(pathRight)) {
Print("Error, directory does not exist: %s\n", pathRight);
return 0;
}
fileNodeLeft = CheckDir(pathLeft, reCheck);
if (!fileNodeLeft) {
return 0;
}
fileNodeRight = CheckDir(pathRight, reCheck);
if (!fileNodeRight) {
return 0;
}
// Build actions
long long tBuild = Time_GetTime();
Print("Building action list.. \n");
ActionFileNode actionFileNode = NULL;
actionFileNode = ActionFileNode_BuildCopy(fileNodeLeft, fileNodeRight);
tBuild = Time_GetTime() - tBuild;
Print("\ttBuild:");
PrintElapsedTime(tBuild);
Print("\n");
int postCheckDir = 0;
long long tRun = Time_GetTime();
if (dryRun) {
// Show action list
ActionFileNode_Print(actionFileNode);
PrintStatistics(actionFileNode, ActionFileNodeResult_Nothing);
} else {
// Run action list
if (ActionFileNode_RunList(actionFileNode, pathLeft, pathRight)) {
PrintStatistics(actionFileNode, ActionFileNodeResult_Ok);
postCheckDir = 1;
}
}
tRun = Time_GetTime() - tRun;
Print("\ttRun:");
PrintElapsedTime(tRun);
Print("\n");
if (postCheckDir) {
CheckDir(pathLeft, reCheck);
CheckDir(pathRight, reCheck);
}
return (1);
}
typedef struct SApplicationConfiguration TApplicationConfiguration,
*ApplicationConfiguration;
struct SApplicationConfiguration {
char *Dirs[10];
bool NoScan;
bool Dummy;
bool Sync;
bool Copy;
bool NoAction;
char *Log;
};
TApplicationConfiguration defaultConfig = {{NULL}, false, false, false,
false, false, NULL};
bool SetParam_Dir(int argc, char *argv[], void *data) {
ApplicationConfiguration config = (ApplicationConfiguration)data;
if (File_ExistsPath(argv[0]) == 0) {
Print("Error: Path \"%s\" does not exist.\n", argv[0]);
return false;
}
char **destDir = config->Dirs;
while (destDir[0] != NULL) {
destDir++;
}
destDir[0] = argv[0];
destDir++;
destDir = NULL;
return true;
}
bool SetParam_NoCheck(int argc, char *argv[], void *data) {
((ApplicationConfiguration)data)->NoScan = true;
return true;
}
bool SetParam_Dummy(int argc, char *argv[], void *data) {
((ApplicationConfiguration)data)->Dummy = true;
return true;
}
bool SetParam_Sync(int argc, char *argv[], void *data) {
((ApplicationConfiguration)data)->Sync = true;
return true;
}
bool SetParam_Copy(int argc, char *argv[], void *data) {
((ApplicationConfiguration)data)->Copy = true;
return true;
}
bool SetParam_Log(int argc, char *argv[], void *data) {
ApplicationConfiguration config = (ApplicationConfiguration)data;
config->Log = argv[0];
Print_SetOutFile(config->Log);
return true;
}
bool Func_Scan(int argc, char *argv[], void *data) {
((ApplicationConfiguration)data)->NoAction = true;
// Scan directory information tree and save
long long tScan = Time_GetTime();
FileNode fileNode;
Print("Building FileNode..\n");
fileNode = FileNode_Build(argv[0]);
tScan = Time_GetTime() - tScan;
Print("\ttScan :");
PrintElapsedTime(tScan);
Print("\n");
FileNode_Save(fileNode, argv[1]);
return true;
}
bool Func_Rescan(int argc, char *argv[], void *data) {
((ApplicationConfiguration)data)->NoAction = true;
// Scan directory information and save tree
FileNode fileNode;
Print("Loading FileNode..\n");
fileNode = FileNode_Load(argv[1]);
if (fileNode) {
Print("Rebuilding FileNode..\n");
long long tScan = Time_GetTime();
fileNode = FileNode_Refresh(fileNode, argv[0]);
tScan = Time_GetTime() - tScan;
Print("\ttScan :");
PrintElapsedTime(tScan);
Print("\n");
FileNode_Save(fileNode, argv[1]);
} else {
Print("Building FileNode..\n");
long long tScan = Time_GetTime();
fileNode = FileNode_Build(argv[0]);
tScan = Time_GetTime() - tScan;
Print("\ttScan :");
PrintElapsedTime(tScan);
Print("\n");
FileNode_Save(fileNode, argv[1]);
}
return true;
}
bool Func_Read(int argc, char *argv[], void *data) {
((ApplicationConfiguration)data)->NoAction = true;
// Read information tree from file
FileNode fileNode;
fileNode = FileNode_Load(argv[0]);
if (fileNode) {
FileNode_Print(fileNode);
}
return true;
}
bool Func_Check(int argc, char *argv[], void *data) {
((ApplicationConfiguration)data)->NoAction = true;
// Read directory information tree
char *path = argv[0];
FileNode fileNode;
fileNode = CheckDir(path, 1);
return true;
}
TParameterOperation _parameterOperations[] = {
{"dir", 1, "Specify a directory", SetParam_Dir},
{"nocheck", 0, "Do not check for changes on directories", SetParam_NoCheck},
{"dummy", 0, "Do not perform operations", SetParam_Dummy},
{"copy", 0, "Copy first directory to second directory", SetParam_Copy},
{"sync", 0, "Synchronize between two directories", SetParam_Sync},
{"log", 1, "Log actions to file", SetParam_Log},
{"scan", 2, "Scan directory and save to filenode file", Func_Scan},
{"rescan", 2, "Rescan directory and save to filenode file", Func_Rescan},
{"read", 1, "Read filenode file", Func_Read},
{"check", 1, "Check changes on a directory", Func_Check},
{NULL, 0, NULL, NULL},
};
int main(int argc, char *argv[]) {
TApplicationConfiguration config = defaultConfig;
Exceptions_Init();
int parameterParsingResult =
ParameterOperation_Parse(argc, argv, _parameterOperations, &config);
if (parameterParsingResult <= 0) {
ParameterOperation_PrintHelp(_parameterOperations);
return 0;
}
if (config.NoAction) {
return 0;
}
Print("\n================================ FileSync "
"===================================\n");
if (config.Copy == false && config.Sync == false) {
Print("Error: Action not specified.\n");
return 0;
}
if (config.Dirs[0] == NULL || config.Dirs[1] == NULL) {
Print("Error: Two directories are needed.\n");
return 0;
}
if (config.Copy) {
Copy(config.Dirs[0], config.Dirs[1], (config.NoScan == false),
config.Dummy);
}
if (config.Sync) {
Sync(config.Dirs[0], config.Dirs[1], (config.NoScan == false),
config.Dummy);
}
return 0;
}

View File

@@ -1,70 +0,0 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2014-2021 Valeriano Alfonso Rodriguez
#include "parameteroperation.h"
#include "util.h"
int ParameterOperation_Parse(int argumentCount, char *arguments[],
TParameterOperation parameterOperations[],
void *data) {
int processedParams = 0;
char **currentArguments = arguments + 1;
for (int i = 1; i < argumentCount; i++) {
char *currentArgument = currentArguments[0];
currentArguments++;
if (currentArgument[0] != '-') {
Print("Error: Garbage found \"%s\" in position %d.\n", arguments[i],
i + 1);
return -1;
}
while (currentArgument[0] == '-') {
currentArgument++;
}
bool processed = false;
int j = 0;
while (parameterOperations[j].Name != NULL) {
ParameterOperation parameterOperation = &parameterOperations[j];
if (String_CompareCaseInsensitive(currentArgument,
parameterOperation->Name) == 0) {
if ((i + parameterOperation->NumItems) >= argumentCount) {
Print("Error: Parsing parameter \"-%s\" in position %d, "
"missig parameter data.\n",
parameterOperations[j].Name, i + 1);
return -1;
}
bool result = parameterOperation->SetFunc(
parameterOperation->NumItems, currentArguments, data);
if (result == false) {
Print("Error: Parsing parameter \"-%s\" in position %d.\n",
parameterOperations[j].Name, i + 1);
return -1;
}
currentArguments += parameterOperation->NumItems;
i += parameterOperation->NumItems;
processedParams++;
processed = true;
break;
}
j++;
}
if (processed == false) {
Print("Error: Unknow parameter \"%s\" in position %d.\n",
arguments[i], i + 1);
return -1;
}
}
return processedParams;
}
void ParameterOperation_PrintHelp(TParameterOperation parameterOperations[]) {
int i = 0;
Print("Parameters:\n");
while (parameterOperations[i].Name != NULL) {
Print("\t-%s", parameterOperations[i].Name);
for (int j = 0; j < parameterOperations[i].NumItems; j++) {
Print(" [Item]");
}
Print(": %s.\n", parameterOperations[i].Description);
i++;
}
}

View File

@@ -1,23 +0,0 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2014-2021 Valeriano Alfonso Rodriguez
#ifndef _PARAMETEROPERATION_
#define _PARAMETEROPERATION_
#include "util.h"
typedef struct SParameterOperation TParameterOperation, *ParameterOperation;
struct SParameterOperation {
char *Name;
int NumItems;
char *Description;
bool (*SetFunc)(int argumentCount, char *arguments[], void *data);
};
int ParameterOperation_Parse(int argumentCount, char *arguments[],
TParameterOperation parameterOperations[],
void *data);
void ParameterOperation_PrintHelp(TParameterOperation parameterOperations[]);
#endif

View File

@@ -1,355 +0,0 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2014-2021 Valeriano Alfonso Rodriguez
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include "util.h"
/////////////////////////////
// String_Copy
//
// Copies a string.
char *String_Copy(char *str) {
char *strnew;
size_t len;
len = strlen(str);
strnew = (char *)malloc(len + 1);
if (strnew != NULL) {
strcpy(strnew, str);
}
return (strnew);
}
/////////////////////////////
// String_CompareCaseInsensitive
//
// Compares a string case insensitive
int String_CompareCaseInsensitive(char *str0, char *str1) {
for (int i = 0;; i++) {
char c0 = tolower(str0[i]);
char c1 = tolower(str1[i]);
if (c0 != c1) {
return (c0 < c1) ? -1 : 1;
}
if (c0 == '\0') {
return 0;
}
}
}
#if WIN32
#include <windows.h>
// WIN32
/////////////////////////////
// Time_GetTime
//
// Gets the time in usecs. WIN32 version.
long long Time_GetTime() {
LARGE_INTEGER freq;
LARGE_INTEGER tim;
long long int microt;
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&tim);
microt = (tim.QuadPart * 1000000) / freq.QuadPart;
return (microt);
}
/////////////////////////////
// Time_Pause
//
// Pauses the execution for t usecs. WIN32 version.
void Time_Pause(int pausa) {
long long tend, t, diff;
t = Time_GetTime();
tend = t + pausa;
do {
diff = tend - t;
if (diff > 1000) {
Sleep((int)diff / 1000);
} else {
Sleep(0);
}
t = Time_GetTime();
} while (tend >= t);
}
#else
#include <sys/time.h>
/////////////////////////////
// Time_GetTime
//
// Gets the time in usecs. UNIX version.
long long Time_GetTime() {
struct timeval t;
long long usecs;
gettimeofday(&t, NULL);
usecs = (t.tv_sec * 1000000ll) + (t.tv_usec);
return (usecs);
}
/////////////////////////////
// Time_Pause
//
// Pauses the execution for t usecs. UNIX version.
void Time_Pause(int pausa) {
struct timeval tv;
tv.tv_sec = (long long)pausa / 1000000;
tv.tv_usec = (long long)pausa % 1000000;
select(0, NULL, NULL, NULL, &tv);
}
#endif // if WIN32
/////////////////////////////
// Time_GetTime
//
// Gets the current time in POSIX.
long long Time_GetCurrentTime() {
time_t t = time(0);
return (long long)t;
}
/////////////////////////////
// PrintElapsedTime
//
// Prints the elapsed time (input in microseconds (us))
int PrintElapsedTime(long long time) {
if (time < 1000) {
return Print("%8lld us", time);
}
double msTime = (double)time / 1000;
if (msTime < 1000) {
return Print("% 8.3f ms", msTime);
}
double seconds = msTime / 1000;
if (seconds < 60) {
return Print("% 8.3f s", seconds);
}
int minutes = (int)seconds / 60;
seconds = seconds - (minutes * 60);
int hours = minutes / 60;
minutes = minutes % 60;
return Print("%02d:%02d:%06.3f", hours, minutes, seconds);
}
/////////////////////////////
// PrintDataSize
//
// Prints the data size (input in bytes)
int PrintDataSize(long long size) {
if (size < 1024) {
return Print("%8lld B ", size);
}
double kibSize = (double)size / 1024;
if (kibSize < 1024) {
return Print("% 8.3f KiB", kibSize);
}
double mibSize = kibSize / 1024;
if (mibSize < 1024) {
return Print("% 8.3f MiB", mibSize);
}
double gibSize = mibSize / 1024;
if (gibSize < 1024) {
return Print("% 8.3f GiB", gibSize);
}
double tibSize = gibSize / 1024;
return Print("% 8.3f TiB", tibSize);
}
FILE *outFile = NULL;
/////////////////////////////
// Print_SetOutFile
//
void Print_SetOutFile(char *fileOut) {
if (fileOut == NULL) {
return;
}
outFile = fopen(fileOut, "a");
}
#define Print_BuferSize 4096
/////////////////////////////
// Print
//
// Prints the formated text screen
int Print(char *fmt, ...) {
va_list ap;
char buffer[Print_BuferSize];
int n;
// Print
va_start(ap, fmt);
// n = vprintf(fmt, ap);
n = vsnprintf(buffer, Print_BuferSize, fmt, ap);
va_end(ap);
// Output to stdout
fputs(buffer, stdout);
fflush(stdout);
// Output to outFile
if (outFile != NULL) {
fputs(buffer, outFile);
fflush(outFile);
}
return (n);
}
/////////////////////////////
// SetError
// GetError
//
char _errorMessage[2048] = "";
char _errorMessageTemp[2048] = "";
void SetError(char *msg) { strcpy(_errorMessage, msg); }
char *GetError() {
strcpy(_errorMessageTemp, _errorMessage);
strcpy(_errorMessage, "");
return _errorMessageTemp;
}
/////////////////////////////
// Exceptions_Init
//
#ifdef WIN32
LONG WINAPI Win32UnhandledExceptionFilter(
struct _EXCEPTION_POINTERS *lpTopLevelExceptionFilter) {
char cadena[255];
sprintf(
cadena, "!!! Crash: Unrecoverable exception at 0x%p",
(void *)lpTopLevelExceptionFilter->ExceptionRecord->ExceptionAddress);
printf(cadena);
printf("\n");
FatalAppExit(0, cadena);
return EXCEPTION_CONTINUE_SEARCH;
}
void Exceptions_Init() {
SetUnhandledExceptionFilter(Win32UnhandledExceptionFilter);
}
#else
#ifdef EMSCRIPTEN
void Exceptions_Init() {}
#else
#include <signal.h>
#include <dlfcn.h>
#include <execinfo.h>
#include <memory.h>
#include <unistd.h>
void Exception_Signal(int senhal, siginfo_t *info, void *ptr) {
int kill_self = 0;
printf("!!! Crash: ");
switch (senhal) {
case SIGHUP:
printf("SIGUP");
break;
case SIGINT:
printf("SIGINT");
break;
case SIGQUIT:
printf("SIGQUIT");
break;
case SIGILL:
printf("SIGILL");
break;
case SIGTRAP:
printf("SIGTRAP");
break;
case SIGFPE:
printf("SIGFPE ");
if (info->si_code == FPE_INTDIV) {
printf("entero div zero");
}
if (info->si_code == FPE_INTOVF) {
printf("entero desbordado");
}
if (info->si_code == FPE_FLTDIV) {
printf("float div zero");
}
if (info->si_code == FPE_FLTOVF) {
printf("float desbordado");
}
if (info->si_code == FPE_FLTUND) {
printf("float desbordado por defecto");
}
if (info->si_code == FPE_FLTRES) {
printf("float inexacto");
}
if (info->si_code == FPE_FLTINV) {
printf("operacion float invalida");
}
if (info->si_code == FPE_FLTSUB) {
printf("subscript fuera de rango");
}
break;
case SIGSEGV:
printf("SIGSEGV");
kill_self = 1;
break;
case SIGTERM:
printf("SIGTERM");
break;
case SIGABRT:
printf("SIGABRT");
break;
default:
printf("%d", senhal);
}
printf("\n");
if (kill_self) {
pid_t parent_pid;
char cadena[256];
parent_pid = getpid();
sprintf(cadena, "kill -9 %d", parent_pid);
system(cadena);
}
// Salir
exit(0);
}
#include <fenv.h>
int feenableexcept();
void Exceptions_Init() {
struct sigaction action;
memset(&action, 0, sizeof(action));
action.sa_sigaction = Exception_Signal;
action.sa_flags = SA_SIGINFO;
sigaction(SIGHUP, &action, 0);
sigaction(SIGINT, &action, 0);
sigaction(SIGQUIT, &action, 0);
sigaction(SIGILL, &action, 0);
sigaction(SIGTRAP, &action, 0);
sigaction(SIGFPE, &action, 0);
sigaction(SIGSEGV, &action, 0);
sigaction(SIGTERM, &action, 0);
sigaction(SIGABRT, &action, 0);
}
#endif
#endif

View File

@@ -1,81 +0,0 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2014-2021 Valeriano Alfonso Rodriguez
#ifndef _UTIL_
#define _UTIL_
#include <stdarg.h>
#include <stdlib.h>
#ifndef bool
typedef int bool;
#endif
#define true 1
#define false 0
/////////////////////////////
// String_Copy
//
// Copies a string.
char *String_Copy(char *str);
/////////////////////////////
// String_CompareCaseInsensitive
//
// Compares a string case insensitive
int String_CompareCaseInsensitive(char *str0, char *str1);
/////////////////////////////
// Time_GetTime
//
// Gets the current time in usecs.
long long Time_GetTime();
/////////////////////////////
// Time_Pause
//
// Pauses the execution for t usecs.
void Time_Pause(int pausa);
/////////////////////////////
// Time_GetTime
//
// Gets the current time in POSIX.
long long Time_GetCurrentTime();
/////////////////////////////
// PrintElapsedTime
//
// Prints the elapsed time (input in microseconds (us))
int PrintElapsedTime(long long time);
/////////////////////////////
// PrintDataSize
//
// Prints the data size (input in bytes)
int PrintDataSize(long long size);
/////////////////////////////
// Print_SetOutFile
//
void Print_SetOutFile(char *fileOut);
/////////////////////////////
// Print
//
// Prints the formated text screen
int Print(char *fmt, ...);
/////////////////////////////
// SetError
// GetError
//
void SetError(char *msg);
char *GetError();
/////////////////////////////
// Exceptions_Init
//
void Exceptions_Init();
#endif

View File

@@ -1,5 +0,0 @@
@echo off
for /r %%v in (test_*.cmd) do call "%%v"
pause

View File

@@ -1,56 +0,0 @@
:: Prepare test
set testName=%~n0
set testDir=tmp\%testName%
IF EXIST %testDir%.A rmdir %testDir%.A /S /Q
IF EXIST %testDir%.B rmdir %testDir%.B /S /Q
IF EXIST %testDir%.txt del %testDir%.txt
echo:Test %testName% started> %testDir%.txt
echo Test %testName% started
IF NOT EXIST tmp md tmp
md %testDir%.A
md %testDir%.B
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
echo:Uno> %testDir%.A\Uno.txt
echo:Dos> %testDir%.A\Dos.txt
..\filesync.exe -sync -dir %testDir%.A -dir %testDir%.B >> %testDir%.txt
del %testDir%.A\Uno.txt
..\filesync.exe -sync -dir %testDir%.A -dir %testDir%.B >> %testDir%.txt
ping 127.0.0.1 -n 2 > nul
echo:UnoRepuesto> %testDir%.A\Uno.txt
..\filesync.exe -sync -dir %testDir%.A -dir %testDir%.B >> %testDir%.txt
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
..\filesync.exe -read %testDir%.A/nodesFile.fs >> %testDir%.txt
..\filesync.exe -read %testDir%.B/nodesFile.fs >> %testDir%.txt
:: Check test results
IF NOT EXIST %testDir%.A\Uno.txt goto error
IF NOT EXIST %testDir%.A\Dos.txt goto error
IF NOT EXIST %testDir%.B\Uno.txt goto error
IF NOT EXIST %testDir%.B\Dos.txt goto error
:: Display test result
goto end
:error
echo:Test %testName% Failed...>> %testDir%.txt
echo Test %testName% Failed...
goto eof
:end
echo:Test %testName% OK!>> %testDir%.txt
echo Test %testName% OK!
:eof
echo:>> %testDir%.txt
echo:
echo:>> %testDir%.txt
echo:

View File

@@ -1,54 +0,0 @@
:: Prepare test
set testName=%~n0
set testDir=tmp\%testName%
IF EXIST %testDir%.A rmdir %testDir%.A /S /Q
IF EXIST %testDir%.B rmdir %testDir%.B /S /Q
IF EXIST %testDir%.txt del %testDir%.txt
echo:Test %testName% started> %testDir%.txt
echo Test %testName% started
IF NOT EXIST tmp md tmp
md %testDir%.A
md %testDir%.B
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
echo:Uno> %testDir%.A\Uno.txt
echo:Dos> %testDir%.A\Dos.txt
..\filesync.exe -sync -dir %testDir%.A -dir %testDir%.B >> %testDir%.txt
md %testDir%.A\dirUno
move %testDir%.A\Uno.txt %testDir%.A\dirUno\Uno.txt >NUL
..\filesync.exe -sync -dir %testDir%.A -dir %testDir%.B >> %testDir%.txt
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
..\filesync.exe -read %testDir%.A/nodesFile.fs >> %testDir%.txt
..\filesync.exe -read %testDir%.B/nodesFile.fs >> %testDir%.txt
:: Check test results
IF EXIST %testDir%.A\Uno.txt goto error
IF NOT EXIST %testDir%.A\dirUno\Uno.txt goto error
IF NOT EXIST %testDir%.A\Dos.txt goto error
IF EXIST %testDir%.B\Uno.txt goto error
IF NOT EXIST %testDir%.B\dirUno\Uno.txt goto error
IF NOT EXIST %testDir%.B\Dos.txt goto error
:: Display test result
goto end
:error
echo:Test %testName% Failed...>> %testDir%.txt
echo Test %testName% Failed...
goto eof
:end
echo:Test %testName% OK!>> %testDir%.txt
echo Test %testName% OK!
:eof
echo:>> %testDir%.txt
echo:
echo:>> %testDir%.txt
echo:

View File

@@ -1,62 +0,0 @@
:: Prepare test
set testName=%~n0
set testDir=tmp\%testName%
IF EXIST %testDir%.A rmdir %testDir%.A /S /Q
IF EXIST %testDir%.B rmdir %testDir%.B /S /Q
IF EXIST %testDir%.txt del %testDir%.txt
echo:Test %testName% started> %testDir%.txt
echo Test %testName% started
IF NOT EXIST tmp md tmp
md %testDir%.A
md %testDir%.B
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
echo:Uno> %testDir%.A\Uno.txt
echo:Dos> %testDir%.A\Dos.txt
..\filesync.exe -sync -dir %testDir%.A -dir %testDir%.B >> %testDir%.txt
md %testDir%.A\dirUno
move %testDir%.A\Uno.txt %testDir%.A\dirUno\Uno.txt >NUL
..\filesync.exe -sync -dir %testDir%.A -dir %testDir%.B >> %testDir%.txt
ping 127.0.0.1 -n 2 > nul
move %testDir%.A\dirUno\Uno.txt %testDir%.A\Uno.txt >NUL
rd %testDir%.A\dirUno
..\filesync.exe -sync -dir %testDir%.A -dir %testDir%.B >> %testDir%.txt
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
..\filesync.exe -read %testDir%.A/nodesFile.fs >> %testDir%.txt
..\filesync.exe -read %testDir%.B/nodesFile.fs >> %testDir%.txt
:: Check test results
IF NOT EXIST %testDir%.A\Uno.txt goto error
IF EXIST %testDir%.A\dirUno goto error
IF EXIST %testDir%.A\dirUno\Uno.txt goto error
IF NOT EXIST %testDir%.A\Dos.txt goto error
IF NOT EXIST %testDir%.B\Uno.txt goto error
IF EXIST %testDir%.B\dirUno goto error
IF EXIST %testDir%.B\dirUno\Uno.txt goto error
IF NOT EXIST %testDir%.B\Dos.txt goto error
:: Display test result
goto end
:error
echo:Test %testName% Failed...>> %testDir%.txt
echo Test %testName% Failed...
goto eof
:end
echo:Test %testName% OK!>> %testDir%.txt
echo Test %testName% OK!
:eof
echo:>> %testDir%.txt
echo:
echo:>> %testDir%.txt
echo:

View File

@@ -1,54 +0,0 @@
:: Prepare test
set testName=%~n0
set testDir=tmp\%testName%
IF EXIST %testDir%.A rmdir %testDir%.A /S /Q
IF EXIST %testDir%.B rmdir %testDir%.B /S /Q
IF EXIST %testDir%.txt del %testDir%.txt
echo:Test %testName% started> %testDir%.txt
echo Test %testName% started
IF NOT EXIST tmp md tmp
md %testDir%.A
md %testDir%.B
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
echo:Uno> %testDir%.A\Uno.txt
echo:Dos> %testDir%.A\Dos.txt
..\filesync.exe -sync -dir %testDir%.A -dir %testDir%.B >> %testDir%.txt
ping 127.0.0.1 -n 2 > nul
echo:Updated>> %testDir%.A\Uno.txt
..\filesync.exe -sync -dir %testDir%.A -dir %testDir%.B >> %testDir%.txt
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
..\filesync.exe -read %testDir%.A/nodesFile.fs >> %testDir%.txt
..\filesync.exe -read %testDir%.B/nodesFile.fs >> %testDir%.txt
:: Check test results
IF NOT EXIST %testDir%.A\Uno.txt goto error
IF NOT EXIST %testDir%.A\Dos.txt goto error
IF NOT EXIST %testDir%.B\Uno.txt goto error
IF NOT EXIST %testDir%.B\Dos.txt goto error
FC %testDir%.A\Uno.txt %testDir%.B\Uno.txt >NUL || goto error
:: Display test result
goto end
:error
echo:Test %testName% Failed...>> %testDir%.txt
echo Test %testName% Failed...
goto eof
:end
echo:Test %testName% OK!>> %testDir%.txt
echo Test %testName% OK!
:eof
echo:>> %testDir%.txt
echo:
echo:>> %testDir%.txt
echo: