Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 577e441929 | |||
| 18d22874c4 | |||
| b5603145a8 | |||
| b8ed4ffeea |
@@ -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
|
|
||||||
...
|
|
||||||
|
|
||||||
25
.gitignore
vendored
25
.gitignore
vendored
@@ -1,25 +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
|
|
||||||
|
|
||||||
/.issues/
|
|
||||||
50
.vscode/c_cpp_properties.json
vendored
50
.vscode/c_cpp_properties.json
vendored
@@ -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
25
.vscode/launch.json
vendored
@@ -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
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"files.associations": {
|
|
||||||
"*.h": "c"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
21
LICENSE.txt
21
LICENSE.txt
@@ -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
102
Makefile
@@ -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)
|
|
||||||
|
|
||||||
72
README.md
72
README.md
@@ -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
0
issues/.keep
Normal file
6
issues/1.yaml
Normal file
6
issues/1.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
id: 1
|
||||||
|
title: Catalogo de directorios sincronizables en cada volumen
|
||||||
|
state: open
|
||||||
|
tags: enhancement
|
||||||
|
|
||||||
|
Catalogo de directorios sincronizables en cada volumen. Para agilizar utilización.
|
||||||
6
issues/2.yaml
Normal file
6
issues/2.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
id: 2
|
||||||
|
title: Corregir bug con caracteres especiales (no ASCII-7) en Windows
|
||||||
|
state: open
|
||||||
|
tags: bug
|
||||||
|
|
||||||
|
|
||||||
6
issues/3.yaml
Normal file
6
issues/3.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
id: 3
|
||||||
|
title: Mejorar informacion de progreso
|
||||||
|
state: open
|
||||||
|
tags: enhancement
|
||||||
|
|
||||||
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
70
src/crc.c
70
src/crc.c
@@ -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);
|
|
||||||
}
|
|
||||||
13
src/crc.h
13
src/crc.h
@@ -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
|
|
||||||
596
src/filenode.c
596
src/filenode.c
@@ -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);
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
422
src/fileutil.c
422
src/fileutil.c
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
376
src/main.c
376
src/main.c
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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 = ¶meterOperations[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++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
355
src/util.c
355
src/util.c
@@ -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
|
|
||||||
|
|
||||||
81
src/util.h
81
src/util.h
@@ -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
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
@echo off
|
|
||||||
|
|
||||||
for /r %%v in (test_*.cmd) do call "%%v"
|
|
||||||
|
|
||||||
pause
|
|
||||||
@@ -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 [7mTest %testName% started[0m
|
|
||||||
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 [41mTest %testName% Failed...[0m
|
|
||||||
goto eof
|
|
||||||
:end
|
|
||||||
echo:Test %testName% OK!>> %testDir%.txt
|
|
||||||
echo [42mTest %testName% OK![0m
|
|
||||||
:eof
|
|
||||||
echo:>> %testDir%.txt
|
|
||||||
echo:
|
|
||||||
echo:>> %testDir%.txt
|
|
||||||
echo:
|
|
||||||
@@ -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 [7mTest %testName% started[0m
|
|
||||||
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 [41mTest %testName% Failed...[0m
|
|
||||||
goto eof
|
|
||||||
:end
|
|
||||||
echo:Test %testName% OK!>> %testDir%.txt
|
|
||||||
echo [42mTest %testName% OK![0m
|
|
||||||
:eof
|
|
||||||
echo:>> %testDir%.txt
|
|
||||||
echo:
|
|
||||||
echo:>> %testDir%.txt
|
|
||||||
echo:
|
|
||||||
@@ -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 [7mTest %testName% started[0m
|
|
||||||
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 [41mTest %testName% Failed...[0m
|
|
||||||
goto eof
|
|
||||||
:end
|
|
||||||
echo:Test %testName% OK!>> %testDir%.txt
|
|
||||||
echo [42mTest %testName% OK![0m
|
|
||||||
:eof
|
|
||||||
echo:>> %testDir%.txt
|
|
||||||
echo:
|
|
||||||
echo:>> %testDir%.txt
|
|
||||||
echo:
|
|
||||||
@@ -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 [7mTest %testName% started[0m
|
|
||||||
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 [41mTest %testName% Failed...[0m
|
|
||||||
goto eof
|
|
||||||
:end
|
|
||||||
echo:Test %testName% OK!>> %testDir%.txt
|
|
||||||
echo [42mTest %testName% OK![0m
|
|
||||||
:eof
|
|
||||||
echo:>> %testDir%.txt
|
|
||||||
echo:
|
|
||||||
echo:>> %testDir%.txt
|
|
||||||
echo:
|
|
||||||
Reference in New Issue
Block a user