2
0
mirror of https://github.com/meganz/MEGAcmd synced 2025-08-22 09:57:09 +00:00

Merge branch 'develop' into feature/CMD-224_Expose_FUSE_functionalit_updated_wrft_develop_and_cmake_build

This commit is contained in:
Diego Ximenez 2025-02-25 20:14:37 +01:00
commit af2b2dcad4
No known key found for this signature in database
GPG Key ID: 8E94095CB5DBCBA0
116 changed files with 3548 additions and 5779 deletions

View File

@ -11,6 +11,7 @@ body:
label: "MEGAcmd version"
description: "Which version of MEGAcmd did you encountered this issue? (Can be looked up using the `version` command)"
options:
- 2.0.0
- 1.7.0
- 1.6.3
- 1.6.2

3
.gitignore vendored
View File

@ -66,6 +66,9 @@ megacmd_src_file_list.h
# macOS packaging files and artifacts
Info.plist
# Synology packaging files and artifacts
/build/SynologyNAS/packages
# Git
*_BACKUP_*
*_BASE_*

View File

@ -9,8 +9,8 @@ execute_process(
OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(MEGACMD_MAJOR_VERSION 1)
set(MEGACMD_MINOR_VERSION 7)
set(MEGACMD_MAJOR_VERSION 2)
set(MEGACMD_MINOR_VERSION 0)
set(MEGACMD_MICRO_VERSION 0)
## Configure megacmdversion.h
@ -28,6 +28,7 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/sdk/cmake/modules) # Mod
set(VCPKG_ROOT "${CMAKE_CURRENT_LIST_DIR}/../vcpkg" CACHE PATH "If set, it will build and use the VCPKG packages defined in the manifest file")
include(detect_host_architecture)
if (WIN32)
execute_process(
@ -183,6 +184,7 @@ add_library(LMEGAcmdCommonUtils STATIC)
add_source_and_corresponding_header_to_target(LMEGAcmdCommonUtils
PUBLIC
"${ProjectDir}/src/megacmdcommonutils.cpp"
"${ProjectDir}/src/megacmd_utf8.cpp"
)
add_library(LMegacmdServer STATIC)
@ -191,7 +193,6 @@ add_source_and_corresponding_header_to_target(LMegacmdServer
"${ProjectDir}/src/megacmd.cpp"
"${ProjectDir}/src/megacmdexecuter.cpp"
"${ProjectDir}/src/megacmd_events.cpp"
"${ProjectDir}/src/megacmdtransfermanager.cpp"
"${ProjectDir}/src/megacmdlogger.cpp"
"${ProjectDir}/src/megacmdsandbox.cpp"
"${ProjectDir}/src/megacmdutils.cpp"
@ -221,6 +222,23 @@ target_compile_definitions(LMegacmdServer
$<$<BOOL:${USE_PCRE}>:USE_PCRE>
)
if (NOT WIN32)
if (ENABLE_ASAN)
add_compile_options("-fsanitize=address" "-fno-omit-frame-pointer" "-fno-common")
link_libraries("-fsanitize=address")
endif()
if (ENABLE_UBSAN)
add_compile_options("-fsanitize=undefined" "-fno-omit-frame-pointer")
link_libraries("-fsanitize=undefined")
endif()
if (ENABLE_TSAN)
add_compile_options("-fsanitize=thread" "-fno-omit-frame-pointer")
link_libraries("-fsanitize=thread")
endif()
endif()
if (APPLE)
set(executablesType MACOSX_BUNDLE)
endif()
@ -317,6 +335,7 @@ if (ENABLE_MEGACMD_TESTS)
add_executable(mega-cmd-tests-integration ${executablesType})
add_source_and_corresponding_header_to_target(mega-cmd-tests-integration PRIVATE
"${ProjectDir}/tests/integration/BasicTests.cpp"
"${ProjectDir}/tests/integration/CatTests.cpp"
"${ProjectDir}/tests/integration/ExportTests.cpp"
"${ProjectDir}/tests/integration/SyncIssuesTests.cpp"
"${ProjectDir}/tests/integration/SyncIgnoreTests.cpp"

View File

@ -196,11 +196,11 @@ And for **bash completion**, source `megacmd_completion.sh`:
```
source /Applications/MEGAcmd.app/Contents/macOS/megacmd_completion.sh
```
*Note for macOS Catalina or above*: since Catalina, macOS uses `zsh` as default shell. If you want to have auto completion, we strongly recommend you to use `bash` shell (just execute `bash` in your terminal).
## NAS systems
Currently we have build scripts for **Synology** and **QNAP**, which can be found in the `build/<system>` folder along with instructions on how to set up the build. Typically this results in a 'package' which can then be manually installed in the NAS. To use MEGAcmd on those systems, ssh into the device and run the commands as normal (having first added their folder to your `PATH` variable).
Currently we have build scripts for **Synology**, which can be found in the `build/SynologyNAS` folder along with instructions on how to set up the build. Typically this results in a 'package' which can then be manually installed in the NAS. To use MEGAcmd on those systems, ssh into the device and run the commands as normal (having first added their folder to your `PATH` variable).
*Important note for macOS Catalina or above: since Catalina, macOS uses `zsh` as default shell. If you want to have auto completion, we strongly recommend you to use `bash` shell (just execute `bash` in your terminal).
# Features:
## Autocompletion:

View File

@ -1,6 +1,6 @@
# MEGAcmd User Guide
This document relates to MEGAcmd version 1.7.0. It contains introductory information and the [Command Summary](#command-summary), with links to detailed command descriptions.
This document relates to MEGAcmd version 2.0.0. It contains introductory information and the [Command Summary](#command-summary), with links to detailed command descriptions.
### What is it
A command line tool to work with your MEGA account and files. The intent is to offer all the MEGA account functionality via command line. You can run it in [interactive](#interactive) mode where it processes all commands directly, or you can run its [scriptable](#scriptable) commands from your favourite Linux or Mac shell such as bash, or you can even run its commands in a Windows command prompt. And of course you can write scripts using those scriptable commands.
@ -254,7 +254,7 @@ Verbosity: You can increase the amount of information given by any command by pa
* [`help`](contrib/docs/commands/help.md)`[-f|-ff|--non-interactive|--upgrade|--paths] [--show-all-options]` Prints list of commands
* [`https`](contrib/docs/commands/https.md)`[on|off]` Shows if HTTPS is used for transfers. Use "https on" to enable it.
* [`info`](contrib/docs/commands/info.md)`remotepath1 remotepath2 ...` Prints media info of remote files
* [`log`](contrib/docs/commands/log.md)`[-sc] level` Prints/Modifies the current logs level
* [`log`](contrib/docs/commands/log.md)`[-sc] level` Prints/Modifies the log level
* [`permissions`](contrib/docs/commands/permissions.md)`[(--files|--folders) [-s XXX]]` Shows/Establish default permissions for files and folders created by MEGAcmd.
* [`proxy`](contrib/docs/commands/proxy.md)`[URL|--auto|--none] [--username=USERNAME --password=PASSWORD]` Show or sets proxy configuration
* [`psa`](contrib/docs/commands/psa.md)`[--discard]` Shows the next available Public Service Announcement (PSA)

View File

@ -51,9 +51,9 @@ WORKDIR /usr/src/megacmd
#ENV CXX "ccache g++-12"
ENV CCACHE_DIR /tmp/ccache
ENV VCPKG_DEFAULT_BINARY_CACHE /tmp/vcpkgcache
ARG ENABLE_ASAN=ON
ARG ENABLE_UBSAN=ON
ARG ENABLE_TSAN=OFF
ARG ENABLE_asan=OFF
ARG ENABLE_ubsan=OFF
ARG ENABLE_tsan=OFF
ARG ENABLE_MEGACMD_TESTS=ON
COPY --from=src /usr/src/megacmd /usr/src/megacmd
@ -73,10 +73,10 @@ RUN --mount=type=cache,target=/tmp/ccache \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_VERBOSE_MAKEFILE=ON \
-D ENABLE_ASAN=${ENABLE_ASAN} -D \
ENABLE_UBSAN=${ENABLE_UBSAN} -D \
ENABLE_TSAN=${ENABLE_TSAN} -D \
ENABLE_MEGACMD_TESTS=${ENABLE_MEGACMD_TESTS} \
-DENABLE_ASAN=${ENABLE_asan} \
-DENABLE_UBSAN=${ENABLE_ubsan} \
-DENABLE_TSAN=${ENABLE_tsan} \
-DENABLE_MEGACMD_TESTS=${ENABLE_MEGACMD_TESTS} \
WITH_FUSE=ON \
&& cmake --build /tmp/build -j$(nproc) --target mega-cmd mega-cmd-server mega-exec \
mega-cmd-updater mega-cmd-tests-integration mega-cmd-tests-unit \

View File

@ -1,38 +0,0 @@
# How to build MEGAcmd for QNAP NAS drives.
We follow the cross compiling system provided by QNAP, described at (https://www.qnap.com/event/dev/en/p_qdk.php#qdk_btn1_show)
Tested with ubuntu 16.04 as the build machine - others may work but that one does for sure.
There are two main steps. First, cross-compiling the executables, which can be done on Ubuntu 16.04 for example. Second, preparing a QNAP package including those binaries, which must be done on a QNAP NAS device.
# Cross-compiling
This example is for ARM, x86 and x86_64 will be similar.
Cross compiling machine requirements:
- **Most or all commands need to be run as 'sudo'**.
- dos2unix
- cross compiler from QNAP: install by following QNAP instructions to unzip one of these (available from qnap) in your `/opt/cross-project` folder
- `cross-project-arm-20110901.tar.gz` (for x19 platform) or
- `TS-x31+_cross-project-arm_al.20150909.tar.gz` (for x41+ platform)
Then copy or git clone the MEGAcmd project to /opt/cross-project/qnap/MEGAcmd. The sdk must be copied or cloned to the 'sdk' subfolder of that.
From the MEGAcmd folder, execute: <p>
`./build/QNAP/build-marvell` (for x19 ARM platform) <p>
`./build/QNAP/build-linaro` (for x41+ ARM platform) <p>
which will result in the binaries and scripts ending up in the MEGAcmd/install folder and being copied to the megacmdpkg folder ready to build the package.
# Building a QNAP package
This must be done on a QNAP NAS as it requires their QDK package. Download QDK_2.2.16.qpkg and use the QNAP package manager to manually install that.
Next, use `scp` or a similar tool to copy the MEGAcmd/build/QNAP_NAS/megacmdpkg folder to the NAS, followed by the contents of the MEGAcmd/install folder:
`scp -r build/QNAP_NAS/megacmdpkg admin@10.12.0.248:/share/CACHEDEV1_DATA/.qpkg/QDK/`
On the NAS, using ssh or similar, run the `qbuild` command from the megacmdpkg folder. The package will be built and put in the 'build' subfolder.

View File

@ -1,12 +0,0 @@
#!/usr/bin/env bash
for architecture in arm x; do
for width in 32 64; do
platform=$architecture$width
result=OK
./build-$platform.sh &> $platform.log || result=FAIL
echo "$platform: $result"
done
done

View File

@ -1,12 +0,0 @@
#!/usr/bin/env bash
export ARCH=arm
export BUILD_ARCH=32
export HOST=arm-linux-gnueabihf
export PATH=/opt/cross-project/arm/linaro/bin:$PATH
export ConfigOpt="--host $HOST"
export PLATFORM=arm-x41
source build-common.sh
build_all

View File

@ -1,12 +0,0 @@
#!/usr/bin/env bash
export ARCH=aarch64
export BUILD_ARCH=64
export HOST=aarch64-QNAP-linux-gnu
export PATH=/opt/cross-project/$HOST/bin:$PATH
export ConfigOpt="--host $HOST"
export PLATFORM=arm_64
source build-common.sh
build_all

View File

@ -1,263 +0,0 @@
#!/usr/bin/env bash
build_all()
{
# Purge prior build artifacts.
clean || die "Couldn't remove prior build artifacts"
# Make sure AR, CC and friends are correctly set.
fix_environment
# Perform the build.
build_sdk || die "Couldn't build the SDK"
build_cmd || die "Couldn't build MEGAcmd"
# Package the build.
package || die "Unable to create package"
}
build_cmd()
{
local prefix="$PWD/sdk/sdk_build/install"
local flag_gtest="--with-gtest=$prefix"
local flag_freeimage="--with-freeimage=$prefix"
local flag_tests="--enable-tests"
local result=0
./autogen.sh
result=$?
if [ $result -ne 0 ]; then
return $result
fi
use_freeimage || flag_freeimage="--without-freeimage"
if ! use_gtest; then
flag_gtest="--without-gtest"
flag_tests="--disable-tests"
fi
env AR=$AR \
ARCH=$ARCH \
CC=$CC \
CFLAGS="$(compiler_flags $CFLAGS)" \
CPPFLAGS="$(preprocessor_flags $CFLAGS $CPPFLAGS)" \
CXX=$CXX \
CXXFLAGS="$(compiler_flags $CXXFLAGS)" \
LD=$LD \
NM=$NM \
OBJCXX=$CXX \
OBJDUMP=$OBJDUMP \
RANLIB=$RANLIB \
STRIP=$STRIP \
./configure $ConfigOpt \
--disable-curl-checks \
--disable-examples \
--disable-shared \
--enable-inotify \
--enable-static \
--enable-sync \
--with-cares="$prefix" \
--with-cryptopp="$prefix" \
--with-curl="$prefix" \
--with-libmediainfo="$prefix" \
--with-libuv="$prefix" \
--with-libzen="$prefix" \
--with-openssl="$prefix" \
--with-readline="$prefix" \
--with-sodium="$prefix" \
--with-sqlite="$prefix" \
--with-termcap="$prefix" \
--with-zlib="$prefix" \
--without-ffmpeg \
--without-libraw \
--without-pcre \
--without-pdfium \
$flag_gtest \
$flag_freeimage \
$flag_tests
result=$?
if [ $result -ne 0 ]; then
return $result
fi
make
result=$?
return $result
}
build_sdk()
{
local flag_configure_only="-c"
local flag_cross_compiling="-X"
local flag_disable_examples="-n"
local flag_disable_freeimage=""
local flag_enable_cares="-e"
local flag_enable_cryptopp="-q"
local flag_enable_curl="-g"
local flag_enable_megaapi="-a"
local flag_enable_readline="-R"
local flag_enable_sodium="-u"
local flag_enable_tests="-T"
local flag_enable_uv="-v"
local flag_openssl_assembly=""
local flag_openssl_compiler="linux-generic$BUILD_ARCH"
local result=0
pushd sdk || return
mkdir -p sdk_build/build || return
mkdir -p sdk_build/install/lib || return
use_assembly || flag_openssl_assembly="no-asm"
use_gtest || flag_enable_tests=""
use_freeimage || flag_disable_freeimage="-f"
env AR=$AR \
ARCH=$ARCH \
CC=$CC \
CFLAGS="$(compiler_flags $CFLAGS)" \
CPPFLAGS="$(preprocessor_flags $CFLAGS $CPPFLAGS)" \
CXX=$CXX \
CXXFLAGS="$(compiler_flags $CXXFLAGS)" \
LD=$LD \
NM=$NM \
OBJCXX=$CXX \
OBJDUMP=$OBJDUMP \
RANLIB=$RANLIB \
STRIP=$STRIP \
./contrib/build_sdk.sh -C "$ConfigOpt" \
-O "$flag_openssl_compiler" \
-S "$flag_openssl_assembly" \
$flag_configure_only \
$flag_cross_compiling \
$flag_disable_examples \
$flag_disable_freeimage \
$flag_enable_cares \
$flag_enable_cryptopp \
$flag_enable_curl \
$flag_enable_megaapi \
$flag_enable_readline \
$flag_enable_sodium \
$flag_enable_tests \
$flag_enable_uv
local result=$?
popd
return $result
}
clean()
{
if [ -f Makefile ]; then
make distclean || return
fi
rm -rf $(package_directory)
}
die()
{
echo "ERROR: $1"
exit 1
}
compiler_flags()
{
local result="$*"
# Strip preprocessor flags.
result="$(echo $result | sed -e 's/ *-[DI][^ ]\+//g')"
# Strip NEON flags (as it breaks freeimage.)
result="$(echo $result | sed -e 's/-mfpu=neon[^ ]*//g')"
# GCC's ARM ABI changed between 7.0 and 7.1.
result="$result -Wno-psabi"
echo "$result"
}
fix_environment()
{
export CC=$HOST-gcc
export CXX=$HOST-g++
for tool in ar ld nm ranlib strip; do
export ${tool^^}=$HOST-$tool
done
}
package()
{
directory=$(package_directory)
mkdir -p $directory || return
cp mega-cmd \
mega-cmd-server \
mega-exec \
src/client/mega-* \
$directory \
|| return
sed -i -e "s/^QPKG_VER=.*/QPKG_VER=\"$(version)\"/" \
$(package_root)/qpkg.cfg
}
package_directory()
{
echo "$(package_root)/$PLATFORM"
}
package_root()
{
echo build/QNAP_NAS/megacmdpkg
}
preprocessor_flags()
{
echo "$*" | grep -o -E -- '-[DI][^ ]+' | xargs
}
use_assembly()
{
test "$ARCH" != "x86_64"
}
use_gtest()
{
false
}
use_freeimage()
{
true
}
version()
{
major=$(version_component MAJOR)
minor=$(version_component MINOR)
micro=$(version_component MICRO)
echo "$major.$minor.$micro"
}
version_component()
{
sed -ne "s/.*$1_VERSION \([0-9]\+\).*/\1/p" \
src/megacmdversion.h
}
# Make sure we're at the root of the MEGAcmd source tree.
cd ../..

View File

@ -1,12 +0,0 @@
#!/usr/bin/env bash
export ARCH=x86
export BUILD_ARCH=32
export HOST=i686-QNAP-linux-gnu
export PATH=/opt/cross-project/CT/$HOST/cross-tools/bin:$PATH
export ConfigOpt="--host $HOST"
export PLATFORM=$ARCH
source build-common.sh
build_all

View File

@ -1,12 +0,0 @@
#!/usr/bin/env bash
export ARCH=x86_64
export BUILD_ARCH=64
export HOST=x86_64-QNAP-linux-gnu
export PATH=/opt/cross-project/CT/$HOST/cross-tools/bin:$PATH
export ConfigOpt="--host $HOST"
export PLATFORM=$ARCH
source build-common.sh
build_all

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -1,141 +0,0 @@
######################################################################
# List of available definitions (it's not necessary to uncomment them)
######################################################################
###### Command definitions #####
#CMD_AWK="/bin/awk"
#CMD_CAT="/bin/cat"
#CMD_CHMOD="/bin/chmod"
#CMD_CHOWN="/bin/chown"
#CMD_CP="/bin/cp"
#CMD_CUT="/bin/cut"
#CMD_DATE="/bin/date"
#CMD_ECHO="/bin/echo"
#CMD_EXPR="/usr/bin/expr"
#CMD_FIND="/usr/bin/find"
#CMD_GETCFG="/sbin/getcfg"
#CMD_GREP="/bin/grep"
#CMD_GZIP="/bin/gzip"
#CMD_HOSTNAME="/bin/hostname"
#CMD_LN="/bin/ln"
#CMD_LOG_TOOL="/sbin/log_tool"
#CMD_MD5SUM="/bin/md5sum"
#CMD_MKDIR="/bin/mkdir"
#CMD_MV="/bin/mv"
#CMD_RM="/bin/rm"
#CMD_RMDIR="/bin/rmdir"
#CMD_SED="/bin/sed"
#CMD_SETCFG="/sbin/setcfg"
#CMD_SLEEP="/bin/sleep"
#CMD_SORT="/usr/bin/sort"
#CMD_SYNC="/bin/sync"
#CMD_TAR="/bin/tar"
#CMD_TOUCH="/bin/touch"
#CMD_WGET="/usr/bin/wget"
#CMD_WLOG="/sbin/write_log"
#CMD_XARGS="/usr/bin/xargs"
#CMD_7Z="/usr/local/sbin/7z"
#
###### System definitions #####
#SYS_EXTRACT_DIR="$(pwd)"
#SYS_CONFIG_DIR="/etc/config"
#SYS_INIT_DIR="/etc/init.d"
#SYS_STARTUP_DIR="/etc/rcS.d"
#SYS_SHUTDOWN_DIR="/etc/rcK.d"
#SYS_RSS_IMG_DIR="/home/httpd/RSS/images"
#SYS_QPKG_DATA_FILE_GZIP="./data.tar.gz"
#SYS_QPKG_DATA_FILE_BZIP2="./data.tar.bz2"
#SYS_QPKG_DATA_FILE_7ZIP="./data.tar.7z"
#SYS_QPKG_DATA_CONFIG_FILE="./conf.tar.gz"
#SYS_QPKG_DATA_MD5SUM_FILE="./md5sum"
#SYS_QPKG_DATA_PACKAGES_FILE="./Packages.gz"
#SYS_QPKG_CONFIG_FILE="$SYS_CONFIG_DIR/qpkg.conf"
#SYS_QPKG_CONF_FIELD_QPKGFILE="QPKG_File"
#SYS_QPKG_CONF_FIELD_NAME="Name"
#SYS_QPKG_CONF_FIELD_VERSION="Version"
#SYS_QPKG_CONF_FIELD_ENABLE="Enable"
#SYS_QPKG_CONF_FIELD_DATE="Date"
#SYS_QPKG_CONF_FIELD_SHELL="Shell"
#SYS_QPKG_CONF_FIELD_INSTALL_PATH="Install_Path"
#SYS_QPKG_CONF_FIELD_CONFIG_PATH="Config_Path"
#SYS_QPKG_CONF_FIELD_WEBUI="WebUI"
#SYS_QPKG_CONF_FIELD_WEBPORT="Web_Port"
#SYS_QPKG_CONF_FIELD_SERVICEPORT="Service_Port"
#SYS_QPKG_CONF_FIELD_SERVICE_PIDFILE="Pid_File"
#SYS_QPKG_CONF_FIELD_AUTHOR="Author"
#SYS_QPKG_CONF_FIELD_RC_NUMBER="RC_Number"
## The following variables are assigned values at run-time.
#SYS_HOSTNAME=$($CMD_HOSTNAME)
## Data file name (one of SYS_QPKG_DATA_FILE_GZIP, SYS_QPKG_DATA_FILE_BZIP2,
## or SYS_QPKG_DATA_FILE_7ZIP)
#SYS_QPKG_DATA_FILE=
## Base location.
#SYS_QPKG_BASE=""
## Base location of QPKG installed packages.
#SYS_QPKG_INSTALL_PATH=""
## Location of installed software.
#SYS_QPKG_DIR=""
## If the QPKG should be enabled or disabled after the installation/upgrade.
#SYS_QPKG_SERVICE_ENABLED=""
## Architecture of the device the QPKG is installed on.
#SYS_CPU_ARCH=""
## Name and location of system shares
#SYS_PUBLIC_SHARE=""
#SYS_PUBLIC_PATH=""
#SYS_DOWNLOAD_SHARE=""
#SYS_DOWNLOAD_PATH=""
#SYS_MULTIMEDIA_SHARE=""
#SYS_MULTIMEDIA_PATH=""
#SYS_RECORDINGS_SHARE=""
#SYS_RECORDINGS_PATH=""
#SYS_USB_SHARE=""
#SYS_USB_PATH=""
#SYS_WEB_SHARE=""
#SYS_WEB_PATH=""
## Path to ipkg or opkg package tool if installed.
#CMD_PKG_TOOL=
#
######################################################################
# All package specific functions shall call 'err_log MSG' if an error
# is detected that shall terminate the installation.
######################################################################
#
######################################################################
# Define any package specific operations that shall be performed when
# the package is removed.
######################################################################
#PKG_PRE_REMOVE="{
#}"
#
#PKG_MAIN_REMOVE="{
#}"
#
#PKG_POST_REMOVE="{
#}"
#
######################################################################
# Define any package specific initialization that shall be performed
# before the package is installed.
######################################################################
#pkg_init(){
#}
#
######################################################################
# Define any package specific requirement checks that shall be
# performed before the package is installed.
######################################################################
#pkg_check_requirement(){
#}
#
######################################################################
# Define any package specific operations that shall be performed when
# the package is installed.
######################################################################
#pkg_pre_install(){
#}
#
#pkg_install(){
#}
pkg_post_install(){
/usr/sbin/dbus-uuidgen --ensure=/etc/machine-id
}

View File

@ -1,2 +0,0 @@
#!/bin/sh
exit 0

View File

@ -1,29 +0,0 @@
# Name of the packaged application.
QPKG_NAME="MEGAcmd"
# Name of the display application.
QPKG_DISPLAY_NAME="MEGAcmd"
# Version of the packaged application.
QPKG_VER="1.7.0"
# Author or maintainer of the package
QPKG_AUTHOR="Mega.nz"
# One-line description of the packaged application
QPKG_SUMMARY="Synchronise or backup your NAS folders to Mega.nz"
# Preferred number in start/stop sequence.
QPKG_RC_NUM="101"
# Init-script used to control the start and stop of the installed application.
QPKG_SERVICE_PROGRAM="MEGAcmd.sh"
# Relative path to web interface
QPKG_WEBUI="/MEGAcmd/"
# Port number for the web interface.
QPKG_WEB_PORT="-1"
#Desktop Application (since 4.1)
# Set value to 1 means to open the QPKG's Web UI inside QTS desktop instead of new window.
QPKG_DESKTOP_APP="1"
# Min/Max QTS version requirement
QTS_MINI_VERSION="4.3.6"
QTS_MAX_VERSION="6.0.0"

View File

@ -1,56 +0,0 @@
#!/bin/sh
service_start()
{
web_config_add
web_config_reload
}
service_stop()
{
web_config_remove
web_config_reload
}
web_config_add()
{
local getcfg="/sbin/getcfg"
local name="MEGAcmd"
local conf="/etc/config/qpkg.conf"
local root="$($getcfg $name Install_Path -f $conf)"
ln -sf $root /home/httpd/cgi-bin/qpkg
ln -sf $root/web/apache-megacmd.conf /etc/default_config/apache/extra
}
web_config_reload()
{
/etc/init.d/thttpd.sh reload
/etc/init.d/stunnel.sh reload
}
web_config_remove()
{
rm -f /etc/default_config/apache/extra/apache-megacmd.conf
rm -f /home/httpd/cgi-bin/qpkg/MEGAcmd
}
case "$1" in
start)
service_start
;;
stop)
service_stop
;;
restart)
service_stop
service_start
;;
*)
echo "Usage: $@ {start|stop|restart}"
exit 1
;;
esac
exit 0

View File

@ -1,7 +0,0 @@
<IfModule alias_module>
Alias /cgi-bin/MEGAcmd "/home/httpd/cgi-bin/qpkg/MEGAcmd/web"
Alias /MEGAcmd "/home/httpd/cgi-bin/qpkg/MEGAcmd/web"
ProxyPass /MEGAcmd !
ProxyPass /cgi-bin/MEGAcmd !
</IfModule>

View File

@ -1,72 +0,0 @@
<html>
<head>
<title>Welcome to MEGAcmd</title>
<link rel="icon" href="https://mega.nz/favicon.ico?v=3" type="image/x-icon" />
</head>
<body>
MEGAcmd is a command line tool. Now that it is installed, please connect to your QNAP NAS drive with ssh, PuTTY, or similar. The executables are at %%%.
In order for the scripts to work, please add that path to your PATH. Please refer to the built-in help or to the <a href="https://github.com/meganz/MEGAcmd/blob/master/UserGuide.md" target="_blank">User Guide</a>.
<p>
Here is an example session:
<p>
<tt>
<PRE>
login as: admin
admin@10.12.0.248's password:
[~] # export PATH=/share/CACHEDEV1_DATA/.qpkg/MEGAcmd:$PATH
[~] # mega-cmd
.=============================================================================.
| __ __ _____ ____ _ _ |
| | \/ | ___|/ ___| / \ ___ _ __ ___ __| | |
| | |\/| | \ / | _ / _ \ / __| '_ ` _ \ / _` | |
| | | | | /__\ |_| |/ ___ \ (__| | | | | | (_| | |
| |_| |_|____|\____/_/ \_\___|_| |_| |_|\__,_| |
| |
| Welcome to MEGAcmd! A Command Line Interactive and Scriptable |
| Application to interact with your MEGA account |
| This is a BETA version, it might not be bug-free. |
| Also, the signature/output of the commands may change in a future. |
| Please write to support@mega.nz if you find any issue or |
| have any suggestion concerning its functionalities. |
| Enter "help --non-interactive" to learn how to use MEGAcmd with scripts. |
| Enter "help" for basic info and a list of available commands. |
`=============================================================================&#180;
[Initiating server in background. Log: /root/.megaCmd/megacmdserver.log]
MEGA CMD&gt; help
Here is the list of available commands and their usage
Use "help -f" to get a brief description of the commands
You can get further help on a specific command with "command" --help
Alternatively, you can use "help" -ff to get a complete description of all commands
Use "help --non-interactive" to learn how to use MEGAcmd with scripts
Use "help --upgrade" to learn about the limitations and obtaining PRO accounts
Commands:
attr graphics preview
backup help put
cancel https pwd
cd import quit
clear invite reload
completion ipc rm
confirm killsession session
confirmcancel lcd share
cp log showpcr
debug login signup
deleteversions logout speedlimit
du lpwd sync
errorcode ls thumbnail
exclude masterkey transfers
exit mkdir userattr
export mount users
find mv version
ftp passwd webdav
get permissions whoami
Verbosity: You can increase the amount of information given by any command by passing "-v" ("-vv", "-vvv", ...)
MEGA CMD&gt;
</PRE>
</tt>
</body>
</html>

View File

@ -1,41 +1,34 @@
# How to build MEGAcmd for Synology NAS drives.
We follow the cross compiling system provided by Synology, described in their [developer-guide.pdf](https://global.download.synology.com/download/Document/DeveloperGuide/DSM_Developer_Guide.pdf) (also at https://originhelp.synology.com/developer-guide/getting_started/index.html).
Tested with ubuntu 16.04 as the build machine - others may work but that one does for sure.
We use docker to cross-compile MEGAcmd for Synology. To build for a specific platform, run:
```
docker build -t megacmd-dms-build-env -f $PWD/build/SynologyNAS/synology-cross-build.dockerfile $PWD --build-arg PLATFORM=<platform>
```
The `-t` argument tags the container with a name, whereas `-f` specifies the dockerfile. Note that the working directory has to be the MEGAcmd repository.
**All commands need to be run as 'sudo'**. We are going to set up a root folder /toolkit, and work out of that. The cross-compile system uses chroot to build inside a subfolder of that.
The possible platforms are:
```
alpine alpine4k apollolake armada37xx armada38x avoton broadwell broadwellnk broadwellnkv2 broadwellntbap bromolow braswell denverton epyc7002 geminilake grantley kvmx64 monaco purley r1000 rtd1296 rtd1619b v1000
```
Copy this folder tree into /toolkit
`cp -r ...git.../MEGAcmd/build/SynologyNAS/toolkit /`
`cd /toolkit`
After building successfully, we need to run the container so we can extract the generated package. To do so, run:
```
docker run -d --name megacmd-dms megacmd-dms-build-env
```
Then, copy the package folder to the current directory with:
```
docker cp megacmd-dms:/image/<platform> .
```
After copying, we can stop and remove the container if needed:
```
docker rm -f megacmd-dms
```
Copy the MEGACmd folder (and sdk subfolder) into it also. The sdk should already be in the 'sdk' subfolder of MEGAcmd
`cp -r ...git.../MEGAcmd /toolkit/source/MEGAcmd/`
The script `build/SynologyNAS/generate_pkg.sh` automates all of these steps, creating the necessary docker container, extracting the package from it, and deleting it afterwards. In this case, the package will be extracted to `build/SynologyNAS/packages`.
Get the Synology scripts
`git clone https://github.com/SynologyOpenSource/pkgscripts-ng`
To install the package on your NAS device, login using the web interface. Navigate to the Package Manager, and click Manual Install. This will open up a menu which lets you choose a local file. Select your generated .pkg file, and install.
Download and install the cross-compile build enviroment for one or many targets. Using armada38x here for the platform, as that's the chip for a DS218j NAS which was tested first. 6.1 is the NAS OS version.
`./pkgscripts-ng/EnvDeploy -v 6.1 -p armada38x`
Adjust the package details, including version number. Adjust OS version in 'depends' if building for a later OS than 6.1
`vi ./source/MEGAcmd/INFO.sh`
`vi ./source/MEGAcmd/SynoBuildConf/depends`
Run the build process
`./pkgscripts-ng/PkgCreate.py MEGAcmd`
Results can now be seen in /toolkit/build_env/ds.armada38x-6.1/source/MEGAcmd/MEGAcmd
Package up the executables and scripts, provided the build actually succeeded (though it may say it failed even though we force 'exit 0' from the build script)
For official releases we may sign with an RSA key at this point, but were we are skipping signing with -S
`./pkgscripts-ng/PkgCreate.py -i -S MEGAcmd`
Package is now available at /toolkit/build_env/ds.armada38x-6.1/image/packages/
Install on your NAS from its web browser interface, Package Manager, Manual Install button which lets you choose a local file
To actually run it, you'll need to enable telnet connections in the Synology NAS, then telnet to it. PuTTY works nicely for this.
Executables are available at /volume1/@appstore/MEGAcmd/usr/local/bin
If you want to make a clean build after making changes inside /toolkit/source, then get rid of this (substitute the platform appropriately), and re-run EnvDeploy:
`rm -rf /toolkit/build_env/ds.armada38x-6.1`
To actually run MEGAcmd, you'll need to enable a telnet or SSH connection in the Synology NAS, and run a remote terminal on it. Executables are available at `/volume1/@appstore/megacmdpkg`.
# Notes

View File

@ -1,22 +0,0 @@
This directory contains scripts to build Synology packages on a continuous
integration server such as Jenkins.
`trigger.sh` and `wait.sh` are run by a regular user where `trigger.sh`
simply touches a file named `start` to indicate that the build should start.
`wait.sh` can then be run to check whether the build has finished by virtue
of the modified time stamp of a file named `result`.
The actual build is performed by running `build.sh` as a root user. This
build script is run through a daemon user when the `start` file changes its
modified time stamp. Once finished, the build script will update the modified
time stamp of `result` and populate the file with the status of the build
artifacts.
The workflow is as follows:
# Start daemon process that watches for `start`
# `trigger.sh` is run that touches `start`
# The daemon process commences the build
# `wait.sh` is run to wait for the build to finish
# The build finishes
# `wait.sh` is notified and exits

View File

@ -1,35 +0,0 @@
#!/bin/bash
# This scripts performs the build for all supported Synology platforms
set -ex
thisdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
builddir=/toolkit
rm -rf $builddir
# Clone MEGAcmd into the build dir
mkdir -p $builddir/source/megacmdpkg
cd $builddir/source/megacmdpkg
git clone --recursive https://github.com/meganz/MEGAcmd.git
# Copy toolkit files into place and clone Synology scripts
cd $builddir
cp -r $builddir/source/megacmdpkg/MEGAcmd/build/SynologyNAS/toolkit/* .
git clone https://github.com/SynologyOpenSource/pkgscripts-ng
# Create a link to the toolkit tarballs
ln -s /toolkit_tarballs toolkit_tarballs
# Perform the actual build
./build_all_synology_packages || true
# Collect results
resultdir=synology_build_results
rm -rf $thisdir/images
mkdir $thisdir/images
cp -r $resultdir/image-* $thisdir/images
rm -f $thisdir/result
touch $thisdir/result
echo `ls -1 $resultdir/*.failed` >> $thisdir/result
echo `ls -1 $resultdir/*.built` >> $thisdir/result

View File

@ -1,5 +0,0 @@
#!/bin/bash
# This script triggers the build by touching `start`
set -ex
thisdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
touch $thisdir/start

View File

@ -1,14 +0,0 @@
#!/bin/bash
# This script waits for the build to finish by checking for the modified
# time stamps of `start` and `result`
set -ex
thisdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
function modified_time_s {
date +%s -r $1 2>/dev/null || echo -1
}
while [ `modified_time_s $thisdir/start` -gt `modified_time_s $thisdir/result` ]; do
sleep 1
done
echo "Build finished!"

View File

@ -0,0 +1,85 @@
# Dockerfile for cross-compiling MEGAcmd for Synology in its different architectures. See README.md for more info.
FROM debian:12-slim
# Set default architecture
ARG PLATFORM=alpine
ENV PLATFORM=${PLATFORM}
RUN apt-get --quiet=2 update && DEBCONF_NOWARNINGS=yes apt-get --quiet=2 install \
aria2 \
autoconf \
autoconf-archive \
build-essential \
ccache \
cmake \
curl \
fakeroot \
git \
nasm \
pkg-config \
python3 \
tar \
unzip \
wget \
xz-utils \
zip \
1> /dev/null
ENV CCACHE_DIR=/tmp/ccache
ENV VCPKG_DEFAULT_BINARY_CACHE=/tmp/vcpkgcache
# We don't wont a potential config coming from host machine to meddle with the build
RUN rm sdk/include/mega/config.h || true
WORKDIR /mega
RUN chmod 777 /mega
# Clone and checkout known pkgscripts baseline
RUN git clone https://github.com/SynologyOpenSource/pkgscripts-ng.git pkgscripts \
&& git -C ./pkgscripts checkout e1d9f52
COPY sdk/dockerfile/dms-toolchain.sh /mega/
COPY sdk/dockerfile/dms-toolchains.conf /mega/
COPY build/SynologyNAS/toolkit/source/MEGAcmd/SynoBuildConf/install /mega/spk_install.sh
RUN chmod +x /mega/dms-toolchain.sh
RUN chmod +x /mega/spk_install.sh
COPY vcpkg.json ./vcpkg.json
COPY build/clone_vcpkg_from_baseline.sh ./clone_vcpkg_from_baseline.sh
RUN /mega/clone_vcpkg_from_baseline.sh /mega/vcpkg
WORKDIR /mega/megacmd
COPY sdk ./sdk
COPY src ./src
COPY build ./build
COPY contrib ./contrib
COPY tests/common ./tests/common
COPY CMakeLists.txt ./CMakeLists.txt
COPY vcpkg.json ./vcpkg.json
RUN /mega/dms-toolchain.sh ${PLATFORM}
# Remove the dynamic version of libatomic to avoid compiling with it, which causes
# execution to fail in the NAS because the shared library object cannot be found
RUN find /mega/toolchain/ \( -type f -o -type l \) -name libatomic.so* -delete
RUN --mount=type=cache,target=/tmp/ccache \
--mount=type=cache,target=/tmp/vcpkgcache \
--mount=type=tmpfs,target=/tmp/build \
cmake -B buildDMS \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DENABLE_MEGACMD_TESTS=OFF \
-DENABLE_ASAN=OFF \
-DENABLE_UBSAN=OFF \
-DENABLE_TSAN=OFF \
-DCMAKE_VERBOSE_MAKEFILE=ON \
-DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/mega/${PLATFORM}.toolchain.cmake \
-DVCPKG_OVERLAY_TRIPLETS=/mega \
-DVCPKG_ROOT=/mega/vcpkg \
-DVCPKG_TARGET_TRIPLET=${PLATFORM} && \
cmake --build buildDMS
RUN export PLATFORM=${PLATFORM} && /mega/spk_install.sh

View File

@ -0,0 +1,35 @@
#!/bin/bash
set -e
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <platform>"
exit 1
fi
PLATFORM="$1"
CONTAINER="megacmd-${PLATFORM}-build-env"
cleanup() {
echo "Cleaning up container..."
docker rm -f $CONTAINER > /dev/null 2>&1 || true
}
trap cleanup EXIT
echo "Starting build for '${PLATFORM}'..."
BUILDER_PARAMETER="${DOCKER_CUSTOM_BUILDER:+--builder $DOCKER_CUSTOM_BUILDER --load}"
MEGACMD_FOLDER="${SOURCE_PATH:-${SCRIPT_DIR}/../..}"
OUTPUT_FOLDER="${OUTPUT_PATH:-${SCRIPT_DIR}/packages}"
docker buildx build $BUILDER_PARAMETER -t $CONTAINER \
-f "$SCRIPT_DIR/dockerfile/synology-cross-build.dockerfile" \
"${MEGACMD_FOLDER}" \
--build-arg PLATFORM="$PLATFORM"
CONTAINER_ID=$(docker create $CONTAINER)
mkdir -p "$OUTPUT_FOLDER"
docker cp "${CONTAINER_ID}:/image/${PLATFORM}" "${OUTPUT_FOLDER}"/
echo "Extracted package for '${PLATFORM}'"

View File

@ -1,162 +0,0 @@
#!/usr/bin/env bash
# Where we are.
declare -r TOOLKIT_DIR=/toolkit
# Where builds are performed.
declare -r BUILD_DIR=${TOOLKIT_DIR}/build_env
# Where we can find necessary patches.
declare -r PATCH_DIR=$TOOLKIT_DIR/patches
# Where we can find Synology's package scripts.
declare -r PKGSCRIPTS_DIR=${TOOLKIT_DIR}/pkgscripts-ng
# What version of DSM are we targeting?
declare -r DSM_VERSION=7.2
# For convenience.
declare -r ENVDEPLOY="${PKGSCRIPTS_DIR}/EnvDeploy -v ${DSM_VERSION}"
declare -r PKGCREATE="${PKGSCRIPTS_DIR}/PkgCreate.py -v ${DSM_VERSION}"
# Full list of platforms.
all_platforms()
{
${ENVDEPLOY} -l |& cut -c 54-
}
# Performs a build for the specified platform.
build()
{
local -r platform="$1"
local -r env_dir="$(environment_path ${platform})"
local -r src_dir="${TOOLKIT_DIR}/source/MEGAcmd"
# Wipe prior SDK build state.
rm -rf ${src_dir}/MEGAcmd/sdk/sdk_build
# Prepare build environment.
deploy_environment ${platform}
# Prepare for SDK build.
mkdir -p ${env_dir}/tmp/megasdkbuild
# Avoid downloading SDK's dependencies.
cp ${TOOLKIT_DIR}/sdk_dep_tarballs/* \
${env_dir}/tmp/megasdkbuild
# Create a standard place where patches can be found.
mkdir -p ${env_dir}/tmp/megapatches
# Make sure no stale patches are present.
rm -f ${env_dir}/tmp/megapatches/*
# Copy patches into environment, if any.
if [ -d "${PATCH_DIR}" ]; then
find ${PATCH_DIR} \
-type f \
-name '*.patch' \
-exec cp {} ${env_dir}/tmp/megapatches \;
fi
# Kick off the build.
if ${PKGCREATE} -p ${platform} MEGAcmd; then
local -r result_dir="${TOOLKIT_DIR}/results/${platform}"
mkdir -p ${result_dir}
cp -av ${env_dir}/image/* ${result_dir}
clean_environment ${platform}
fi
}
# Platforms we'll be building for.
build_platforms()
{
local -r info_dir="${PKGSCRIPTS_DIR}/include"
# Output all non-x64 platforms.
for platform in $(all_platforms); do
info_path="${info_dir}/platform.${platform}"
if ! grep -q 'ARCH="x86_64"' ${info_path}; then
echo ${platform}
fi
done
# Output a representative x64 platform.
echo kvmx64
}
# Discards the environment for the specified platform.
clean_environment()
{
local -r platform="$1"
local -r env_dir="$(environment_path ${platform})"
if grep -q "${env_dir}/proc" /etc/mtab; then
umount ${env_dir}/proc
fi
rm -rf ${env_dir}
}
# Deploys the environment for the specified platform.
deploy_environment()
{
local -r platform="$1"
clean_environment ${platform}
${ENVDEPLOY} -D \
-p $1 \
-t ${TOOLKIT_DIR}/toolkit_tarballs
}
# Checks that a directory is present.
check_directory()
{
if [ ! -d $1 ]; then
echo "ERROR: Directory $1 does not exist."
exit 1
fi
}
# Path to the specified platform's environment.
environment_path()
{
echo "${BUILD_DIR}/ds.$1-${DSM_VERSION}"
}
if [ "$(id -u)" != "0" ]; then
echo "You must be root to run this script."
exit 1
fi
check_directory $TOOLKIT_DIR
check_directory ${PKGSCRIPTS_DIR}
check_directory $TOOLKIT_DIR/sdk_dep_tarballs
check_directory $TOOLKIT_DIR/source/MEGAcmd
check_directory $TOOLKIT_DIR/toolkit_tarballs
# Clear prior build results.
rm -rf ${TOOLKIT_DIR}/results
platforms=$(build_platforms)
# Try and build the packages.
for platform in ${platforms}; do
build ${platform}
done
# Check whether all the packages were built.
for platform in ${platforms}; do
echo -n "${platform}: "
if [ -d "${TOOLKIT_DIR}/results/${platform}" ]; then
echo "OK"
else
echo "FAIL"
fi
done

View File

@ -1,89 +0,0 @@
#!/bin/bash
set -o pipefail
# Prints a message and terminates the script.
die()
{
local message="$1"
echo "${message}"
exit 1
}
# Checks if a command is present.
present()
{
local program="$1"
if ! command -v "${program}" >/dev/null; then
die "Couldn't find ${program}"
fi
}
# Get a list of toolchain URIs.
toolchains()
{
local root="https://archive.synology.com/download/ToolChain/toolkit"
local version="$1"
local uri="${root}/${version}"
curl "${uri}" 2>/dev/null | pup 'a[href$=.txz] attr{href}'
}
# Display usage.
usage()
{
die "get-toolchains.sh -d DESTINATION -v X.Y"
}
# Make sure aria2 is present.
present aria2c
# Make sure pup is present.
present pup
# Make sure xargs is present.
present xargs
destination=""
version=""
# Parse arguments.
while getopts ":d:v:" arguments; do
case "${arguments}" in
d)
destination="${OPTARG}"
;;
v)
version="${OPTARG}"
;;
?)
usage
;;
esac
done
# Did the user specify where we should store the toolchains?
test -n "${destination}" || die "You must specify a destination."
# Did the user specify a DSM version?
test -n "${version}" || die "You must specify a DSM version."
# Try and retrieve a list of toolchain URIs.
uris="$(toolchains ${version})"
# Couldn't get a list of toolchains.
test -n "${uris}" || die "Couldn't get toolchains for DSM${version}"
echo "Trying to download toolchains..."
# Try and download the toolchains.
aria2c --continue=true \
--dir=${destination} \
--force-sequential=true \
${uris} \
|| die "Couldn't download toolchains."
echo "Toolchains downloaded."

View File

@ -1,17 +1,12 @@
#!/bin/bash
source /pkgscripts/include/pkg_util.sh
source /mega/pkgscripts/include/pkg_util.sh
package="megacmdpkg"
version="1.7.0-0001"
version="2.0.0-0001"
displayname="MEGAcmd"
maintainer="Mega NZ"
arch="$(pkg_get_platform)"
if [ "$arch" = "kvmx64" ]; then
arch="x86_64"
fi
arch="$PLATFORM"
description="MEGAcmd command line tool. Access your MEGA.nz secure cloud storage account and upload/download files, use its commands in scripts, automatically synchronise folders between your MEGA.nz account and your Synology NAS. Connect to your NAS via ssh or Putty to use the MEGAcmd commands. Run mega-help from the command line for documentation, or see our User Guide online."
os_min_ver="7.0-40000"
maintainer="Mega Ltd."

View File

@ -1,217 +0,0 @@
#!/usr/bin/env bash
apply_patches()
{
test -d /tmp/megapatches || return
for patch in $(ls /tmp/megapatches/* 2> /dev/null); do
patch -d / -i $patch -p 0 || return
done
}
build_cmd()
{
pushd MEGAcmd || return
local prefix="$PWD/sdk/sdk_build/install"
local flag_gtest="--with-gtest=$prefix"
local flag_freeimage="--with-freeimage=$prefix"
local flag_tests="--enable-tests"
local result=0
./autogen.sh
result=$?
if [ $result -ne 0 ]; then
popd
return $result
fi
use_freeimage || flag_freeimage="--without-freeimage"
if ! use_gtest; then
flag_gtest="--without-gtest"
flag_tests="--disable-tests"
fi
env AR=$AR \
ARCH=$ARCH \
CC=$CC \
CFLAGS="$(compiler_flags $CFLAGS)" \
CPPFLAGS="$(preprocessor_flags $CFLAGS $CPPFLAGS)" \
CXX=$CXX \
CXXFLAGS="$(compiler_flags -std=c++14 $CXXFLAGS)" \
LD=$LD \
NM=$NM \
OBJCXX=$CXX \
OBJDUMP=$OBJDUMP \
RANLIB=$RANLIB \
STRIP=$STRIP \
./configure $ConfigOpt \
--disable-curl-checks \
--disable-examples \
--disable-shared \
--enable-inotify \
--enable-static \
--enable-sync \
--with-cares="$prefix" \
--with-cryptopp="$prefix" \
--with-curl="$prefix" \
--with-libmediainfo="$prefix" \
--with-libuv="$prefix" \
--with-libzen="$prefix" \
--with-openssl="$prefix" \
--with-readline="$prefix" \
--with-sodium="$prefix" \
--with-sqlite="$prefix" \
--with-termcap="$prefix" \
--with-zlib="$prefix" \
--without-ffmpeg \
--without-libraw \
--without-pcre \
--without-pdfium \
$flag_gtest \
$flag_freeimage \
$flag_tests
result=$?
if [ $result -ne 0 ]; then
popd
return $result
fi
make
result=$?
popd
return $result
}
build_sdk()
{
local flag_configure_only="-c"
local flag_cross_compiling="-X"
local flag_disable_examples="-n"
local flag_disable_freeimage=""
local flag_enable_cares="-e"
local flag_enable_cryptopp="-q"
local flag_enable_curl="-g"
local flag_enable_megaapi="-a"
local flag_enable_sodium="-u"
local flag_enable_tests="-T"
local flag_enable_uv="-v"
local flag_openssl_assembly=""
local flag_openssl_compiler="linux-generic$BUILD_ARCH"
local result=0
pushd MEGAcmd/sdk || return
mkdir -p sdk_build/build || return
mkdir -p sdk_build/install/lib || return
use_assembly || flag_openssl_assembly="no-asm"
use_gtest || flag_enable_tests=""
use_freeimage || flag_disable_freeimage="-f"
env AR=$AR \
ARCH=$ARCH \
CC=$CC \
CFLAGS="$(compiler_flags $CFLAGS)" \
CPPFLAGS="$(preprocessor_flags $CFLAGS $CPPFLAGS)" \
CXX=$CXX \
CXXFLAGS="$(compiler_flags $CXXFLAGS)" \
LD=$LD \
NM=$NM \
OBJCXX=$CXX \
OBJDUMP=$OBJDUMP \
RANLIB=$RANLIB \
STRIP=$STRIP \
./contrib/build_sdk.sh -C "$ConfigOpt" \
-O "$flag_openssl_compiler" \
-S "$flag_openssl_assembly" \
$flag_configure_only \
$flag_cross_compiling \
$flag_disable_examples \
$flag_disable_freeimage \
$flag_enable_cares \
$flag_enable_cryptopp \
$flag_enable_curl \
$flag_enable_megaapi \
$flag_enable_sodium \
$flag_enable_tests \
$flag_enable_uv
local result=$?
popd
return $result
}
die()
{
echo "ERROR: $1"
exit 1
}
compiler_flags()
{
local result="$*"
# Strip preprocessor flags.
result="$(echo $result | sed -e 's/ *-[DI][^ ]\+//g')"
# Strip NEON flags (as it breaks freeimage.)
result="$(echo $result | sed -e 's/-mfpu=neon[^ ]*//g')"
# GCC's ARM ABI changed between 7.0 and 7.1.
result="$result -Wno-psabi"
echo "$result"
}
fix_environment()
{
find /usr -type f -name '*.la' \
| xargs sed -i -e 's!\(/[^/]\+\)\+\(/usr.*\)!\2!g'
find /usr -type f -name '*.la' \
| xargs sed -i -e 's!/home/cpt/hi3535/x-tools!/usr/local!g'
}
preprocessor_flags()
{
echo "$*" | grep -o -E -- '-[DI][^ ]+' | xargs
}
use_assembly()
{
# kvmx64 doesn't support AESNI instructions.
test "$PLATFORM_ABBR" != "kvmx64" \
-a "$PLATFORM_ABBR" != "apollolake"
}
use_gtest()
{
# The comcerto toolchain doesn't support all of C++11.
test "$PLATFORM_ABBR" != "comcerto2k"
}
use_freeimage()
{
true
}
printenv
apply_patches || die "Couldn't apply SDK patches"
fix_environment
build_sdk || die "Couldn't build the SDK"
build_cmd || die "Couldn't build MEGAcmd"

View File

@ -1,43 +1,35 @@
#!/bin/bash
mkdir /ccache-tmp
export CCACHE_DIR=/ccache-tmp
### Use PKG_DIR as working directory.
PKG_DIR=/tmp/_test_spk
rm -rf $PKG_DIR
mkdir -p $PKG_DIR
### get spk packing functions
source /pkgscripts/include/pkg_util.sh
source /mega/pkgscripts/include/pkg_util.sh
create_inner_tarball() {
local inner_tarball_dir=/tmp/_inner_tarball
### clear destination directory
### Clear destination directory
rm -rf $inner_tarball_dir && mkdir -p $inner_tarball_dir
pushd MEGAcmd
cp mega-cmd \
mega-cmd-server \
mega-exec \
cp buildDMS/mega-cmd \
buildDMS/mega-cmd-server \
buildDMS/mega-exec \
src/client/mega-* \
"$inner_tarball_dir"
if [ -x "sdk/tests/test_integration" ]; then
cp sdk/tests/test_integration \
sdk/tests/test_unit \
"$inner_tarball_dir"
fi
popd
### create package.txz: $1=source_dir, $2=dest_dir
### Create package.txz: $1=source_dir, $2=dest_dir
pkg_make_package $inner_tarball_dir "${PKG_DIR}"
}
create_spk(){
get_platform_family() {
plat_to_family "$PLATFORM"
}
create_spk() {
pushd build/SynologyNAS/toolkit/source/MEGAcmd
### Copy conf and scripts.
cp -av conf $PKG_DIR/.
cp -av scripts $PKG_DIR/.
@ -50,12 +42,11 @@ create_spk(){
./INFO.sh > INFO
cp -av INFO ${PKG_DIR}
### Create the final spk.
# pkg_make_spk <source path> <dest path> <spk file name>
# Please put the result spk into /image/packages
# spk name functions: pkg_get_spk_name pkg_get_spk_unified_name pkg_get_spk_family_name
mkdir -p /image/packages
pkg_make_spk ${PKG_DIR} "/image/packages" $(pkg_get_spk_family_name)
### Create the final spk
mkdir -p "/image/${PLATFORM}"
pkg_make_spk ${PKG_DIR} "/image/${PLATFORM}" $(__get_spk_name get_platform_family INFO)
popd
}
create_inner_tarball

View File

@ -25,12 +25,6 @@ VIAddVersionKey "FileDescription" "MEGAcmd"
VIAddVersionKey "LegalCopyright" "MEGA Limited 2019"
VIAddVersionKey "ProductName" "MEGAcmd"
; Version info
VIProductVersion "1.7.0.0"
VIAddVersionKey "FileVersion" "1.7.0.0"
VIAddVersionKey "ProductVersion" "1.7.0.0"
!define PRODUCT_VERSION "1.7.0"
!define PRODUCT_PUBLISHER "Mega Limited"
!define PRODUCT_WEB_SITE "http://www.mega.nz"
!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\MEGAcmdShell.exe"
@ -56,6 +50,29 @@ VIAddVersionKey "ProductVersion" "1.7.0.0"
!define SRCDIR_BATFILES "..\src\client\win"
; Version info: get version directly from the binary
!getdllversion "${SRCDIR_MEGACMD}/MEGAcmdServer.exe" Expv_
VIAddVersionKey "FileVersion" "${Expv_1}.${Expv_2}.${Expv_3}.${Expv_4}"
!ifdef VERSION_SUFFIX
VIProductVersion "${Expv_1}.${Expv_2}.${Expv_3}.${Expv_4}-${VERSION_SUFFIX}"
VIAddVersionKey "ProductVersion" "${Expv_1}.${Expv_2}.${Expv_3}.${Expv_4}-${VERSION_SUFFIX}"
!define PRODUCT_VERSION "${Expv_1}.${Expv_2}.${Expv_3}-${VERSION_SUFFIX}"
!else
VIProductVersion "${Expv_1}.${Expv_2}.${Expv_3}.${Expv_4}"
VIAddVersionKey "ProductVersion" "${Expv_1}.${Expv_2}.${Expv_3}.${Expv_4}"
!define PRODUCT_VERSION "${Expv_1}.${Expv_2}.${Expv_3}"
!endif
!define VcRedistBasePath "C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Redist\MSVC\14.42.34433"
!define VcRedist32BasePath "${VcRedistBasePath}\x86"
!define VcRedist32Path "${VcRedist32BasePath}\Microsoft.VC143.CRT"
!define VcRedist64BasePath "${VcRedistBasePath}\x64"
!define VcRedist64Path "${VcRedist64BasePath}\Microsoft.VC143.CRT"
!define WinRedistBasePath "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs"
!define WinRedist32BasePath "${winRedistBasePath}\x86"
!define WinRedist64BasePath "${winRedistBasePath}\x64"
!define MULTIUSER_MUI
!define MULTIUSER_INSTALLMODE_COMMANDLINE
!define MULTIUSER_EXECUTIONLEVEL Standard
@ -360,108 +377,108 @@ modeselected:
SetOutPath "$INSTDIR"
!ifdef BUILD_X64_VERSION
!insertmacro Install3264DLL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Redist\MSVC\14.29.30133\x64\Microsoft.VC142.CRT\vcruntime140.dll" "$INSTDIR\vcruntime140.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Redist\MSVC\14.29.30133\x64\Microsoft.VC142.CRT\vcruntime140_1.dll" "$INSTDIR\vcruntime140_1.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Redist\MSVC\14.29.30133\x64\Microsoft.VC142.CRT\msvcp140.dll" "$INSTDIR\msvcp140.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Redist\MSVC\14.29.30133\x64\Microsoft.VC142.CRT\msvcp140_1.dll" "$INSTDIR\msvcp140_1.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Redist\MSVC\14.29.30133\x64\Microsoft.VC142.CRT\msvcp140_2.dll" "$INSTDIR\msvcp140_2.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Redist\MSVC\14.29.30133\x64\Microsoft.VC142.CRT\msvcp140_atomic_wait.dll" "$INSTDIR\msvcp140_atomic_wait.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Redist\MSVC\14.29.30133\x64\Microsoft.VC142.CRT\msvcp140_codecvt_ids.dll" "$INSTDIR\msvcp140_codecvt_ids.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Redist\MSVC\14.29.30133\x64\Microsoft.VC142.CRT\concrt140.dll" "$INSTDIR\concrt140.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Redist\MSVC\14.29.30133\x64\Microsoft.VC142.CRT\vccorlib140.dll" "$INSTDIR\vccorlib140.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Redist\MSVC\14.29.30133\x64\Microsoft.VC142.OpenMP\vcomp140.dll" "$INSTDIR\vcomp140.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\ucrtbase.dll" "$INSTDIR\ucrtbase.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-crt-utility-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-utility-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-crt-time-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-time-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-crt-string-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-string-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-crt-stdio-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-stdio-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-crt-runtime-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-runtime-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-crt-process-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-process-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-crt-private-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-private-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-crt-multibyte-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-multibyte-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-crt-math-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-math-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-crt-locale-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-locale-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-crt-heap-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-heap-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-crt-filesystem-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-filesystem-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-crt-environment-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-environment-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-crt-convert-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-convert-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-crt-conio-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-conio-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-core-util-l1-1-0.dll" "$INSTDIR\api-ms-win-core-util-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-core-timezone-l1-1-0.dll" "$INSTDIR\api-ms-win-core-timezone-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-core-sysinfo-l1-1-0.dll" "$INSTDIR\api-ms-win-core-sysinfo-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-core-synch-l1-2-0.dll" "$INSTDIR\api-ms-win-core-synch-l1-2-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-core-synch-l1-1-0.dll" "$INSTDIR\api-ms-win-core-synch-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-core-string-l1-1-0.dll" "$INSTDIR\api-ms-win-core-string-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-core-rtlsupport-l1-1-0.dll" "$INSTDIR\api-ms-win-core-rtlsupport-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-core-profile-l1-1-0.dll" "$INSTDIR\api-ms-win-core-profile-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-core-processthreads-l1-1-1.dll" "$INSTDIR\api-ms-win-core-processthreads-l1-1-1.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-core-processthreads-l1-1-0.dll" "$INSTDIR\api-ms-win-core-processthreads-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-core-processenvironment-l1-1-0.dll" "$INSTDIR\api-ms-win-core-processenvironment-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-core-namedpipe-l1-1-0.dll" "$INSTDIR\api-ms-win-core-namedpipe-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-core-memory-l1-1-0.dll" "$INSTDIR\api-ms-win-core-memory-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-core-localization-l1-2-0.dll" "$INSTDIR\api-ms-win-core-localization-l1-2-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-core-libraryloader-l1-1-0.dll" "$INSTDIR\api-ms-win-core-libraryloader-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-core-interlocked-l1-1-0.dll" "$INSTDIR\api-ms-win-core-interlocked-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-core-heap-l1-1-0.dll" "$INSTDIR\api-ms-win-core-heap-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-core-handle-l1-1-0.dll" "$INSTDIR\api-ms-win-core-handle-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-core-file-l2-1-0.dll" "$INSTDIR\api-ms-win-core-file-l2-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-core-file-l1-2-0.dll" "$INSTDIR\api-ms-win-core-file-l1-2-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-core-file-l1-1-0.dll" "$INSTDIR\api-ms-win-core-file-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-core-errorhandling-l1-1-0.dll" "$INSTDIR\api-ms-win-core-errorhandling-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-core-debug-l1-1-0.dll" "$INSTDIR\api-ms-win-core-debug-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-core-datetime-l1-1-0.dll" "$INSTDIR\api-ms-win-core-datetime-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x64\api-ms-win-core-console-l1-1-0.dll" "$INSTDIR\api-ms-win-core-console-l1-1-0.dll"
!insertmacro Install3264DLL "${VcRedist64Path}\vcruntime140.dll" "$INSTDIR\vcruntime140.dll"
!insertmacro Install3264DLL "${VcRedist64Path}\vcruntime140_1.dll" "$INSTDIR\vcruntime140_1.dll"
!insertmacro Install3264DLL "${VcRedist64Path}\msvcp140.dll" "$INSTDIR\msvcp140.dll"
!insertmacro Install3264DLL "${VcRedist64Path}\msvcp140_1.dll" "$INSTDIR\msvcp140_1.dll"
!insertmacro Install3264DLL "${VcRedist64Path}\msvcp140_2.dll" "$INSTDIR\msvcp140_2.dll"
!insertmacro Install3264DLL "${VcRedist64Path}\msvcp140_atomic_wait.dll" "$INSTDIR\msvcp140_atomic_wait.dll"
!insertmacro Install3264DLL "${VcRedist64Path}\msvcp140_codecvt_ids.dll" "$INSTDIR\msvcp140_codecvt_ids.dll"
!insertmacro Install3264DLL "${VcRedist64Path}\concrt140.dll" "$INSTDIR\concrt140.dll"
!insertmacro Install3264DLL "${VcRedist64Path}\vccorlib140.dll" "$INSTDIR\vccorlib140.dll"
!insertmacro Install3264DLL "${VcRedist64BasePath}\Microsoft.VC143.OpenMP\vcomp140.dll" "$INSTDIR\vcomp140.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\ucrtbase.dll" "$INSTDIR\ucrtbase.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-crt-utility-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-utility-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-crt-time-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-time-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-crt-string-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-string-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-crt-stdio-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-stdio-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-crt-runtime-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-runtime-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-crt-process-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-process-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-crt-private-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-private-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-crt-multibyte-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-multibyte-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-crt-math-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-math-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-crt-locale-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-locale-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-crt-heap-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-heap-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-crt-filesystem-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-filesystem-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-crt-environment-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-environment-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-crt-convert-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-convert-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-crt-conio-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-conio-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-core-util-l1-1-0.dll" "$INSTDIR\api-ms-win-core-util-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-core-timezone-l1-1-0.dll" "$INSTDIR\api-ms-win-core-timezone-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-core-sysinfo-l1-1-0.dll" "$INSTDIR\api-ms-win-core-sysinfo-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-core-synch-l1-2-0.dll" "$INSTDIR\api-ms-win-core-synch-l1-2-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-core-synch-l1-1-0.dll" "$INSTDIR\api-ms-win-core-synch-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-core-string-l1-1-0.dll" "$INSTDIR\api-ms-win-core-string-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-core-rtlsupport-l1-1-0.dll" "$INSTDIR\api-ms-win-core-rtlsupport-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-core-profile-l1-1-0.dll" "$INSTDIR\api-ms-win-core-profile-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-core-processthreads-l1-1-1.dll" "$INSTDIR\api-ms-win-core-processthreads-l1-1-1.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-core-processthreads-l1-1-0.dll" "$INSTDIR\api-ms-win-core-processthreads-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-core-processenvironment-l1-1-0.dll" "$INSTDIR\api-ms-win-core-processenvironment-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-core-namedpipe-l1-1-0.dll" "$INSTDIR\api-ms-win-core-namedpipe-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-core-memory-l1-1-0.dll" "$INSTDIR\api-ms-win-core-memory-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-core-localization-l1-2-0.dll" "$INSTDIR\api-ms-win-core-localization-l1-2-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-core-libraryloader-l1-1-0.dll" "$INSTDIR\api-ms-win-core-libraryloader-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-core-interlocked-l1-1-0.dll" "$INSTDIR\api-ms-win-core-interlocked-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-core-heap-l1-1-0.dll" "$INSTDIR\api-ms-win-core-heap-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-core-handle-l1-1-0.dll" "$INSTDIR\api-ms-win-core-handle-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-core-file-l2-1-0.dll" "$INSTDIR\api-ms-win-core-file-l2-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-core-file-l1-2-0.dll" "$INSTDIR\api-ms-win-core-file-l1-2-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-core-file-l1-1-0.dll" "$INSTDIR\api-ms-win-core-file-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-core-errorhandling-l1-1-0.dll" "$INSTDIR\api-ms-win-core-errorhandling-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-core-debug-l1-1-0.dll" "$INSTDIR\api-ms-win-core-debug-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-core-datetime-l1-1-0.dll" "$INSTDIR\api-ms-win-core-datetime-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist64BasePath}\api-ms-win-core-console-l1-1-0.dll" "$INSTDIR\api-ms-win-core-console-l1-1-0.dll"
!else
!insertmacro Install3264DLL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Redist\MSVC\14.29.30133\x86\Microsoft.VC142.CRT\vcruntime140.dll" "$INSTDIR\vcruntime140.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Redist\MSVC\14.29.30133\x86\Microsoft.VC142.CRT\msvcp140.dll" "$INSTDIR\msvcp140.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Redist\MSVC\14.29.30133\x86\Microsoft.VC142.CRT\msvcp140_1.dll" "$INSTDIR\msvcp140_1.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Redist\MSVC\14.29.30133\x86\Microsoft.VC142.CRT\msvcp140_2.dll" "$INSTDIR\msvcp140_2.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Redist\MSVC\14.29.30133\x86\Microsoft.VC142.CRT\msvcp140_atomic_wait.dll" "$INSTDIR\msvcp140_atomic_wait.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Redist\MSVC\14.29.30133\x86\Microsoft.VC142.CRT\msvcp140_codecvt_ids.dll" "$INSTDIR\msvcp140_codecvt_ids.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Redist\MSVC\14.29.30133\x86\Microsoft.VC142.CRT\concrt140.dll" "$INSTDIR\concrt140.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Redist\MSVC\14.29.30133\x86\Microsoft.VC142.CRT\vccorlib140.dll" "$INSTDIR\vccorlib140.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Redist\MSVC\14.29.30133\x86\Microsoft.VC142.OpenMP\vcomp140.dll" "$INSTDIR\vcomp140.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\ucrtbase.dll" "$INSTDIR\ucrtbase.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-crt-utility-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-utility-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-crt-time-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-time-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-crt-string-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-string-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-crt-stdio-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-stdio-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-crt-runtime-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-runtime-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-crt-process-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-process-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-crt-private-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-private-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-crt-multibyte-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-multibyte-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-crt-math-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-math-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-crt-locale-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-locale-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-crt-heap-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-heap-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-crt-filesystem-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-filesystem-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-crt-environment-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-environment-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-crt-convert-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-convert-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-crt-conio-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-conio-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-core-util-l1-1-0.dll" "$INSTDIR\api-ms-win-core-util-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-core-timezone-l1-1-0.dll" "$INSTDIR\api-ms-win-core-timezone-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-core-sysinfo-l1-1-0.dll" "$INSTDIR\api-ms-win-core-sysinfo-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-core-synch-l1-2-0.dll" "$INSTDIR\api-ms-win-core-synch-l1-2-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-core-synch-l1-1-0.dll" "$INSTDIR\api-ms-win-core-synch-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-core-string-l1-1-0.dll" "$INSTDIR\api-ms-win-core-string-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-core-rtlsupport-l1-1-0.dll" "$INSTDIR\api-ms-win-core-rtlsupport-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-core-profile-l1-1-0.dll" "$INSTDIR\api-ms-win-core-profile-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-core-processthreads-l1-1-1.dll" "$INSTDIR\api-ms-win-core-processthreads-l1-1-1.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-core-processthreads-l1-1-0.dll" "$INSTDIR\api-ms-win-core-processthreads-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-core-processenvironment-l1-1-0.dll" "$INSTDIR\api-ms-win-core-processenvironment-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-core-namedpipe-l1-1-0.dll" "$INSTDIR\api-ms-win-core-namedpipe-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-core-memory-l1-1-0.dll" "$INSTDIR\api-ms-win-core-memory-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-core-localization-l1-2-0.dll" "$INSTDIR\api-ms-win-core-localization-l1-2-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-core-libraryloader-l1-1-0.dll" "$INSTDIR\api-ms-win-core-libraryloader-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-core-interlocked-l1-1-0.dll" "$INSTDIR\api-ms-win-core-interlocked-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-core-heap-l1-1-0.dll" "$INSTDIR\api-ms-win-core-heap-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-core-handle-l1-1-0.dll" "$INSTDIR\api-ms-win-core-handle-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-core-file-l2-1-0.dll" "$INSTDIR\api-ms-win-core-file-l2-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-core-file-l1-2-0.dll" "$INSTDIR\api-ms-win-core-file-l1-2-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-core-file-l1-1-0.dll" "$INSTDIR\api-ms-win-core-file-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-core-errorhandling-l1-1-0.dll" "$INSTDIR\api-ms-win-core-errorhandling-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-core-debug-l1-1-0.dll" "$INSTDIR\api-ms-win-core-debug-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-core-datetime-l1-1-0.dll" "$INSTDIR\api-ms-win-core-datetime-l1-1-0.dll"
!insertmacro Install3264DLL "C:\Program Files (x86)\Windows Kits\10\Redist\${WINKITVER}\ucrt\DLLs\x86\api-ms-win-core-console-l1-1-0.dll" "$INSTDIR\api-ms-win-core-console-l1-1-0.dll"
!insertmacro Install3264DLL "${VcRedist32Path}\vcruntime140.dll" "$INSTDIR\vcruntime140.dll"
!insertmacro Install3264DLL "${VcRedist32Path}\msvcp140.dll" "$INSTDIR\msvcp140.dll"
!insertmacro Install3264DLL "${VcRedist32Path}\msvcp140_1.dll" "$INSTDIR\msvcp140_1.dll"
!insertmacro Install3264DLL "${VcRedist32Path}\msvcp140_2.dll" "$INSTDIR\msvcp140_2.dll"
!insertmacro Install3264DLL "${VcRedist32Path}\msvcp140_atomic_wait.dll" "$INSTDIR\msvcp140_atomic_wait.dll"
!insertmacro Install3264DLL "${VcRedist32Path}\msvcp140_codecvt_ids.dll" "$INSTDIR\msvcp140_codecvt_ids.dll"
!insertmacro Install3264DLL "${VcRedist32Path}\concrt140.dll" "$INSTDIR\concrt140.dll"
!insertmacro Install3264DLL "${VcRedist32Path}\vccorlib140.dll" "$INSTDIR\vccorlib140.dll"
!insertmacro Install3264DLL "${VcRedist32BasePath}\Microsoft.VC143.OpenMP\vcomp140.dll" "$INSTDIR\vcomp140.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\ucrtbase.dll" "$INSTDIR\ucrtbase.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-crt-utility-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-utility-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-crt-time-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-time-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-crt-string-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-string-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-crt-stdio-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-stdio-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-crt-runtime-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-runtime-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-crt-process-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-process-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-crt-private-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-private-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-crt-multibyte-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-multibyte-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-crt-math-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-math-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-crt-locale-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-locale-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-crt-heap-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-heap-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-crt-filesystem-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-filesystem-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-crt-environment-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-environment-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-crt-convert-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-convert-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-crt-conio-l1-1-0.dll" "$INSTDIR\api-ms-win-crt-conio-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-core-util-l1-1-0.dll" "$INSTDIR\api-ms-win-core-util-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-core-timezone-l1-1-0.dll" "$INSTDIR\api-ms-win-core-timezone-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-core-sysinfo-l1-1-0.dll" "$INSTDIR\api-ms-win-core-sysinfo-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-core-synch-l1-2-0.dll" "$INSTDIR\api-ms-win-core-synch-l1-2-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-core-synch-l1-1-0.dll" "$INSTDIR\api-ms-win-core-synch-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-core-string-l1-1-0.dll" "$INSTDIR\api-ms-win-core-string-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-core-rtlsupport-l1-1-0.dll" "$INSTDIR\api-ms-win-core-rtlsupport-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-core-profile-l1-1-0.dll" "$INSTDIR\api-ms-win-core-profile-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-core-processthreads-l1-1-1.dll" "$INSTDIR\api-ms-win-core-processthreads-l1-1-1.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-core-processthreads-l1-1-0.dll" "$INSTDIR\api-ms-win-core-processthreads-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-core-processenvironment-l1-1-0.dll" "$INSTDIR\api-ms-win-core-processenvironment-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-core-namedpipe-l1-1-0.dll" "$INSTDIR\api-ms-win-core-namedpipe-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-core-memory-l1-1-0.dll" "$INSTDIR\api-ms-win-core-memory-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-core-localization-l1-2-0.dll" "$INSTDIR\api-ms-win-core-localization-l1-2-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-core-libraryloader-l1-1-0.dll" "$INSTDIR\api-ms-win-core-libraryloader-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-core-interlocked-l1-1-0.dll" "$INSTDIR\api-ms-win-core-interlocked-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-core-heap-l1-1-0.dll" "$INSTDIR\api-ms-win-core-heap-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-core-handle-l1-1-0.dll" "$INSTDIR\api-ms-win-core-handle-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-core-file-l2-1-0.dll" "$INSTDIR\api-ms-win-core-file-l2-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-core-file-l1-2-0.dll" "$INSTDIR\api-ms-win-core-file-l1-2-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-core-file-l1-1-0.dll" "$INSTDIR\api-ms-win-core-file-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-core-errorhandling-l1-1-0.dll" "$INSTDIR\api-ms-win-core-errorhandling-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-core-debug-l1-1-0.dll" "$INSTDIR\api-ms-win-core-debug-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-core-datetime-l1-1-0.dll" "$INSTDIR\api-ms-win-core-datetime-l1-1-0.dll"
!insertmacro Install3264DLL "${WinRedist32BasePath}\api-ms-win-core-console-l1-1-0.dll" "$INSTDIR\api-ms-win-core-console-l1-1-0.dll"
!endif
!ifndef BUILD_UNINSTALLER ; if building uninstaller, skip files below

View File

@ -1,3 +1,14 @@
megacmd (2.0.0) stable; urgency=low
* New Sync Engine: See sync-issues and sync-ignore commands
* Rotating Logger: Introduced a robust rotating logging system across all platforms for better performance and debugging
* Platform-specific enhancements: Addressed various file descriptor issues on Linux and macOS, and improved non-ascii support on Windows
* Improved overall reliability: Fixed memory leaks, resolved potential data races, and eliminated deadlock scenarios
* Fixed an issue when handling double-quoted arguments
* Various fixes and refinements to enhance usability and performance
-- MEGA Team <linux@mega.co.nz> Fri, 24 Jan 2025 13:20:06 +0100
megacmd (1.7.0) stable; urgency=low
* Improved startup time

View File

@ -5,6 +5,7 @@ VCPKG_ROOT := $(shell [ -f /opt/vcpkg.tar.gz ] && echo "-DVCPKG_ROOT=vcpkg" || e
EXTRADEFINES := $(shell cat /etc/issue | grep "Ubuntu 1[2345789]\|Ubuntu 20.10\|Ubuntu 21\|Ubuntu 22.10\|Ubuntu 23\|Debian.* [789]" >/dev/null && echo "$$CPPFLAGS -DMEGACMD_DEPRECATED_OS" || echo "")
DPKGXZ := $(shell cat /etc/issue | grep "Ubuntu 24\|Oracular Oriole\|Noble Numbat\|Ubuntu 23\|Mantic Minotaur\|Lunar Lobster\|Ubuntu 22\|Jammy Jellyfish\|Ubuntu 21.10" >/dev/null && echo "-- -Zxz" || echo "")
#LDFLAGS := $(shell dpkg --print-architecture | grep -i "i386\|arm" >/dev/null && echo "" || echo "$$LDFLAGS -Wl,-rpath,/opt/megacmd/lib")
EXPORT_VCPKG_FORCE_SYSTEM_BINARIES := $(shell uname -m | grep "armv7l" >/dev/null && echo "VCPKG_FORCE_SYSTEM_BINARIES=1" || echo "")
DEB_TESTING := $(shell cat /etc/issue | grep "Debian" > /dev/null && cat /etc/apt/sources.list.d/debian.sources | grep -v "^\#" | grep testing > /dev/null && echo "testing")
#TODO: Ensure raspbian builds with that export
EXPORTCCMFPU := $(shell cat /etc/issue | grep "Raspbian GNU/Linux 12" >/dev/null && echo "export CC='cc -mfpu=vfp'" || echo ":")
@ -34,7 +35,7 @@ build-stamp:
fi
cmake --version
cmake $(VCPKG_ROOT) -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -S $(CURDIR) -B $(CURDIR)/build_dir
$(EXPORT_VCPKG_FORCE_SYSTEM_BINARIES) cmake $(VCPKG_ROOT) -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -S $(CURDIR) -B $(CURDIR)/build_dir
cmake --build $(CURDIR)/build_dir -j$(NJOBS)
cmake --install $(CURDIR)/build_dir --prefix $(CURDIR)/install_dir

View File

@ -1,3 +1,13 @@
Fri Jan 24 01:20:16 PM CET 2025 - linux@mega.co.nz
- Update to version 2.0.0:
* New Sync Engine: See sync-issues and sync-ignore commands
* Rotating Logger: Introduced a robust rotating logging system across all platforms for better performance and debugging
* Platform-specific enhancements: Addressed various file descriptor issues on Linux and macOS, and improved non-ascii support on Windows
* Improved overall reliability: Fixed memory leaks, resolved potential data races, and eliminated deadlock scenarios
* Fixed an issue when handling double-quoted arguments
* Various fixes and refinements to enhance usability and performance
-------------------------------------------------------------------
Mon May 20 02:06:31 PM CEST 2024 - linux@mega.co.nz
- Update to version 1.7.0:
* Improved startup time

View File

@ -13,7 +13,7 @@ IF EXIST build-x64-windows-mega (
mkdir build-x64-windows-mega
cd build-x64-windows-mega
cmake -G "Visual Studio 16 2019" -A x64 -DCMAKE_VERBOSE_MAKEFILE="ON" -DCMAKE_CXX_FLAGS_RELWITHDEBINFO="/Zi /O2 /Ob2 /DNDEBUG" %VCPKG_ROOT_ARG% -DCMAKE_C_FLAGS_RELWITHDEBINFO="/Zi /O2 /Ob2 /DNDEBUG" -S "..\.." -B . || exit 1 /b
cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_VERBOSE_MAKEFILE="ON" -DCMAKE_CXX_FLAGS_RELWITHDEBINFO="/Zi /O2 /Ob2 /DNDEBUG" %VCPKG_ROOT_ARG% -DCMAKE_C_FLAGS_RELWITHDEBINFO="/Zi /O2 /Ob2 /DNDEBUG" -S "..\.." -B . || exit 1 /b
cmake --build . --config RelWithDebInfo --target mega-exec --target mega-cmd-server --target mega-cmd --target mega-cmd-updater -j%MEGA_CORES% || exit 1 /b
cd ..
@ -28,6 +28,6 @@ IF EXIST build-x86-windows-mega (
mkdir build-x86-windows-mega
cd build-x86-windows-mega
cmake -G "Visual Studio 16 2019" -A Win32 -DCMAKE_VERBOSE_MAKEFILE="ON" -DCMAKE_CXX_FLAGS_RELWITHDEBINFO="/Zi /O2 /Ob2 /DNDEBUG" %VCPKG_ROOT_ARG% -DCMAKE_C_FLAGS_RELWITHDEBINFO="/Zi /O2 /Ob2 /DNDEBUG" -S "..\.." -B . || exit 1 /b
cmake -G "Visual Studio 17 2022" -A Win32 -DCMAKE_VERBOSE_MAKEFILE="ON" -DCMAKE_CXX_FLAGS_RELWITHDEBINFO="/Zi /O2 /Ob2 /DNDEBUG" %VCPKG_ROOT_ARG% -DCMAKE_C_FLAGS_RELWITHDEBINFO="/Zi /O2 /Ob2 /DNDEBUG" -S "..\.." -B . || exit 1 /b
cmake --build . --config RelWithDebInfo --target mega-exec --target mega-cmd-server --target mega-cmd --target mega-cmd-updater -j%MEGA_CORES% || exit 1 /b
cd ..

View File

@ -1 +1 @@
1.7.0
2.0.0

View File

@ -1,96 +1,56 @@
# Debugging MEGAcmd
There are two different kinds of logging messages:
- MEGAcmd based: those messages reported by MEGAcmd itself.
- MEGAcmd: these messages are reported by MEGAcmd itself. These messages will show information regarding the processing of user commands. They will be labeled with `cmd`.
These messages will show information regarding the processing of user commands.
- SDK: these messages are reported by the sdk and its dependent libraries. These messages will show information regarding requests, transfers, network, etc. They will be labeled with `sdk`.
- SDK based: those messages reported by the sdk and dependent libraries.
The MEGAcmd server logs messages depending on the level of log adjusted to those two categories. You can adjust the level of logging for those kinds with `log` command. Log levels range from FATAL (the lowest) to VERBOSE (the highest). The log level of each message is displayed after the cmd/sdk prefix.
These messages will show information regarding requests, transfers, network, etc.
They will be labeled with `SDK:`.
Here's an example of some random log messages:
```
2025-02-07_16-47-56.662269 cmd DBG Registering state listener petition with socket: 85 [comunicationsmanagerfilesockets.cpp:189]
2025-02-07_16-47-56.662366 cmd DTL Unregistering no longer listening client. Original petition: registerstatelistener [comunicationsmanagerfilesockets.cpp:346]
2025-02-07_16-47-56.662671 sdk INFO Request (RETRY_PENDING_CONNECTIONS) starting [megaapi_impl.cpp:16964]
```
The source file and line the message was logged from is appended at the end of the log message, to help developers quickly find out where they came from.
MEGAcmdServer logs messages depending on the level of log adjusted to those
two categories. You can adjust the level of logging for those kinds with `log` command.
Log levels range from FATAL (the lowest) to VERBOSE (the highest).
## How to access the logs
Accessing the logs depends on the platform you are in.
Logs coming from MEGAcmd are written to the `megacmdserver.log` file. This file is not removed across restarts, so when it gets too large it is automatically compressed and renamed to include a timestamp (without stopping the logging).
### MacOS
By default, whenever MEGAcmdServer is executed, it will log the output to `$HOME/.megaCmd/megacmdserver.log`.
If you want to launch it manually execute in a terminal:
```
export PATH=/Applications/MEGAcmd.app/Contents/MacOS:$PATH
./mega-cmd
```
### Linux
By default, whenever MEGAcmdServer is executed, it will log the output to `$HOME/.megaCmd/megacmdserver.log`.
If you want to launch it manually execute in a terminal:
```
mega-cmd-server
```
### Windows
MEGAcmdServer is executed in the background without saving the log into a file. If you want to
see the output you would need to execute the server (MEGAcmdServer.exe) manually.
## Accessing stdout and stderr
The standard output and error streams can be found in the `megacmdserver.log.out` and `megacmdserver.log.err` files, respectively. They're located in the same directories as the logs.
The log file is located in `$HOME/.megaCmd` for Linux and macOS, and `%LOCALAPPDATA%\MEGAcmd\.megaCmd` for Windows.
## Verbosity on startup
You can start the server with higher level of verbosity in order to have log levels increased at startup.
In Windows & Linux you will need to pass `--debug-full` as an argument to the executable (e.g: `MEGAcmdServer.exe --debug-full`).
You can start the server with higher level of verbosity in order to have log levels increased at startup, regardless of the log level configured by the `log` command mentioned above.
You will need to pass `--debug-full` as an argument to the executable (e.g: `MEGAcmdServer.exe --debug-full`). Alternatively, you can set the `MEGACMD_LOGLEVEL` environment variable to `FULLVERBOSE` before starting the server.
In MacOS, you can use `MEGACMD_LOGLEVEL` environment variable like this: `MEGACMD_LOGLEVEL=FULLDEBUG ./mega-cmd`.
If you want other startup level of logging, you can use the following:
* `--debug` or `MEGACMD_LOGLEVEL=DEBUG` will set
```
MEGAcmd log level = DEBUG
SDK log level = DEFAULT
```
If you want other startup level of loggin, you can use:
* `--debug-full` or `MEGACMD_LOGLEVEL=DEBUG` will set
```
MEGAcmd log level = DEBUG
SDK log level = DEBUG
```
* `--debug`
* `MEGACMD_LOGLEVEL=DEBUG`
This will set:
MEGAcmd log level = DEBUG
SDK log level = DEFAULT
* `--debug-full`
* `MEGACMD_LOGLEVEL=DEBUG`
This will set:
MEGAcmd log level = DEBUG
SDK log level = DEBUG
* `--verbose`
* `MEGACMD_LOGLEVEL=VERBOSE`
This will set:
MEGAcmd log level = VERBOSE
SDK log level = DEFAULT
* `--verbose-full`
* `MEGACMD_LOGLEVEL=FULLVERBOSE`
This will set:
MEGAcmd log level = VERBOSE
SDK log level = VERBOSE
* `--verbose` or `MEGACMD_LOGLEVEL=VERBOSE` will set
```
MEGAcmd log level = VERBOSE
SDK log level = DEFAULT
```
* `--verbose-full` or `MEGACMD_LOGLEVEL=FULLVERBOSE` will set
```
MEGAcmd log level = VERBOSE
SDK log level = VERBOSE
```
## Controlling verbosity of a single command
You can pass `-v` (`-vv`, `-vvv`, and so on for a more verbose output)
to an specific command and it will use higher level of verbosity of MEGAcmd based messages.
In general, as we've mentioned before, lower verbosity log messages are not printed directly to the console. Only errors are. You can pass `-v`, `-vv`, and `-vvv` when running a command to ensure warning, debug, and verbose messages are printed (respectively). Note that this is only for the console; log level of `megacmdserver.log` will follow the rules explained above.

View File

@ -19,6 +19,7 @@ Options:
*If you serve more than one location, these parameters will be ignored and used those of the first location served.
If you want to change those parameters, you need to stop serving all locations and configure them again.
Note: FTP settings and locations will be saved for the next time you open MEGAcmd, but will be removed if you logout.
Caveat: This functionality is in BETA state. It might not be available on all platforms. If you experience any issue with this, please contact: support@mega.nz
</pre>

View File

@ -12,5 +12,5 @@ It's only recommended to disable these features before uploading files
with image or video extensions that are not really images or videos,
or that are encrypted in the local drive so they can't be analyzed anyway.
Notice that this setting will be saved for the next time you open MEGAcmd
Notice that this setting will be saved for the next time you open MEGAcmd, but will be removed if you logout.
</pre>

View File

@ -6,5 +6,5 @@ Usage: `https [on|off]`
HTTPS is not necesary since all data is stored and transfered encrypted.
Enabling it will increase CPU usage and add network overhead.
Notice that this setting will be saved for the next time you open MEGAcmd
Notice that this setting will be saved for the next time you open MEGAcmd, but will be removed if you logout.
</pre>

View File

@ -1,5 +1,5 @@
### log
Prints/Modifies the current logs level
Prints/Modifies the log level
Usage: `log [-sc] level`
<pre>
@ -8,6 +8,7 @@ Options:
Messages captured by MEGAcmd server.
-s SDK log level (lower level messages).
Messages captured by the engine and libs
Note: this setting will be saved for the next time you open MEGAcmd, but will be removed if you logout.
Regardless of the log level of the
interactive shell, you can increase the amount of information given

View File

@ -11,4 +11,6 @@ URL Proxy URL (e.g: https://127.0.0.1:8080)
--auto To use the proxy configured in your system
--username=USERNAME The username, for authenticated proxies
--password=PASSWORD The password, for authenticated proxies. Please, avoid using passwords containing " or '
Note: Proxy settings will be saved for the next time you open MEGAcmd, but will be removed if you logout.
</pre>

View File

@ -3,9 +3,9 @@ Show all issues with current syncs
Usage: `sync-issues [[--detail (ID|--all)] [--limit=rowcount] [--disable-path-collapse]] | [--enable-warning|--disable-warning]`
<pre>
When MEGAcmd detects conflicts with the data it's synchronizing, a sync issue is triggered. Syncing is stopped, and no progress is made on the conflicting data.
A notification will appear when sync issues are detected. Because the sync engine might clear the internal issue list when processing, the notification can appear even if there were already issues before.
Note: the sync issue list might not contain the latest updated data. Some issues might still be being processing by the sync engine, and some might not have been removed yet.
When MEGAcmd detects conflicts with the data it's synchronizing, a sync issue is triggered. Syncing is stopped on the conflicting data, and no progress is made. Recovering from an issue usually requires user intervention.
A notification warning will appear whenever sync issues are detected. You can disable the warning if you wish. Note: the notification may appear even if there were already issues before.
Note: the list of sync issues provides a snapshot of the issues detected at the moment of requesting it. Thus, it might not contain the latest updated data. Some issues might still be being processed by the sync engine, and some might not have been removed yet.
Options:
--detail (ID | --all) Provides additional information on a particular sync issue.
@ -16,14 +16,14 @@ Options:
LAST_MODIFIED: The most recent date when this file or directory was updated.
UPLOADED: For cloud paths, the date of upload or creation. Empty for local paths.
SIZE: The size of the file. Empty for directories.
TYPE: The type of the path (file or directory). This column is hidden if the information it's not relevant for the particular sync issue.
TYPE: The type of the path (file or directory). This column is hidden if the information is not relevant for the particular sync issue.
The "--all" argument can be used to show the details of all issues.
--limit=rowcount Limits the amount of rows displayed. Can also be combined with "--detail".
--limit=rowcount Limits the amount of rows displayed. Set to 0 to display unlimited rows. Default is 10. Can also be combined with "--detail".
--disable-path-collapse Ensures all paths are fully shown. By default long paths are truncated for readability.
--enable-warning Enables the notification that appears when issues are detected. This setting is stored locally for all users.
--disable-warning Disables the notification that appears when issues are detected. This setting is stored locally for all users.
--col-separator=X Use the string "X" as column separator. Otherwise, spaces will be added between columns to align them.
--output-cols=COLUMN_NAME_1,COLUMN_NAME2,... Select which columns to show and their order.
--enable-warning Enables the notification that appears when issues are detected. This setting is saved for the next time you open MEGAcmd, but will be removed if you logout.
--disable-warning Disables the notification that appears when issues are detected. This setting is saved for the next time you open MEGAcmd, but will be removed if you logout.
--col-separator=X Uses the string "X" as column separator. Otherwise, spaces will be added between columns to align them.
--output-cols=COLUMN_NAME_1,COLUMN_NAME2,... Selects which columns to show and their order.
DISPLAYED columns:
ISSUE_ID: A unique identifier of the sync issue. The ID can be used alongside the "--detail" argument.

View File

@ -20,8 +20,8 @@ Options:
[deprecated] -r ID|localpath same as --enable.
--path-display-size=N Use at least N characters for displaying paths.
--show-handles Prints remote nodes handles (H:XXXXXXXX).
--col-separator=X Use the string "X" as column separator. Otherwise, spaces will be added between columns to align them.
--output-cols=COLUMN_NAME_1,COLUMN_NAME2,... Select which columns to show and their order.
--col-separator=X Uses the string "X" as column separator. Otherwise, spaces will be added between columns to align them.
--output-cols=COLUMN_NAME_1,COLUMN_NAME2,... Selects which columns to show and their order.
DISPLAYED columns:
ID: an unique identifier of the sync.
@ -31,7 +31,6 @@ DISPLAYED columns:
Pending: Sync config has loaded but we have not attempted to start it yet.
Loading: Sync is in the process of loading from disk.
Running: Sync loaded and active.
Paused: Sync loaded but sync logic is suspended for now..
Suspended: Sync is not loaded, but it is on disk with the last known sync state.
Disabled: Sync has been disabled (no state cached). Starting it is like configuring a brand new sync with those settings.
STATUS: State of the sync, possible values:

View File

@ -18,8 +18,8 @@ Show options:
--only-completed Show only completed download
--limit=N Show only first N transfers
--path-display-size=N Use at least N characters for displaying paths
--col-separator=X Use the string "X" as column separator. Otherwise, spaces will be added between columns to align them.
--output-cols=COLUMN_NAME_1,COLUMN_NAME2,... Select which columns to show and their order.
--col-separator=X Uses the string "X" as column separator. Otherwise, spaces will be added between columns to align them.
--output-cols=COLUMN_NAME_1,COLUMN_NAME2,... Selects which columns to show and their order.
TYPE legend correspondence:
⇓ = Download transfer

View File

@ -18,6 +18,7 @@ Options:
*If you serve more than one location, these parameters will be ignored and use those of the first location served.
If you want to change those parameters, you need to stop serving all locations and configure them again.
Note: WEBDAV settings and locations will be saved for the next time you open MEGAcmd, but will be removed if you logout.
Caveat: This functionality is in BETA state. It might not be available on all platforms. If you experience any issue with this, please contact: support@mega.nz
</pre>

View File

@ -1,23 +1,19 @@
#version=1070000
#version=2000000
#baseurl=http://g.static.mega.co.nz/upd/mcmd/MEGAcmd.app/
#Hash: note this is the hash of the public key assuming an "\n" at the end
#pubkeysha256sum=1d3a6360832e193cb98707692c3816b5022ec976e2915cee60994ba20e292b4a
Contents/Frameworks/libavcodec.59.dylib;Contents/Frameworks/libavcodec.59.dylib;7511963e256fb2c47fe34e9b18c9e877be908d287007b267ce6570b854715683
Contents/Frameworks/libavdevice.59.dylib;Contents/Frameworks/libavdevice.59.dylib;a4c2e6c1329ad087769f9a2bbea0dc7fbbe4f5e078ad1e811da4386d28ade37d
Contents/Frameworks/libavfilter.8.dylib;Contents/Frameworks/libavfilter.8.dylib;9d8318dd9b48115595d863ff8c43f3c1863b1be04e41055332ffc4bf4200fb8f
Contents/Frameworks/libavformat.59.dylib;Contents/Frameworks/libavformat.59.dylib;5c58aa48366b61fdc6cd1a165df384191ac0e3e9a001e6e9fa273fd5673150a8
Contents/Frameworks/libavutil.57.dylib;Contents/Frameworks/libavutil.57.dylib;f1a23a79d0ac9820a6e2bea188f413e8297027852b37277ce47207af4b11d68e
Contents/Frameworks/libcares.2.dylib;Contents/Frameworks/libcares.2.dylib;881f830d96ebb3a65a610081af815c4078a648ec19c483c5433f96e5092844c5
Contents/Frameworks/libcurl.4.dylib;Contents/Frameworks/libcurl.4.dylib;b7542b97fee9864cb78e562b3199d4533002e83962716873fb714cd6f4ad2eb1
Contents/Frameworks/libswresample.4.dylib;Contents/Frameworks/libswresample.4.dylib;9f180e8d59887e13471e5edbae75eb564592d267cac00b6cd36cd292d40a1538
Contents/Frameworks/libswscale.6.dylib;Contents/Frameworks/libswscale.6.dylib;5ee4b1982ca846d91f3d9e165a8b7c93248a8e6504d76e325b5ff03305953458
Contents/Info.plist;Contents/Info.plist;2006b3f0fbe2a8b0d8df98226450d9e5c6d7a0032b12d5680601871bb18921e9
Contents/Frameworks/libavcodec.59.37.100.dylib;Contents/Frameworks/libavcodec.59.37.100.dylib;2b51e739b34966ead1f17e50de30ff5b0a9d6d6841c66e5a1d898f5ad7696e79
Contents/Frameworks/libavformat.59.27.100.dylib;Contents/Frameworks/libavformat.59.27.100.dylib;03e74e3c8701bffbd3487aa7fb602f2cc52c36b176818f4a7e490e8ffcf39650
Contents/Frameworks/libavutil.57.28.100.dylib;Contents/Frameworks/libavutil.57.28.100.dylib;92366d200425ae969f934367405d3947f1b4b7f7e7287cb2955df76497654b62
Contents/Frameworks/libswresample.4.7.100.dylib;Contents/Frameworks/libswresample.4.7.100.dylib;12abee82bda65f7295bbb73d8d4e66a952d31c1285377502e1aaf4323990f1bb
Contents/Frameworks/libswscale.6.7.100.dylib;Contents/Frameworks/libswscale.6.7.100.dylib;58806c5775c0e436960f1e385b158a4de409cdd7aa743d70962ca8cc1d5b8431
Contents/Info.plist;Contents/Info.plist;469bf08176fd57ff07441e05e872442c5a1a0a11dbe57333a4dc07793127379e
Contents/MacOS/mega-attr;Contents/MacOS/mega-attr;a1f60255288b7f01eb9c43b1de59eeac50ad370c0853ee352a3aeefe13472b6c
Contents/MacOS/mega-backup;Contents/MacOS/mega-backup;ef37df5a4d97a7729cb9414ce5c0639f2d9b0fd9d9ee138f7655af2580b33682
Contents/MacOS/mega-cancel;Contents/MacOS/mega-cancel;343ab60a070927d55e83372c756213594d39cfc0d5b2e21a1f43c9c582098ef3
Contents/MacOS/mega-cat;Contents/MacOS/mega-cat;cc6dc3c50adec44d7aa6436845603d9eb4e7688458632fd0bef4aa4c7d9e30af
Contents/MacOS/mega-cd;Contents/MacOS/mega-cd;09af358bfb59012385bcf540045e017ec4aadfd5ab7a06f6bdaef4a6d5828c09
Contents/MacOS/mega-cmd;Contents/MacOS/mega-cmd;94c1799c5bd9b3ba294b7ae244083fba326a92ea6a3ddd1209bc5256699cf9ba
Contents/MacOS/mega-cmd;Contents/MacOS/mega-cmd;c3c8852d930fc4c87bb3ff67bb3abbe5f53121e34c1f6b61e37aa16782ead2a9
Contents/MacOS/mega-confirm;Contents/MacOS/mega-confirm;62373fc155c0a2a2f1b67355a2570c4f812042f67272fc12afafabf60ed08318
Contents/MacOS/mega-confirmcancel;Contents/MacOS/mega-confirmcancel;d81b018029c263ebe52fb6367ceafea3e0961416cb54dfbdf79a68416ef1ed9d
Contents/MacOS/mega-cp;Contents/MacOS/mega-cp;7f999e5e030c3636f8e5cdbf44050c51bf6a0c05bdbbb85394616384690a925c
@ -27,7 +23,7 @@ Contents/MacOS/mega-df;Contents/MacOS/mega-df;1c106981101143063c8b76f08c0df8e21b
Contents/MacOS/mega-du;Contents/MacOS/mega-du;af7e98fdb28e70fbaf69fffdca4762956a4b00a086dd8c50f3de78e2bad7b457
Contents/MacOS/mega-errorcode;Contents/MacOS/mega-errorcode;bdebcaefaa073d12707a6b9a0b3141754eb1637fa6a48c800a9bdbf5dd7511f8
Contents/MacOS/mega-exclude;Contents/MacOS/mega-exclude;86c94893e7c380c29f9e36f624d6598ed836851ab95d491e74064a35d0d54aac
Contents/MacOS/mega-exec;Contents/MacOS/mega-exec;ee96c5e86c6e51b6115258a2997a960a94a012b23aa635b8494308d8431b01f7
Contents/MacOS/mega-exec;Contents/MacOS/mega-exec;34d1b38419ae374c701e33888b02eb910232a9a67c2766c0647adccdb3f9c922
Contents/MacOS/mega-export;Contents/MacOS/mega-export;280e5ec5ed2339fee7c82716ff15cff86814fc1b89d34ddc7adacc4f10f2d3f4
Contents/MacOS/mega-find;Contents/MacOS/mega-find;497b25404e2390e6415726b21a76d36f0e91a11929fb7487ab23fd77acce58a8
Contents/MacOS/mega-ftp;Contents/MacOS/mega-ftp;55cfb9f97e6c8814a2e59f139fad1390bb9b0bcf7699b68f4ffc642e4f858393
@ -63,6 +59,8 @@ Contents/MacOS/mega-share;Contents/MacOS/mega-share;63c4a6c1bf2868f5dac9fcb1a965
Contents/MacOS/mega-showpcr;Contents/MacOS/mega-showpcr;7f6ef6eb29c53580bf4034d16dda0e053af7e186c019e982206d536984b1cbae
Contents/MacOS/mega-signup;Contents/MacOS/mega-signup;ca94246b3f6311a7842f9eb0e84afd37b177a855cdcab31732241349c06cea47
Contents/MacOS/mega-speedlimit;Contents/MacOS/mega-speedlimit;17154a2f88001d7c895d38c31c81957b0d6d6539fb4e3053b01728b9069bcbc2
Contents/MacOS/mega-sync-ignore;Contents/MacOS/mega-sync-ignore;2363ee4e0b8fbe08b7c75af77b95299a1045eaa8d21e21711699727a7ecf4c33
Contents/MacOS/mega-sync-issues;Contents/MacOS/mega-sync-issues;0e9dde40c8429860e27cffd4ba0d742e83b0e3d813b096b19375ae6424766816
Contents/MacOS/mega-sync;Contents/MacOS/mega-sync;ad2340fe390ed1126da319eefcf11a7f94346ff0b90ff70162e929bb830c4875
Contents/MacOS/mega-thumbnail;Contents/MacOS/mega-thumbnail;cc937f5076861b8879801af5efc32974e7564a918a527f08460a86e6c4dfb89a
Contents/MacOS/mega-transfers;Contents/MacOS/mega-transfers;97d83c17ce3ba7c4a422d10b960d8a6808afedd929e5d0e9ce5d7a060a44840b
@ -73,14 +71,12 @@ Contents/MacOS/mega-version;Contents/MacOS/mega-version;3c69fb0a46cdd9ffcc2a5560
Contents/MacOS/mega-webdav;Contents/MacOS/mega-webdav;bcf797f1ca84d18d320457221e944c2f565797c2131bfeab895565ef643f79cc
Contents/MacOS/mega-whoami;Contents/MacOS/mega-whoami;ba6144c61e81af13e2e797b6d1e600cfb00de0b47b02fd639373fbef4087730b
Contents/MacOS/MEGAcmd;Contents/MacOS/MEGAcmd;427fda9b9d57298e7012081cd00d0efc823596403616e94602e86e5c8fac478d
Contents/MacOS/MEGAcmdShell;Contents/MacOS/MEGAcmdShell;d872f64262ac93cd0e3cc5df8947b5477daf902f4320b30007aa1f5b7dbc7776
Contents/MacOS/MEGAcmdUpdater;Contents/MacOS/MEGAcmdUpdater;8df893dfb1e472fb52b9f90268b8a74bde94705d51f97d76c970ff942d06efa9
Contents/MacOS/MEGAcmdShell;Contents/MacOS/MEGAcmdShell;d9f1562a2b2ac67af3db6a5d1888e73c13840634fd36b30c66a3d9d3d0346091
Contents/MacOS/MEGAcmdUpdater;Contents/MacOS/MEGAcmdUpdater;d1ba141e48d8048112ccf5b30ae119073061534770a6a3578dd62d3c8524704f
Contents/MacOS/megacmd_completion.sh;Contents/MacOS/megacmd_completion.sh;35f87a3a37e303cf2e4c15f7fcc30a7ec3703c59a060c0a80a273be58fec744b
Contents/PkgInfo;Contents/PkgInfo;7e50a30efad50208a173203ced60818d693bb61266b75aa10927d1a2adce80cb
Contents/Resources/app.icns;Contents/Resources/app.icns;57d343b7b03e81c2eb8f5bd71002427160650572e4d9c01a94295b316f8330dd
Contents/Resources/empty.lproj;Contents/Resources/empty.lproj;e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
Contents/_CodeSignature/CodeDirectory;Contents/_CodeSignature/CodeDirectory;076110e4aeb72ef5c5da1ba33e0dea6f022d0b5b413a717b199bcea466df8110
Contents/_CodeSignature/CodeRequirements-1;Contents/_CodeSignature/CodeRequirements-1;416aa75f08b2136092153866ae1cfe284e2d3fb1cb3938383baf122027bdc55b
Contents/_CodeSignature/CodeDirectory;Contents/_CodeSignature/CodeDirectory;bb41fc27c14bd488ccb3b5820b99ddcf8fc82137525084d51cb9bad7fe83ccb9
Contents/_CodeSignature/CodeRequirements-1;Contents/_CodeSignature/CodeRequirements-1;c4724569f7dbcf768f672e53121a496e188a5ecffd4f32323600ed23aa4c9d46
Contents/_CodeSignature/CodeRequirements;Contents/_CodeSignature/CodeRequirements;badc6c4e7f899b7b1acead903f9e02ab8a1fdcce7bde4d85cb385fe778f647b7
Contents/_CodeSignature/CodeResources;Contents/_CodeSignature/CodeResources;2bcc672bcd5a11c543d669eec2bdbf42d343e2fc8e5be78010f247fe188332de
Contents/_CodeSignature/CodeSignature;Contents/_CodeSignature/CodeSignature;29d3978934f1c1083ee682e88f2c65cac8bc091c6cca542ad93c4c961f0638e2
Contents/_CodeSignature/CodeResources;Contents/_CodeSignature/CodeResources;56953ca4059f067e0c03ff7e15063d604841af5b18f61f4e774ea20da2a52cf6
Contents/_CodeSignature/CodeSignature;Contents/_CodeSignature/CodeSignature;a9a9bcfc2460896c707115a7420038a84377810054bb5fa3748eb2f39436bb13

View File

@ -1,126 +1,122 @@
#version=1070000
#version=2000000
#baseurl=http://g.static.mega.co.nz/upd/wcmd/
#Hash: note this is the hash of the public key assuming an "\n" at the end
#pubkeysha256sum=1d3a6360832e193cb98707692c3816b5022ec976e2915cee60994ba20e292b4a
api-ms-win-core-console-l1-1-0.dll;api-ms-win-core-console-l1-1-0.dll;213cdeffc15c734e42565c90512491113652de9e52694ae335131d0e24f91df7
api-ms-win-core-datetime-l1-1-0.dll;api-ms-win-core-datetime-l1-1-0.dll;05baccf67fc6360068a9836a1a5ebf0e62697e92990665a6b73ce6c8a4a1b633
api-ms-win-core-debug-l1-1-0.dll;api-ms-win-core-debug-l1-1-0.dll;1c2705257c272c7736ef10b81d65f28fc76b4d34412b8db72f5a23b530d847e8
api-ms-win-core-errorhandling-l1-1-0.dll;api-ms-win-core-errorhandling-l1-1-0.dll;8b3669326bb61770fb013e4d9a9e1722a1c6e4699be4eb61a620bdb64871cb78
api-ms-win-core-file-l1-1-0.dll;api-ms-win-core-file-l1-1-0.dll;6ff3ebd6589cc824e00a9fc548cfcaf8221e046a07f9fb822900d288b9010a2d
api-ms-win-core-file-l1-2-0.dll;api-ms-win-core-file-l1-2-0.dll;62a4810420d997c7fdd9e86a42917a44b78fb367a9d3c0a204e44b3ff05de6d4
api-ms-win-core-file-l2-1-0.dll;api-ms-win-core-file-l2-1-0.dll;6572965fd3909af60310db1e00c8820b2deef4864612e757d3babab896f59ed7
api-ms-win-core-handle-l1-1-0.dll;api-ms-win-core-handle-l1-1-0.dll;cd5c2a10518023d9238f526af78d2fda8265cd10db0edd97be29049ed7aa331c
api-ms-win-core-heap-l1-1-0.dll;api-ms-win-core-heap-l1-1-0.dll;ff80c5e44535b1b623a0320df677a6c6dd106f8a5e14cfee49cd3c9d47589646
api-ms-win-core-interlocked-l1-1-0.dll;api-ms-win-core-interlocked-l1-1-0.dll;4c1e732b43efec26d8cc467a5ffc13f062b3e3111cf369a8c94253711c77c330
api-ms-win-core-libraryloader-l1-1-0.dll;api-ms-win-core-libraryloader-l1-1-0.dll;bbdffc7563c7e4eabce9fc8ff8a3160c7e4d75d5bd50786cc6621e131f668d40
api-ms-win-core-localization-l1-2-0.dll;api-ms-win-core-localization-l1-2-0.dll;3dd2e16b6f135cdd45bce4065f6493540ebbaf2f7f1553085a2442ea2cf80a10
api-ms-win-core-memory-l1-1-0.dll;api-ms-win-core-memory-l1-1-0.dll;031b58e1621211ed8f41aed863e5e4c05c271d5fdf8abd51aa8e9d5eb3536511
api-ms-win-core-namedpipe-l1-1-0.dll;api-ms-win-core-namedpipe-l1-1-0.dll;1920e3afa821558badeaba7bda9b8fe4ed5a5e7bdbb9f85b31d92fc0452030f4
api-ms-win-core-processenvironment-l1-1-0.dll;api-ms-win-core-processenvironment-l1-1-0.dll;5009391754032b93bc3f950b5e17d4ed7bfd37941170f97f65c596d9ecdf8e75
api-ms-win-core-processthreads-l1-1-0.dll;api-ms-win-core-processthreads-l1-1-0.dll;d7716ba9db032b306be6b48e93b379b4e0a9e763a12671441422507236abecb5
api-ms-win-core-processthreads-l1-1-1.dll;api-ms-win-core-processthreads-l1-1-1.dll;3a5d176b1f2c97bca7d4e7a52590b84b726796191ae892d38ad757fd595f414d
api-ms-win-core-profile-l1-1-0.dll;api-ms-win-core-profile-l1-1-0.dll;49e587c970471a29bc49b8ace18510b4bd2b1a561484314cddddd10fbf5334da
api-ms-win-core-rtlsupport-l1-1-0.dll;api-ms-win-core-rtlsupport-l1-1-0.dll;0d365a06fad099cfa98dc2ddf0ca16dabbc5319b99c29b49be25f3c9809da2d9
api-ms-win-core-string-l1-1-0.dll;api-ms-win-core-string-l1-1-0.dll;3c48d059b21126a3755e676758df54b6779c975d13cfd10990a3c29ccfd95571
api-ms-win-core-synch-l1-1-0.dll;api-ms-win-core-synch-l1-1-0.dll;c8925ee61e3135aca8b56498c0304bf0db981930d1e3d36ccae2f84791c86908
api-ms-win-core-synch-l1-2-0.dll;api-ms-win-core-synch-l1-2-0.dll;42367b6b7285bddc185c0badefe49e883646f574b1d7d832c226f2d1ce489c5b
api-ms-win-core-sysinfo-l1-1-0.dll;api-ms-win-core-sysinfo-l1-1-0.dll;77b5019d54aa05ad70d0c1bec4a7ea5f3ba499b493c03ea198b27ceb8509d1af
api-ms-win-core-timezone-l1-1-0.dll;api-ms-win-core-timezone-l1-1-0.dll;4f77abb5c5014769f907a194fd2e43b3c977df1fb87f8c98dd15a7b950d1e092
api-ms-win-core-util-l1-1-0.dll;api-ms-win-core-util-l1-1-0.dll;8c2d5915b436c2848cefac33ae47e5ba1e96eba0310b9836f069bb5c767a7d42
api-ms-win-crt-conio-l1-1-0.dll;api-ms-win-crt-conio-l1-1-0.dll;687be4f560dc3fb96bcda9332617a2d4b1d587411dd1c31ad088146ac0b24a76
api-ms-win-crt-convert-l1-1-0.dll;api-ms-win-crt-convert-l1-1-0.dll;347ceeb26c97124fb49add1e773e24883e84bf9e23204291066855cd0baea173
api-ms-win-crt-environment-l1-1-0.dll;api-ms-win-crt-environment-l1-1-0.dll;cf601a7b883bb4fb87c28b4a1d9f823d2454b298cdbcb4da4f508db8bd1278ba
api-ms-win-crt-filesystem-l1-1-0.dll;api-ms-win-crt-filesystem-l1-1-0.dll;6cc23b34f63ba8861742c207f0020f7b89530d6cdd8469c567246a5879d62b82
api-ms-win-crt-heap-l1-1-0.dll;api-ms-win-crt-heap-l1-1-0.dll;a3f13fa93131a17e05ad0c4253c34b4db30d15eae2b43c9d7ec56fdc6709d371
api-ms-win-crt-locale-l1-1-0.dll;api-ms-win-crt-locale-l1-1-0.dll;4615ec9effc0c27fc0cfd23ad9d87534cbe745998b7d318ae84ece5ea1338551
api-ms-win-crt-math-l1-1-0.dll;api-ms-win-crt-math-l1-1-0.dll;190a2cc8c8e47fcd4d07b4e260e247fb3b5fb4661aa50f7b05158cd062d80762
api-ms-win-crt-multibyte-l1-1-0.dll;api-ms-win-crt-multibyte-l1-1-0.dll;b05a5303c9c1059216787e878884b96474480ae5505dc60be97095f8cdf876d5
api-ms-win-crt-private-l1-1-0.dll;api-ms-win-crt-private-l1-1-0.dll;e5799a718cfa39b0b6ccdc88f3732cd5dd13c5e4a64de6cff4ed4eba20de3371
api-ms-win-crt-process-l1-1-0.dll;api-ms-win-crt-process-l1-1-0.dll;194f04516084785a9650eac58777ae7acebd90d5fabc3e21cebdf705cc0d34b6
api-ms-win-crt-runtime-l1-1-0.dll;api-ms-win-crt-runtime-l1-1-0.dll;078d2551f53ca55715f5c6a045de1260ce331b97fd6d047f8455e06d97ef88dc
api-ms-win-crt-stdio-l1-1-0.dll;api-ms-win-crt-stdio-l1-1-0.dll;e6bab87156c9e7ae14ce36a754eb6891891a22ddfff584b706538152017fbb0f
api-ms-win-crt-string-l1-1-0.dll;api-ms-win-crt-string-l1-1-0.dll;d343529d2a49cbb89d644deafce573b873ab45e0bf57e2d906b2f2a964d7bd9a
api-ms-win-crt-time-l1-1-0.dll;api-ms-win-crt-time-l1-1-0.dll;704ad27cab084be488b5757395ad5129e28f57a7c6680976af0f096b3d536e66
api-ms-win-crt-utility-l1-1-0.dll;api-ms-win-crt-utility-l1-1-0.dll;340ced80fbcfca804925ff680da1929f68b95959fd7e4d0c9f67322bb5fe2155
avcodec-59.dll;avcodec-59.dll;972f2a85d787e01fad9587a86a66e307d102160298ebb24bdc1fadfda3cd139a
avformat-59.dll;avformat-59.dll;bd1c608eb2a739d46c64668c8738d54c2e2c3ba42d8675e0d1fe5012dfd2d599
avutil-57.dll;avutil-57.dll;ae7735084049d72d4f1dba73963faffce1a1a3ae24c0fd37ceb47705c90aa4d1
cares.dll;cares.dll;7e04b2ab55612b3c71256da2a4a2a2f4ffa498d532459536dd4cd0dcdf2c4470
concrt140.dll;concrt140.dll;1cddacbfb0c61652fcd543fef1e72cf649e27f3ee8f0d1c0d3988c0b5093e74e
libcrypto-3.dll;libcrypto-3.dll;57ecc4490508ee741886912dfc3d59c88cf86eb733daf5c54a0a3f275e08512d
libcurl.dll;libcurl.dll;f9fbaca3aea435b5ea73c91d3957b4d6e4022f0bf70d9fd43eccd93586a2e437
libssl-3.dll;libssl-3.dll;ce9ba129dd8ea500ef44e8dcc326f752d6d2bc3e87ee2f0c7aff604b03d92496
api-ms-win-core-console-l1-1-0.dll;api-ms-win-core-console-l1-1-0.dll;0dbd6a13824e330165c43c5117c9fa40f0a10cdc4c6510454f342f2e1a51613b
api-ms-win-core-datetime-l1-1-0.dll;api-ms-win-core-datetime-l1-1-0.dll;286aca8a2ea785ced5570aa0f1071e19d4a3dd08071503cfc8bd0d61f0a954f3
api-ms-win-core-debug-l1-1-0.dll;api-ms-win-core-debug-l1-1-0.dll;6107ef427edd7b89e0e8b8efd296e6481fe190e661bbffc7c24ee29faf314d46
api-ms-win-core-errorhandling-l1-1-0.dll;api-ms-win-core-errorhandling-l1-1-0.dll;e26a8aeea94d3c91511651b556507b98eabfe811dae24a4ef3171f9ee76bb5b0
api-ms-win-core-file-l1-1-0.dll;api-ms-win-core-file-l1-1-0.dll;e4bf8a3fa4f20e9ba6a18a9ffa6b0996cfcd642d2fc7daabd1f5a562a2605b72
api-ms-win-core-file-l1-2-0.dll;api-ms-win-core-file-l1-2-0.dll;c35468a6aca68f379c1408031ebdf8d1d13ff0ddc34e981b5ac40f1fa28931c4
api-ms-win-core-file-l2-1-0.dll;api-ms-win-core-file-l2-1-0.dll;e6a69128016cd321b406a2235d119b02d5140296ca2cd73d24fb0358a956ed21
api-ms-win-core-handle-l1-1-0.dll;api-ms-win-core-handle-l1-1-0.dll;86395deb6ea7af94289e1661a178931878e04a1dc31a45e757904ceacf7c1942
api-ms-win-core-heap-l1-1-0.dll;api-ms-win-core-heap-l1-1-0.dll;15c7b7eae718f91465fb9eea408ebd810f227276709120b1d62d5bacd2ebda6f
api-ms-win-core-interlocked-l1-1-0.dll;api-ms-win-core-interlocked-l1-1-0.dll;89cdd11237e3a1c8b166a0a3d75140af78583a70a963c6b840b60771ff532a3e
api-ms-win-core-libraryloader-l1-1-0.dll;api-ms-win-core-libraryloader-l1-1-0.dll;ccd4ba2311d007cc99ab37c4c11a8aaf0f8e004fce1d60bc30e45723a58ebcff
api-ms-win-core-localization-l1-2-0.dll;api-ms-win-core-localization-l1-2-0.dll;4483be14a92203b0cfa4dbc635cedf584912d74c74fda3291c638294e70d2fc6
api-ms-win-core-memory-l1-1-0.dll;api-ms-win-core-memory-l1-1-0.dll;8baa809ea5a3833f5533b17a206ace82481df8deb74dfacdbf7bd854e281b5e1
api-ms-win-core-namedpipe-l1-1-0.dll;api-ms-win-core-namedpipe-l1-1-0.dll;9b3014a4345a2abf9c6f2e62de7c33d0f390949665617fb1c59f6885c85f21b7
api-ms-win-core-processenvironment-l1-1-0.dll;api-ms-win-core-processenvironment-l1-1-0.dll;1457543a4dfad7766acaf5f9974667621e284087925c0946441a45ffde88b5c1
api-ms-win-core-processthreads-l1-1-0.dll;api-ms-win-core-processthreads-l1-1-0.dll;de9913163ed36db9d6bc7926c1b392ec4d75e460835ba4b7a8e51fafe872109c
api-ms-win-core-processthreads-l1-1-1.dll;api-ms-win-core-processthreads-l1-1-1.dll;f1ba9475a5ad7fee3826de5b2363b19d574e2c48ceb4f9effafa97a7fc2c2c95
api-ms-win-core-profile-l1-1-0.dll;api-ms-win-core-profile-l1-1-0.dll;7ad3da8908e8f824dc53f9886ee69edf28dc513f970a2a53506a7ccb63a443b7
api-ms-win-core-rtlsupport-l1-1-0.dll;api-ms-win-core-rtlsupport-l1-1-0.dll;240f3027579d782b55cf5f043e2bcaf96c58046f7eb1b9289895930ca38b6421
api-ms-win-core-string-l1-1-0.dll;api-ms-win-core-string-l1-1-0.dll;780e6a825d4be11817c650ac544b85d3516a8a2dd2bf8150d2c782b7eb1d68aa
api-ms-win-core-synch-l1-1-0.dll;api-ms-win-core-synch-l1-1-0.dll;08d9bcd59e447f3c99170ccdfede4d47737d3362398d25fc6c871fb3ec79d52e
api-ms-win-core-synch-l1-2-0.dll;api-ms-win-core-synch-l1-2-0.dll;e42313934eb3de9129f95963589193b1341461e715b6b8ed06dc7bd910043249
api-ms-win-core-sysinfo-l1-1-0.dll;api-ms-win-core-sysinfo-l1-1-0.dll;17b0ab4de61eec301a3db893a6aec480f84080a73ab4bd06657d1dd27404ea6f
api-ms-win-core-timezone-l1-1-0.dll;api-ms-win-core-timezone-l1-1-0.dll;effa64deaa9871fce680fe4d0286234c604d420b6c2ecc05fac0c2f9de56cf33
api-ms-win-core-util-l1-1-0.dll;api-ms-win-core-util-l1-1-0.dll;069d50a1253397985c9f774114534f0369ec8d178c1f07cacc1c4af3411dd57d
api-ms-win-crt-conio-l1-1-0.dll;api-ms-win-crt-conio-l1-1-0.dll;d5571d47740d9bff9e13b49aa2be1657e08d819d6422fe352e83f006362e1296
api-ms-win-crt-convert-l1-1-0.dll;api-ms-win-crt-convert-l1-1-0.dll;cd5003a91a604e1ffc72b63f4cd59caac1578a116d13064fa765318f97e43e00
api-ms-win-crt-environment-l1-1-0.dll;api-ms-win-crt-environment-l1-1-0.dll;dcd2e26fd2964f722317f2fafbabbe8c2f61a96785f5bc0aeb2ce583469f2357
api-ms-win-crt-filesystem-l1-1-0.dll;api-ms-win-crt-filesystem-l1-1-0.dll;52e5555f58e5803f41ba628e0150fea780defb2040dba6e81cdb6d05c16a0272
api-ms-win-crt-heap-l1-1-0.dll;api-ms-win-crt-heap-l1-1-0.dll;6823f436c41df41252bbb4f16d8888e8020960afc0c217c0dfa1673c760c72b9
api-ms-win-crt-locale-l1-1-0.dll;api-ms-win-crt-locale-l1-1-0.dll;fa285f2f45b36988d3b6486f8f8a6ab535ee80f232cf5d1aea9d85751ab34939
api-ms-win-crt-math-l1-1-0.dll;api-ms-win-crt-math-l1-1-0.dll;12900f76f2874fb75d922e460c075334571d28b264ac2894a98b29da04d737f4
api-ms-win-crt-multibyte-l1-1-0.dll;api-ms-win-crt-multibyte-l1-1-0.dll;0d3decb779c934ffd831eba92a80ecea9420d9839bb1fa879921e8dfa1ff6963
api-ms-win-crt-private-l1-1-0.dll;api-ms-win-crt-private-l1-1-0.dll;1677c9571d17ebc1c4dbddd8a17833cc73780c19b52fcc68abf2a90f4665aa5f
api-ms-win-crt-process-l1-1-0.dll;api-ms-win-crt-process-l1-1-0.dll;fd4e81019d0ddd13cc61fa5963d7d8cedb703f0ec952333170ad0b758eb1ff40
api-ms-win-crt-runtime-l1-1-0.dll;api-ms-win-crt-runtime-l1-1-0.dll;55ade67a6e64caa2b624187f875ee562ffac8eac5a2d49d06d935c09812e2cf5
api-ms-win-crt-stdio-l1-1-0.dll;api-ms-win-crt-stdio-l1-1-0.dll;1a01f3af5a35594b1b92c2e4a244b7d5c1ce1d6d75e394d8d45456fc19446a4c
api-ms-win-crt-string-l1-1-0.dll;api-ms-win-crt-string-l1-1-0.dll;7edf261a399f10359bd833766bf0ae2254e86dc86305da28e69be8b731c78c48
api-ms-win-crt-time-l1-1-0.dll;api-ms-win-crt-time-l1-1-0.dll;10bb36bb6f91219371fd5f93c5155aca4c65a0c665f8318a4b6c84763fc66430
api-ms-win-crt-utility-l1-1-0.dll;api-ms-win-crt-utility-l1-1-0.dll;f07d088f2a5eea9413bc3aafbcaab9ae73ea8a1691026d5ee898a34c939d52a3
avcodec-59.dll;avcodec-59.dll;d2855b02ad0a2e36fa1a267fbfd7a8bfd3b78da5f1383dc000202a6913ac1e11
avformat-59.dll;avformat-59.dll;94d0bbba5f5a761cb7047bc005f999edb1ccff8e4b76b3a265906f76f3186c83
avutil-57.dll;avutil-57.dll;3b905870f8d44107f6a04a3192b0de4ca35f2e80425e5a764a20d2b4c7302fe4
concrt140.dll;concrt140.dll;0604ee7df2abb2272e2d6fc3615bbfc7c1e385bc9f7f3a3efb780570499055df
MEGA Website.url;MEGA Website.url;7b5f1278de755dde65017404b662b6ab97fa7328974eec3872ce571f7e462dac
mega-attr.bat;mega-attr.bat;89a1b21160a0e3890c45596d7832ff37474a2c3200423f23adee11ff676b295b
mega-backup.bat;mega-backup.bat;167d72cbaa49b8c6c54d57ab44ad9e907f4bf9551460574f4231a9dd956c4c32
mega-cancel.bat;mega-cancel.bat;aab45aa9eac5e0b9865f44a234f6c5cddbc3b2fcb14aa4fee101cbcef2ba37d8
mega-cat.bat;mega-cat.bat;03d39664173b9baf2ae530b457510c4ee915e9060be46063511ed903d3afa265
mega-cd.bat;mega-cd.bat;d3b331e8568b4aa59710b2a731541d625138fa0d37aa26fda679a6b8713827ad
mega-confirm.bat;mega-confirm.bat;e45eeac40ace7b050f9747d79954c4b7bb82792b727a691799694f109938b338
mega-confirmcancel.bat;mega-confirmcancel.bat;5c3128dfd3f4d604afa6e602aca4a346d758d889400eb74584c88f1e40fe9bac
mega-cp.bat;mega-cp.bat;f5cc9ce16100354271c7b385377053076c486cba84f21151a65721d24caecf09
mega-debug.bat;mega-debug.bat;df39fd5831826cb988eb5bfdfb4a98ca75eda8c03f6acdc286a7741448849c9b
mega-deleteversions.bat;mega-deleteversions.bat;ac1d8b0b8458ec134d5c85fa863c3d8ed016e35454dedae79698ad0818919b7f
mega-df.bat;mega-df.bat;b47b85efda1561b559c7d1a81e0d4b49958607f6e4933bf46f97f43c917f69a7
mega-du.bat;mega-du.bat;fbb81f40c843fc33e57a23db01ee0f206c99c6ed75520a5594e0b3d525725215
mega-errorcode.bat;mega-errorcode.bat;f5793c201602a3619cac14d31d0356d058d8128b13027b1e64073dd029193614
mega-exclude.bat;mega-exclude.bat;a347a180847fa3dca00bc28dd1321f5b332fdf574c73ea2b30ef3fab63b2380b
mega-export.bat;mega-export.bat;30fe5d62f0f47418dc83e03bc80977426010c8edcf01e4e7db820965e2781442
mega-find.bat;mega-find.bat;0e683610f7369c674cebc1ecf8d6e030f0433226887b902e74fe1e174c23a6a7
mega-ftp.bat;mega-ftp.bat;df52291409a56fd512402124a94b51dda27c0b5caf2c93d36932e6ce2268bb3c
mega-get.bat;mega-get.bat;b309f0785461dbe35a63b0a674cc70381ef7f87720d2aa884a8dbc8ae3c2c42e
mega-graphics.bat;mega-graphics.bat;d692deb721e9ac81db35e26542abbc64f26aebb0f232dab53d390de7a03461da
mega-help.bat;mega-help.bat;8558ee2389b4493ff9b3d9bcab252564a817284583d651649ce79d7091ea45d3
mega-https.bat;mega-https.bat;91c60eb7b5f95951e96a2437ee51dbae7821377e8e4864279b41c53791481b6a
mega-import.bat;mega-import.bat;90eff64c5a742c7d96d87648a15bcb33145ebebab593f0c0161dae22880b90a0
mega-invite.bat;mega-invite.bat;7d9713740d78deeabff15b6080a387460a315a680777d4f1e04c498f1b708826
mega-ipc.bat;mega-ipc.bat;04fe985dcc18c3ab8dc4ecf5ebf61ed9dd4bafdcd0937c8d10235c98b2f4a9ae
mega-killsession.bat;mega-killsession.bat;7b2aeb01bd57aa53f1d615294fa425aaa3d82f43474ed529d9a33efb873a183e
mega-lcd.bat;mega-lcd.bat;776a5e227d275f6a777ea5c7886e69efe5b9ee9da3fd79700965f4809cde5d27
mega-log.bat;mega-log.bat;4e703495f3616dd936afdfa2c32958189ae5e90328d9389b86e49a50654e6393
mega-login.bat;mega-login.bat;9bc358f934bfbeb12347083aef6b7a6efe26846b83ce0e653a4b89c64ba89073
mega-logout.bat;mega-logout.bat;ab36f1dcf6cfd93b95bf5394b1ef22deff505df685c9b0a36d25fa9c94f4b548
mega-lpwd.bat;mega-lpwd.bat;6364d746c3f1f0329fd67cec0f6a1f09ae3e521f3ef37b0ab728009cf55c4a5c
mega-ls.bat;mega-ls.bat;d57684855baf42e911b235c7ffb5a106aac875461d5faeb059c4d941e7b5cfd6
mega-mediainfo.bat;mega-mediainfo.bat;59606376cabc50a19af3732cddbbcda40c59e0c85aa6bc0320420a6a19abca49
mega-mkdir.bat;mega-mkdir.bat;690c56c5ebd58d596632a4ff28596df8aa478309fc979b9eb8b07fb89db4d944
mega-mount.bat;mega-mount.bat;6f0a3e80dcde8611beb4ac1d9e575601997e58b9a4a17054c5cb4eedf6f8062f
mega-mv.bat;mega-mv.bat;4e694c7eb85dcf55d7642f3504a5d63493e46ebd711735c57a45569ef2a7b88a
mega-passwd.bat;mega-passwd.bat;0f5947f5dbd2543c49853451d6d0deb64b04796e4c61327a1b5aa1c295b2a861
mega-preview.bat;mega-preview.bat;caed90cc51561edd29eb5e842c266add1bb477261cf5254a0e2c218ed0737b93
mega-proxy.bat;mega-proxy.bat;a22417b2eccc3ab5a32aecee8bd004cbbef73fe80d58119d23223163985d1f6b
mega-put.bat;mega-put.bat;a20fb6cf0d1e9c86de68b8665fbbf0974b04c69beccd41d7123f6b3004221beb
mega-pwd.bat;mega-pwd.bat;38744af426f8304c5ee9c2857291225726bffe2788870f2cb9e6a3b8836297e6
mega-quit.bat;mega-quit.bat;44026a4ab85bb59d02241e400848ac77be17c60fc86a0d07055e8ed8fe490ba2
mega-reload.bat;mega-reload.bat;4a0231a6f5ccb7f5908a9d7f12987efa1b45ff2148214360b4a205f15e77075f
mega-rm.bat;mega-rm.bat;1e55e2b5357bce9f5fa54d2a12801dfba6c70262a6ddceae4b227a014db0aa92
mega-session.bat;mega-session.bat;20c963d0749b58afccdb7d45ff36451015689bec1c035ee7bf809c7ee5b6b483
mega-share.bat;mega-share.bat;66fc8fa5564448729b569b843c158d933d8774666651f98cfbd757ea9d721d94
mega-showpcr.bat;mega-showpcr.bat;e5d799f4ebb0f0a02c6c7efb0fd946a9a9f7b8283c5ccb697132974711060ccf
mega-signup.bat;mega-signup.bat;f64064f35b2c464cb20fdcb70a8aa73856b6a8af65acd5be8d58b79df9889c1c
mega-speedlimit.bat;mega-speedlimit.bat;c6f2a4b09f9249c4e77ad03cc0e15940f080c125187137bc88a7d2adf2a4916f
mega-sync.bat;mega-sync.bat;c39719e5e79043b28a6368cdc942032bf5b2ab18fff2f66bd726058e9e921ef7
mega-thumbnail.bat;mega-thumbnail.bat;58574690db6cfff0ffa7864a0a13265ae1bd37d5fc3b0d9e0c88a1f7d69c193d
mega-transfers.bat;mega-transfers.bat;6f35a34033499938700e42f4123399f711003d2dab83ed50e69f7df5ecf976d8
mega-tree.bat;mega-tree.bat;92a11c9ee2af4ffb55d05210813c7ff309f90274a1d211018acc2643367b2534
mega-userattr.bat;mega-userattr.bat;a48dfc0e20bd69e3774d74860f2a74691addf9fbaae42c71450561a4d526f92a
mega-users.bat;mega-users.bat;24d85b5700f05d7b638d294c87e8b8809df80f0611c63ee818f60ed487f1b4bc
mega-version.bat;mega-version.bat;b69c2f0acc58d45ae4dae502892af08ce9abaa0de2433573a07e9a06fae3a255
mega-webdav.bat;mega-webdav.bat;233717710c3ac45906e2cbd110a167d7779bd6697a508013c5b6559bbce97815
mega-whoami.bat;mega-whoami.bat;b6ff6c05c78901dfc6291751bab1ae93a0ac836d8d506e57d2bb6fb927facc7d
MEGAclient.exe;MEGAclient.exe;ec47410a39b921fa6e88237eeeb8b74bf598ab3bff2b736d766a09b557d41fff
MEGAcmdServer.exe;MEGAcmdServer.exe;5267ce6ef96a186aabea878e57d9e80ede18c0d98e570f74a373827b33ec3599
MEGAcmdShell.exe;MEGAcmdShell.exe;25473a6c0680518b277c162aca631a7f48b3d9a0b7ef0990aec95b3e3e5a79c1
MEGAcmdUpdater.exe;MEGAcmdUpdater.exe;07ea647aa5d0b8f4c06589e0d963faec33762b48168bae5113f182898518b201
msvcp140.dll;msvcp140.dll;5a6dfa5e1ffb6c1e7fc76bd121c6c91305e10dd75fc2124f79fee291a9dd9e86
msvcp140_1.dll;msvcp140_1.dll;4e94f9c89188fba7cae4bde37cf824d654717731559d47985d2b0749cfb11aa6
msvcp140_2.dll;msvcp140_2.dll;94a12bedb9a25393dc75fccde7243d5e90acf40b1f14406132a44ff42e220f2e
msvcp140_atomic_wait.dll;msvcp140_atomic_wait.dll;641613d28d039af4c9efa79303b6f57825fe9f43c345fe06b45094d61c5e8a66
msvcp140_codecvt_ids.dll;msvcp140_codecvt_ids.dll;74ee4398ae24c1b787af944d650aa345ba0e9787cd112542d782b714209e35cc
swresample-4.dll;swresample-4.dll;4bc8c640aaa42aa5ef3e711b16c6e2de711a237abc10055c15564d91b49c1d60
swscale-6.dll;swscale-6.dll;4d36dfed7746024d187420e8a98e5f080ce8f2ae0ff61541809130f5ca5067d3
ucrtbase.dll;ucrtbase.dll;10f8f24aa678db8e38e6917748c52bbcd219161b9a07286d6f8093ab1d0318fa
uninst.exe;uninst.exe;0c668357e06963fdf28dc80f6336336e452055cf76b0bd67c691906453e17e1b
vccorlib140.dll;vccorlib140.dll;d43812f712f02a50017128463c357eae8f78b665353f889848f59a9faefd8ff7
vcomp140.dll;vcomp140.dll;de30db4af8ae1790048168a13913318e66aa1d2feb0b45a62983c10caecd9772
vcruntime140.dll;vcruntime140.dll;f1fd5f6ec1cfe0cc3b66b5322ac97568bc63b19c1e415b99aad7c69ddbafa33c
mega-attr.bat;mega-attr.bat;7a5b5b221bc921a5eb98633f519b2141bd0daede6eae40cba113333992967de7
mega-backup.bat;mega-backup.bat;d0df6b91202750d3b13071e3e231c1954ff032c1340cf051e968a91d74dbb80a
mega-cancel.bat;mega-cancel.bat;fa68a5dd1e0051425c3e8c41f5695810eadc2058397046b1848a0599f47c9953
mega-cat.bat;mega-cat.bat;6225ce58605e8795fe2e48220607ac193744cb313cd181fb6e90a190484a9bbf
mega-cd.bat;mega-cd.bat;c102ccb99cf3e83b1eb0886b15ed5b3e5deff7b2fedfba9408558cd9aa8f1e18
mega-confirm.bat;mega-confirm.bat;7ce93a6a402b631760477079861796cf1dd25517866cbd2d5be27635d7783fee
mega-confirmcancel.bat;mega-confirmcancel.bat;dde5415005ad473cc98ef9b9b28f210350bb8d4efca6f4af8eb63d394efdf0e0
mega-cp.bat;mega-cp.bat;36292230fd45e595e98667653646ee1baaa87bc4e9b22b566ec5bc0cc7347821
mega-debug.bat;mega-debug.bat;423e02ee02c0d24e2aec7c02ebc295954d2d2ab3166f1174ef96fc5111179d0d
mega-deleteversions.bat;mega-deleteversions.bat;c67afe7a90012f5885348d6ca6bb4abbf27f9b891ec61204fe53763281505c13
mega-df.bat;mega-df.bat;b98a9f278dbc417aa51c4eb34af5cfe076be0e5700dbae1558b7aa381a926881
mega-du.bat;mega-du.bat;1e91bfb1ad81e12c1068f42b612e95c986ff6807919195188f3a4cacf692183f
mega-errorcode.bat;mega-errorcode.bat;d431d2d116ccfd9f01d4f54f9580fa89615848aa6814b7d8f2da347b3127050a
mega-exclude.bat;mega-exclude.bat;ab9f76a28ba0a5efb0eb2e240e599409d6d6380a18dd680f93bc3d705409b299
mega-export.bat;mega-export.bat;42dd5f70a8f78854e01b175fa7672b2a0d894da716a910807e2373e2dd983947
mega-find.bat;mega-find.bat;08147ae1b71d69a09f48ea145f183fba304a2884e5b27953fc89943ba41df69c
mega-ftp.bat;mega-ftp.bat;8c049a43a7f13856bf8f6667beb6a5496a4b0e111a5a3afb40b7c1f36b97e456
mega-get.bat;mega-get.bat;2e40e197c0fa5b74cb164f2b696cc064de1b356c42450c1028e77568efdc1eff
mega-graphics.bat;mega-graphics.bat;3c91e02f744d7b84cb76577bf354a54adce1562e7bfcea98588a3204a82ed396
mega-help.bat;mega-help.bat;cef87d1319c235952d238bc5111935bc8312bb1cfc17d61e522151077857715e
mega-https.bat;mega-https.bat;1cf2a5175ee289514f70c8f956145725dd501c3fd9860413bc77abc93022b57d
mega-import.bat;mega-import.bat;3343902b8d3cbc6f62529d6920178f0e6042472f2772a08df15ed73121d04619
mega-invite.bat;mega-invite.bat;20be9c6d549733269ac7a9ce7ab3928c29134625b1e84eb54e52cda192774a55
mega-ipc.bat;mega-ipc.bat;7b29de9117b7b48d9e57ac6a0df6e7b229905ab3d5858daccb354116b0039ba3
mega-killsession.bat;mega-killsession.bat;9f83aada9c370952e9b49a9c41eb7d98f30e5b024d070e371244ee6b76f64c96
mega-lcd.bat;mega-lcd.bat;de56d34a0e884ce8691ebc86ac55832a5d8a22eb5eb5fdbe345d69301500f746
mega-log.bat;mega-log.bat;ebbb6703ef76be60e030058b2ca56934fa573d9891096bfb43be5b7adcbc14cc
mega-login.bat;mega-login.bat;af44e84d703d44e46e8aba3b9e6bc8d0d4304d143493fd14eaff70742013ab81
mega-logout.bat;mega-logout.bat;b10da32e4da3c750ce8874222b7348a58c9c61f7d2ec11f73c91fc7d31722a02
mega-lpwd.bat;mega-lpwd.bat;eefe4d679a99d507cf49d434746b22bc3d312802b9a4ac48824e0d363b8c1b12
mega-ls.bat;mega-ls.bat;cfc0d9ce93645ae56a5e9e27a6d59090b615027a4678e4b8ab57f86b2c49d5ad
mega-mediainfo.bat;mega-mediainfo.bat;7364d4c609c2030136837f70765586494d6951058530d828b75e57eedcac2626
mega-mkdir.bat;mega-mkdir.bat;1535df364439afcf86860495c71eccb1b40cc202f30d3180a30b389298ffbbd9
mega-mount.bat;mega-mount.bat;22b5c4a02c0df84d025b6315b8f8098b0be250b1237c8aad89f07c3b707073a7
mega-mv.bat;mega-mv.bat;bd253db0f09da734afc3c6d31058fb20551fbc18197e85e9bdf52d62e00fdfaa
mega-passwd.bat;mega-passwd.bat;3aa3bedfc45eaf3f1e1609fe96b028821a79d1915a5b930609a8ca2b3730c2dc
mega-preview.bat;mega-preview.bat;54a263b9fe0ac933aa77b73a5219bb0fa813ea0501ba331dbfb7b16c61ea5cef
mega-proxy.bat;mega-proxy.bat;f323cf922dee4aac447b504399c367ed45e752a6cbe0adec5c68a675611118b6
mega-put.bat;mega-put.bat;ca3e2c5aa77a6b7b4a9a4d7699416e714a9aa027c7d68fda47023405716766f8
mega-pwd.bat;mega-pwd.bat;cdf78fb7b00f2c50db3672a02923bfd05d380741b582570db194ccf7d4b22033
mega-quit.bat;mega-quit.bat;bb82d8e26f81007f19683422bc021791d1ce74fd5f11f3c1c29307a6b98752f0
mega-reload.bat;mega-reload.bat;9e0d368d6f7863944711697cf54e1201c405ab37b8f1ebbf520ad15d0c96f4fa
mega-rm.bat;mega-rm.bat;7e503e07f13199e35faad58590b56938ab53b14745afa5f596f31f8921c72859
mega-session.bat;mega-session.bat;91a24d34d4752deb4a76215f564f202edb9eaba2285b5f26f3f9dc40aad7c702
mega-share.bat;mega-share.bat;270c97a6e71b03a67297a534dc1d7299fe801f9c654f68e0fbe0276a65921054
mega-showpcr.bat;mega-showpcr.bat;39a7f816821855676392dcb437378bfbfa61a595748af6a4b82e43cd9704955d
mega-signup.bat;mega-signup.bat;6e8c13eb91c9d38d2ce48c75c569bd151d3f3c7641e3b2b3ed04994ae3e4a33f
mega-speedlimit.bat;mega-speedlimit.bat;c037351ecf3cd9fae0b1416b60cd651fe317fc57fd06f996c9b7f6450c9a07b3
mega-sync.bat;mega-sync.bat;62a2334922a0ea0867b2a71a6900e44975b03612dbeeb181aca6d44d48222922
mega-thumbnail.bat;mega-thumbnail.bat;8f7b42ac9e6358534bed0355e70b6f007070006f38328e35c860ff502d4768b4
mega-transfers.bat;mega-transfers.bat;38b4bb079557909927336aeddda2c8f937b5d089b2bfe224cb0b895250b85d5e
mega-tree.bat;mega-tree.bat;0f03785c46a12893100f360da48fb473de9011bffd9562a327aa76626078d263
mega-userattr.bat;mega-userattr.bat;28cede25ba267f57d1c60b531764f1290a8fc78b64b1bcc307b0e23f5fea1bd2
mega-users.bat;mega-users.bat;6f4499de547c0d5c5bcba21d5c226bb83a6f01909d9fc4cd1c578c4bdc8e6955
mega-version.bat;mega-version.bat;2f1794963704f4dc65e23155ef1fb27788ea48e6099479c4809093f7281c28fc
mega-webdav.bat;mega-webdav.bat;97c8f94a273c7d7d9e5b6b1929a8e227c3a15d6c09c8124f12d7fe3723a7beae
mega-whoami.bat;mega-whoami.bat;48f9d5104bb5364f6831b11d9847871c528ad656655c3fa49ce9be70e932767f
MEGAclient.exe;MEGAclient.exe;5ddd680fe8df08a840f96c337f8cff6d58cfbb958aa137f9787f980546d75dee
MEGAcmdServer.exe;MEGAcmdServer.exe;fcc11cbbe4b26e37dd6a024f4ae8eb89c8b40395c042c5196a2e2fac29f1129f
MEGAcmdShell.exe;MEGAcmdShell.exe;87372890ba45b72e3bd3645cf191f60148daaf8d6f9767998f660fa877799421
MEGAcmdUpdater.exe;MEGAcmdUpdater.exe;646851e19053237a9412fa2a30d2e637e21ec22358306f5ec4e90f47091c5beb
msvcp140.dll;msvcp140.dll;718812adb0d669eea9606432202371e358c7de6cdeafeddad222c36ae0d3f263
msvcp140_1.dll;msvcp140_1.dll;1ed68ad44005f5db536d720c0dec06e3b096a9887f3412ca99277d520185aeb5
msvcp140_2.dll;msvcp140_2.dll;505cbb87d025355e09eb25686e4b0f617f659af993f9699ad1846ddffc120212
msvcp140_atomic_wait.dll;msvcp140_atomic_wait.dll;f4bc71d60fc5d28a6f6eff967428055f2cdd0189e5cb8d336842baa7a13de2bf
msvcp140_codecvt_ids.dll;msvcp140_codecvt_ids.dll;4a5e991f66087466dc7105b5d67ecdf8c87a9cde085909036abebdf792fa191b
swresample-4.dll;swresample-4.dll;27ff1406ae83ef1428516f8a39b46c89a09e7bb96ce0966d0039c411322442b4
swscale-6.dll;swscale-6.dll;d9bfec0c01f9520980de59a64a2b72a1fc14327ce51f6178ea8ae69c309953f2
ucrtbase.dll;ucrtbase.dll;9793b5f7890034ea345726fc9df07b79f518e1aebef2ab8b3d409f67465cefa9
uninst.exe;uninst.exe;ddbaaeb10dca4112c290188155f1afc8acf30cf9eaa3519634fadae455c5301b
vccorlib140.dll;vccorlib140.dll;cf8d3df3c5374afce1094666b34665dca65743be7cb2e6199131037a344c3d02
vcomp140.dll;vcomp140.dll;c698b3eae090f07231560edbcb5fc3ae5aa6d30dbc3b3d75a7943e924b6b9158
vcruntime140.dll;vcruntime140.dll;09d1e604e8cdd06176fcc3d3698861be20638a4391f9f2d9e23f868c1576ca94

View File

@ -1,127 +1,123 @@
#version=1070000
#version=2000000
#baseurl=http://g.static.mega.co.nz/upd/wcmd64/
#Hash: note this is the hash of the public key assuming an "\n" at the end
#pubkeysha256sum=1d3a6360832e193cb98707692c3816b5022ec976e2915cee60994ba20e292b4a
api-ms-win-core-console-l1-1-0.dll;api-ms-win-core-console-l1-1-0.dll;8f8b79150e850acc92fd6aab614f6e3759bea875134a62087d5dd65581e3001f
api-ms-win-core-datetime-l1-1-0.dll;api-ms-win-core-datetime-l1-1-0.dll;913eaaa7997a6aee53574cffb83f9c9c1700b1d8b46744a5e12d76a1e53376fd
api-ms-win-core-debug-l1-1-0.dll;api-ms-win-core-debug-l1-1-0.dll;58a8d69df60ecbee776cd9a74b2a32b14bf2b0bd92d527ec5f19502a0d3eb8e9
api-ms-win-core-errorhandling-l1-1-0.dll;api-ms-win-core-errorhandling-l1-1-0.dll;46079c0a1b660fc187aafd760707f369d0b60d424d878c57685545a3fce95819
api-ms-win-core-file-l1-1-0.dll;api-ms-win-core-file-l1-1-0.dll;5c9bc70586ad538b0df1fcf5d6f1f3527450ae16935aa34bd7eb494b4f1b2db9
api-ms-win-core-file-l1-2-0.dll;api-ms-win-core-file-l1-2-0.dll;629e52ba4e2dca91b10ef7729a1722888e01284eed7dda6030d0a1ec46c94086
api-ms-win-core-file-l2-1-0.dll;api-ms-win-core-file-l2-1-0.dll;dac867476caa42ff8df8f5dfe869ffd56a18dadee17d47889afb69ed6519afbf
api-ms-win-core-handle-l1-1-0.dll;api-ms-win-core-handle-l1-1-0.dll;0b3dfb8554ead94d5da7859a12db353942406f9d1dfe3fac3d48663c233ea99d
api-ms-win-core-heap-l1-1-0.dll;api-ms-win-core-heap-l1-1-0.dll;c43075b1d2386a8a262de628c93a65350e52eae82582b27f879708364b978e29
api-ms-win-core-interlocked-l1-1-0.dll;api-ms-win-core-interlocked-l1-1-0.dll;c23fe8d5c3ca89189d11ec8df983cc144d168cb54d9eab5d9532767bcb2f1fa3
api-ms-win-core-libraryloader-l1-1-0.dll;api-ms-win-core-libraryloader-l1-1-0.dll;f320f9c0463de641b396ce7561af995de32211e144407828b117088cf289df91
api-ms-win-core-localization-l1-2-0.dll;api-ms-win-core-localization-l1-2-0.dll;8664222823e122fca724620fd8b72187fc5336c737d891d3cef85f4f533b8de2
api-ms-win-core-memory-l1-1-0.dll;api-ms-win-core-memory-l1-1-0.dll;5d9767d8cca0fbfd5801bff2e0c2adddd1baaaa8175543625609abce1a9257bd
api-ms-win-core-namedpipe-l1-1-0.dll;api-ms-win-core-namedpipe-l1-1-0.dll;8e015cdf2561450ed9a0773be1159463163c19eab2b6976155117d16c36519da
api-ms-win-core-processenvironment-l1-1-0.dll;api-ms-win-core-processenvironment-l1-1-0.dll;058eb7ce88c22d2ff7d3e61e6593ca4e3d6df449f984bf251d9432665e1517d1
api-ms-win-core-processthreads-l1-1-0.dll;api-ms-win-core-processthreads-l1-1-0.dll;a5b733e3dce21ab62bd4010f151b3578c6f1246da4a96d51ac60817865648dd3
api-ms-win-core-processthreads-l1-1-1.dll;api-ms-win-core-processthreads-l1-1-1.dll;1ef06c600c451e66e744b2ca356b7f4b7b88ba2f52ec7795858d21525848ac8c
api-ms-win-core-profile-l1-1-0.dll;api-ms-win-core-profile-l1-1-0.dll;e63550608dd58040304ea85367e9e0722038ba8e7dc7bf9d91c4d84f0ec65887
api-ms-win-core-rtlsupport-l1-1-0.dll;api-ms-win-core-rtlsupport-l1-1-0.dll;91508ab353b90b30ff2551020e9755d7ab0e860308f16c2f6417dfb2e9a75014
api-ms-win-core-string-l1-1-0.dll;api-ms-win-core-string-l1-1-0.dll;f3a7a9c98ebe915b1b57c16e27fffd4ddf31a82f0f21c06fe292878e48f5883e
api-ms-win-core-synch-l1-1-0.dll;api-ms-win-core-synch-l1-1-0.dll;d6708d1254ed88a948871771d6d1296945e1aa3aeb7e33e16cc378f396c61045
api-ms-win-core-synch-l1-2-0.dll;api-ms-win-core-synch-l1-2-0.dll;72c639d1afda32a65143bcbe016fe5d8b46d17924f5f5190eb04efe954c1199a
api-ms-win-core-sysinfo-l1-1-0.dll;api-ms-win-core-sysinfo-l1-1-0.dll;76d8e4ed946deefeefa0d0012c276f0b61f3d1c84af00533f4931546cbb2f99e
api-ms-win-core-timezone-l1-1-0.dll;api-ms-win-core-timezone-l1-1-0.dll;b0eda99eabd32fefecc478fd9fe7439a3f646a864fdab4ec3c1f18574b5f8b34
api-ms-win-core-util-l1-1-0.dll;api-ms-win-core-util-l1-1-0.dll;f28a8fe2cd7e8e00b6d2ec273c16db6e6eea9b6b16f7f69887154b6228af981e
api-ms-win-crt-conio-l1-1-0.dll;api-ms-win-crt-conio-l1-1-0.dll;e677497c1baefffb33a17d22a99b76b7fa7ae7a0c84e12fda27d9be5c3d104cf
api-ms-win-crt-convert-l1-1-0.dll;api-ms-win-crt-convert-l1-1-0.dll;5cf5bbb861608131b5f560cbf34a3292c80886b7c75357acc779e0bf98e16639
api-ms-win-crt-environment-l1-1-0.dll;api-ms-win-crt-environment-l1-1-0.dll;b7ee468f5b6c650dada7db3ad9e115a0e97135b3df095c3220dfd22ba277b607
api-ms-win-crt-filesystem-l1-1-0.dll;api-ms-win-crt-filesystem-l1-1-0.dll;7102f8d9d0f3f689129d7fe071b234077fba4dd3687071d1e2aeaa137b123f86
api-ms-win-crt-heap-l1-1-0.dll;api-ms-win-crt-heap-l1-1-0.dll;f5183b8d7462c01031992267fe85680ab9c5b279bedc0b25ab219f7c2184766f
api-ms-win-crt-locale-l1-1-0.dll;api-ms-win-crt-locale-l1-1-0.dll;2eb96422375f1a7b687115b132a4005d2e7d3d5dc091fb0eb22a6471e712848e
api-ms-win-crt-math-l1-1-0.dll;api-ms-win-crt-math-l1-1-0.dll;a768339f0b03674735404248a039ec8591fcba6ff61a3c6812414537badd23b0
api-ms-win-crt-multibyte-l1-1-0.dll;api-ms-win-crt-multibyte-l1-1-0.dll;7101b3dff525ea47b7a40dd96544c944ae400447df7a6acd07363b6d7968b889
api-ms-win-crt-private-l1-1-0.dll;api-ms-win-crt-private-l1-1-0.dll;785c49fd9f99c6eb636d78887aa186233e9304921dd835dee8f72e2609ff65c4
api-ms-win-crt-process-l1-1-0.dll;api-ms-win-crt-process-l1-1-0.dll;3af38920e767bd9ebc08f88eaf2d08c748a267c7ec60eab41c49b3f282a4cf65
api-ms-win-crt-runtime-l1-1-0.dll;api-ms-win-crt-runtime-l1-1-0.dll;d899c2f061952b3b97ab9cdbca2450290b0f005909ddd243ed0f4c511d32c198
api-ms-win-crt-stdio-l1-1-0.dll;api-ms-win-crt-stdio-l1-1-0.dll;f9d3f380023a4c45e74170fe69b32bca506ee1e1fbe670d965d5b50c616da0cb
api-ms-win-crt-string-l1-1-0.dll;api-ms-win-crt-string-l1-1-0.dll;1a916c0db285deb02c0b9df4d08dad5ea95700a6a812ea067bd637a91101a9f6
api-ms-win-crt-time-l1-1-0.dll;api-ms-win-crt-time-l1-1-0.dll;b56bc94e8539603dd2f0fea2f25efd17966315067442507db4bffafcbc2955b0
api-ms-win-crt-utility-l1-1-0.dll;api-ms-win-crt-utility-l1-1-0.dll;dd14133adf5c534539298422f6c4b52739f80aca8c5a85ca8c966dea9964ceb1
avcodec-59.dll;avcodec-59.dll;45e50b64e064a5141a4df2879585157518b16844f6c91eda5586ae46cb943927
avformat-59.dll;avformat-59.dll;70b978af3b037aa18d30a1efcd5ce64293258aa2f9ef66995326b155c3e11b14
avutil-57.dll;avutil-57.dll;37f34550423d69506f18be89e33de605e0264b91124fb506c060f6ff68b0e3a1
cares.dll;cares.dll;5cbb51e0feca7bf313f51c750b962a528e71a82d769871ee73f6cbabc6f8059c
concrt140.dll;concrt140.dll;d1a9b1a0ebe71e886b42a59faa67d4bf7646c3f46e0153dd2519b0e77ebbcdc5
libcrypto-3-x64.dll;libcrypto-3-x64.dll;dea680dfa433abb5749723ac8a4d91a0bcd1e1dcbb85a6bdd61161d6b9813128
libcurl.dll;libcurl.dll;6fc08c9f74cdea3bbd493b294c0348f234caefe8cb6e155eede4ddfb1497e701
libssl-3-x64.dll;libssl-3-x64.dll;8595d476b5318a127c8191da929878af83795a666fa901cdcff1770ff1a69c40
api-ms-win-core-console-l1-1-0.dll;api-ms-win-core-console-l1-1-0.dll;22b0d0412c274a04d11d7fd3f6545eff245e6f032e21b86d920c2844dd1007c6
api-ms-win-core-datetime-l1-1-0.dll;api-ms-win-core-datetime-l1-1-0.dll;631a106755f13a78032d7c17cd19c5185fe89d93fda2ac108c4f53e27dcdecdb
api-ms-win-core-debug-l1-1-0.dll;api-ms-win-core-debug-l1-1-0.dll;1ce185afeea0a30a12b496d95df395c18bd0e99570c0ac3126758476d4b6aea0
api-ms-win-core-errorhandling-l1-1-0.dll;api-ms-win-core-errorhandling-l1-1-0.dll;cdbc9ee30658188fd9af68ad52b5d8e7f59111191b0681ec2ed9095d9c85ebee
api-ms-win-core-file-l1-1-0.dll;api-ms-win-core-file-l1-1-0.dll;f36025fd0715ec893c112f06472072c565385b8c5fa675cce5b4a9158bfb87e9
api-ms-win-core-file-l1-2-0.dll;api-ms-win-core-file-l1-2-0.dll;3d95961590fe6da5c569bcb0a54651488e70dd7b15c257e1b9faf8a3cc0e63e4
api-ms-win-core-file-l2-1-0.dll;api-ms-win-core-file-l2-1-0.dll;c6515fb573cd8190ebc401aab4646069066205ee9eeca548ae5ddbec3633336b
api-ms-win-core-handle-l1-1-0.dll;api-ms-win-core-handle-l1-1-0.dll;523b4c1528aab62c5f8622e4e2c4a4ba0df43114098a05f0c58c69c716c42626
api-ms-win-core-heap-l1-1-0.dll;api-ms-win-core-heap-l1-1-0.dll;4fff338c18ab8a1a37d1190e3b9edcca55afa86b0ba0f97d87c4c841e4e29678
api-ms-win-core-interlocked-l1-1-0.dll;api-ms-win-core-interlocked-l1-1-0.dll;841aa4632552c47b43d453968da2c8d0861b1eb776d530a4e985d0290516d6c8
api-ms-win-core-libraryloader-l1-1-0.dll;api-ms-win-core-libraryloader-l1-1-0.dll;e989c62edade6b3333d798e0481f4c2ec08f7d2a0c47acfcca2a869cd4b68a1f
api-ms-win-core-localization-l1-2-0.dll;api-ms-win-core-localization-l1-2-0.dll;945dacfe53f62d83acd0537a6712658558faafb18f68b76b88127db78482fd8f
api-ms-win-core-memory-l1-1-0.dll;api-ms-win-core-memory-l1-1-0.dll;a505bdf2e4dfd5120de230fd9d159ef75aa00fb3f98e24d259f5c0a456713c74
api-ms-win-core-namedpipe-l1-1-0.dll;api-ms-win-core-namedpipe-l1-1-0.dll;b26de5e517b05e10ee34fdf4996f82c465668670329e7f19d21f39a7e39011e7
api-ms-win-core-processenvironment-l1-1-0.dll;api-ms-win-core-processenvironment-l1-1-0.dll;32d11f07156248c7906027e0f17e93e51de848f136e6d3fd0d4f9d1ffb2c70da
api-ms-win-core-processthreads-l1-1-0.dll;api-ms-win-core-processthreads-l1-1-0.dll;562e2619e1e685080faf2122c12ae3c35202ce34ce8330d1ff0a3b566095fd38
api-ms-win-core-processthreads-l1-1-1.dll;api-ms-win-core-processthreads-l1-1-1.dll;73fabc60a9b24c1eb65ec886a59a190046af5853800572df1d48634417a15729
api-ms-win-core-profile-l1-1-0.dll;api-ms-win-core-profile-l1-1-0.dll;2401cc9407ebb1fa60ddf520d422ec1eefec050dd9871554756c869c9b730558
api-ms-win-core-rtlsupport-l1-1-0.dll;api-ms-win-core-rtlsupport-l1-1-0.dll;b5a61cd60ec9088ee27bf61d37c55abc9d6db3f722616d74fc191cf671a4902a
api-ms-win-core-string-l1-1-0.dll;api-ms-win-core-string-l1-1-0.dll;7e97fbf5cee26ab01227d564f023337736310868c1cf23920e4dceeeb1c11701
api-ms-win-core-synch-l1-1-0.dll;api-ms-win-core-synch-l1-1-0.dll;4f47aad2664ed21dd80d30ffd954a34503ffe2493bebb39da058d452212e75af
api-ms-win-core-synch-l1-2-0.dll;api-ms-win-core-synch-l1-2-0.dll;a885774d4a5419db2e9f7fbd0ac06f7244e046aa614cd6585ab22fc428f2c7ee
api-ms-win-core-sysinfo-l1-1-0.dll;api-ms-win-core-sysinfo-l1-1-0.dll;ac3b86a3e66c5ae2cb30d8a386b0574e6b59fe0f549120c16b7790c3489bc593
api-ms-win-core-timezone-l1-1-0.dll;api-ms-win-core-timezone-l1-1-0.dll;003751ed79881bce98017b66206a2ba411321edd61fd51768779f29dfa99968d
api-ms-win-core-util-l1-1-0.dll;api-ms-win-core-util-l1-1-0.dll;eb41c514f2660813fa6ac58a28bcd2adfb64552b945dfcad5123f51a1a71f863
api-ms-win-crt-conio-l1-1-0.dll;api-ms-win-crt-conio-l1-1-0.dll;e7fc8d3956ce856b1ce0b8d16c10fa4c886a33717a64b818aa6d2492d7492429
api-ms-win-crt-convert-l1-1-0.dll;api-ms-win-crt-convert-l1-1-0.dll;4d80b38c49c9e507190b133e97c7b06ac926c5e1d93095bef8e35c51e7be4e3c
api-ms-win-crt-environment-l1-1-0.dll;api-ms-win-crt-environment-l1-1-0.dll;65eb6a1276426e0bffc0a7686770cae2fb15a0f819cab4b96003a292c483ec5d
api-ms-win-crt-filesystem-l1-1-0.dll;api-ms-win-crt-filesystem-l1-1-0.dll;61424c4c6cf665ef1c6e092a105721813d495ff17d81c809b505acf9ac0c575a
api-ms-win-crt-heap-l1-1-0.dll;api-ms-win-crt-heap-l1-1-0.dll;42fed4693a9f2ee8ebb29b34ac92aaef9ff070f609e0cbff74258f65ea53d666
api-ms-win-crt-locale-l1-1-0.dll;api-ms-win-crt-locale-l1-1-0.dll;f2d099d580c733d3132ac3cd0179c7bfa0f1ed8f7bd063e411cd57e920510488
api-ms-win-crt-math-l1-1-0.dll;api-ms-win-crt-math-l1-1-0.dll;8483828a6781dc3cc4a121e2a90f54abb6f6c42680a0634e02db8b736d16f877
api-ms-win-crt-multibyte-l1-1-0.dll;api-ms-win-crt-multibyte-l1-1-0.dll;63c233965965c6eab235c0e1e7530788fee44d5cab910a2cd22d325334a3dce2
api-ms-win-crt-private-l1-1-0.dll;api-ms-win-crt-private-l1-1-0.dll;65e8380924c6b54147185cfd84deb0795c617b8c316d3767daa616f9fd88d6c0
api-ms-win-crt-process-l1-1-0.dll;api-ms-win-crt-process-l1-1-0.dll;f426c73f187c4c3c6759514c11f752a1f8411a1f4392bbee984652e62d2e7296
api-ms-win-crt-runtime-l1-1-0.dll;api-ms-win-crt-runtime-l1-1-0.dll;21c3d46f74f4249c81d723373da639ac2fb2733a626ec11310df49874663d2bc
api-ms-win-crt-stdio-l1-1-0.dll;api-ms-win-crt-stdio-l1-1-0.dll;e4a6bd5d65d39da4424ab7828959cfeb7c362e29008bc63ecf16fb3b20001807
api-ms-win-crt-string-l1-1-0.dll;api-ms-win-crt-string-l1-1-0.dll;a1cf3656daa57afb840714f891e7f072ca56bf5838f525d4394c362ef5c8ed8f
api-ms-win-crt-time-l1-1-0.dll;api-ms-win-crt-time-l1-1-0.dll;fc27f6061faf91d696a2b3685a3bfac4de49fbf78d578b9970e1ed21f683b209
api-ms-win-crt-utility-l1-1-0.dll;api-ms-win-crt-utility-l1-1-0.dll;788611c05ef16759ac57df231b25b413be33fccabbeb446caaf4b5cbedd8e1dc
avcodec-59.dll;avcodec-59.dll;512eccc75c494b7733c619bfa20aa7b2a5dda67d0be6e70dce7ef8ae97f313d8
avformat-59.dll;avformat-59.dll;dc8b124d09871272470ef66cf7cce885b00af05c8512ce060271ba0f8b55df64
avutil-57.dll;avutil-57.dll;00096750c7892e50c38981977354593efbd77d540935eb7a618778be072478d1
concrt140.dll;concrt140.dll;e2e4609c569c69f7b1686f6d0e81ce62187ac5df05e0247954500053b3c3de3f
MEGA Website.url;MEGA Website.url;7b5f1278de755dde65017404b662b6ab97fa7328974eec3872ce571f7e462dac
mega-attr.bat;mega-attr.bat;89a1b21160a0e3890c45596d7832ff37474a2c3200423f23adee11ff676b295b
mega-backup.bat;mega-backup.bat;167d72cbaa49b8c6c54d57ab44ad9e907f4bf9551460574f4231a9dd956c4c32
mega-cancel.bat;mega-cancel.bat;aab45aa9eac5e0b9865f44a234f6c5cddbc3b2fcb14aa4fee101cbcef2ba37d8
mega-cat.bat;mega-cat.bat;03d39664173b9baf2ae530b457510c4ee915e9060be46063511ed903d3afa265
mega-cd.bat;mega-cd.bat;d3b331e8568b4aa59710b2a731541d625138fa0d37aa26fda679a6b8713827ad
mega-confirm.bat;mega-confirm.bat;e45eeac40ace7b050f9747d79954c4b7bb82792b727a691799694f109938b338
mega-confirmcancel.bat;mega-confirmcancel.bat;5c3128dfd3f4d604afa6e602aca4a346d758d889400eb74584c88f1e40fe9bac
mega-cp.bat;mega-cp.bat;f5cc9ce16100354271c7b385377053076c486cba84f21151a65721d24caecf09
mega-debug.bat;mega-debug.bat;df39fd5831826cb988eb5bfdfb4a98ca75eda8c03f6acdc286a7741448849c9b
mega-deleteversions.bat;mega-deleteversions.bat;ac1d8b0b8458ec134d5c85fa863c3d8ed016e35454dedae79698ad0818919b7f
mega-df.bat;mega-df.bat;b47b85efda1561b559c7d1a81e0d4b49958607f6e4933bf46f97f43c917f69a7
mega-du.bat;mega-du.bat;fbb81f40c843fc33e57a23db01ee0f206c99c6ed75520a5594e0b3d525725215
mega-errorcode.bat;mega-errorcode.bat;f5793c201602a3619cac14d31d0356d058d8128b13027b1e64073dd029193614
mega-exclude.bat;mega-exclude.bat;a347a180847fa3dca00bc28dd1321f5b332fdf574c73ea2b30ef3fab63b2380b
mega-export.bat;mega-export.bat;30fe5d62f0f47418dc83e03bc80977426010c8edcf01e4e7db820965e2781442
mega-find.bat;mega-find.bat;0e683610f7369c674cebc1ecf8d6e030f0433226887b902e74fe1e174c23a6a7
mega-ftp.bat;mega-ftp.bat;df52291409a56fd512402124a94b51dda27c0b5caf2c93d36932e6ce2268bb3c
mega-get.bat;mega-get.bat;b309f0785461dbe35a63b0a674cc70381ef7f87720d2aa884a8dbc8ae3c2c42e
mega-graphics.bat;mega-graphics.bat;d692deb721e9ac81db35e26542abbc64f26aebb0f232dab53d390de7a03461da
mega-help.bat;mega-help.bat;8558ee2389b4493ff9b3d9bcab252564a817284583d651649ce79d7091ea45d3
mega-https.bat;mega-https.bat;91c60eb7b5f95951e96a2437ee51dbae7821377e8e4864279b41c53791481b6a
mega-import.bat;mega-import.bat;90eff64c5a742c7d96d87648a15bcb33145ebebab593f0c0161dae22880b90a0
mega-invite.bat;mega-invite.bat;7d9713740d78deeabff15b6080a387460a315a680777d4f1e04c498f1b708826
mega-ipc.bat;mega-ipc.bat;04fe985dcc18c3ab8dc4ecf5ebf61ed9dd4bafdcd0937c8d10235c98b2f4a9ae
mega-killsession.bat;mega-killsession.bat;7b2aeb01bd57aa53f1d615294fa425aaa3d82f43474ed529d9a33efb873a183e
mega-lcd.bat;mega-lcd.bat;776a5e227d275f6a777ea5c7886e69efe5b9ee9da3fd79700965f4809cde5d27
mega-log.bat;mega-log.bat;4e703495f3616dd936afdfa2c32958189ae5e90328d9389b86e49a50654e6393
mega-login.bat;mega-login.bat;9bc358f934bfbeb12347083aef6b7a6efe26846b83ce0e653a4b89c64ba89073
mega-logout.bat;mega-logout.bat;ab36f1dcf6cfd93b95bf5394b1ef22deff505df685c9b0a36d25fa9c94f4b548
mega-lpwd.bat;mega-lpwd.bat;6364d746c3f1f0329fd67cec0f6a1f09ae3e521f3ef37b0ab728009cf55c4a5c
mega-ls.bat;mega-ls.bat;d57684855baf42e911b235c7ffb5a106aac875461d5faeb059c4d941e7b5cfd6
mega-mediainfo.bat;mega-mediainfo.bat;59606376cabc50a19af3732cddbbcda40c59e0c85aa6bc0320420a6a19abca49
mega-mkdir.bat;mega-mkdir.bat;690c56c5ebd58d596632a4ff28596df8aa478309fc979b9eb8b07fb89db4d944
mega-mount.bat;mega-mount.bat;6f0a3e80dcde8611beb4ac1d9e575601997e58b9a4a17054c5cb4eedf6f8062f
mega-mv.bat;mega-mv.bat;4e694c7eb85dcf55d7642f3504a5d63493e46ebd711735c57a45569ef2a7b88a
mega-passwd.bat;mega-passwd.bat;0f5947f5dbd2543c49853451d6d0deb64b04796e4c61327a1b5aa1c295b2a861
mega-preview.bat;mega-preview.bat;caed90cc51561edd29eb5e842c266add1bb477261cf5254a0e2c218ed0737b93
mega-proxy.bat;mega-proxy.bat;a22417b2eccc3ab5a32aecee8bd004cbbef73fe80d58119d23223163985d1f6b
mega-put.bat;mega-put.bat;a20fb6cf0d1e9c86de68b8665fbbf0974b04c69beccd41d7123f6b3004221beb
mega-pwd.bat;mega-pwd.bat;38744af426f8304c5ee9c2857291225726bffe2788870f2cb9e6a3b8836297e6
mega-quit.bat;mega-quit.bat;44026a4ab85bb59d02241e400848ac77be17c60fc86a0d07055e8ed8fe490ba2
mega-reload.bat;mega-reload.bat;4a0231a6f5ccb7f5908a9d7f12987efa1b45ff2148214360b4a205f15e77075f
mega-rm.bat;mega-rm.bat;1e55e2b5357bce9f5fa54d2a12801dfba6c70262a6ddceae4b227a014db0aa92
mega-session.bat;mega-session.bat;20c963d0749b58afccdb7d45ff36451015689bec1c035ee7bf809c7ee5b6b483
mega-share.bat;mega-share.bat;66fc8fa5564448729b569b843c158d933d8774666651f98cfbd757ea9d721d94
mega-showpcr.bat;mega-showpcr.bat;e5d799f4ebb0f0a02c6c7efb0fd946a9a9f7b8283c5ccb697132974711060ccf
mega-signup.bat;mega-signup.bat;f64064f35b2c464cb20fdcb70a8aa73856b6a8af65acd5be8d58b79df9889c1c
mega-speedlimit.bat;mega-speedlimit.bat;c6f2a4b09f9249c4e77ad03cc0e15940f080c125187137bc88a7d2adf2a4916f
mega-sync.bat;mega-sync.bat;c39719e5e79043b28a6368cdc942032bf5b2ab18fff2f66bd726058e9e921ef7
mega-thumbnail.bat;mega-thumbnail.bat;58574690db6cfff0ffa7864a0a13265ae1bd37d5fc3b0d9e0c88a1f7d69c193d
mega-transfers.bat;mega-transfers.bat;6f35a34033499938700e42f4123399f711003d2dab83ed50e69f7df5ecf976d8
mega-tree.bat;mega-tree.bat;92a11c9ee2af4ffb55d05210813c7ff309f90274a1d211018acc2643367b2534
mega-userattr.bat;mega-userattr.bat;a48dfc0e20bd69e3774d74860f2a74691addf9fbaae42c71450561a4d526f92a
mega-users.bat;mega-users.bat;24d85b5700f05d7b638d294c87e8b8809df80f0611c63ee818f60ed487f1b4bc
mega-version.bat;mega-version.bat;b69c2f0acc58d45ae4dae502892af08ce9abaa0de2433573a07e9a06fae3a255
mega-webdav.bat;mega-webdav.bat;233717710c3ac45906e2cbd110a167d7779bd6697a508013c5b6559bbce97815
mega-whoami.bat;mega-whoami.bat;b6ff6c05c78901dfc6291751bab1ae93a0ac836d8d506e57d2bb6fb927facc7d
MEGAclient.exe;MEGAclient.exe;216b4f04c38d81371ecc9f0344c13133bfa43c2d643c37fadfa44de1bda35df0
MEGAcmdServer.exe;MEGAcmdServer.exe;05241b87973924df675f2ae9560de1924e4a8f64abeca49c286b5c191fe155fd
MEGAcmdShell.exe;MEGAcmdShell.exe;58438c8b77ce5f41866f85962c1b1d88d52723db895b1e39780760d3c3b032ad
MEGAcmdUpdater.exe;MEGAcmdUpdater.exe;5ba09c067584bc4f32e58afbe1f4d5b2b1a023478af318b55c1e924f725b44d0
msvcp140.dll;msvcp140.dll;e0a22a594e148fa55ceef3e49969bfa77011a801267a0bd7805b681b593c9d0b
msvcp140_1.dll;msvcp140_1.dll;768e0829decea713afb35a7de07e276f051581c8ff2c17e1bae9b07dd1445dd0
msvcp140_2.dll;msvcp140_2.dll;5c12eaef6db18b168f712bff9b55793e0effddf15b89552e7f5ca4f8f1887b9b
msvcp140_atomic_wait.dll;msvcp140_atomic_wait.dll;0193cdcff562f12218ecab5841fd6bbc4d24295cd8e4dcae960e2fb47cceb662
msvcp140_codecvt_ids.dll;msvcp140_codecvt_ids.dll;9c6c0d8fa51ecca5e274295cbd72d45be474f3c6ce1070ec5e90f70242ae7185
swresample-4.dll;swresample-4.dll;6df991ae9d55d6bf107bca6ec1156ce6c53cc0feaa5052a3fb2e6cb5819cda3f
swscale-6.dll;swscale-6.dll;94ffb8148bbccbd3c3382727775bb5ee70030d88ae940fa3ee00a00b9c66d4b7
ucrtbase.dll;ucrtbase.dll;6238cbfe9f57c142b75e153c399c478d492252fda8cb40ee539c2dcb0f2eb232
uninst.exe;uninst.exe;85da75f6601212bbd48fb9ae624284281dbe57fe570c58509c41e2f31f0b7c8a
vccorlib140.dll;vccorlib140.dll;3e194d5ab03fdb1e97b0bae61070994013487c567f82c9338e7adc202f7d7d67
vcomp140.dll;vcomp140.dll;d5aa2fc36a84144ca2a420b797f4e645fca530e0ff7bd01383010d5a81d194ef
vcruntime140.dll;vcruntime140.dll;c179d8914ba8e57b2f8f4d6c101c2c550c7c6712a7f0f9920a97db340f9d9574
vcruntime140_1.dll;vcruntime140_1.dll;7cf38d20d00b6640d510eab70171e1c6f8fa2e42040832e17c7433ab61d94a8e
mega-attr.bat;mega-attr.bat;7a5b5b221bc921a5eb98633f519b2141bd0daede6eae40cba113333992967de7
mega-backup.bat;mega-backup.bat;d0df6b91202750d3b13071e3e231c1954ff032c1340cf051e968a91d74dbb80a
mega-cancel.bat;mega-cancel.bat;fa68a5dd1e0051425c3e8c41f5695810eadc2058397046b1848a0599f47c9953
mega-cat.bat;mega-cat.bat;6225ce58605e8795fe2e48220607ac193744cb313cd181fb6e90a190484a9bbf
mega-cd.bat;mega-cd.bat;c102ccb99cf3e83b1eb0886b15ed5b3e5deff7b2fedfba9408558cd9aa8f1e18
mega-confirm.bat;mega-confirm.bat;7ce93a6a402b631760477079861796cf1dd25517866cbd2d5be27635d7783fee
mega-confirmcancel.bat;mega-confirmcancel.bat;dde5415005ad473cc98ef9b9b28f210350bb8d4efca6f4af8eb63d394efdf0e0
mega-cp.bat;mega-cp.bat;36292230fd45e595e98667653646ee1baaa87bc4e9b22b566ec5bc0cc7347821
mega-debug.bat;mega-debug.bat;423e02ee02c0d24e2aec7c02ebc295954d2d2ab3166f1174ef96fc5111179d0d
mega-deleteversions.bat;mega-deleteversions.bat;c67afe7a90012f5885348d6ca6bb4abbf27f9b891ec61204fe53763281505c13
mega-df.bat;mega-df.bat;b98a9f278dbc417aa51c4eb34af5cfe076be0e5700dbae1558b7aa381a926881
mega-du.bat;mega-du.bat;1e91bfb1ad81e12c1068f42b612e95c986ff6807919195188f3a4cacf692183f
mega-errorcode.bat;mega-errorcode.bat;d431d2d116ccfd9f01d4f54f9580fa89615848aa6814b7d8f2da347b3127050a
mega-exclude.bat;mega-exclude.bat;ab9f76a28ba0a5efb0eb2e240e599409d6d6380a18dd680f93bc3d705409b299
mega-export.bat;mega-export.bat;42dd5f70a8f78854e01b175fa7672b2a0d894da716a910807e2373e2dd983947
mega-find.bat;mega-find.bat;08147ae1b71d69a09f48ea145f183fba304a2884e5b27953fc89943ba41df69c
mega-ftp.bat;mega-ftp.bat;8c049a43a7f13856bf8f6667beb6a5496a4b0e111a5a3afb40b7c1f36b97e456
mega-get.bat;mega-get.bat;2e40e197c0fa5b74cb164f2b696cc064de1b356c42450c1028e77568efdc1eff
mega-graphics.bat;mega-graphics.bat;3c91e02f744d7b84cb76577bf354a54adce1562e7bfcea98588a3204a82ed396
mega-help.bat;mega-help.bat;cef87d1319c235952d238bc5111935bc8312bb1cfc17d61e522151077857715e
mega-https.bat;mega-https.bat;1cf2a5175ee289514f70c8f956145725dd501c3fd9860413bc77abc93022b57d
mega-import.bat;mega-import.bat;3343902b8d3cbc6f62529d6920178f0e6042472f2772a08df15ed73121d04619
mega-invite.bat;mega-invite.bat;20be9c6d549733269ac7a9ce7ab3928c29134625b1e84eb54e52cda192774a55
mega-ipc.bat;mega-ipc.bat;7b29de9117b7b48d9e57ac6a0df6e7b229905ab3d5858daccb354116b0039ba3
mega-killsession.bat;mega-killsession.bat;9f83aada9c370952e9b49a9c41eb7d98f30e5b024d070e371244ee6b76f64c96
mega-lcd.bat;mega-lcd.bat;de56d34a0e884ce8691ebc86ac55832a5d8a22eb5eb5fdbe345d69301500f746
mega-log.bat;mega-log.bat;ebbb6703ef76be60e030058b2ca56934fa573d9891096bfb43be5b7adcbc14cc
mega-login.bat;mega-login.bat;af44e84d703d44e46e8aba3b9e6bc8d0d4304d143493fd14eaff70742013ab81
mega-logout.bat;mega-logout.bat;b10da32e4da3c750ce8874222b7348a58c9c61f7d2ec11f73c91fc7d31722a02
mega-lpwd.bat;mega-lpwd.bat;eefe4d679a99d507cf49d434746b22bc3d312802b9a4ac48824e0d363b8c1b12
mega-ls.bat;mega-ls.bat;cfc0d9ce93645ae56a5e9e27a6d59090b615027a4678e4b8ab57f86b2c49d5ad
mega-mediainfo.bat;mega-mediainfo.bat;7364d4c609c2030136837f70765586494d6951058530d828b75e57eedcac2626
mega-mkdir.bat;mega-mkdir.bat;1535df364439afcf86860495c71eccb1b40cc202f30d3180a30b389298ffbbd9
mega-mount.bat;mega-mount.bat;22b5c4a02c0df84d025b6315b8f8098b0be250b1237c8aad89f07c3b707073a7
mega-mv.bat;mega-mv.bat;bd253db0f09da734afc3c6d31058fb20551fbc18197e85e9bdf52d62e00fdfaa
mega-passwd.bat;mega-passwd.bat;3aa3bedfc45eaf3f1e1609fe96b028821a79d1915a5b930609a8ca2b3730c2dc
mega-preview.bat;mega-preview.bat;54a263b9fe0ac933aa77b73a5219bb0fa813ea0501ba331dbfb7b16c61ea5cef
mega-proxy.bat;mega-proxy.bat;f323cf922dee4aac447b504399c367ed45e752a6cbe0adec5c68a675611118b6
mega-put.bat;mega-put.bat;ca3e2c5aa77a6b7b4a9a4d7699416e714a9aa027c7d68fda47023405716766f8
mega-pwd.bat;mega-pwd.bat;cdf78fb7b00f2c50db3672a02923bfd05d380741b582570db194ccf7d4b22033
mega-quit.bat;mega-quit.bat;bb82d8e26f81007f19683422bc021791d1ce74fd5f11f3c1c29307a6b98752f0
mega-reload.bat;mega-reload.bat;9e0d368d6f7863944711697cf54e1201c405ab37b8f1ebbf520ad15d0c96f4fa
mega-rm.bat;mega-rm.bat;7e503e07f13199e35faad58590b56938ab53b14745afa5f596f31f8921c72859
mega-session.bat;mega-session.bat;91a24d34d4752deb4a76215f564f202edb9eaba2285b5f26f3f9dc40aad7c702
mega-share.bat;mega-share.bat;270c97a6e71b03a67297a534dc1d7299fe801f9c654f68e0fbe0276a65921054
mega-showpcr.bat;mega-showpcr.bat;39a7f816821855676392dcb437378bfbfa61a595748af6a4b82e43cd9704955d
mega-signup.bat;mega-signup.bat;6e8c13eb91c9d38d2ce48c75c569bd151d3f3c7641e3b2b3ed04994ae3e4a33f
mega-speedlimit.bat;mega-speedlimit.bat;c037351ecf3cd9fae0b1416b60cd651fe317fc57fd06f996c9b7f6450c9a07b3
mega-sync.bat;mega-sync.bat;62a2334922a0ea0867b2a71a6900e44975b03612dbeeb181aca6d44d48222922
mega-thumbnail.bat;mega-thumbnail.bat;8f7b42ac9e6358534bed0355e70b6f007070006f38328e35c860ff502d4768b4
mega-transfers.bat;mega-transfers.bat;38b4bb079557909927336aeddda2c8f937b5d089b2bfe224cb0b895250b85d5e
mega-tree.bat;mega-tree.bat;0f03785c46a12893100f360da48fb473de9011bffd9562a327aa76626078d263
mega-userattr.bat;mega-userattr.bat;28cede25ba267f57d1c60b531764f1290a8fc78b64b1bcc307b0e23f5fea1bd2
mega-users.bat;mega-users.bat;6f4499de547c0d5c5bcba21d5c226bb83a6f01909d9fc4cd1c578c4bdc8e6955
mega-version.bat;mega-version.bat;2f1794963704f4dc65e23155ef1fb27788ea48e6099479c4809093f7281c28fc
mega-webdav.bat;mega-webdav.bat;97c8f94a273c7d7d9e5b6b1929a8e227c3a15d6c09c8124f12d7fe3723a7beae
mega-whoami.bat;mega-whoami.bat;48f9d5104bb5364f6831b11d9847871c528ad656655c3fa49ce9be70e932767f
MEGAclient.exe;MEGAclient.exe;5401d804c6873201476666f9190ce6a1e1f4b94b7988201cc632ac4a29320ccc
MEGAcmdServer.exe;MEGAcmdServer.exe;46ee3cbb168bacfbc1ac7f6b35b3a34416bee9c85a66b14fe236c890088d5a46
MEGAcmdShell.exe;MEGAcmdShell.exe;2bcb1f39d25151ae9c1565120973538c691fd352db1977b2be0faae6b7f88ebe
MEGAcmdUpdater.exe;MEGAcmdUpdater.exe;475300b56fe62db463baf68e91267100fa949a1bfd995785f4e1c79179ff3125
msvcp140.dll;msvcp140.dll;9057d39b36b6c7d054865ee2bf9cde7a490fe3b01ec4e82514687e24f576269f
msvcp140_1.dll;msvcp140_1.dll;a65249861238e1c18b84ae5d112617c438d83a76b67eddc170ad82dbc2338665
msvcp140_2.dll;msvcp140_2.dll;89e2e9a163165e20c540f9adea081e927ddfe4a556547b0f45f11586d4cce165
msvcp140_atomic_wait.dll;msvcp140_atomic_wait.dll;fbf41e4b53f51bbf73fee37b6120103fea6b7d5ae29916f8ef50c50cfdedeead
msvcp140_codecvt_ids.dll;msvcp140_codecvt_ids.dll;0e1d3d76e899a89fb3893fb13abae232ff62ad4f573214dd2f02b8398166bcc6
swresample-4.dll;swresample-4.dll;ad2df528f8458fcec995f3d7afdd3161d6dea16cdd92694f12888f22994fc635
swscale-6.dll;swscale-6.dll;1cdf13dd9ba8f50da5c228ad6f84f2c7d068eeffcc57bc429ff1d23b1309e06a
ucrtbase.dll;ucrtbase.dll;91d027417ff2301b7135e864a5df6693488f8412ff87040f4897e0e03bc2577b
uninst.exe;uninst.exe;581003e0efbef54d67066e048723d058dfa9717b22538cc8852457aa09720eed
vccorlib140.dll;vccorlib140.dll;8903b5d88968791d2a93648a54a1ac3d1c708c579a72311ffe194f6d66903043
vcomp140.dll;vcomp140.dll;036b9b3f7ece8dfd48aeccd77113721c5305043aaa9c64d1e72812252727aa7c
vcruntime140.dll;vcruntime140.dll;da72e6677bd1bcd01c453c1998aaa19aeaf6659f4774cf6848409da8232a95b2
vcruntime140_1.dll;vcruntime140_1.dll;26e470b29bed3d873e0c328186e53f95e9edbfe0b0fd0cda44743a0b1a04a828

View File

@ -4,6 +4,7 @@ pipeline {
options {
buildDiscarder(logRotator(numToKeepStr: '135', daysToKeepStr: '21'))
gitLabConnection('GitLabConnectionJenkins')
timestamps() // Add timestamps to all console output
}
stages {
@ -42,7 +43,7 @@ pipeline {
axes {
axis {
name 'SANITIZERS'
values 'ubsan', 'asan', 'tsan'
values 'baseline', 'ubsan', 'asan', 'tsan'
}
axis {
name 'BUILD_SYSTEM'
@ -73,9 +74,9 @@ pipeline {
timeout(time: 10, unit: 'MINUTES')
}
environment {
ASAN_OPTIONS="atexit=1,print_stats=1,log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/mega-cmd-tests-unit-report"
TSAN_OPTIONS="log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/mega-cmd-tests-unit-report"
UBSAN_OPTIONS="log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/mega-cmd-tests-unit-report"
ASAN_OPTIONS="print_stats=1,log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/unit-asan-report.log"
TSAN_OPTIONS="log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/unit-tsan-report.log"
UBSAN_OPTIONS="log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/unit-ubsan-report.log"
HOME="${megacmd_sources_workspace}/test-dir-${SANITIZERS}"
}
steps {
@ -90,6 +91,7 @@ pipeline {
post {
always {
archiveArtifacts artifacts: "test-dir-${SANITIZERS}/.megaCmd/megacmdserver.log*", allowEmptyArchive: true
archiveArtifacts artifacts: "test-dir-${SANITIZERS}/results/unit-*-report.log.*", allowEmptyArchive: true
junit "test-dir-${SANITIZERS}/results/mega-cmd-tests-unit.xml"
}
}
@ -108,9 +110,9 @@ pipeline {
environment {
MEGACMD_TEST_USER=''
MEGACMD_TEST_PASS=credentials('MEGACMD_TESTS_PASSWORD')
ASAN_OPTIONS="atexit=1,print_stats=1,log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/mega-cmd-tests-integration-report"
TSAN_OPTIONS="log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/mega-cmd-tests-integration-report"
UBSAN_OPTIONS="log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/mega-cmd-tests-integration-report"
ASAN_OPTIONS="print_stats=1,log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/integration-asan-report.log"
TSAN_OPTIONS="log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/integration-tsan-report.log"
UBSAN_OPTIONS="log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/integration-ubsan-report.log"
HOME="${megacmd_sources_workspace}/test-dir-${SANITIZERS}"
}
steps {
@ -127,6 +129,7 @@ pipeline {
post {
always {
archiveArtifacts "test-dir-${SANITIZERS}/.megaCmd/megacmdserver.log*"
archiveArtifacts artifacts: "test-dir-${SANITIZERS}/results/integration-*-report.log.*", allowEmptyArchive: true
junit "test-dir-${SANITIZERS}/results/mega-cmd-tests-integration.xml"
}
}
@ -140,14 +143,18 @@ pipeline {
}
}
options {
timeout(time: 1, unit: 'HOURS')
timeout(time: 2, unit: 'HOURS')
}
environment {
MEGA_EMAILS=''
MEGA_PWD=credentials('MEGACMD_TESTS_PASSWORD')
MEGA_PWD_AUX=credentials('MEGACMD_TESTS_PASSWORD')
ASAN_OPTIONS="print_stats=1,log_path=${megacmd_sources_workspace}/pytest-dir-${SANITIZERS}/results/pyserver-asan-report.log"
TSAN_OPTIONS="log_path=${megacmd_sources_workspace}/pytest-dir-${SANITIZERS}/results/pyserver-tsan-report.log"
UBSAN_OPTIONS="log_path=${megacmd_sources_workspace}/pytest-dir-${SANITIZERS}/results/pyserver-ubsan-report.log"
HOME="${megacmd_sources_workspace}/pytest-dir-${SANITIZERS}"
YES_I_KNOW_THIS_WILL_CLEAR_MY_MEGA_ACCOUNT=1
VERBOSE=1
}
steps {
dir("pytest-dir-${SANITIZERS}") {
@ -158,20 +165,39 @@ pipeline {
script {
// Skipping the 'serving' test until CMD-389 is resolved
for (test in ['misc', 'put', 'rm', 'find', 'get']) {
stage("MEGAcmd Python ${test} test") {
withEnv([
"MEGA_EMAIL=${env.MEGA_EMAILS0}",
"MEGA_EMAIL_AUX=${env.MEGA_EMAILS1}",
"ASAN_OPTIONS=atexit=1,print_stats=1,log_path=${megacmd_sources_workspace}/pytest-dir-${SANITIZERS}/${test}-results/mega-cmd-tests-python-report",
"TSAN_OPTIONS=log_path=${megacmd_sources_workspace}/pytest-dir-${SANITIZERS}/${test}-results/mega-cmd-tests-python-report",
"UBSAN_OPTIONS=log_path=${megacmd_sources_workspace}/pytest-dir-${SANITIZERS}/${test}-results/mega-cmd-tests-python-report",
"OUT_DIR_JUNIT_XML=${megacmd_sources_workspace}/pytest-dir-${SANITIZERS}/${test}-results"
]) {
dir("pytest-dir-${SANITIZERS}/working-dir") {
sh "/usr/local/bin/megacmd_${test}_test.py"
deleteDir()
for (cmdshell in ['', 'cmdshell-']) {
def testDir = "pytest-dir-${SANITIZERS}/${cmdshell}${test}-results"
def asanOptions = "print_stats=1,log_path=${megacmd_sources_workspace}/${testDir}/py-asan-report.log"
def tsanOptions = "log_path=${megacmd_sources_workspace}/${testDir}/py-tsan-report.log"
def ubsanOptions = "log_path=${megacmd_sources_workspace}/${testDir}/py-ubsan-report.log"
stage("MEGAcmd Python ${cmdshell}${test} test") {
withEnv([
"MEGA_EMAIL=${env.MEGA_EMAILS0}",
"MEGA_EMAIL_AUX=${env.MEGA_EMAILS1}",
"ASAN_OPTIONS=${asanOptions}",
"TSAN_OPTIONS=${tsanOptions}",
"UBSAN_OPTIONS=${ubsanOptions}",
"OUT_DIR_JUNIT_XML=${megacmd_sources_workspace}/${testDir}"
]) {
def envStr = ''
if (cmdshell != '') {
envStr = "MEGACMDSHELL=/usr/bin/mega-cmd LSAN_OPTIONS=suppressions=${megacmd_sources_workspace}/${testDir}/suppressed_asan.txt "
}
try {
dir("pytest-dir-${SANITIZERS}/working-dir") {
// CMD-578 Fix readline leak instead of suppressing it
writeFile file: "${megacmd_sources_workspace}/${testDir}/suppressed_asan.txt", text: 'leak:expand_prompt'
sh "/usr/local/bin/megacmd_${test}_test.py"
}
junit "${testDir}/TEST-*.xml"
} finally {
archiveArtifacts artifacts: "${testDir}/py-*-report.log.*", allowEmptyArchive: true
dir("pytest-dir-${SANITIZERS}/working-dir") {
deleteDir()
}
}
}
junit "pytest-dir-${SANITIZERS}/${test}-results/TEST-*.xml"
}
}
}
@ -183,6 +209,7 @@ pipeline {
sh "/usr/bin/mega-exec logout || true"
sh "/usr/bin/mega-exec quit || true"
archiveArtifacts "pytest-dir-${SANITIZERS}/.megaCmd/megacmdserver.log*"
archiveArtifacts artifacts: "pytest-dir-${SANITIZERS}/results/pyserver-*-report.log.*", allowEmptyArchive: true
}
}
}
@ -195,6 +222,7 @@ pipeline {
}
}
}
post {
always {
script {

View File

@ -10,6 +10,7 @@ pipeline {
booleanParam(name: 'IS_RELEASE_CANDIDATE', defaultValue: false, description: 'Is it a Release Candidate?')
string(name: 'RELEASE_CANDIDATE_NAME', defaultValue: '', description: 'i.e: RC2, RC3 (only needed if IS_RELEASE_CANDIDATE is true)')
booleanParam(name: 'CUSTOM_BUILD', defaultValue: true, description: 'If true, will use DISTRO_TO_BUILD If false, will build all distributions')
choice(name: 'ARCH_TO_BUILD', choices: ['amd64', 'armhf'], description: 'Only used if CUSTOM_BUILD is true')
string(name: 'DISTRO_TO_BUILD', defaultValue: 'xUbuntu_22.04', description: 'Only used if CUSTOM_BUILD is true')
string(name: 'MEGACMD_BRANCH', defaultValue: "${env.BRANCH_NAME}", description: 'Which version of MEGAcmd should we build? Default is current branch.')
string(name: 'SDK_BRANCH', defaultValue: ' ', description: 'Optionally, define a custom SDK branch.')
@ -70,8 +71,8 @@ pipeline {
steps {
echo "Do Build for ${params.DISTRO_TO_BUILD}"
dir(linux_sources_workspace) {
lock(resource: "${params.DISTRO_TO_BUILD}-amd64-MEGAcmd-build", quantity: 1) {
buildAndSignPackage("${params.DISTRO_TO_BUILD}", "amd64", "megacmd")
lock(resource: "${params.DISTRO_TO_BUILD}-${params.ARCH_TO_BUILD}-MEGAcmd-build", quantity: 1) {
buildAndSignPackage("${params.DISTRO_TO_BUILD}", "${params.ARCH_TO_BUILD}", "megacmd")
}
script{
if ( params.IS_RELEASE_CANDIDATE == true) {
@ -102,17 +103,44 @@ pipeline {
axes {
axis {
name 'ARCHITECTURE';
values 'amd64'
values 'amd64','armhf'
}
axis {
name 'DISTRO';
values 'xUbuntu_24.10','xUbuntu_24.04', 'xUbuntu_22.04', 'xUbuntu_20.04',
'Debian_11','Debian_12','Debian_testing',
'DEB_Arch_Extra',
'Raspbian_11', 'Raspbian_12',
'Fedora_39', 'Fedora_40', 'Fedora_41',
'openSUSE_Leap_15.5','openSUSE_Leap_15.6', 'openSUSE_Tumbleweed'
}
}
excludes {
exclude {
axis {
name 'ARCHITECTURE';
values 'armhf'
}
axis {
name 'DISTRO';
values 'xUbuntu_24.10','xUbuntu_24.04', 'xUbuntu_22.04', 'xUbuntu_20.04',
'Debian_11','Debian_12','Debian_testing',
'DEB_Arch_Extra',
'Fedora_39', 'Fedora_40', 'Fedora_41',
'openSUSE_Leap_15.5','openSUSE_Leap_15.6', 'openSUSE_Tumbleweed'
}
}
exclude {
axis {
name 'ARCHITECTURE';
values 'amd64'
}
axis {
name 'DISTRO';
values 'Raspbian_11', 'Raspbian_12'
}
}
}
stages {
stage('Build') {
agent { label 'linux-testing-package-builder' }
@ -136,7 +164,7 @@ pipeline {
def MEGACMD_VERSION = getVersionFromHeader("CMakeLists.txt")
withCredentials([string(credentialsId: 'MEGACMD_ARTIFACTORY_TOKEN', variable: 'MEGACMD_ARTIFACTORY_TOKEN')]) {
sh 'jf rt del --url $REPO_URL --access-token $MEGACMD_ARTIFACTORY_TOKEN MEGAcmd-releases/$MEGACMD_VERSION/$RELEASE_CANDIDATE_NAME/linux/$DISTRO'
sh "cd ${env.INTERNAL_REPO_PATH}/repo/private/$DISTRO && jf rt upload --url ${REPO_URL} --access-token ${MEGACMD_ARTIFACTORY_TOKEN} --regexp '((x86_64|amd64|i386)/megacmd.*deb\$|(x86_64|amd64|i386)/megacmd.*rpm\$|(x86_64|amd64|i386)/megacmd.*\\.pkg\\.tar\\.zst\$|(x86_64|amd64|i386)/megacmd.*\\.pkg\\.tar\\.xz\$)' MEGAcmd-releases/$MEGACMD_VERSION/$RELEASE_CANDIDATE_NAME/linux/$DISTRO/"
sh "cd ${env.INTERNAL_REPO_PATH}/repo/private/$DISTRO && jf rt upload --url ${REPO_URL} --access-token ${MEGACMD_ARTIFACTORY_TOKEN} --regexp '((x86_64|amd64|i386|armhf)/megacmd.*deb\$|(x86_64|amd64|i386)/megacmd.*rpm\$|(x86_64|amd64|i386)/megacmd.*\\.pkg\\.tar\\.zst\$|(x86_64|amd64|i386)/megacmd.*\\.pkg\\.tar\\.xz\$)' MEGAcmd-releases/$MEGACMD_VERSION/$RELEASE_CANDIDATE_NAME/linux/$DISTRO/"
}
echo "Packages successfully uploaded. URL: [${env.REPO_URL}/MEGAcmd-releases/$MEGACMD_VERSION/$RELEASE_CANDIDATE_NAME/linux/$DISTRO/]"
}
@ -147,10 +175,15 @@ pipeline {
}
}
}
post {
always {
deleteDir()
}
}
}
def buildAndSignPackage(String distro, String architecture, String packageName) {
sh "${env.BUILDTOOLS_PATH}/build/buildManager.sh -a ${architecture} -j 1 build ${distro} . ${packageName}"
sh "${env.BUILDTOOLS_PATH}/build/buildManager.sh -a ${architecture} -j 2 build ${distro} . ${packageName}"
sh "${env.BUILDTOOLS_PATH}/repo/repoManager.sh add ${env.INTERNAL_REPO_PATH}/builder/results/${distro}/${architecture}/${packageName}/ ${distro}"
sh "SIGN_KEY_PATH=${env.INTERNAL_REPO_PATH}/sign_test/ ${env.BUILDTOOLS_PATH}/repo/repoManager.sh build -n ${distro}"
}

View File

@ -151,4 +151,9 @@ pipeline {
}
}
}
post {
always {
deleteDir()
}
}
}

View File

@ -75,9 +75,9 @@ pipeline {
@echo on
mkdir tmp
set _MSPDBSRV_ENDPOINT_= ${BUILD_TAG}
set TMP=${Workspace}\\tmp
set TEMP=${Workspace}\\tmp
set TMPDIR=${Workspace}\\tmp
set TMP=${windows_sources_workspace}\\build\\tmp
set TEMP=${windows_sources_workspace}\\build\\tmp
set TMPDIR=${windows_sources_workspace}\\build\\tmp
full_build_process.cmd ${params.ARCHITECTURE} nosign 2
"""
}
@ -136,6 +136,11 @@ pipeline {
}
}
}
post {
always {
deleteDir()
}
}
}
def getVersionFromHeader(String versionFilePath) {

View File

@ -4,6 +4,7 @@ pipeline {
options {
buildDiscarder(logRotator(numToKeepStr: '135', daysToKeepStr: '21'))
gitLabConnection('GitLabConnectionJenkins')
timestamps() // Add timestamps to all console output
}
stages {
@ -106,7 +107,7 @@ pipeline {
axes {
axis {
name 'SANITIZERS'
values 'ubsan', 'asan', 'tsan'
values 'baseline', 'ubsan', 'asan', 'tsan'
}
axis {
name 'BUILD_SYSTEM'
@ -122,7 +123,7 @@ pipeline {
DOCKER_BUILDKIT=1
}
steps {
sh "docker build -t meganz/megacmd-${BUILD_SYSTEM}-${SANITIZERS}:${env.BUILD_NUMBER} -f ${megacmd_sources_workspace}/build-with-docker/Dockerfile.${BUILD_SYSTEM} --build-arg=BUILD_OPT_SANITIZERS=${SANITIZERS} --ulimit=core=-1 --cpuset-cpus=0,1 -- ${megacmd_sources_workspace}"
sh "docker build -t meganz/megacmd-${BUILD_SYSTEM}-${SANITIZERS}:${env.BUILD_NUMBER} -f ${megacmd_sources_workspace}/build-with-docker/Dockerfile.${BUILD_SYSTEM} --build-arg=ENABLE_${SANITIZERS}=ON --ulimit=core=-1 --cpuset-cpus=0,1 -- ${megacmd_sources_workspace}"
}
}
stage("MEGAcmd unit tests") {
@ -137,9 +138,9 @@ pipeline {
timeout(time: 10, unit: 'MINUTES')
}
environment {
ASAN_OPTIONS="atexit=1,print_stats=1,log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/mega-cmd-tests-unit-report"
TSAN_OPTIONS="log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/mega-cmd-tests-unit-report"
UBSAN_OPTIONS="log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/mega-cmd-tests-unit-report"
ASAN_OPTIONS="print_stats=1,log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/unit-asan-report.log"
TSAN_OPTIONS="log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/unit-tsan-report.log"
UBSAN_OPTIONS="log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/unit-ubsan-report.log"
HOME="${megacmd_sources_workspace}/test-dir-${SANITIZERS}"
}
steps {
@ -164,6 +165,7 @@ pipeline {
archiveArtifacts artifacts: "test-dir-${SANITIZERS}/.megaCmd/megacmdserver.log*", allowEmptyArchive: true
archiveArtifacts artifacts: "**/core*zstd", allowEmptyArchive: true
archiveArtifacts artifacts: "**/mega-cmd-tests-unit.zstd", allowEmptyArchive: true
archiveArtifacts artifacts: "test-dir-${SANITIZERS}/results/unit-*-report.log.*", allowEmptyArchive: true
junit "test-dir-${SANITIZERS}/results/mega-cmd-tests-unit.xml"
}
}
@ -182,9 +184,9 @@ pipeline {
environment {
MEGACMD_TEST_USER=''
MEGACMD_TEST_PASS=credentials('MEGACMD_TESTS_PASSWORD')
ASAN_OPTIONS="atexit=1,print_stats=1,log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/mega-cmd-tests-integration-report"
TSAN_OPTIONS="log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/mega-cmd-tests-integration-report"
UBSAN_OPTIONS="log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/mega-cmd-tests-integration-report"
ASAN_OPTIONS="print_stats=1,log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/integration-asan-report.log"
TSAN_OPTIONS="log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/integration-tsan-report.log"
UBSAN_OPTIONS="log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/integration-ubsan-report.log"
HOME="${megacmd_sources_workspace}/test-dir-${SANITIZERS}"
}
steps {
@ -211,6 +213,7 @@ pipeline {
archiveArtifacts "test-dir-${SANITIZERS}/.megaCmd/megacmdserver.log*"
archiveArtifacts artifacts: "**/core*zstd", allowEmptyArchive: true
archiveArtifacts artifacts: "**/mega-cmd-tests-integration.zstd", allowEmptyArchive: true
archiveArtifacts artifacts: "test-dir-${SANITIZERS}/results/integration-*-report.log.*", allowEmptyArchive: true
junit "test-dir-${SANITIZERS}/results/mega-cmd-tests-integration.xml"
}
}
@ -230,6 +233,9 @@ pipeline {
MEGA_EMAILS=''
MEGA_PWD=credentials('MEGACMD_TESTS_PASSWORD')
MEGA_PWD_AUX=credentials('MEGACMD_TESTS_PASSWORD')
ASAN_OPTIONS="print_stats=1,log_path=${megacmd_sources_workspace}/pytest-dir-${SANITIZERS}/results/pyserver-asan-report.log"
TSAN_OPTIONS="log_path=${megacmd_sources_workspace}/pytest-dir-${SANITIZERS}/results/pyserver-tsan-report.log"
UBSAN_OPTIONS="log_path=${megacmd_sources_workspace}/pytest-dir-${SANITIZERS}/results/pyserver-ubsan-report.log"
HOME="${megacmd_sources_workspace}/pytest-dir-${SANITIZERS}"
YES_I_KNOW_THIS_WILL_CLEAR_MY_MEGA_ACCOUNT=1
VERBOSE=1
@ -254,18 +260,21 @@ pipeline {
for (test in ['misc', 'put', 'rm', 'find', 'get']) {
for (cmdshell in ['', 'cmdshell-']) {
def testDir = "pytest-dir-${SANITIZERS}/${cmdshell}${test}-results"
def asanOptions = "print_stats=1,log_path=${megacmd_sources_workspace}/${testDir}/py-asan-report.log"
def tsanOptions = "log_path=${megacmd_sources_workspace}/${testDir}/py-tsan-report.log"
def ubsanOptions = "log_path=${megacmd_sources_workspace}/${testDir}/py-ubsan-report.log"
stage("MEGAcmd Python ${cmdshell}${test} test") {
withEnv([
"MEGA_EMAIL=${env.MEGA_EMAILS0}",
"MEGA_EMAIL_AUX=${env.MEGA_EMAILS1}",
"ASAN_OPTIONS=atexit=1,print_stats=1,log_path=${megacmd_sources_workspace}/${testDir}/mega-cmd-tests-python-report",
"TSAN_OPTIONS=log_path=${megacmd_sources_workspace}/${testDir}/mega-cmd-tests-python-report",
"UBSAN_OPTIONS=log_path=${megacmd_sources_workspace}/${testDir}/mega-cmd-tests-python-report",
"ASAN_OPTIONS=${asanOptions}",
"TSAN_OPTIONS=${tsanOptions}",
"UBSAN_OPTIONS=${ubsanOptions}",
"OUT_DIR_JUNIT_XML=${megacmd_sources_workspace}/${testDir}"
]) {
def envStr = ''
if (cmdshell != '') {
envStr = 'MEGACMDSHELL=/usr/bin/mega-cmd '
envStr = "MEGACMDSHELL=/usr/bin/mega-cmd "
}
try {
dir("pytest-dir-${SANITIZERS}/working-dir") {
@ -278,6 +287,7 @@ pipeline {
}
junit "${testDir}/TEST-*.xml"
} finally {
archiveArtifacts artifacts: "${testDir}/py-*-report.log.*", allowEmptyArchive: true
dir("pytest-dir-${SANITIZERS}") {
sh "find . -name core -exec zstd -z --fast=3 {} -o core_client_${cmdshell}${test}.zstd \\; -exec rm {} \\; || true"
}
@ -302,6 +312,7 @@ pipeline {
|| true
"""
archiveArtifacts "pytest-dir-${SANITIZERS}/.megaCmd/megacmdserver.log*"
archiveArtifacts artifacts: "pytest-dir-${SANITIZERS}/results/pyserver-*-report.log.*", allowEmptyArchive: true
archiveArtifacts artifacts: "**/core*zstd", allowEmptyArchive: true
archiveArtifacts artifacts: "**/mega-*.zstd", allowEmptyArchive: true
}

View File

@ -0,0 +1,181 @@
pipeline {
agent { label "linux-testing-package-builder" }
options {
buildDiscarder(logRotator(numToKeepStr: '135', daysToKeepStr: '21'))
gitLabConnection('GitLabConnectionJenkins')
timestamps() // Add timestamps to all console output
}
stages {
stage('Clean previous runs and update gitlab commit status') {
steps {
deleteDir()
updateGitlabCommitStatus(name: 'Build linux packages', state: 'running')
}
}
stage('Get build parameters') {
parallel {
stage('Get build options') {
steps {
script{
BUILD_OPTIONS = ' '
env.ARCHITECTURE = sh(script: 'echo "$gitlabTriggerPhrase" | grep ARCHITECTURE | awk -F "ARCHITECTURE=" \'{print \$2}\' | cut -d"\\"" -f2 || :', returnStdout: true).trim()
if (env.ARCHITECTURE == "")
{ env.ARCHITECTURE = "amd64" }
env.BUILD_OPTIONS = sh(script: 'echo "$gitlabTriggerPhrase" | grep BUILD_OPTIONS | awk -F "BUILD_OPTIONS=" \'{print \$2}\' | cut -d"\\"" -f2 || :', returnStdout: true).trim()
env.DISTRIBUTION = sh(script: 'echo "$gitlabTriggerPhrase" | grep DISTRIBUTION | awk -F "DISTRIBUTION=" \'{print \$2}\' | cut -d\\" -f2', returnStdout: true).trim()
if (env.DISTRIBUTION == "")
{ env.DISTRIBUTION = "xUbuntu_22.04" }
println BUILD_OPTIONS
println DISTRIBUTION
}
}
post{
always {
script{
if (currentBuild.currentResult == 'FAILURE'){
addGitLabMRComment(comment: ":red_circle: ${env.JOB_NAME} FAILURE when getting the additional build parameters :worried:<br/>Build results: [Jenkins [${env.JOB_NAME} ${env.BUILD_DISPLAY_NAME}]](${env.RUN_DISPLAY_URL})<br/>Commit: ${env.GIT_COMMIT}" )
}
}
}
}
}
stage('Get SDK branch'){
steps {
script{
env.SDK_BRANCH = sh(script: 'echo "$gitlabMergeRequestDescription" | grep SDK_SUBMODULE_TEST | awk -F "SDK_SUBMODULE_TEST=" \'{print \$2}\' | cut -d" " -f1', returnStdout: true).trim()
if (SDK_BRANCH == ""){
echo "SDK_BRANCH was not found on description so develop will be used by default"
env.SDK_BRANCH = "develop"
}
println SDK_BRANCH
}
}
post{
always {
script{
if (currentBuild.currentResult == 'FAILURE'){
addGitLabMRComment(comment: ":red_circle: ${env.JOB_NAME} FAILURE when getting the SDK branch :worried:<br/>Build results: [Jenkins [${env.JOB_NAME} ${env.BUILD_DISPLAY_NAME}]](${env.RUN_DISPLAY_URL})<br/>Commit: ${env.GIT_COMMIT}" )
}
}
}
}
}
}
}
stage('Checkout sources') {
parallel {
stage('Checkout MEGAcmd') {
steps {
checkout([
$class: 'GitSCM',
branches: [[name: "origin/${env.gitlabSourceBranch}"]],
userRemoteConfigs: [[url: "${env.GIT_URL_MEGACMD}", credentialsId: "12492eb8-0278-4402-98f0-4412abfb65c1"]],
extensions: [
[$class: "UserIdentity",name: "jenkins", email: "jenkins@jenkins"],
]
])
}
}
stage('Checkout SDK') {
steps {
dir('sdk') {
checkout([
$class: 'GitSCM',
branches: [[name: "${SDK_BRANCH}"]],
userRemoteConfigs: [[url: "${env.GIT_URL_SDK}", credentialsId: "12492eb8-0278-4402-98f0-4412abfb65c1"]],
extensions: [
[$class: "UserIdentity",name: "jenkins", email: "jenkins@jenkins"],
[$class: "CloneOption", depth: 1, shallow: true, noTags: false, reference: '']
]
])
}
script {
linux_sources_workspace = WORKSPACE
sdk_sources_workspace = "${linux_sources_workspace}/sdk"
}
}
}
}
}
stage('Build packages'){
when {
beforeAgent true
expression { env.gitlabTriggerPhrase != null && (env.gitlabTriggerPhrase == 'trigger package' || env.gitlabTriggerPhrase.startsWith('trigger package linux')) }
}
stages{
stage('Build linux package'){
options {
timeout(time: 600, unit: 'MINUTES')
}
steps {
echo "Do Build for $DISTRIBUTION-$ARCHITECTURE"
dir(linux_sources_workspace){
lock(resource: "$DISTRIBUTION-$ARCHITECTURE-MEGAcmd-build", quantity: 1, ){
sh "/opt/buildTools/build/buildManager.sh -a $ARCHITECTURE -j 3 build $DISTRIBUTION . megacmd"
sh "/opt/buildTools/repo/repoManager.sh add /srv/builder/results/$DISTRIBUTION/$ARCHITECTURE/megacmd/ $DISTRIBUTION"
sh "SIGN_KEY_PATH=/srv/sign_test/ /opt/buildTools/repo/repoManager.sh build -n $DISTRIBUTION"
}
}
}
}
stage ('Upload Linux package') {
steps {
dir(linux_sources_workspace){
script{
withCredentials([string(credentialsId: 'MEGACMD_ARTIFACTORY_TOKEN', variable: 'MEGACMD_ARTIFACTORY_TOKEN')]) {
sh """
jf rt del \
--url ${REPO_URL} \
--access-token ${MEGACMD_ARTIFACTORY_TOKEN} \
MEGAcmd-sprints/${env.gitlabMergeRequestIid}/linux/$DISTRIBUTION
"""
dir("/srv/repo/private/$DISTRIBUTION"){
sh """
jf rt upload \
--url ${REPO_URL} \
--access-token ${MEGACMD_ARTIFACTORY_TOKEN} \
--regexp '(megacmd.*deb\$|megacmd.*rpm\$|megacmd.*\\.pkg\\.tar\\.zst\$|megacmd.*\\.pkg\\.tar\\.xz\$)' \
MEGAcmd-sprints/${env.gitlabMergeRequestIid}/linux/$DISTRIBUTION/
"""
}
}
uploadPackagesExecuted = true
}
}
}
}
}
}
}
post {
always {
script {
if (currentBuild.currentResult == 'SUCCESS') {
addGitLabMRComment(comment: ":white_check_mark: ${currentBuild.projectName} :penguin: <b>LINUX</b> SUCCEEDED :muscle:<br/>Build results: [Jenkins [${currentBuild.displayName}]](${currentBuild.absoluteUrl})<br/>Commit: ${env.GIT_COMMIT}<br/>Packages URL: [${env.REPO_URL}/MEGAcmd-sprints/${env.gitlabMergeRequestIid}/linux/$DISTRIBUTION]" )
updateGitlabCommitStatus(name: 'Build linux packages', state: 'success')
}
if (currentBuild.currentResult == 'FAILURE') {
addGitLabMRComment(comment: ":red_circle: ${currentBuild.projectName} :penguin: <b>Linux</b> FAILURE :worried:<br/>Build results: [Jenkins [${currentBuild.displayName}]](${currentBuild.absoluteUrl})<br/>Commit: ${env.GIT_COMMIT}" )
updateGitlabCommitStatus(name: 'Build linux packages', state: 'failed')
}
if (currentBuild.currentResult == 'ABORTED') {
addGitLabMRComment(comment: ":interrobang: ${currentBuild.projectName} :penguin: <b>Linux</b> ABORTED :confused:<br/>Build results: [Jenkins [${currentBuild.displayName}]](${currentBuild.absoluteUrl})<br/>Commit: ${env.GIT_COMMIT}" )
updateGitlabCommitStatus(name: 'Build linux packages', state: 'canceled')
}
if (currentBuild.currentResult == 'UNSTABLE') {
addGitLabMRComment(comment: ":interrobang: ${currentBuild.projectName} :penguin: <b>Linux</b> UNSTABLE :confused:<br/>Build results: [Jenkins [${currentBuild.displayName}]](${currentBuild.absoluteUrl})<br/>Commit: ${env.GIT_COMMIT}" )
updateGitlabCommitStatus(name: 'Build linux packages', state: 'failed')
}
}
}
}
}

View File

@ -8,6 +8,7 @@ pipeline {
options {
buildDiscarder(logRotator(numToKeepStr: '135', daysToKeepStr: '21'))
gitLabConnection('GitLabConnectionJenkins')
timestamps() // Add timestamps to all console output
}
stages {
@ -192,6 +193,7 @@ pipeline {
updateGitlabCommitStatus(name: 'Build macos', state: 'failed')
}
}
deleteDir()
}
}
}

View File

@ -8,6 +8,7 @@ pipeline {
options {
buildDiscarder(logRotator(numToKeepStr: '135', daysToKeepStr: '21'))
gitLabConnection('GitLabConnectionJenkins')
timestamps() // Add timestamps to all console output
}
stages {
@ -224,6 +225,7 @@ pipeline {
updateGitlabCommitStatus(name: 'Build windows', state: 'failed')
}
}
deleteDir()
}
}
}

2
sdk

@ -1 +1 @@
Subproject commit e448c09e73a4496329f46e538f1f20143b618ed1
Subproject commit ddaaf5e587055897f3054a52d4a6dc74d52bb732

View File

@ -20,5 +20,9 @@
int main(int argc, char* argv[])
{
#ifdef WIN32
megacmd::Instance<megacmd::WindowsConsoleController> windowsConsoleController;
#endif
return megacmd::executeClient(argc, argv, COUT);
}

View File

@ -144,8 +144,6 @@ wstring getWAbsPath(wstring localpath)
}
#endif
string clientID; //identifier for a registered state listener
string getAbsPath(string relativePath)
{
if (!relativePath.size())
@ -220,7 +218,7 @@ string getAbsPath(string relativePath)
}
string parseArgs(int argc, char* argv[])
string parseArgs(int argc, char* argv[], MegaCmdShellCommunications& comsManager)
{
vector<string> absolutedargs;
int totalRealArgs = 0;
@ -240,17 +238,10 @@ string parseArgs(int argc, char* argv[])
|| !strcmp(argv[1],"login")
|| !strcmp(argv[1],"reload") )
{
int waittime = 15000;
while (waittime > 0 && !clientID.size())
auto clientIdOpt = comsManager.tryToGetClientId();
if (clientIdOpt)
{
sleepMilliSeconds(100);
waittime -= 100;
}
if (clientID.size())
{
string sclientID = "--clientID=";
sclientID+=clientID;
absolutedargs.push_back(sclientID);
absolutedargs.push_back("--clientID=" + *clientIdOpt);
}
}
@ -439,19 +430,23 @@ string parseArgs(int argc, char* argv[])
#ifdef _WIN32
wstring parsewArgs(int argc, wchar_t* argv[])
wstring parsewArgs(int argc, wchar_t* argv[], MegaCmdShellCommunications& comsManager)
{
// remove "-o path" argument if found:
for (int i=1;i<argc;i++)
{
if (i<(argc-1) && !wcscmp(argv[i],L"-o"))
if (i<(argc-1) && std::wstring_view(argv[i]) == L"-o")
{
if (i < (argc-2))
argv[i]=argv[i+2];
argc=argc-2;
for (int j = i; j < argc - 2; ++j)
{
argv[j] = argv[j + 2];
}
argc -= 2;
argv[argc] = nullptr;
--i; // Stay at the same index to process the shifted arguments
}
}
vector<wstring> absolutedargs;
int totalRealArgs = 0;
if (argc>1)
@ -472,18 +467,10 @@ wstring parsewArgs(int argc, wchar_t* argv[])
|| !wcscmp(argv[1],L"login")
|| !wcscmp(argv[1],L"reload") )
{
int waittime = 5000;
while (waittime > 0 && !clientID.size())
auto clientIdOpt = comsManager.tryToGetClientId();
if (clientIdOpt)
{
sleepMilliSeconds(100);
waittime -= 100;
}
if (clientID.size())
{
wstring sclientID = L"--clientID=";
std::wstring wclientID(clientID.begin(), clientID.end());
sclientID+=wclientID;
absolutedargs.push_back(sclientID);
absolutedargs.push_back(L"--clientID=" + std::wstring(clientIdOpt->begin(), clientIdOpt->end()));
}
}
@ -762,13 +749,10 @@ void statechangehandle(string statestring, MegaCmdShellCommunications & comsMana
#ifdef _WIN32
wstring wbuffer;
stringtolocalw((const char*)os.str().data(),&wbuffer);
int oldmode;
std::lock_guard<std::mutex> stdOutLockGuard(comsManager.getStdoutLockGuard());
oldmode = _setmode(_fileno(stdout), _O_U8TEXT);
WindowsUtf8StdoutGuard utf8Guard;
OUTSTREAM << wbuffer << flush;
_setmode(_fileno(stdout), oldmode);
#else
StdoutMutexGuard stdoutGuard;
OUTSTREAM << os.str();
#endif
}
@ -780,7 +764,7 @@ void statechangehandle(string statestring, MegaCmdShellCommunications & comsMana
}
else if (newstate.compare(0, strlen("login:"), "login:") == 0)
{
std::lock_guard<std::mutex> stdOutLockGuard(comsManager.getStdoutLockGuard());
StdoutMutexGuard stdoutGuard;
printCenteredContentsCerr(string("Resuming session ... ").c_str(), width, false);
}
else if (newstate.compare(0, strlen("message:"), "message:") == 0)
@ -789,28 +773,25 @@ void statechangehandle(string statestring, MegaCmdShellCommunications & comsMana
{
lastMessage = newstate;
string contents = newstate.substr(strlen("message:"));
std::string_view messageContents = std::string_view(newstate).substr(strlen("message:"));
string contents = std::string(shown_partial_progress ? "\n": "").append(messageContents);
replaceAll(contents, "%mega-%", "mega-");
std::lock_guard<std::mutex> stdOutLockGuard(comsManager.getStdoutLockGuard());
if (shown_partial_progress)
{
cerr << endl;
}
if (contents.find("-----") != 0)
if (messageContents.rfind("-----", 0) != 0)
{
printCenteredContentsCerr(contents, width);
}
else
{
StdoutMutexGuard stdoutGuard;
cerr << endl << contents << endl;
}
}
}
else if (newstate.compare(0, strlen("clientID:"), "clientID:") == 0)
{
clientID = newstate.substr(strlen("clientID:")).c_str();
std::string clientId = newstate.substr(strlen("clientID:"));
comsManager.setClientIdPromise(clientId);
}
else if (newstate.compare(0, strlen("progress:"), "progress:") == 0)
{
@ -840,8 +821,6 @@ void statechangehandle(string statestring, MegaCmdShellCommunications & comsMana
shown_partial_progress = false;
}
std::lock_guard<std::mutex> stdOutLockGuard(comsManager.getStdoutLockGuard());
long long completed = received == SPROGRESS_COMPLETE ? PROGRESS_COMPLETE : charstoll(received.c_str());
const char * progressTitle = title.empty() ? "TRANSFERRING" : title.c_str();
printprogress(completed, charstoll(total.c_str()), progressTitle);
@ -881,6 +860,14 @@ int executeClient(int argc, char* argv[], OUTSTREAMTYPE & outstream)
{
freopen(argv[i+1],"w",stdout);
redirectedoutput = true;
for (int j = i; j < argc - 2; ++j)
{
argv[j] = argv[j + 2];
}
argc -= 2;
argv[argc] = nullptr;
--i; // Stay at the same index to process the shifted arguments
}
}
@ -915,10 +902,10 @@ int executeClient(int argc, char* argv[], OUTSTREAMTYPE & outstream)
{
return -3;
}
wstring wParsedArgs = parsewArgs(wargc, szArglist);
wstring wParsedArgs = parsewArgs(wargc, szArglist, *comms);
LocalFree(szArglist);
#else
string parsedArgs = parseArgs(argc,argv);
string parsedArgs = parseArgs(argc, argv, *comms);
#endif
bool isInloginInValidCommands = false;

View File

@ -18,20 +18,11 @@
#include "comunicationsmanager.h"
#include <regex>
using namespace mega;
namespace megacmd {
OUTSTREAMTYPE &operator<<(OUTSTREAMTYPE &os, const CmdPetition& p)
{
return os << p.line;
}
#ifdef _WIN32
std::ostream &operator<<(std::ostream &os, const CmdPetition& p)
{
return os << p.line;
}
#endif
ComunicationsManager::ComunicationsManager()
{
@ -123,16 +114,6 @@ void ComunicationsManager::returnAndClosePetition(std::unique_ptr<CmdPetition> i
{
}
void ComunicationsManager::sendPartialOutput(CmdPetition *inf, OUTSTRING *s)
{
return;
}
void ComunicationsManager::sendPartialOutput(CmdPetition *inf, char *s, size_t size)
{
return;
}
/**
* @brief getPetition
@ -153,9 +134,57 @@ std::string ComunicationsManager::getUserResponse(CmdPetition *inf, string messa
return string();
}
void CmdPetition::setLine(std::string_view line)
{
mLine = line;
}
std::string_view CmdPetition::getLine() const
{
return mLine;
}
std::string_view CmdPetition::getUniformLine() const
{
return ltrim(std::string_view(line), 'X');
return ltrim(std::string_view(mLine), 'X');
}
std::string CmdPetition::getRedactedLine() const
{
const char* doNotRedactEnv = getenv("MEGACMD_DO_NOT_REDACT_LINES");
if (doNotRedactEnv)
{
return mLine;
}
static const std::string redacted = "$1<REDACTED>";
static const std::string asterisks = "$1********";
static const std::regex fullCommandRegex(R"(^((X?)(passwd|login|confirm|confirmcancel)\s+).*$)");
static const std::regex passwordRegex(R"((--password=)("[^"]+"|'[^']+'|\S+))");
static const std::regex authRegex(R"((--auth-(code|key)=)\S+)");
static const std::regex linkRegex(R"((https://mega\.nz/(file|folder)/[^#]+#)\S+)");
static const std::regex oldLinkRegex(R"((https://mega\.nz/#F?![^!]+#)\S+)");
static const std::regex encryptedLinkRegex(R"((https://mega\.nz/#P!)\S+)");
if (std::regex_match(mLine, fullCommandRegex))
{
return std::regex_replace(mLine, fullCommandRegex, redacted);
}
std::string output = mLine;
output = std::regex_replace(output, passwordRegex, asterisks);
output = std::regex_replace(output, authRegex, asterisks);
output = std::regex_replace(output, linkRegex, asterisks);
output = std::regex_replace(output, oldLinkRegex, asterisks);
output = std::regex_replace(output, encryptedLinkRegex, asterisks);
return output;
}
bool CmdPetition::isFromCmdShell() const
{
return startsWith(mLine, "X");
}
MegaThread *CmdPetition::getPetitionThread() const

View File

@ -23,29 +23,33 @@
#include "megacmdcommonutils.h"
namespace megacmd {
struct CmdPetition
class CmdPetition
{
std::string line;
std::string mLine;
public:
mega::MegaThread *petitionThread = nullptr;
int clientID = -27;
bool clientDisconnected = false;
virtual ~CmdPetition() = default;
void setLine(std::string_view line);
std::string_view getLine() const;
// Remove the starting 'X' if present (petitions coming from interactive mode)
std::string_view getUniformLine() const;
// Remove possible confidential info from the line
std::string getRedactedLine() const;
bool isFromCmdShell() const;
mega::MegaThread *getPetitionThread() const;
void setPetitionThread(mega::MegaThread *value);
virtual std::string getPetitionDetails() const { return {}; }
};
OUTSTREAMTYPE &operator<<(OUTSTREAMTYPE &os, CmdPetition const &p);
#ifdef _WIN32
std::ostream &operator<<(std::ostream &os, CmdPetition const &p);
#endif
class ComunicationsManager
{
private:
@ -78,8 +82,8 @@ public:
*/
virtual void returnAndClosePetition(std::unique_ptr<CmdPetition> inf, OUTSTRINGSTREAM *s, int);
virtual void sendPartialOutput(CmdPetition *inf, OUTSTRING *s);
virtual void sendPartialOutput(CmdPetition *inf, char *s, size_t size);
virtual void sendPartialOutput(CmdPetition *inf, OUTSTRING *s) = 0;
virtual void sendPartialOutput(CmdPetition *inf, char *s, size_t size, bool binaryContents = false) = 0;
/**

View File

@ -241,7 +241,13 @@ void ComunicationsManagerFileSockets::returnAndClosePetition(std::unique_ptr<Cmd
{
LOG_err << "ERROR writing output Code to socket: " << errno;
}
n = send(socket, sout.data(), max(static_cast<size_t>(1), sout.size()), MSG_NOSIGNAL); // for some reason without the max recv never quits in the client for empty responses
if (sout.empty())
{
return; // socket shutdown will send EOF (0 bytes upon recv)
}
n = send(socket, sout.data(), sout.size(), MSG_NOSIGNAL);
if (n < 0)
{
LOG_err << "ERROR writing to socket: " << errno;
@ -249,6 +255,11 @@ void ComunicationsManagerFileSockets::returnAndClosePetition(std::unique_ptr<Cmd
}
void ComunicationsManagerFileSockets::sendPartialOutput(CmdPetition *inf, OUTSTRING *s)
{
sendPartialOutput(inf, s->data(), s->size());
}
void ComunicationsManagerFileSockets::sendPartialOutput(CmdPetition *inf, char *s, size_t size, bool binaryContents)
{
if (inf->clientDisconnected)
{
@ -263,10 +274,15 @@ void ComunicationsManagerFileSockets::sendPartialOutput(CmdPetition *inf, OUTSTR
return;
}
if (s->size())
if (!binaryContents && !isValidUtf8(s, size))
{
size_t size = s->size();
std::cerr << "Attempt to sendPartialOutput of invalid utf8 of size " << size << std::endl;
assert(false && "Attempt to sendPartialOutput of invalid utf8");
return;
}
if (size)
{
int outCode = MCMD_PARTIALOUT;
auto n = send(connectedsocket, (void*)&outCode, sizeof( outCode ), MSG_NOSIGNAL);
if (n < 0)
@ -287,7 +303,7 @@ void ComunicationsManagerFileSockets::sendPartialOutput(CmdPetition *inf, OUTSTR
}
n = send(connectedsocket, s->data(), size, MSG_NOSIGNAL); // for some reason without the max recv never quits in the client for empty responses
n = send(connectedsocket, s, size, MSG_NOSIGNAL); // for some reason without the max recv never quits in the client for empty responses
if (n < 0)
{
@ -297,8 +313,15 @@ void ComunicationsManagerFileSockets::sendPartialOutput(CmdPetition *inf, OUTSTR
}
}
int ComunicationsManagerFileSockets::informStateListener(CmdPetition *inf, const string &s)
int ComunicationsManagerFileSockets::informStateListener(CmdPetition *inf, const std::string &s)
{
if (!isValidUtf8(s))
{
LOG_err << "Attempt to write an invalid utf-8 string of size " << s.size();
assert(false && "Attempt to write an invalid utf-8 string");
return 0;
}
std::lock_guard<std::mutex> g(informerMutex);
LOG_verbose << "Inform State Listener: Output to write in socket " << ((CmdPetitionPosixSockets *)inf)->outSocket << ": <<" << s << ">>";
@ -320,12 +343,12 @@ int ComunicationsManagerFileSockets::informStateListener(CmdPetition *inf, const
{
if (errno == EPIPE) //socket closed
{
LOG_verbose << "Unregistering no longer listening client. Original petition: " << inf->line;
LOG_verbose << "Unregistering no longer listening client. Original petition: " << inf->getRedactedLine();
return -1;
}
else if (errno == EAGAIN || errno == EWOULDBLOCK) // timed out
{
LOG_warn << "Unregistering timed out listening client. Original petition: " << inf->line;
LOG_warn << "Unregistering timed out listening client. Original petition: " << inf->getRedactedLine();
return -1;
}
else
@ -361,7 +384,7 @@ std::unique_ptr<CmdPetition> ComunicationsManagerFileSockets::getPetition()
}
sleep(1);
inf->line = "ERROR";
inf->setLine("ERROR");
return inf;
}
@ -399,13 +422,13 @@ std::unique_ptr<CmdPetition> ComunicationsManagerFileSockets::getPetition()
if (n < 0)
{
LOG_fatal << "ERROR reading from socket at getPetition: " << errno;
inf->line = "ERROR";
inf->setLine("ERROR");
close(newsockfd);
return inf;
}
inf->outSocket = newsockfd;
inf->line = wholepetition;
inf->setLine(wholepetition);
return inf;
}

View File

@ -32,6 +32,7 @@ struct CmdPetitionPosixSockets: public CmdPetition
virtual ~CmdPetitionPosixSockets()
{
shutdown(outSocket, SHUT_RDWR);
close(outSocket);
}
@ -79,7 +80,8 @@ public:
*/
void returnAndClosePetition(std::unique_ptr<CmdPetition> inf, OUTSTRINGSTREAM *s, int) override;
virtual void sendPartialOutput(CmdPetition *inf, OUTSTRING *s);
void sendPartialOutput(CmdPetition *inf, OUTSTRING *s) override;
void sendPartialOutput(CmdPetition *inf, char *s, size_t size, bool binaryContents = false) override;
int informStateListener(CmdPetition *inf, const std::string &s) override;

View File

@ -224,11 +224,16 @@ void ComunicationsManagerNamedPipes::returnAndClosePetition(std::unique_ptr<CmdP
connectsucceeded = true;
break;
}
else
else if (ERRNO == ERROR_NO_DATA)
{
LOG_fatal << "ERROR on connecting to namedPipe " << outNamedPipe << ". errno: " << ERRNO << ". Attempts: " << attempts;
break;
}
sleepMilliSeconds(500);
else
{ // Problem: this, caused by a client shutdown, entails trying to sendPartialOutput again (via MEGAcmdLogger::formatLogToStream)
LOG_err << "ERROR on connecting to namedPipe " << outNamedPipe << ". errno: " << ERRNO << ". Attempts: " << attempts;
assert(false);
}
sleepMilliSeconds(50);
}
else
{
@ -238,7 +243,7 @@ void ComunicationsManagerNamedPipes::returnAndClosePetition(std::unique_ptr<CmdP
if (!connectsucceeded)
{
LOG_fatal << "Return and close: Unable to connect on outnamedPipe " << outNamedPipe << " error: " << ERRNO;
LOG_err << "Return and close: Unable to connect on outnamedPipe " << outNamedPipe << " error: " << ERRNO;
return;
}
@ -282,11 +287,16 @@ void ComunicationsManagerNamedPipes::sendPartialOutput(CmdPetition *inf, OUTSTRI
connectsucceeded = true;
break;
}
else if (ERRNO == ERROR_NO_DATA)
{
break;
}
else
{
cerr << "ERROR on connecting to namedPipe " << outNamedPipe << ". errno: " << ERRNO << ". Attempts: " << attempts << endl;
assert(false);
}
sleepMilliSeconds(500);
sleepMilliSeconds(50);
}
else
{
@ -297,20 +307,7 @@ void ComunicationsManagerNamedPipes::sendPartialOutput(CmdPetition *inf, OUTSTRI
if (!connectsucceeded)
{
cerr << "sendPartialOutput: Unable to connect on outnamedPipe " << outNamedPipe << " error: " << ERRNO << endl;
if (errno == ERROR_NO_DATA) //TODO: pipe disconnected error?
{
std::cerr << "WARNING: Client disconnected, the rest of the output will be discarded" << endl;
inf->clientDisconnected = true;
}
return;
}
int outCode = MCMD_PARTIALOUT;
DWORD n;
if (!WriteFile(outNamedPipe,(const char*)&outCode, sizeof(outCode), &n, NULL))
{
LOG_err << "ERROR writing output Code to namedPipe: " << ERRNO;
if (errno == ERROR_NO_DATA) //TODO: pipe disconnected error?
if (ERRNO == ERROR_NO_DATA)
{
std::cerr << "WARNING: Client disconnected, the rest of the output will be discarded" << endl;
inf->clientDisconnected = true;
@ -319,25 +316,46 @@ void ComunicationsManagerNamedPipes::sendPartialOutput(CmdPetition *inf, OUTSTRI
}
string sutf8;
localwtostring(s,&sutf8);
localwtostring(s, &sutf8);
assert(isValidUtf8(sutf8)); // above localwtostring should produce an empty string if the input had broken encoding or valid utf-8 otherwise
int outCode = MCMD_PARTIALOUT;
DWORD n;
if (!WriteFile(outNamedPipe,(const char*)&outCode, sizeof(outCode), &n, NULL))
{
std::cerr << "ERROR writing output Code to namedPipe: " << ERRNO << std::endl;
if (ERRNO == ERROR_NO_DATA) //TODO: pipe disconnected error?
{
std::cerr << "WARNING: Client disconnected, the rest of the output will be discarded" << endl;
inf->clientDisconnected = true;
}
return;
}
size_t size = sutf8.size() > 1 ? sutf8.size() : 1; // client does not like empty responses
if (!WriteFile(outNamedPipe,(const char*)&size, sizeof(size), &n, NULL))
{
LOG_err << "ERROR writing output Code to namedPipe: " << ERRNO;
std::cerr << "ERROR writing output Code to namedPipe: " << std::endl;
return;
}
if (!WriteFile(outNamedPipe,sutf8.data(), DWORD(size), &n, NULL))
{
LOG_err << "ERROR writing to namedPipe: " << ERRNO;
std::cerr << "ERROR writing to namedPipe: " << ERRNO << std::endl;
}
}
void ComunicationsManagerNamedPipes::sendPartialOutput(CmdPetition *inf, char *s, size_t size)
void ComunicationsManagerNamedPipes::sendPartialOutput(CmdPetition *inf, char *s, size_t size, bool binaryContents)
{
HANDLE outNamedPipe = ((CmdPetitionNamedPipes *)inf)->outNamedPipe;
if (!binaryContents &&!isValidUtf8(s, size))
{
std::cerr << "Attempt to sendPartialOutput of invalid utf8 of size " << size << std::endl;
assert(false && "Attempt to sendPartialOutput of invalid utf8");
return;
}
bool connectsucceeded = false;
int attempts = 10;
while (--attempts && !connectsucceeded)
@ -350,6 +368,10 @@ void ComunicationsManagerNamedPipes::sendPartialOutput(CmdPetition *inf, char *s
connectsucceeded = true;
break;
}
else if (ERRNO == ERROR_NO_DATA)
{
break;
}
else
{
cerr << "ERROR on connecting to namedPipe " << outNamedPipe << ". errno: " << ERRNO << ". Attempts: " << attempts << endl;
@ -365,7 +387,7 @@ void ComunicationsManagerNamedPipes::sendPartialOutput(CmdPetition *inf, char *s
if (!connectsucceeded)
{
cerr << "sendPartialOutput: Unable to connect on outnamedPipe " << outNamedPipe << " error: " << ERRNO << endl;
if (errno == ERROR_NO_DATA)
if (ERRNO == ERROR_NO_DATA)
{
std::cerr << "WARNING: Client disconnected, the rest of the output will be discarded" << endl;
inf->clientDisconnected = true;
@ -378,7 +400,7 @@ void ComunicationsManagerNamedPipes::sendPartialOutput(CmdPetition *inf, char *s
if (!WriteFile(outNamedPipe,(const char*)&outCode, sizeof(outCode), &n, NULL))
{
LOG_err << "ERROR writing output Code to namedPipe: " << ERRNO;
if (errno == ERROR_NO_DATA)
if (ERRNO == ERROR_NO_DATA)
{
std::cerr << "WARNING: Client disconnected, the rest of the output will be discarded" << endl;
inf->clientDisconnected = true;
@ -400,6 +422,13 @@ void ComunicationsManagerNamedPipes::sendPartialOutput(CmdPetition *inf, char *s
int ComunicationsManagerNamedPipes::informStateListener(CmdPetition *inf, const string &s)
{
if (!isValidUtf8(s))
{
LOG_err << "Attempt to write an invalid utf8 string of size " << s.size();
assert(false && "Attempt to write an invalid utf8 string");
return 0;
}
std::lock_guard<std::mutex> g(*informerMutex);
LOG_verbose << "Inform State Listener: Output to write in namedPipe " << ((CmdPetitionNamedPipes *)inf)->outNamedPipe << ": <<" << s << ">>";
@ -428,7 +457,7 @@ int ComunicationsManagerNamedPipes::informStateListener(CmdPetition *inf, const
{
if (ERRNO == 32 || ERRNO == 109 || (ERRNO == 232 && s == "ack")) //namedPipe closed | pipe has been ended
{
LOG_debug << "namedPipe closed. Client probably disconnected. Original petition: " << inf->line;
LOG_debug << "namedPipe closed. Client probably disconnected. Original petition: " << inf->getRedactedLine();
return -1;
}
else
@ -480,7 +509,7 @@ std::unique_ptr<CmdPetition> ComunicationsManagerNamedPipes::getPetition()
if (!readok)
{
LOG_err << "Failed to read petition from named pipe. errno: L" << ERRNO;
inf->line = "ERROR";
inf->setLine("ERROR");
return inf;
}
@ -493,14 +522,14 @@ std::unique_ptr<CmdPetition> ComunicationsManagerNamedPipes::getPetition()
if (!namedPipeValid(inf->outNamedPipe) || !namedPipe_id)
{
LOG_fatal << "ERROR creating output namedPipe at getPetition";
inf->line = "ERROR";
inf->setLine("ERROR");
return inf;
}
if(!WriteFile(pipeGeneral,(const char*)&namedPipe_id, sizeof( namedPipe_id ), &n, NULL))
{
LOG_fatal << "ERROR writing to namedPipe at getPetition: ERRNO = " << ERRNO;
inf->line = "ERROR";
inf->setLine("ERROR");
return inf;
}
@ -509,7 +538,7 @@ std::unique_ptr<CmdPetition> ComunicationsManagerNamedPipes::getPetition()
LOG_fatal << " Error disconnecting from general pip. errno: " << ERRNO;
}
inf->line = receivedutf8;
inf->setLine(receivedutf8);
return inf;
}

View File

@ -95,9 +95,8 @@ public:
*/
void returnAndClosePetition(std::unique_ptr<CmdPetition> inf, OUTSTRINGSTREAM *s, int) override;
void sendPartialOutput(CmdPetition *inf, OUTSTRING *s);
void sendPartialOutput(CmdPetition *inf, char *s, size_t size);
void sendPartialOutput(CmdPetition *inf, OUTSTRING *s) override;
void sendPartialOutput(CmdPetition *inf, char *s, size_t size, bool binaryContents = false) override;
int informStateListener(CmdPetition *inf, const std::string &s) override;

View File

@ -16,8 +16,8 @@
* program.
*/
#include "configurationmanager.h"
#include "megacmdcommonutils.h"
#include "configurationmanager.h"
#include "megacmdversion.h"
#include "megacmdutils.h"
#include "listeners.h"
@ -25,7 +25,6 @@
#include "sync_ignore.h"
#include <fstream>
#include <filesystem>
#ifndef ERRNO
#ifdef _WIN32
@ -52,27 +51,13 @@
#define PATH_MAX_LOCAL_BACKUP PATH_MAX
#endif
#if defined(_WIN32)
#define unlink _unlink
#endif
using namespace mega;
namespace fs = std::filesystem;
using namespace std;
namespace megacmd {
static const char* const LOCK_FILE_NAME = "lockMCMD";
using namespace std;
bool is_file_exist(const char *fileName)
{
std::ifstream infile(fileName);
return infile.good();
}
string ConfigurationManager::mConfigFolder;
bool ConfigurationManager::hasBeenUpdated = false;
#ifdef WIN32
HANDLE ConfigurationManager::mLockFileHandle;
#elif defined(LOCK_EX) && defined(LOCK_NB)
@ -83,9 +68,9 @@ string ConfigurationManager::session;
map<std::string, backup_struct *> ConfigurationManager::configuredBackups;
std::recursive_mutex ConfigurationManager::settingsMutex;
std::string ConfigurationManager::getConfigFolder()
fs::path ConfigurationManager::getConfigFolder()
{
if (!mConfigFolder.size())
if (mConfigFolder.empty())
{
ConfigurationManager::loadConfigDir();
}
@ -102,6 +87,33 @@ static const char* const persistentmcmdconfigurationkeys[] =
"autoupdate", "updaterregistered"
};
void ConfigurationManager::createFolderIfNotExisting(const fs::path &folder)
{
std::error_code ec;
auto createdOk = fs::create_directory(folder, ec);
bool alreadyExisting = !createdOk && !ec;
if (alreadyExisting)
{
return;
}
LOG_debug << "Creating directory " << folder;
if (!createdOk)
{
LOG_err << "Directory " << folder << " creation failed: " << errorCodeStr(ec);
return;
}
#ifndef WIN32
fs::permissions(folder, fs::perms::owner_all, fs::perm_options::replace, ec);
if (!ec)
{
LOG_warn << "Failed to set permissions on new folder " << folder << ": " << errorCodeStr(ec);
}
#endif
}
void ConfigurationManager::loadConfigDir()
{
auto dirs = PlatformDirectories::getPlatformSpecificDirectories();
@ -113,79 +125,48 @@ void ConfigurationManager::loadConfigDir()
return;
}
auto fsAccess = std::make_unique<MegaFileSystemAccess>();
fsAccess->setdefaultfolderpermissions(0700);
LocalPath localConfigFolder = LocalPath::fromAbsolutePath(mConfigFolder);
constexpr bool isHidden = true;
constexpr bool reportExisting = false;
if (!pathIsExistingDir(mConfigFolder.c_str()) && !fsAccess->mkdirlocal(localConfigFolder, isHidden, reportExisting))
{
LOG_err << "Config directory not created";
}
createFolderIfNotExisting(mConfigFolder);
}
std::string ConfigurationManager::getAndCreateConfigDir()
fs::path ConfigurationManager::getAndCreateConfigDir()
{
auto dirs = PlatformDirectories::getPlatformSpecificDirectories();
auto configDir = dirs->configDirPath();
const fs::path configDir = dirs->configDirPath();
if (configDir.empty())
{
LOG_fatal << "Could not get config directory path";
throw std::runtime_error("Could not get config directory path");
}
auto fsAccess = std::make_unique<MegaFileSystemAccess>();
fsAccess->setdefaultfolderpermissions(0700);
LocalPath localConfigDir = LocalPath::fromAbsolutePath(configDir);
if (!pathIsExistingDir(configDir.c_str()) && !fsAccess->mkdirlocal(localConfigDir, false, false))
{
LOG_err << "Config directory not created";
}
createFolderIfNotExisting(configDir);
return configDir;
}
std::string ConfigurationManager::getAndCreateRuntimeDir()
fs::path ConfigurationManager::getAndCreateRuntimeDir()
{
auto dirs = PlatformDirectories::getPlatformSpecificDirectories();
auto runtimeDir = dirs->runtimeDirPath();
const fs::path runtimeDir = dirs->runtimeDirPath();
if (runtimeDir.empty())
{
LOG_fatal << "Could not get runtime directory path";
throw std::runtime_error("Could not get runtime directory path");
}
auto fsAccess = std::make_unique<MegaFileSystemAccess>();
fsAccess->setdefaultfolderpermissions(0700);
LocalPath localRuntimeDir = LocalPath::fromAbsolutePath(runtimeDir);
if (!pathIsExistingDir(runtimeDir.c_str()) && !fsAccess->mkdirlocal(localRuntimeDir, false, false))
{
LOG_err << "Runtime directory not created";
}
createFolderIfNotExisting(runtimeDir);
return runtimeDir;
}
std::string ConfigurationManager::getConfigFolderSubdir(const string &utf8Name)
fs::path ConfigurationManager::getConfigFolderSubdir(const fs::path& subdirName)
{
auto dirs = PlatformDirectories::getPlatformSpecificDirectories();
auto configDir = dirs->configDirPath();
const fs::path configDir = dirs->configDirPath();
assert(!configDir.empty());
MegaFileSystemAccess fsAccess;
fsAccess.setdefaultfolderpermissions(0700);
LocalPath configSubdir = LocalPath::fromAbsolutePath(configDir);
fs::path configSubDir = configDir / subdirName;
configSubdir.appendWithSeparator(LocalPath::fromRelativePath(utf8Name), true);
createFolderIfNotExisting(configSubDir);
constexpr bool isHidden = true;
constexpr bool reportExisting = false;
if (!pathIsExistingDir(configSubdir.toPath(false).c_str()) && !fsAccess.mkdirlocal(configSubdir, isHidden, reportExisting))
{
LOG_err << "State subfolder not created";
}
return configSubdir.toPath(false);
return configSubDir;
}
void ConfigurationManager::saveSession(const char*session)
@ -194,12 +175,10 @@ void ConfigurationManager::saveSession(const char*session)
auto configDir = getAndCreateConfigDir();
assert(!configDir.empty());
stringstream sessionfile;
sessionfile << configDir << "/" << "session";
LOG_debug << "Session file: " << sessionfile.str();
ofstream fo(sessionfile.str().c_str(), ios::out);
const fs::path sessionFilePath = configDir / "session";
LOG_debug << "Session file: " << sessionFilePath;
ofstream fo(sessionFilePath, ios::out);
if (fo.is_open())
{
if (session)
@ -210,7 +189,7 @@ void ConfigurationManager::saveSession(const char*session)
}
}
void ConfigurationManager::saveProperty(const char *property, const char *value)
string ConfigurationManager::saveProperty(const char *property, const char *value)
{
std::lock_guard<std::recursive_mutex> g(settingsMutex);
@ -221,12 +200,12 @@ void ConfigurationManager::saveProperty(const char *property, const char *value)
assert(!mConfigFolder.empty());
bool found = false;
stringstream configFile;
configFile << mConfigFolder << "/" << "megacmd.cfg";
const fs::path configFilePath = mConfigFolder / "megacmd.cfg";
stringstream formerlines;
ifstream infile(configFile.str().c_str());
string line;
ifstream infile(configFilePath);
string line, prevValue;
while (getline(infile, line))
{
if (line.length() > 0 && line[0] != '#')
@ -238,12 +217,10 @@ void ConfigurationManager::saveProperty(const char *property, const char *value)
key = line.substr(0, pos);
rtrimProperty(key, ' ');
if (!strcmp(key.c_str(), property))
if (!strcmp(key.c_str(), property) && !found)
{
if (!found)
{
formerlines << property << "=" << value << endl;
}
formerlines << property << "=" << value << endl;
prevValue = line.substr(pos + 1);
found = true;
}
else
@ -257,8 +234,8 @@ void ConfigurationManager::saveProperty(const char *property, const char *value)
}
}
}
ofstream fo(configFile.str().c_str());
ofstream fo(configFilePath);
if (fo.is_open())
{
fo << formerlines.str();
@ -268,6 +245,7 @@ void ConfigurationManager::saveProperty(const char *property, const char *value)
}
fo.close();
}
return prevValue;
}
void ConfigurationManager::migrateSyncConfig(MegaApi *api)
@ -338,17 +316,16 @@ void ConfigurationManager::saveSyncs(map<string, sync_struct *> *syncsmap)
{
std::lock_guard<std::recursive_mutex> g(settingsMutex);
stringstream syncsfile;
if (mConfigFolder.empty())
{
loadConfigDir();
}
if (!mConfigFolder.empty())
{
syncsfile << mConfigFolder << "/" << "syncs";
LOG_debug << "Syncs file: " << syncsfile.str();
const fs::path syncsFilePath = mConfigFolder / "syncs";
LOG_debug << "Syncs file: " << syncsFilePath;
ofstream fo(syncsfile.str().c_str(), ios::out | ios::binary);
ofstream fo(syncsFilePath, ios::out | ios::binary);
if (fo.is_open())
{
@ -387,17 +364,16 @@ void ConfigurationManager::saveBackups(map<string, backup_struct *> *backupsmap)
{
std::lock_guard<std::recursive_mutex> g(settingsMutex);
stringstream backupsfile;
if (mConfigFolder.empty())
{
loadConfigDir();
}
if (!mConfigFolder.empty())
{
backupsfile << mConfigFolder << "/" << "backups";
LOG_debug << "Backups file: " << backupsfile.str();
const fs::path backupsFilePath = mConfigFolder / "backups";
LOG_debug << "Backups file: " << backupsFilePath;
ofstream fo(backupsfile.str().c_str(), ios::out | ios::binary);
ofstream fo(backupsFilePath, ios::out | ios::binary);
if (fo.is_open())
{
@ -449,15 +425,15 @@ void ConfigurationManager::transitionLegacyExclusionRules(MegaApi& api)
// and since we also need to manually read the legacy file, it's just easier to rely on our custom
// method to generate the default file.
const string defaultMegaIgnorePath = MegaIgnoreFile::getDefaultPath();
const fs::path defaultMegaIgnorePath = MegaIgnoreFile::getDefaultPath();
if (fs::exists(defaultMegaIgnorePath))
{
LOG_debug << "Default .megaignore file already exists. Skipping legacy transition";
return;
}
const string excludeFilePath = mConfigFolder + "/excluded";
const string hiddenExcludeFilePath = mConfigFolder + "/.excluded";
const fs::path excludeFilePath = mConfigFolder / "excluded";
const fs::path hiddenExcludeFilePath = mConfigFolder / ".excluded";
if (!fs::exists(excludeFilePath))
{
LOG_debug << "Missing legacy exclude file. Skipping transition";
@ -518,7 +494,7 @@ void ConfigurationManager::transitionLegacyExclusionRules(MegaApi& api)
}
string message = "Your legacy sync exclusion rules have been ported to \"" +
defaultMegaIgnorePath + "\"\n" +
pathAsUtf8(defaultMegaIgnorePath) + "\"\n" +
"See \"%mega-%sync-ignore\" for more info.";
broadcastMessage(message, true);
}
@ -546,17 +522,16 @@ void ConfigurationManager::unloadConfiguration()
void ConfigurationManager::loadsyncs()
{
std::lock_guard<std::recursive_mutex> g(settingsMutex);
stringstream syncsfile;
if (mConfigFolder.empty())
{
loadConfigDir();
}
if (!mConfigFolder.empty())
{
syncsfile << mConfigFolder << "/" << "syncs";
LOG_debug << "Syncs file: " << syncsfile.str();
const fs::path syncsFilePath = mConfigFolder / "syncs";
LOG_debug << "Syncs file: " << syncsFilePath;
ifstream fi(syncsfile.str().c_str(), ios::in | ios::binary);
ifstream fi(syncsFilePath, ios::in | ios::binary);
if (fi.is_open())
{
@ -623,17 +598,16 @@ void ConfigurationManager::loadsyncs()
void ConfigurationManager::loadbackups()
{
std::lock_guard<std::recursive_mutex> g(settingsMutex);
stringstream backupsfile;
if (mConfigFolder.empty())
{
loadConfigDir();
}
if (!mConfigFolder.empty())
{
backupsfile << mConfigFolder << "/" << "backups";
LOG_debug << "Backups file: " << backupsfile.str();
const fs::path backupsFilePath = mConfigFolder / "backups";
LOG_debug << "Backups file: " << backupsFilePath;
ifstream fi(backupsfile.str().c_str(), ios::in | ios::binary);
ifstream fi(backupsFilePath, ios::in | ios::binary);
if (fi.is_open())
{
@ -698,20 +672,21 @@ void ConfigurationManager::loadConfiguration(bool debug)
{
std::lock_guard<std::recursive_mutex> g(settingsMutex);
// SESSION
auto configDir = getAndCreateConfigDir();
#ifdef _WIN32
WindowsUtf8StdoutGuard utf8Guard;
#endif
// SESSION
const fs::path configDir = getAndCreateConfigDir();
if (!configDir.empty())
{
stringstream sessionfile;
sessionfile << configDir << "/" << "session";
const fs::path sessionFilePath = configDir / "session";
if (debug)
{
std::cout << "Session file: " << sessionfile.str() << std::endl;
COUT << "Session file: " << sessionFilePath << std::endl;
}
ifstream fi(sessionfile.str().c_str(), ios::in);
ifstream fi(sessionFilePath, ios::in);
if (fi.is_open())
{
string line;
@ -720,23 +695,22 @@ void ConfigurationManager::loadConfiguration(bool debug)
session = line;
if (debug)
{
std::cout << "Session read from configuration: " << line.substr(0, 5) << "..." << std::endl;
COUT << "Session read from configuration: " << line.substr(0, 5) << "..." << std::endl;
}
}
fi.close();
}
// Check if version has been updated.
stringstream versionionfile;
if (mConfigFolder.empty())
{
loadConfigDir();
}
versionionfile << mConfigFolder << "/" << VERSION_FILE_NAME;
const fs::path versionFilePath = mConfigFolder / VERSION_FILE_NAME;
// Get latest version if any.
string latestVersion;
ifstream fiVer(versionionfile.str().c_str());
ifstream fiVer(versionFilePath);
if (fiVer.is_open())
{
fiVer >> latestVersion;
@ -748,12 +722,12 @@ void ConfigurationManager::loadConfiguration(bool debug)
hasBeenUpdated = true;
if (debug)
{
std::cout << "MEGAcmd has been updated." << std::endl;
COUT << "MEGAcmd has been updated." << std::endl;
}
}
// Store current version.
ofstream fo(versionionfile.str().c_str(), ios::out);
ofstream fo(versionFilePath, ios::out);
if (fo.is_open())
{
fo << MEGACMD_CODE_VERSION;
@ -761,14 +735,14 @@ void ConfigurationManager::loadConfiguration(bool debug)
}
else
{
std::cerr << "Could not write MEGAcmd version to " << versionionfile.str() << std::endl;
CERR << "Could not write MEGAcmd version to " << versionFilePath << std::endl;
}
}
else
{
if (debug)
{
std::cout << "Couldnt access data folder " << std::endl;
COUT << "Couldnt access data folder " << std::endl;
}
}
}
@ -781,13 +755,8 @@ bool ConfigurationManager::lockExecution()
auto runtimeDir = getAndCreateRuntimeDir();
if (runtimeDir != configDir)
{
auto lockFileAtConfigDir = std::string(configDir).append(1, LocalPath::localPathSeparator_utf8).append(LOCK_FILE_NAME);
static MegaFileSystemAccess fsAccess;
LocalPath localPath = LocalPath::fromAbsolutePath(lockFileAtConfigDir);
static std::unique_ptr<FileAccess> fa(fsAccess.newfileaccess());
bool lockFileAtConfigDirExists = fa->isfile(localPath);
if (lockFileAtConfigDirExists)
const fs::path lockFileAtConfigDir = configDir / LOCK_FILE_NAME;
if (fs::is_regular_file(lockFileAtConfigDir))
{
LOG_warn << "Found a lock file from a previous MEGAcmd version. Will try to acquire the lock and remove it";
bool legacyLockResult = lockExecution(configDir);
@ -809,23 +778,15 @@ bool ConfigurationManager::lockExecution()
return lockExecution(runtimeDir);
}
bool ConfigurationManager::lockExecution(const std::string &lockFileFolder)
bool ConfigurationManager::lockExecution(const fs::path &lockFileFolder)
{
assert(!lockFileFolder.empty());
stringstream lockfile;
#ifdef _WIN32
lockfile << "\\\\?\\";
lockfile << lockFileFolder << "\\" << LOCK_FILE_NAME;
#else
lockfile << lockFileFolder << "/" << LOCK_FILE_NAME;
#endif
LOG_info << "Lock file: " << lockfile.str();
const fs::path lockFilePath = lockFileFolder / LOCK_FILE_NAME;
LOG_info << "Lock file: " << lockFilePath;
#ifdef _WIN32
string wlockfile;
MegaApi::utf8ToUtf16(lockfile.str().c_str(), &wlockfile);
mLockFileHandle = CreateFileW((LPCWSTR)(wlockfile).data(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
mLockFileHandle = CreateFileW(lockFilePath.wstring().c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (mLockFileHandle == INVALID_HANDLE_VALUE)
{
LOG_err << "ERROR creating lock file: " << ERRNO;
@ -833,7 +794,7 @@ bool ConfigurationManager::lockExecution(const std::string &lockFileFolder)
return false;
}
#elif defined(LOCK_EX) && defined(LOCK_NB)
fd = open(lockfile.str().c_str(), O_RDWR | O_CREAT, 0666); // open or create lockfile
fd = open(lockFilePath.string().c_str(), O_RDWR | O_CREAT, 0666); // open or create lockfile
//check open success...
if (flock(fd, LOCK_EX | LOCK_NB))
{
@ -848,8 +809,9 @@ bool ConfigurationManager::lockExecution(const std::string &lockFileFolder)
}
#else
ifstream fi(thelockfile.c_str());
if(!fi.fail()){
ifstream fi(lockFilePath);
if(!fi.fail())
{
close(fd);
return false;
}
@ -857,7 +819,7 @@ bool ConfigurationManager::lockExecution(const std::string &lockFileFolder)
{
fi.close();
}
ofstream fo(thelockfile.c_str());
ofstream fo(lockFilePath);
if (fo.is_open())
{
fo.close();
@ -872,60 +834,56 @@ bool ConfigurationManager::unlockExecution()
return unlockExecution(getAndCreateRuntimeDir());
}
bool ConfigurationManager::unlockExecution(const std::string &lockFileFolder)
bool ConfigurationManager::unlockExecution(const fs::path &lockFileFolder)
{
assert(!lockFileFolder.empty());
stringstream lockfile;
lockfile << lockFileFolder << LocalPath::localPathSeparator_utf8 << LOCK_FILE_NAME;
#ifdef _WIN32
CloseHandle(mLockFileHandle);
#elif defined(LOCK_EX) && defined(LOCK_NB)
flock(fd, LOCK_UN | LOCK_NB);
close(fd);
#endif
bool succeeded = !unlink(lockfile.str().c_str());
if (!succeeded)
{
LOG_err << " Failed to remove lock file, errno = " << errno;
}
return succeeded;
const fs::path lockFilePath = lockFileFolder / LOCK_FILE_NAME;
if (std::error_code ec; !fs::remove(lockFilePath, ec))
{
LOG_err << "Failed to remove lock file, error = " << errorCodeStr(ec);
return false;
}
return true;
}
string ConfigurationManager::getConfigurationSValue(string propertyName)
{
std::lock_guard<std::recursive_mutex> g(settingsMutex);
if (!mConfigFolder.size())
if (mConfigFolder.empty())
{
loadConfigDir();
}
if (mConfigFolder.size())
if (!mConfigFolder.empty())
{
stringstream configFile;
configFile << mConfigFolder << "/" << "megacmd.cfg";
return getPropertyFromFile(configFile.str().c_str(),propertyName.c_str());
const fs::path configFilePath = mConfigFolder / "megacmd.cfg";
return getPropertyFromFile(configFilePath, propertyName.c_str());
}
return string();
return "";
}
void ConfigurationManager::clearConfigurationFile()
{
std::lock_guard<std::recursive_mutex> g(settingsMutex);
if (!mConfigFolder.size())
if (mConfigFolder.empty())
{
loadConfigDir();
}
if (mConfigFolder.size())
if (!mConfigFolder.empty())
{
stringstream configFile;
configFile << mConfigFolder << "/" << "megacmd.cfg";
const fs::path configFilePath = mConfigFolder / "megacmd.cfg";
ifstream infile(configFilePath);
stringstream formerlines;
ifstream infile(configFile.str().c_str());
string line;
while (getline(infile, line))
{
@ -949,8 +907,8 @@ void ConfigurationManager::clearConfigurationFile()
formerlines << line << endl;
}
}
ofstream fo(configFile.str().c_str());
ofstream fo(configFilePath);
if (fo.is_open())
{
fo << formerlines.str();

View File

@ -32,14 +32,15 @@ namespace megacmd {
class ConfigurationManager
{
private:
static std::string mConfigFolder;
static bool hasBeenUpdated;
inline static fs::path mConfigFolder;
inline static bool hasBeenUpdated = false;
#ifdef WIN32
static HANDLE mLockFileHandle;
#elif defined(LOCK_EX) && defined(LOCK_NB)
static int fd;
#endif
static void createFolderIfNotExisting(const fs::path &folder);
static void loadConfigDir();
static void removeSyncConfig(sync_struct *syncToRemove);
@ -47,8 +48,8 @@ private:
#ifdef MEGACMD_TESTING_CODE
public:
#endif
static bool lockExecution(const std::string &lockFileFolder);
static bool unlockExecution(const std::string &lockFileFolder);
static bool lockExecution(const fs::path &lockFileFolder);
static bool unlockExecution(const fs::path &lockFileFolder);
public:
static std::map<std::string, sync_struct *> oldConfiguredSyncs; //This will refer to old syncs from now on
@ -73,14 +74,45 @@ public:
static void saveSession(const char*session);
static void saveProperty(const char* property, const char* value);
static std::string /* prev value, if any */ saveProperty(const char* property, const char* value);
template<typename T>
static void savePropertyValue(const char* property, T value)
template<typename T,
typename Opt_T = std::optional<typename std::conditional_t<std::is_same_v<std::decay_t<T>, const char*>, std::string, T>>>
static Opt_T savePropertyValue(const char* property, const T& value)
{
std::ostringstream os;
os << value;
saveProperty(property,os.str().c_str());
constexpr bool isStr = std::is_same_v<std::remove_cv_t<T>, std::string>;
constexpr bool isConstChar = std::is_same_v<std::decay_t<T>, const char*>;
std::string prevValueStr;
if constexpr (isStr)
{
prevValueStr = saveProperty(property, value.c_str());
}
else if constexpr (isConstChar)
{
prevValueStr = saveProperty(property, value);
}
else
{
prevValueStr = saveProperty(property, std::to_string(value).c_str());
}
if (prevValueStr.empty())
{
return std::nullopt;
}
if constexpr (isStr || isConstChar)
{
return prevValueStr;
}
else
{
T prevValue;
std::istringstream is(prevValueStr);
is >> prevValue;
return prevValue;
}
}
template<typename T>
@ -235,12 +267,12 @@ public:
return toret;
}
static std::string getConfigFolder();
static fs::path getConfigFolder();
// creates a subfolder within the state dir and returns it (utf8)
static std::string getConfigFolderSubdir(const std::string &utf8Name);
static std::string getAndCreateRuntimeDir();
static std::string getAndCreateConfigDir();
static fs::path getConfigFolderSubdir(const fs::path& subdirName);
static fs::path getAndCreateRuntimeDir();
static fs::path getAndCreateConfigDir();
static bool getHasBeenUpdated();

View File

@ -19,7 +19,6 @@
#include "listeners.h"
#include "configurationmanager.h"
#include "megacmdutils.h"
#include "megacmdtransfermanager.h"
#include <utility>
@ -139,10 +138,10 @@ void MegaCmdGlobalListener::onNodesUpdate(MegaApi *api, MegaNodeList *nodes)
nFiles += details->getNumFiles(handle);
nFolders += details->getNumFolders(handle);
}
auto inboxNode = std::unique_ptr<MegaNode>(api->getInboxNode());
if (inboxNode != nullptr)
auto vaultNode = std::unique_ptr<MegaNode>(api->getVaultNode());
if (vaultNode != nullptr)
{
auto handle = inboxNode->getHandle();
auto handle = vaultNode->getHandle();
nFiles += details->getNumFiles(handle);
nFolders += details->getNumFolders(handle);
}
@ -391,11 +390,6 @@ void MegaCmdGlobalListener::onEvent(MegaApi *api, MegaEvent *event)
else if (event->getType() == MegaEvent::EVENT_NODES_CURRENT)
{
sandboxCMD->mNodesCurrentPromise.fulfil();
#ifdef HAVE_DOWNLOADS_COMMAND
// we need to cancel transfers here, because, even if fetchnodes finished, the actual transfer resumption
// won't happen until all action packets are received. And cancellation of transfers need them to be loaded already
std::thread([this](){sandboxCMD->cmdexecuter->cleanSlateTranfers();}).detach();
#endif
}
}
@ -522,6 +516,10 @@ void MegaCmdMegaListener::onSyncAdded(MegaApi *api, MegaSync *sync)
sendEvent(StatsManager::MegacmdEvent::FIRST_CONFIGURED_SYNC, api, false);
ConfigurationManager::savePropertyValue("firstSyncConfigured", true);
}
else
{
sendEvent(StatsManager::MegacmdEvent::SUBSEQUENT_CONFIGURED_SYNC, api, false);
}
}
void MegaCmdMegaListener::onSyncStateChanged(MegaApi *api, MegaSync *sync)
@ -536,7 +534,7 @@ void MegaCmdMegaListener::onSyncStateChanged(MegaApi *api, MegaSync *sync)
}
auto msg = ss.str();
if (sync->getError() || sync->getRunState() >= MegaSync::RUNSTATE_PAUSED)
if (sync->getError() || sync->getRunState() >= MegaSync::RUNSTATE_SUSPENDED)
{
broadcastDelayedMessage(msg, true);
}
@ -1142,13 +1140,6 @@ long long MegaCmdMultiTransferListener::getOngoingTotalBytes()
return total;
}
#ifdef HAVE_DOWNLOADS_COMMAND
std::vector<DownloadId> MegaCmdMultiTransferListener::getStartedTransfers() const
{
return mStartedTransfers;
}
#endif
bool MegaCmdMultiTransferListener::getProgressinformed() const
{
return progressinformed;
@ -1191,9 +1182,6 @@ void MegaCmdMultiTransferListener::onTransferStarted(const std::string &path, in
{
std::lock_guard<std::mutex> g(mStartedTransfersMutex);
mStartedTransfersCount++;
#ifdef HAVE_DOWNLOADS_COMMAND
mStartedTransfers.emplace_back(DownloadId(tag,path));
#endif
mStartedConditionVariable.notify_one();
}
}
@ -1212,13 +1200,6 @@ MegaCmdGlobalTransferListener::MegaCmdGlobalTransferListener(MegaApi *megaApi, M
void MegaCmdGlobalTransferListener::onTransferFinish(MegaApi* api, MegaTransfer *transfer, MegaError* error)
{
#ifdef HAVE_DOWNLOADS_COMMAND
if (transfer->getType() == transfer->TYPE_DOWNLOAD && ConfigurationManager::getConfigurationValue("downloads_tracking_enabled", false))
{
DownloadsManager::Instance().onTransferFinish(api, transfer, error);
}
#endif
completedTransfersMutex.lock();
completedTransfers.push_front(transfer->copy());
@ -1242,24 +1223,6 @@ void MegaCmdGlobalTransferListener::onTransferFinish(MegaApi* api, MegaTransfer
completedTransfersMutex.unlock();
}
void MegaCmdGlobalTransferListener::onTransferStart(MegaApi* api, MegaTransfer *transfer)
{
#ifdef HAVE_DOWNLOADS_COMMAND
if (transfer->getType() == transfer->TYPE_DOWNLOAD && ConfigurationManager::getConfigurationValue("downloads_tracking_enabled", false))
{
DownloadsManager::Instance().onTransferStart(api, transfer);
}
#endif
}
void MegaCmdGlobalTransferListener::onTransferUpdate(MegaApi* api, MegaTransfer *transfer)
{
#ifdef HAVE_DOWNLOADS_COMMAND
if (transfer->getType() == transfer->TYPE_DOWNLOAD && ConfigurationManager::getConfigurationValue("downloads_tracking_enabled", false))
{
DownloadsManager::Instance().onTransferUpdate(api, transfer);
}
#endif
}
void MegaCmdGlobalTransferListener::onTransferTemporaryError(MegaApi *api, MegaTransfer *transfer, MegaError* e)
{
if (e && e->getErrorCode() == MegaError::API_EOVERQUOTA && e->getValue())
@ -1276,13 +1239,6 @@ void MegaCmdGlobalTransferListener::onTransferTemporaryError(MegaApi *api, MegaT
sandboxCMD->timeOfOverquota = m_time(NULL);
sandboxCMD->secondsOverQuota=e->getValue();
}
#ifdef HAVE_DOWNLOADS_COMMAND
if (transfer->getType() == transfer->TYPE_DOWNLOAD && ConfigurationManager::getConfigurationValue("downloads_tracking_enabled", false))
{
DownloadsManager::Instance().onTransferUpdate(api, transfer);
}
#endif
}
bool MegaCmdGlobalTransferListener::onTransferData(MegaApi *api, MegaTransfer *transfer, char *buffer, size_t size) {return false;};
@ -1302,14 +1258,14 @@ bool MegaCmdCatTransferListener::onTransferData(MegaApi *api, MegaTransfer *tran
{
if (!ls->isClientConnected())
{
LOG_debug << " CatTransfer listener, cancelled transfer due to client disconnected";
LOG_verbose << " CatTransfer listener, cancelled transfer due to client disconnected";
api->cancelTransfer(transfer);
}
else
{
LOG_debug << " CatTransfer listener, streaming " << size << " bytes"; //TODO: verbose
*ls << string(buffer,size);
LOG_verbose << " CatTransfer listener, streaming " << size << " bytes";
*ls << BinaryStringView(buffer, size);
}
return true;
@ -1326,40 +1282,29 @@ ATransferListener::~ATransferListener()
}
void ATransferListener::onTransferStart(MegaApi *api, MegaTransfer *transfer)
{
auto tag = transfer->getTag();
#ifdef HAVE_DOWNLOADS_COMMAND
if (transfer->getType() == transfer->TYPE_DOWNLOAD && ConfigurationManager::getConfigurationValue("downloads_tracking_enabled", false))
{
DownloadsManager::Instance().addNewTopLevelTransfer(api, transfer, tag, mPath);
}
#endif
mMultiTransferListener->onTransferStarted(mPath, tag);
mMultiTransferListener->onTransferStart(api, transfer);
}
void ATransferListener::onTransferFinish(MegaApi *api, MegaTransfer *transfer, MegaError *e)
{
static_cast<MegaTransferListener *>(mMultiTransferListener.get())->onTransferFinish(api, transfer, e);
delete this;
}
void ATransferListener::onTransferUpdate(MegaApi *api, MegaTransfer *transfer)
{
mMultiTransferListener->onTransferUpdate(api, transfer);
}
void ATransferListener::onTransferTemporaryError(MegaApi *api, MegaTransfer *transfer, MegaError *e)
{
mMultiTransferListener->onTransferTemporaryError(api, transfer, e);
}
bool ATransferListener::onTransferData(MegaApi *api, MegaTransfer *transfer, char *buffer, size_t size)
{
return mMultiTransferListener->onTransferData(api, transfer, buffer, size);

View File

@ -21,8 +21,6 @@
#include "megacmdlogger.h"
#include "megacmdsandbox.h"
#include "megacmdtransfermanager.h"
namespace megacmd {
class MegaCmdSandbox;
@ -150,10 +148,6 @@ private:
std::condition_variable mStartedConditionVariable;
unsigned mStartedTransfersCount = 0;
#ifdef HAVE_DOWNLOADS_COMMAND
// string to tag map
std::vector<DownloadId> mStartedTransfers;
#endif
public:
MegaCmdMultiTransferListener(mega::MegaApi *megaApi, MegaCmdSandbox * sandboxCMD, mega::MegaTransferListener *listener = NULL, int clientID=-1);
virtual ~MegaCmdMultiTransferListener();
@ -180,10 +174,6 @@ public:
bool getProgressinformed() const;
#ifdef HAVE_DOWNLOADS_COMMAND
std::vector<DownloadId> getStartedTransfers() const;
#endif
protected:
mega::MegaTransferListener *listener;
};
@ -301,14 +291,10 @@ public:
virtual ~MegaCmdGlobalTransferListener();
//Transfer callbacks
void onTransferStart(mega::MegaApi* api, mega::MegaTransfer *transfer);
void onTransferFinish(mega::MegaApi* api, mega::MegaTransfer *transfer, mega::MegaError* error);
void onTransferUpdate(mega::MegaApi* api, mega::MegaTransfer *transfer);
void onTransferTemporaryError(mega::MegaApi *api, mega::MegaTransfer *transfer, mega::MegaError* e);
bool onTransferData(mega::MegaApi *api, mega::MegaTransfer *transfer, char *buffer, size_t size);
protected:
mega::MegaApi *megaApi;
mega::MegaTransferListener *listener;

View File

@ -16,6 +16,7 @@
* program.
*/
#include "megacmdcommonutils.h"
#include "megacmd.h"
#include "megaapi.h"
@ -778,24 +779,6 @@ void insertValidParamsPerCommand(set<string> *validParams, string thecommand, se
{
validOptValues->insert("clientID");
}
#ifdef HAVE_DOWNLOADS_COMMAND
else if ("downloads" == thecommand)
{
validParams->insert("show-subtransfers");
validParams->insert("report-all");
validParams->insert("disable-tracking");
validParams->insert("enable-tracking");
validParams->insert("query-enabled");
validParams->insert("enable-clean-slate");
validParams->insert("disable-clean-slate");
validParams->insert("purge");
validOptValues->insert("path-display-size");
validOptValues->insert("col-separator");
validOptValues->insert("output-cols");
}
#endif
else if ("transfers" == thecommand)
{
validParams->insert("show-completed");
@ -2013,12 +1996,6 @@ const char * getUsageStr(const char *command, const HelpFlags& flags)
{
return "transfers [-c TAG|-a] | [-r TAG|-a] | [-p TAG|-a] [--only-downloads | --only-uploads] [SHOWOPTIONS]";
}
#ifdef HAVE_DOWNLOADS_COMMAND
if (!strcmp(command, "downloads"))
{
return "downloads [--purge|--enable-clean-slate|--disable-clean-slate|--enable-tracking|--disable-tracking|query-enabled|report-all| [id_1 id_2 ... id_n]] [SHOWOPTIONS]";
}
#endif
if (((flags.win && !flags.readline) || flags.showAll) && !strcmp(command, "autocomplete"))
{
return "autocomplete [dos | unix]";
@ -2175,7 +2152,7 @@ string getHelpStr(const char *command, const HelpFlags& flags = {})
os << "with image or video extensions that are not really images or videos," << endl;
os << "or that are encrypted in the local drive so they can't be analyzed anyway." << endl;
os << endl;
os << "Notice that this setting will be saved for the next time you open MEGAcmd" << endl;
os << "Notice that this setting will be saved for the next time you open MEGAcmd, but will be removed if you logout." << endl;
}
else if (!strcmp(command, "signup"))
{
@ -2313,13 +2290,14 @@ string getHelpStr(const char *command, const HelpFlags& flags = {})
}
else if (!strcmp(command, "log"))
{
os << "Prints/Modifies the current logs level" << endl;
os << "Prints/Modifies the log level" << endl;
os << endl;
os << "Options:" << endl;
os << " -c" << "\t" << "CMD log level (higher level messages)." << endl;
os << " " << "\t" << " Messages captured by MEGAcmd server." << endl;
os << " -s" << "\t" << "SDK log level (lower level messages)." << endl;
os << " " << "\t" << " Messages captured by the engine and libs" << endl;
os << "Note: this setting will be saved for the next time you open MEGAcmd, but will be removed if you logout." << endl;
os << endl;
os << "Regardless of the log level of the" << endl;
@ -2525,7 +2503,7 @@ string getHelpStr(const char *command, const HelpFlags& flags = {})
os << "HTTPS is not necesary since all data is stored and transfered encrypted." << endl;
os << "Enabling it will increase CPU usage and add network overhead." << endl;
os << endl;
os << "Notice that this setting will be saved for the next time you open MEGAcmd" << endl;
os << "Notice that this setting will be saved for the next time you open MEGAcmd, but will be removed if you logout." << endl;
}
else if (!strcmp(command, "deleteversions"))
{
@ -2573,6 +2551,7 @@ string getHelpStr(const char *command, const HelpFlags& flags = {})
os << endl;
os << "*If you serve more than one location, these parameters will be ignored and use those of the first location served." << endl;
os << " If you want to change those parameters, you need to stop serving all locations and configure them again." << endl;
os << "Note: WEBDAV settings and locations will be saved for the next time you open MEGAcmd, but will be removed if you logout." << endl;
os << endl;
os << "Caveat: This functionality is in BETA state. It might not be available on all platforms. If you experience any issue with this, please contact: support@mega.nz" << endl;
os << endl;
@ -2602,6 +2581,7 @@ string getHelpStr(const char *command, const HelpFlags& flags = {})
os << endl;
os << "*If you serve more than one location, these parameters will be ignored and used those of the first location served." << endl;
os << " If you want to change those parameters, you need to stop serving all locations and configure them again." << endl;
os << "Note: FTP settings and locations will be saved for the next time you open MEGAcmd, but will be removed if you logout." << endl;
os << endl;
os << "Caveat: This functionality is in BETA state. It might not be available on all platforms. If you experience any issue with this, please contact: support@mega.nz" << endl;
os << endl;
@ -2679,8 +2659,8 @@ string getHelpStr(const char *command, const HelpFlags& flags = {})
os << " " << "\t" << "The \"--all\" argument can be used to show the details of all issues." << endl;
os << " --limit=rowcount " << "\t" << "Limits the amount of rows displayed. Set to 0 to display unlimited rows. Default is 10. Can also be combined with \"--detail\"." << endl;
os << " --disable-path-collapse " << "\t" << "Ensures all paths are fully shown. By default long paths are truncated for readability." << endl;
os << " --enable-warning " << "\t" << "Enables the notification that appears when issues are detected. This setting is stored locally for all users." << endl;
os << " --disable-warning " << "\t" << "Disables the notification that appears when issues are detected. This setting is stored locally for all users." << endl;
os << " --enable-warning " << "\t" << "Enables the notification that appears when issues are detected. This setting is saved for the next time you open MEGAcmd, but will be removed if you logout." << endl;
os << " --disable-warning " << "\t" << "Disables the notification that appears when issues are detected. This setting is saved for the next time you open MEGAcmd, but will be removed if you logout." << endl;
printColumnDisplayerHelp(os);
os << endl;
os << "DISPLAYED columns:" << endl;
@ -3023,6 +3003,8 @@ string getHelpStr(const char *command, const HelpFlags& flags = {})
os << " --username=USERNAME" << "\t" << "The username, for authenticated proxies" << endl;
os << " --password=PASSWORD" << "\t" << "The password, for authenticated proxies. Please, avoid using passwords containing \" or '" << endl;
os << endl;
os << "Note: Proxy settings will be saved for the next time you open MEGAcmd, but will be removed if you logout." << endl;
}
else if (!strcmp(command, "cat"))
{
@ -3136,90 +3118,6 @@ string getHelpStr(const char *command, const HelpFlags& flags = {})
os << "To only exit current shell and keep server running, use \"exit --only-shell\"" << endl;
}
}
#ifdef HAVE_DOWNLOADS_COMMAND
else if (!strcmp(command, "downloads"))
{
os << "Lists or configure downloads tracking and reporting." << endl;
os << endl;
os << "It will print the information regarding one or more downloads give their tags or object ids"<< endl;
os << " (both will be reported when using \"get\" with -q)." << endl;
os << "IMPORTANT: it is disabled by default, you need to enable it with \"downloads --enable-tracking\"." << endl;
os << endl;
os << "Options:" << endl;
os << " --query-enabled" << "\t" << "Indicates if download tracking is enabled" << endl;
os << " --enable-tracking" << "\t" << "Starts tracking downloads. It will store the information in a sqlite3 db" << endl;
os << " --disable-tracking" << "\t" << "Stops tracking downloads. Notice, it will remove the associated database" << endl;
os << " --enable-clean-slate" << "\t" << "Transfers from previous executions will be discarded upon restart" << endl;
os << " --disable-clean-slate" << "\t" << "Transfers from previous executions will not be discarded upon restart" << endl;
os << " --purge" << "\t" << "Cancells all onging transfers, and cleans all tracking (included persisted data)" << endl;
os << endl;
os << "Show options:" << endl;
os << " --report-all" << "\t" << "Prints a report of all active and finished downloads kept in memory" << endl;
os << " --show-subtransfers" << "\t" << "Show information regarding transfers" << endl;
os << " --path-display-size=N" << "\t" << "Use at least N characters for displaying paths" << endl;
printColumnDisplayerHelp(os);
os << endl;
os << "Displaying cols:" << endl;
os << " OBJECT_ID" << "\t" << "Id of the object (it will always be the same for the same download)" << endl;
os << " SUB_STARTED" << "\t" << "Number of subtransfers started" << endl;
os << " SUB_OK" << "\t" << "Number of subtransfers that completed ok" << endl;
os << " SUB_FAIL" << "\t" << "Number of subtransfers that completed with some error" << endl;
os << " SUBTRANSFER" << "\t" << "Tag of the subtransfers (only when using --show-subtransfers)" << endl;
os << " ERROR_CODE" << "\t" << "Error of the transfer (if any)" << endl;
os << " TYPE" << "\t" << "Type of transfer (see below)" << endl;
os << " TAG" << "\t" << "A tag that uniquely identifies a tranfer in current execution of MEGAcmd" << endl;
os << " SOURCEPATH" << "\t" << "Path of the folder/file downloaded" << endl;
os << " DESTINYPATH" << "\t" << "Local path for the downloaded file/folder" << endl;
os << " PROGRESS" << "\t" << "Human readable progress of the download" << endl;
os << " STATE" << "\t" << "State of the transfer. " << endl;
os << " " << "\t" << " Values:" << endl;
os << " " << "\t" << " QUEUED:" << "\t" << "queued in the system, waiting for an slot to be assigned" << endl;
os << " " << "\t" << " ACTIVE:" << "\t" << "doing I/O" << endl;
os << " " << "\t" << " PAUSED:" << "\t" << "paused" << endl;
os << " " << "\t" << " RETRYING:" << "\t" << "retrying after some potentially recoverable error" << endl;
os << " " << "\t" << " COMPLETING:" << "\t" << "final stages (e.g: moving temporal transfer file to its final destination)" << endl;
os << " " << "\t" << " COMPLETED:" << "\t" << "finished ok" << endl;
os << " " << "\t" << " CANCELLED:" << "\t" << "cancelled" << endl;
os << " " << "\t" << " FAILED:" << "\t" << "Failed (or subtransfers failed)" << endl;
os << " TRANSFERRED" << "\t" << "Number of bytes transferred" << endl;
os << " TOTAL" << "\t" << "Number of total bytes to be transferred" << endl;
os << endl;
os << "TYPE legend correspondence:" << endl;
#ifdef _WIN32
const string cD = getutf8fromUtf16(L"\u25bc");
const string cU = getutf8fromUtf16(L"\u25b2");
const string cS = getutf8fromUtf16(L"\u21a8");
const string cB = getutf8fromUtf16(L"\u2191");
#else
const string cD = "\u21d3";
const string cU = "\u21d1";
const string cS = "\u21f5";
const string cB = "\u23eb";
#endif
os << " " << cD <<" = \t" << "Download transfer" << endl;
os << " " << cU <<" = \t" << "Upload transfer" << endl;
os << " " << cS <<" = \t" << "Sync transfer. The transfer is done in the context of a synchronization" << endl;
os << " " << cB <<" = \t" << "Backup transfer. The transfer is done in the context of a backup" << endl;
os << endl;
os << "Configuration values" << endl;
os << "In your configuration folder (HOME/Appdata) there is megacmd.cfg configuration file." << endl;
os << "This are the properties used in the downloads tracking & report mechanism:" << endl;
os << " downloads_tracking_enabled" << "\t" << "If downloads tracking is enabled. Default=0 (false)!" << endl;
os << " downloads_tracking_max_finished_in_memory_high_threshold" << "\t" << "Max number of downloads to keep in memory. It this is surpassed, " << endl;
os << " " << "\t" << "finished transfers will start to be deleted (first the least recently updated)." << endl;
os << " " << "\t" << "Note: you can still get the information from the db using OJBECT_ID." << endl;
os << " " << "\t" << "Default=40000" << endl;
os << " downloads_tracking_max_finished_in_memory_low_threshold" << "\t" << "When pruning is executed it will clean until this threshold. Default=20000" << endl;
os << " downloads_db_path" << "\t" << "Path to store tracking information of downloads. Default: ~/.megaCmd/downloads.db" << endl;
os << " downloads_db_io_frequency_ms" << "\t" << "Frequency in milliseconds to commit pending changes in the database. Default=10000" << endl;
os << " downloads_db_max_queued_changes" << "\t" << "Max allowed number of changes to be queued before writting. Default=1000" << endl;
os << " downloads_cleanslate_enabled" << "\t" << "If transfers from previous executions will be discarded upon restart. Default=0 (false)" << endl;
}
#endif
else if (!strcmp(command, "transfers"))
{
os << "List or operate with transfers" << endl;
@ -3244,10 +3142,10 @@ string getHelpStr(const char *command, const HelpFlags& flags = {})
os << "TYPE legend correspondence:" << endl;
#ifdef _WIN32
const string cD = getutf8fromUtf16(L"\u25bc");
const string cU = getutf8fromUtf16(L"\u25b2");
const string cS = getutf8fromUtf16(L"\u21a8");
const string cB = getutf8fromUtf16(L"\u2191");
const string cD = utf16ToUtf8(L"\u25bc");
const string cU = utf16ToUtf8(L"\u25b2");
const string cS = utf16ToUtf8(L"\u21a8");
const string cB = utf16ToUtf8(L"\u2191");
#else
const string cD = "\u21d3";
const string cU = "\u21d1";
@ -3833,32 +3731,32 @@ bool executeUpdater(bool *restartRequired, bool doNotInstall = false)
if ( pidupdater == 0 )
{
char * donotinstallstr = NULL;
const char * donotinstallstr = NULL;
if (doNotInstall)
{
donotinstallstr = "--do-not-install";
}
auto versionStr = std::to_string(MEGACMD_CODE_VERSION);
char* version = const_cast<char*>(versionStr.c_str());
const char* version = const_cast<char*>(versionStr.c_str());
#ifdef __MACH__
#ifndef NDEBUG
char * args[] = {"./mega-cmd-updater", "--normal-update", donotinstallstr, "--version", version, NULL};
const char * args[] = {"./mega-cmd-updater", "--normal-update", donotinstallstr, "--version", version, NULL};
#else
char * args[] = {"/Applications/MEGAcmd.app/Contents/MacOS/MEGAcmdUpdater", "--normal-update", donotinstallstr, "--version", version, NULL};
const char * args[] = {"/Applications/MEGAcmd.app/Contents/MacOS/MEGAcmdUpdater", "--normal-update", donotinstallstr, "--version", version, NULL};
#endif
#else //linux doesn't use autoupdater: this is just for testing
#ifndef NDEBUG
char * args[] = {"./mega-cmd-updater", "--normal-update", donotinstallstr, "--version", version, NULL}; // notice: won't work after lcd
const char * args[] = {"./mega-cmd-updater", "--normal-update", donotinstallstr, "--version", version, NULL}; // notice: won't work after lcd
#else
char * args[] = {"mega-cmd-updater", "--normal-update", donotinstallstr, "--version", version, NULL};
const char * args[] = {"mega-cmd-updater", "--normal-update", donotinstallstr, "--version", version, NULL};
#endif
#endif
LOG_verbose << "Exec updater line: " << args[0] << " " << args[1] << " " << args[2];
if (execvp(args[0], args) < 0)
if (execvp(args[0], const_cast<char* const*>(args)) < 0)
{
LOG_err << " FAILED to initiate updater. errno = " << ERRNO;
@ -3944,16 +3842,16 @@ bool restartServer()
pid_t childid = fork();
if ( childid ) //parent
{
char **argv = new char*[mcmdMainArgc+3];
const char **argv = new const char*[mcmdMainArgc+3];
int i = 0, j = 0;
#ifdef __linux__
string executable = mcmdMainArgv[0];
string executable = const_cast<char* const>(mcmdMainArgv[0]);
if (executable.find("/") != 0)
{
executable.insert(0, getCurrentExecPath()+"/");
}
argv[0]=(char *)executable.c_str();
argv[0] = executable.c_str();
i++;
j++;
#endif
@ -3970,12 +3868,11 @@ bool restartServer()
}
}
argv[j++]="--wait-for";
argv[j++]=(char*)SSTR(childid).c_str();
argv[j++]=NULL;
argv[j++] = "--wait-for";
argv[j++] = std::to_string(childid).c_str();
argv[j++] = NULL;
LOG_debug << "Restarting the server : <" << argv[0] << ">";
execv(argv[0],argv);
execv(argv[0], const_cast<char* const*>(argv));
}
#endif
@ -4015,8 +3912,33 @@ bool isBareCommand(const char *l, const string &command)
return true;
}
void MegaCmdExecuter::mayExecutePendingStuffInWorkerThread()
{
{ // send INVALID_UTF8_INCIDENCES if there have been incidences
static std::mutex mutexSendEventInvalidUtf8Incidences;
std::lock_guard<std::mutex> g(mutexSendEventInvalidUtf8Incidences);
if (auto incidencesFound = sInvalidUtf8Incidences.exchange(0))
{
static HammeringLimiter hammeringLimiter(10);
if (!hammeringLimiter.runRecently())
{
LOG_err << "Invalid utf8 accumulated occurences: " << incidencesFound;
sendEvent(StatsManager::MegacmdEvent::INVALID_UTF8_INCIDENCES, api, false);
}
else
{
// add them again to the count, to be reconsidered later.
sInvalidUtf8Incidences += incidencesFound;
}
}
}
}
static bool process_line(const std::string_view line)
{
cmdexecuter->mayExecutePendingStuffInWorkerThread();
const char* l = line.data();
assert(line.size() == strlen(l)); // string_view does not guarantee null termination, which is depended upon
switch (prompt)
@ -4195,10 +4117,10 @@ void* doProcessLine(void* infRaw)
LoggedStreamPartialOutputs ls(cm, inf.get());
setCurrentThreadOutStream(ls);
setCurrentThreadIsCmdShell(!inf->line.empty() && inf->line[0] == 'X');
setCurrentThreadIsCmdShell(inf->isFromCmdShell());
LOG_verbose << " Processing " << inf->line << " in thread: " << MegaThread::currentThreadId() << " " << inf->getPetitionDetails();
LOG_verbose << " Processing " << inf->getRedactedLine() << " in thread: " << MegaThread::currentThreadId() << " " << inf->getPetitionDetails();
doExit = process_line(inf->getUniformLine());
@ -4208,7 +4130,7 @@ void* doProcessLine(void* infRaw)
LOG_verbose << " Exit registered upon process_line: " ;
}
LOG_verbose << " Procesed " << inf->line << " in thread: " << MegaThread::currentThreadId() << " " << inf->getPetitionDetails();
LOG_verbose << " Procesed " << inf->getRedactedLine() << " in thread: " << MegaThread::currentThreadId() << " " << inf->getPetitionDetails();
MegaThread * petitionThread = inf->getPetitionThread();
@ -4331,12 +4253,6 @@ void finalize(bool waitForRestartSignal_param)
alreadyfinalized = true;
LOG_info << "closing application ...";
#ifdef HAVE_DOWNLOADS_COMMAND
LOG_debug << "Shuting down downloads manager";
DownloadsManager::Instance().shutdown(false);
LOG_debug << "Downloads manager shut down";
#endif
delete_finished_threads();
if (!consoleFailed)
{
@ -4384,6 +4300,7 @@ void finalize(bool waitForRestartSignal_param)
#endif
delete cm; //this needs to go after restartServer();
LOG_debug << "resources have been cleaned ...";
LOG_info << "----------------------------- program end -------------------------------";
MegaApi::removeLoggerObject(loggerCMD);
delete loggerCMD;
@ -4535,14 +4452,14 @@ void processCommandInPetitionQueues(std::unique_ptr<CmdPetition> inf)
petitionThreads.emplace_back(petitionThread);
inf->setPetitionThread(petitionThread);
LOG_verbose << "starting processing: <" << inf->line << ">";
LOG_verbose << "starting processing: <" << inf->getRedactedLine() << ">";
petitionThread->start(doProcessLine, (void*) inf.release());
}
void processCommandLinePetitionQueues(std::string what)
{
auto inf = std::make_unique<CmdPetition>();
inf->line = what;
inf->setLine(what);
inf->clientDisconnected = true; // There's no actual client
inf->clientID = -3;
processCommandInPetitionQueues(std::move(inf));
@ -4585,7 +4502,7 @@ void megacmd()
CmdPetition* inf = infOwned.get();
LOG_verbose << "petition registered: " << inf->line;
LOG_verbose << "petition registered: " << inf->getRedactedLine();
delete_finished_threads();
if (inf->getUniformLine() == "ERROR")
@ -4601,51 +4518,24 @@ void megacmd()
continue;
}
// communicate client ID
string s = "clientID:";
s+=SSTR(currentclientID);
s+=(char)0x1F;
inf->clientID = currentclientID;
currentclientID++;
cm->informStateListener(inf,s);
{
// Communicate client ID
string clientIdStr = "clientID:" + std::to_string(currentclientID) + (char) 0x1F;
inf->clientID = currentclientID;
currentclientID++;
cm->informStateListener(inf, clientIdStr);
}
std::string s;
#if defined(_WIN32) || defined(__APPLE__)
string message="";
ostringstream os;
MegaCmdListener *megaCmdListener = new MegaCmdListener(NULL);
api->getLastAvailableVersion("BdARkQSQ",megaCmdListener);
if (!megaCmdListener->trywait(2000))
auto updatMsgOpt = lookForAvailableNewerVersions(api);
//TODO: have this executed in worker thread instead (see MegaCmdExecuter::mayExecutePendingStuffInWorkerThread)
// still store the update message to be consumed here
if (updatMsgOpt)
{
if (!megaCmdListener->getError())
{
LOG_fatal << "No MegaError at getLastAvailableVersion: ";
}
else if (megaCmdListener->getError()->getErrorCode() != MegaError::API_OK)
{
LOG_debug << "Couldn't get latests available version: " << megaCmdListener->getError()->getErrorString();
}
else
{
if (megaCmdListener->getRequest()->getNumber() != MEGACMD_CODE_VERSION)
{
os << "---------------------------------------------------------------------" << endl;
os << "-- There is a new version available of megacmd: " << setw(12) << left << megaCmdListener->getRequest()->getName() << "--" << endl;
os << "-- Please, update this one: See \"update --help\". --" << endl;
os << "-- Or download the latest from https://mega.nz/cmd --" << endl;
#if defined(__APPLE__)
os << "-- Before installing enter \"exit\" to close MEGAcmd --" << endl;
#endif
os << "---------------------------------------------------------------------" << endl;
}
}
delete megaCmdListener;
}
else
{
LOG_debug << "Couldn't get latests available version (petition timed out)";
api->removeRequestListener(megaCmdListener);
delete megaCmdListener;
os << *updatMsgOpt;
}
int autoupdate = ConfigurationManager::getConfigurationValue("autoupdate", -1);
@ -4659,14 +4549,13 @@ void megacmd()
{
startcheckingForUpdates();
}
message=os.str();
auto message = os.str();
if (message.size())
{
s += "message:";
s+=message;
s+=(char)0x1F;
s += message;
s += (char) 0x1F;
}
#endif
@ -4692,7 +4581,7 @@ void megacmd()
s += "Your Operative System is too old.\n";
s += "You might not receive new updates for this application.\n";
s += "We strongly recommend you to update to a new version.\n";
s+=(char)0x1F;
s += (char) 0x1F;
}
if (sandboxCMD->storageStatus != MegaApi::STORAGE_STATE_GREEN)
@ -4758,7 +4647,7 @@ void megacmd()
s += "You can change your account plan to increase your quota limit.\n";
}
s += "See \"help --upgrade\" for further details.\n";
s += (char)0x1F;
s += (char) 0x1F;
}
// if server resuming session, lets give him a very litle while before sending greeting message to the early clients
@ -4779,7 +4668,7 @@ void megacmd()
for (auto m: greetingsAllClientMsgs)
{
cm->informStateListener(inf,m.append(1, (char)0x1F));
cm->informStateListener(inf, m.append(1, (char)0x1F));
}
}
@ -4792,16 +4681,16 @@ void megacmd()
}
// communicate status info
s+= "prompt:";
s+=dynamicprompt;
s+=(char)0x1F;
s += "prompt:";
s += dynamicprompt;
s += (char) 0x1F;
if (!sandboxCMD->getReasonblocked().size())
{
cmdexecuter->checkAndInformPSA(inf);
}
cm->informStateListener(inf,s);
cm->informStateListener(inf, s);
}
else
{ // normal petition
@ -4828,30 +4717,62 @@ void printWelcomeMsg()
width--;
#endif
COUT << endl;
COUT << ".";
for (unsigned int i = 0; i < width; i++)
COUT << "=" ;
COUT << ".";
COUT << endl;
printCenteredLine(" __ __ _____ ____ _ _ ",width);
printCenteredLine("| \\/ | ___|/ ___| / \\ ___ _ __ ___ __| |",width);
printCenteredLine("| |\\/| | \\ / | _ / _ \\ / __| '_ ` _ \\ / _` |",width);
printCenteredLine("| | | | /__\\ |_| |/ ___ \\ (__| | | | | | (_| |",width);
printCenteredLine("|_| |_|____|\\____/_/ \\_\\___|_| |_| |_|\\__,_|",width);
std::ostringstream oss;
COUT << "|";
oss << endl;
oss << ".";
for (unsigned int i = 0; i < width; i++)
COUT << " " ;
COUT << "|";
COUT << endl;
printCenteredLine("SERVER",width);
oss << "=" ;
oss << ".";
oss << endl;
printCenteredLine(oss, " __ __ _____ ____ _ _ ",width);
printCenteredLine(oss, "| \\/ | ___|/ ___| / \\ ___ _ __ ___ __| |",width);
printCenteredLine(oss, "| |\\/| | \\ / | _ / _ \\ / __| '_ ` _ \\ / _` |",width);
printCenteredLine(oss, "| | | | /__\\ |_| |/ ___ \\ (__| | | | | | (_| |",width);
printCenteredLine(oss, "|_| |_|____|\\____/_/ \\_\\___|_| |_| |_|\\__,_|",width);
COUT << "`";
oss << "|";
for (unsigned int i = 0; i < width; i++)
COUT << "=" ;
COUT << "´";
COUT << endl;
oss << " " ;
oss << "|";
oss << endl;
printCenteredLine(oss, "SERVER",width);
oss << "`";
for (unsigned int i = 0; i < width; i++)
{
oss << "=" ;
}
#ifndef _WIN32
oss << "\u00b4\n";
COUT << oss.str() << std::flush;
#else
WindowsUtf8StdoutGuard utf8Guard;
// So far, all is ASCII.
COUT << oss.str();
// Now let's tray the non ascii forward acute
// We are about to write some non ascii character.
// Let's set (from now on, the console code page to UTF-8 translation (65001)
// but revert to the initial code page if outputing the special forward acute character
// fails. <- This could happen, for instance in Windows 7.
auto initialCP = GetConsoleOutputCP();
bool codePageChangedSuccesfully = false;
if (initialCP != CP_UTF8 && !getenv("MEGACMDSERVER_DONOT_SET_CONSOLE_CP"))
{
codePageChangedSuccesfully = SetConsoleOutputCP(CP_UTF8);
}
if (!(COUT << L"\u00b4")) // failed to output using utf-8
{
if (codePageChangedSuccesfully) // revert codepage
{
SetConsoleOutputCP(initialCP);
}
COUT << "/";
}
COUT << std::endl;
#endif
}
@ -4994,7 +4915,7 @@ bool registerUpdater()
stringSID = getCurrentSid();
if (!stringSID)
{
MegaApi::log(MegaApi::LOG_LEVEL_ERROR, "Unable to get the current SID");
LOG_err << "Unable to get the current SID";
return false;
}
@ -5080,21 +5001,21 @@ bool registerUpdater()
&pRegisteredTask)))
{
success = true;
MegaApi::log(MegaApi::LOG_LEVEL_ERROR, "Update task registered OK");
LOG_err << "Update task registered OK";
}
else
{
MegaApi::log(MegaApi::LOG_LEVEL_ERROR, "Error registering update task");
LOG_err << "Error registering update task";
}
}
else
{
MegaApi::log(MegaApi::LOG_LEVEL_ERROR, "Error creating update task");
LOG_err << "Error creating update task";
}
}
else
{
MegaApi::log(MegaApi::LOG_LEVEL_ERROR, "Error getting root task folder");
LOG_err << "Error getting root task folder";
}
if (pRegisteredTask)
@ -5260,7 +5181,8 @@ void sendEvent(StatsManager::MegacmdEvent event, ::mega::MegaApi *megaApi, bool
#ifdef _WIN32
void uninstall()
{
MegaApi::removeRecursively(megacmd::ConfigurationManager::getConfigFolder().c_str());
std::error_code ec; // to use the non-throwing overload below
fs::remove_all(ConfigurationManager::getConfigFolder(), ec);
ITaskService *pService = NULL;
ITaskFolder *pRootFolder = NULL;
@ -5335,6 +5257,8 @@ int executeServer(int argc, char* argv[],
setlocale(LC_ALL, "en-US");
#endif
printWelcomeMsg();
// keep a copy of argc & argv in order to allow restarts
mcmdMainArgv = argv;
mcmdMainArgc = argc;
@ -5363,11 +5287,14 @@ int executeServer(int argc, char* argv[],
char userAgent[40];
sprintf(userAgent, "MEGAcmd" MEGACMD_STRINGIZE(MEGACMD_USERAGENT_SUFFIX) "/%d.%d.%d.%d", MEGACMD_MAJOR_VERSION,MEGACMD_MINOR_VERSION,MEGACMD_MICRO_VERSION,MEGACMD_BUILD_ID);
LOG_debug << "----------------------------- program start -----------------------------";
LOG_info << "----------------------- program start -----------------------";
LOG_debug << "MEGAcmd version: " << MEGACMD_MAJOR_VERSION << "." << MEGACMD_MINOR_VERSION << "." << MEGACMD_MICRO_VERSION << "." << MEGACMD_BUILD_ID << ": code " << MEGACMD_CODE_VERSION;
LOG_debug << "MEGA SDK version: " << SDK_COMMIT_HASH;
api = new MegaApi("BdARkQSQ", (MegaGfxProcessor*)NULL, ConfigurationManager::getAndCreateConfigDir().c_str(), userAgent);
const fs::path configDirPath = ConfigurationManager::getAndCreateConfigDir();
const std::string configDirStrUtf8 = pathAsUtf8(configDirPath);
api = new MegaApi("BdARkQSQ", configDirStrUtf8.c_str(), userAgent);
if (!debug_api_url.empty())
{
@ -5378,9 +5305,10 @@ int executeServer(int argc, char* argv[],
for (int i = 0; i < 5; i++)
{
MegaApi *apiFolder = new MegaApi("BdARkQSQ", (MegaGfxProcessor*)NULL,
ConfigurationManager::getConfigFolderSubdir(std::string("apiFolder_").append(std::to_string(i))).c_str()
, userAgent);
const fs::path apiFolderPath = ConfigurationManager::getConfigFolderSubdir("apiFolder_" + std::to_string(i));
const std::string apiFolderStrUtf8 = pathAsUtf8(apiFolderPath);
MegaApi *apiFolder = new MegaApi("BdARkQSQ", apiFolderStrUtf8.c_str(), userAgent);
apiFolder->setLanguage(localecode.c_str());
apiFolders.push(apiFolder);
apiFolder->setLogLevel(MegaApi::LOG_LEVEL_MAX);
@ -5455,9 +5383,6 @@ int executeServer(int argc, char* argv[],
}
#endif
printWelcomeMsg();
int configuredProxyType = ConfigurationManager::getConfigurationValue("proxy_type", -1);
auto configuredProxyUrl = ConfigurationManager::getConfigurationSValue("proxy_url");
@ -5509,4 +5434,54 @@ void stopServer()
processCommandLinePetitionQueues("quit"); //TODO: have set doExit instead, and wake the loop.
}
std::optional<std::string> lookForAvailableNewerVersions(::mega::MegaApi *api)
{
#ifdef __linux__
return {}; // Linux updates are _announced_ via packages manageres
#endif
//NOTE: expected to be called from main megacmd thread (no concurrency control required)
static HammeringLimiter hammeringLimiter(300);
if (hammeringLimiter.runRecently())
{
return {};
}
ostringstream os;
auto megaCmdListener = std::make_unique<MegaCmdListener>(api);
api->getLastAvailableVersion("BdARkQSQ", megaCmdListener.get());
if (megaCmdListener->trywait(2000)) //timed out:
{
LOG_debug << "Couldn't get latests available version (petition timed out)";
api->removeRequestListener(megaCmdListener.get());
return {};
}
if (!megaCmdListener->getError())
{
LOG_fatal << "No MegaError at getLastAvailableVersion: ";
}
else if (megaCmdListener->getError()->getErrorCode() != MegaError::API_OK)
{
LOG_debug << "Couldn't get latests available version: " << megaCmdListener->getError()->getErrorString();
}
else
{
if (megaCmdListener->getRequest()->getNumber() != MEGACMD_CODE_VERSION)
{
os << "---------------------------------------------------------------------" << endl;
os << "-- There is a new version available of megacmd: " << setw(12) << left << megaCmdListener->getRequest()->getName() << "--" << endl;
os << "-- Please, update this one: See \"update --help\". --" << endl;
os << "-- Or download the latest from https://mega.nz/cmd --" << endl;
#if defined(__APPLE__)
os << "-- Before installing enter \"exit\" to close MEGAcmd --" << endl;
#endif
os << "---------------------------------------------------------------------" << endl;
}
return os.str();
}
return {};
}
} //end namespace

View File

@ -36,6 +36,8 @@ using std::locale;
using std::stringstream;
using std::exception;
#include "megacmdcommonutils.h"
#include "megaapi_impl.h"
#include "megacmd_events.h"
@ -208,10 +210,16 @@ void* checkForUpdates(void *param);
void stopcheckingForUpdates();
void startcheckingForUpdates();
/**
* @brief synchronously request the API for a a new version of MEGAcmd
* It will skip the check if already checked in the past 5 minutes
* @param api
* @return a string with a msg with the announcement if a new version is available
*/
std::optional<std::string> lookForAvailableNewerVersions(::mega::MegaApi *api);
void informTransferUpdate(mega::MegaTransfer *transfer, int clientID);
void informStateListenerByClientId(int clientID, std::string s);
void informProgressUpdate(long long transferred, long long total, int clientID, std::string title = "");
void sendEvent(StatsManager::MegacmdEvent event, mega::MegaApi *megaApi, bool wait = true);

View File

@ -33,7 +33,16 @@ namespace megacmd::StatsManager {
GENERATOR_MACRO(FIRST_CONFIGURED_SYNC , 98903, "MEGAcmd first sync configured") \
GENERATOR_MACRO(WAITED_TOO_LONG_FOR_NODES_CURRENT , 98904, "MEGAcmd nodes current wait timed out") \
GENERATOR_MACRO(ROOT_NODE_NOT_FOUND_AFTER_FETCHING , 98906, "MEGAcmd root node was not found after fetching nodes") \
GENERATOR_MACRO(TRANSITIONING_PRE_SRW_EXCLUSIONS , 98907, "MEGAcmd transition of legacy exclusion rules started")
GENERATOR_MACRO(TRANSITIONING_PRE_SRW_EXCLUSIONS , 98907, "MEGAcmd transition of legacy exclusion rules started") \
GENERATOR_MACRO(FIRST_CONFIGURED_WEBDAV , 98908, "MEGAcmd first WebDAV location configured") \
GENERATOR_MACRO(FIRST_CONFIGURED_FTP , 98909, "MEGAcmd first FTP location configured") \
GENERATOR_MACRO(FIRST_CONFIGURED_SCHEDULED_BACKUP , 98910, "MEGAcmd first scheduled backup configured") \
GENERATOR_MACRO(SUBSEQUENT_CONFIGURED_SYNC , 98911, "MEGAcmd subsequent sync configured") \
GENERATOR_MACRO(SUBSEQUENT_CONFIGURED_WEBDAV , 98912, "MEGAcmd subsequent WebDAV location configured") \
GENERATOR_MACRO(SUBSEQUENT_CONFIGURED_FTP , 98913, "MEGAcmd subsequent FPT location configured") \
GENERATOR_MACRO(SUBSEQUENT_CONFIGURED_SCHEDULED_BACKUP , 98914, "MEGAcmd subsequent scheduled backup configured") \
GENERATOR_MACRO(INVALID_UTF8_INCIDENCES , 98915, "MEGAcmd Found Invalid UTF-8 incidences") \
static constexpr auto FIRST_EVENT_NUMBER = 98900u;

View File

@ -13,6 +13,7 @@
* program.
*/
#include "megacmdcommonutils.h"
#include "megacmd_rotating_logger.h"
#include <cassert>
@ -23,10 +24,10 @@
namespace {
class ReopenScope final
{
OUTFSTREAMTYPE& mOutFile;
const std::string mOutFilePath;
std::ofstream& mOutFile;
const fs::path mOutFilePath;
public:
ReopenScope(OUTFSTREAMTYPE& outFile, const std::string& outFilePath) :
ReopenScope(std::ofstream& outFile, const fs::path& outFilePath) :
mOutFile(outFile),
mOutFilePath(outFilePath)
{
@ -38,17 +39,6 @@ public:
mOutFile.open(mOutFilePath, std::ofstream::out | std::ofstream::app);
}
};
std::string outstringToString(const OUTSTRING& outstring)
{
#ifdef _WIN32
std::string str;
megacmd::localwtostring(&outstring, &str);
return str;
#else
return outstring;
#endif
}
}
namespace megacmd {
@ -360,13 +350,13 @@ void FileRotatingLoggedStream::mainLoop()
{
while (!shouldExit() || !mMessageBuffer.isEmpty())
{
std::string errorMessages;
std::ostringstream errorStream;
bool reopenFile = false;
if (!waitForOutputFile())
{
errorMessages += "Error writing to log file " + mOutputFilePath + '\n';
errorMessages += "Re-opening...\n";
errorStream << "Error writing to log file " << mOutputFilePath << '\n';
errorStream << "Re-opening...\n";
reopenFile = true;
}
@ -387,8 +377,15 @@ void FileRotatingLoggedStream::mainLoop()
mFileManager.rotateFiles();
}
errorMessages += mFileManager.popErrors();
std::cerr << errorMessages;
errorStream << mFileManager.popErrors();
#ifdef WIN32
{
WindowsUtf8StdoutGuard utf8Guard;
std::wcerr << utf8StringToUtf16WString(errorStream.str().c_str()) << std::flush;
}
#else
std::cerr << errorStream.str() << std::flush;
#endif
if (!mOutputFile)
{
@ -405,7 +402,7 @@ void FileRotatingLoggedStream::mainLoop()
continue;
}
}
mOutputFile << errorMessages;
mOutputFile << errorStream.str();
bool writeMessages = false;
{
@ -430,7 +427,7 @@ void FileRotatingLoggedStream::mainLoop()
FileRotatingLoggedStream::FileRotatingLoggedStream(const OUTSTRING& outputFilePath) :
mMessageBuffer(500 * 1024 * 1024 /* 500MB */),
mOutputFilePath(outstringToString(outputFilePath)),
mOutputFilePath(outputFilePath),
mOutputFile(outputFilePath, std::ofstream::out | std::ofstream::app),
mFileManager(mOutputFilePath),
mForceRenew(false),
@ -466,6 +463,12 @@ const LoggedStream& FileRotatingLoggedStream::operator<<(std::string str) const
return *this;
}
const LoggedStream& FileRotatingLoggedStream::operator<<(BinaryStringView v) const
{
writeToBuffer(v.get().data(), v.get().size());
return *this;
}
const LoggedStream& FileRotatingLoggedStream::operator<<(std::string_view str) const
{
writeToBuffer(str.data(), str.size());
@ -652,7 +655,8 @@ fs::path TimestampRotationEngine::rotateBaseFile(const fs::path& directory, cons
const std::string timestampStr = timestampToString(Clock::now());
fs::path srcFilePath = directory / baseFilename;
fs::path dstFilePath = srcFilePath.string() + "." + timestampStr;
fs::path dstFilePath = srcFilePath;
dstFilePath += "." + timestampStr;
std::error_code ec;
@ -787,7 +791,15 @@ void GzipCompressionEngine::gzipFile(const fs::path& srcFilePath, const fs::path
}
auto gzdeleter = [] (gzFile_s* f) { if (f) gzclose(f); };
std::unique_ptr<gzFile_s, decltype(gzdeleter)> gzFile(gzopen(dstFilePath.string().c_str(), "wb"), gzdeleter);
auto gzOpenHelper = [](const fs::path& path) {
#ifdef _WIN32
return gzopen_w(path.wstring().c_str(), "wb");
#else
return gzopen(path.string().c_str(), "wb");
#endif
};
std::unique_ptr<gzFile_s, decltype(gzdeleter)> gzFile(gzOpenHelper(dstFilePath), gzdeleter);
if (!gzFile)
{
mErrorStream << "Failed to open gzfile " << dstFilePath << " for writing" << std::endl;
@ -886,7 +898,8 @@ void GzipCompressionEngine::cancelAll()
void GzipCompressionEngine::compressFile(const fs::path& filePath)
{
std::error_code ec;
fs::path tmpFilePath = filePath.string() + ".zipping";
fs::path tmpFilePath = filePath;
tmpFilePath += ".zipping";
// Ensure there is not a clashing .zipping file
if (fs::exists(tmpFilePath, ec) && !ec)
@ -906,7 +919,8 @@ void GzipCompressionEngine::compressFile(const fs::path& filePath)
return;
}
fs::path targetFilePath = filePath.string() + getExtension();
fs::path targetFilePath = filePath;
targetFilePath += getExtension();
pushToQueue(tmpFilePath, targetFilePath);
}
}

View File

@ -22,12 +22,9 @@
#include <condition_variable>
#include <chrono>
#include <thread>
#include <filesystem>
#include "megacmdlogger.h"
namespace fs = std::filesystem;
namespace megacmd {
template<size_t BlockSize>
@ -128,8 +125,8 @@ class FileRotatingLoggedStream final : public LoggedStream
{
mutable MessageBuffer<1024> mMessageBuffer;
std::string mOutputFilePath;
OUTFSTREAMTYPE mOutputFile;
fs::path mOutputFilePath;
std::ofstream mOutputFile;
RotatingFileManager mFileManager;
mutable std::mutex mWriteMtx;
@ -167,6 +164,7 @@ public:
const LoggedStream& operator<<(const char& c) const override;
const LoggedStream& operator<<(const char* str) const override;
const LoggedStream& operator<<(std::string str) const override;
const LoggedStream& operator<<(BinaryStringView v) const override;
const LoggedStream& operator<<(std::string_view str) const override;
const LoggedStream& operator<<(int v) const override;
const LoggedStream& operator<<(unsigned int v) const override;
@ -190,6 +188,8 @@ MessageBuffer<BlockSize>::MemoryBlock::MemoryBlock() :
mSize(0),
mMemoryAllocationFailed(false)
{
// Ensure null-termination even if the memory block is empty
mBuffer[0] = '\0';
}
template<size_t BlockSize>
@ -231,6 +231,7 @@ void MessageBuffer<BlockSize>::MemoryBlock::appendData(const char* data, size_t
std::memcpy(&mBuffer[mSize], data, size);
mSize += size;
assert(mSize < BlockSize);
// Append null after the last character so the buffer
// is properly treated as a C-string
@ -289,7 +290,10 @@ typename MessageBuffer<BlockSize>::MemoryBlockList MessageBuffer<BlockSize>::pop
std::lock_guard<std::mutex> lock(mListMtx);
initialMemoryError = mInitialMemoryError;
mInitialMemoryError = false;
return std::move(mList);
MemoryBlockList poppedList;
std::swap(poppedList, mList);
return poppedList;
}
template<size_t BlockSize>

View File

@ -16,9 +16,9 @@
#include "megacmd.h"
#include "megaapi.h"
#include "megacmdlogger.h"
#include "megacmd_rotating_logger.h"
#include "configurationmanager.h"
#include <vector>
@ -54,23 +54,23 @@ bool extractargparam(vector<const char*>& args, const char *what, std::string& p
std::pair<int/*sdk*/, int/*cmd*/> getLogLevels(std::vector<const char*>& args)
{
using mega::MegaApi;
// default log levels
int sdkLogLevel = MegaApi::LOG_LEVEL_ERROR;
int cmdLogLevel = MegaApi::LOG_LEVEL_INFO;
using megacmd::ConfigurationManager;
// for !Windows have DEBUG builds use debug level by default
#if defined(DEBUG) && !defined(_WIN32)
sdkLogLevel = MegaApi::LOG_LEVEL_DEBUG;
cmdLogLevel = MegaApi::LOG_LEVEL_DEBUG;
#ifndef DEBUG
constexpr int defaultSdkLogLevel = (int) MegaApi::LOG_LEVEL_ERROR;
#else
constexpr int defaultSdkLogLevel = (int) MegaApi::LOG_LEVEL_DEBUG;
#endif
constexpr int defaultCmdLogLevel = (int) MegaApi::LOG_LEVEL_DEBUG;
int sdkLogLevel = ConfigurationManager::getConfigurationValue("sdkLogLevel", defaultSdkLogLevel);
int cmdLogLevel = ConfigurationManager::getConfigurationValue("cmdLogLevel", defaultCmdLogLevel);
// read parameters from argumetns
bool debug = extractarg(args, "--debug");
bool debugfull = extractarg(args, "--debug-full");
bool verbose = extractarg(args, "--verbose");
bool verbosefull = extractarg(args, "--verbose-full");
// overridance by environment variable
const char *envCmdLogLevel = getenv("MEGACMD_LOGLEVEL");
if (envCmdLogLevel)
{
@ -170,6 +170,10 @@ void waitIfRequired(std::vector<const char*> &args)
// - linux forking (clients into server)
int main(int argc, char* argv[])
{
#ifdef WIN32
megacmd::Instance<megacmd::WindowsConsoleController> windowsConsoleController;
#endif
std::vector<const char*> args;
if (argc > 1)
{
@ -184,7 +188,7 @@ int main(int argc, char* argv[])
waitIfRequired(args);
constexpr bool logToCout = true;
bool logToCout = !extractarg(args, "--do-not-log-to-stdout");
auto logLevels = getLogLevels(args);
int sdkLogLevel = logLevels.first;
int cmdLogLevel = logLevels.second;

271
src/megacmd_utf8.cpp Normal file
View File

@ -0,0 +1,271 @@
/**
* @file src/megacmd_utf8.cpp
* @brief MEGAcmd: utf8 and console resources
*
* (c) 2013 by Mega Limited, Auckland, New Zealand
*
* This file is part of the MEGAcmd.
*
* MEGAcmd is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* @copyright Simplified (2-clause) BSD License.
*
* You should have received a copy of the license along with this
* program.
*/
#include "megacmd_utf8.h"
#ifdef WIN32
#include <Shlwapi.h>
#include <Shellapi.h>
#include <windows.h>
#endif
namespace megacmd {
#ifdef _WIN32
std::wostream & operator<< ( std::wostream & ostr, std::string const & str )
{
std::wstring toout;
stringtolocalw(str.c_str(),&toout);
ostr << toout;
return ( ostr );
}
std::wostream & operator<< ( std::wostream & ostr, const char * str )
{
std::wstring toout;
stringtolocalw(str,&toout);
ostr << toout;
return ( ostr );
}
// convert UTF-8 to Windows Unicode wstring (UTF-16)
void stringtolocalw(const char* path, size_t lenutf8, std::wstring* local)
{
assert(isValidUtf8(std::string(path, lenutf8)));
// make space for the worst case
local->resize((strlen(path) + 1) * sizeof(wchar_t));
int wchars_num = MultiByteToWideChar(CP_UTF8, 0, path, lenutf8 + 1, NULL,0);
local->resize(wchars_num);
int len = MultiByteToWideChar(CP_UTF8, 0, path, lenutf8 + 1, (wchar_t*)local->data(), wchars_num);
if (len)
{
local->resize(len-1);
}
else
{
local->clear();
}
}
// convert UTF-8 to Windows Unicode wstring (UTF-16)
void stringtolocalw(const char* path, std::wstring* local)
{
stringtolocalw(path, strlen(path), local);
}
std::wstring utf8StringToUtf16WString(const char* str)
{
std::wstring toret;
stringtolocalw(str, &toret);
return toret;
}
std::wstring utf8StringToUtf16WString(const char* str, size_t lenutf8)
{
std::wstring toret;
stringtolocalw(str, lenutf8, &toret);
return toret;
}
void localwtostring(const std::wstring* wide, std::string *multibyte)
{
utf16ToUtf8(wide->data(), (int)wide->size(), multibyte);
}
void utf16ToUtf8(const wchar_t* utf16data, int utf16size, std::string* utf8string)
{
if(!utf16size)
{
utf8string->clear();
return;
}
int size_needed = WideCharToMultiByte(CP_UTF8, 0, utf16data, utf16size, NULL, 0, NULL, NULL);
utf8string->resize(size_needed);
WideCharToMultiByte(CP_UTF8, 0, utf16data, utf16size, (char*)utf8string->data(), size_needed, NULL, NULL);
assert(isValidUtf8(*utf8string));
}
std::string utf16ToUtf8(const std::wstring &ws)
{
std::string utf8s;
utf16ToUtf8(ws.c_str(), ws.size(), &utf8s);
return utf8s;
}
std::string utf16ToUtf8(const wchar_t *ws)
{
std::string utf8s;
utf16ToUtf8(ws, int(wcslen(ws)), &utf8s);
return utf8s;
}
std::wstring nonMaxPathLimitedWstring(const fs::path &localpath)
{
static const std::wstring wprefix(LR"(\\?\)");
if (localpath.wstring().rfind(wprefix, 0) == 0)
{
return localpath.wstring();
}
auto prefixedPathWstring = std::wstring(wprefix).append(localpath.wstring());
assert(prefixedPathWstring.rfind(wprefix, 0) == 0);
return prefixedPathWstring;
}
fs::path nonMaxPathLimitedPath(const fs::path &localpath)
{
auto prefixedPath = fs::path(nonMaxPathLimitedWstring(localpath));
assert(prefixedPath.wstring().rfind(LR"(\\?\)", 0) == 0);
return prefixedPath;
}
WindowsConsoleController::WindowsConsoleController()
{
if (!getenv("MEGACMD_DISABLE_UTF8_OUTPUT_MODE_BY_DEFAULT"))
{
// set default mode to U8TEXT.
// PROs: we could actually get rid of _setmode to U8TEXT in WindowsUtf8StdoutGuard
// CONS: any low level printing to stdout may crash if the mode is not _O_TEXT.
// Even if we do not do that, for instance, gtests would do.
auto OUTPUT_MODE = _O_U8TEXT;
auto oldModeStdout = _setmode(_fileno(stdout), OUTPUT_MODE);
auto oldModeStderr = _setmode(_fileno(stderr), OUTPUT_MODE);
}
if (!getenv("MEGACMD_DISABLE_NARROW_OUTSTREAMS_INTERCEPTING"))
{
enableInterceptors(true);
}
}
void WindowsConsoleController::enableInterceptors(bool enable)
{
std::cout.flush();
std::cerr.flush();
if (enable)
{
mInterceptCout.reset(new InterceptStreamBuffer(std::cout, std::wcout));
mInterceptCerr.reset(new InterceptStreamBuffer(std::cerr, std::wcerr));
}
else
{
mInterceptCout.reset();
mInterceptCerr.reset();
}
}
#endif
std::atomic<uint64_t> sInvalidUtf8Incidences = 0;
std::string pathAsUtf8(const fs::path& path)
{
#ifdef _WIN32
return utf16ToUtf8(path.wstring().c_str());
#else
return path.string();
#endif
}
bool isValidUtf8(const char* data, size_t size)
{
static bool disableUTF8Valiations = getenv("MEGACMD_DISABLE_UTF8_VALIDATIONS");
if (disableUTF8Valiations)
{
return true;
}
// checks that the byte starts with bits 10 (i.e. continuation bytes)
auto check10 = [&data](size_t n) -> bool {
return (data[n] & 0xc0) == 0x80;
};
while (size)
{
const uint8_t lead = static_cast<uint8_t>(*data);
// 0xxxxxxx -> U+0000..U+007F (1-byte character)
if (lead < 0x80)
{
++data;
--size;
continue;
}
// 110xxxxx -> U+0080..U+07FF (2-byte character)
else if ((lead & 0xe0) == 0xc0)
{
// check codepoint is at least 0x80 and check continuation byte
if (lead > 0xc1 && size >= 2 && check10(1))
{
data += 2;
size -= 2;
continue;
}
}
// 1110xxxx -> U+0800..U+FFFF (3-byte character)
else if ((lead & 0xf0) == 0xe0)
{
// check continuation bytes
if (size >= 3 && check10(1) && check10(2))
{
const auto secondByte = static_cast<uint8_t>(data[1]);
// check codepoint is at least 0x800 and not a surrogate codepoint in the range 0xd800-0xdfff
if (((lead << 8) | secondByte) > 0xe09f &&
(lead != 0xed || secondByte < 0xa0))
{
data += 3;
size -= 3;
continue;
}
}
}
// 11110xxx -> U+10000..U+10FFFF (4-byte character)
else if ((lead & 0xf8) == 0xf0)
{
// check continuation bytes5
if (size >= 4 && check10(1) && check10(2) && check10(3))
{
const auto firstHalf = (lead << 8) | static_cast<uint8_t>(data[1]);
// check codepoint is at least 0x10000 and not greater than 0x10FFFF (not encodable by UTF-16)
if (firstHalf > 0xf08f && firstHalf < 0xf490)
{
data += 4;
size -= 4;
continue;
}
}
}
sInvalidUtf8Incidences++;
return false;
}
return true;
}
bool isValidUtf8(const std::string &str)
{
return isValidUtf8(str.data(), str.size());
}
} //end namespace

257
src/megacmd_utf8.h Normal file
View File

@ -0,0 +1,257 @@
/**
* @file src/megacmd_utf8.h
* @brief MEGAcmd: utf8 and console resources
*
* (c) 2013 by Mega Limited, Auckland, New Zealand
*
* This file is part of the MEGAcmd.
*
* MEGAcmd is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* @copyright Simplified (2-clause) BSD License.
*
* You should have received a copy of the license along with this
* program.
*/
#pragma once
#include <iostream>
#include <cassert>
#include <mutex>
#include <atomic>
#ifdef _WIN32
#include <streambuf>
#include <conio.h>
#include <fstream>
#include <iomanip>
#include <io.h>
#include <fcntl.h>
#include <algorithm>
#include <string>
#include <cwctype>
#include <fcntl.h>
#include <io.h>
#include <stdio.h>
#ifndef _O_U16TEXT
#define _O_U16TEXT 0x00020000
#endif
#ifndef _O_U8TEXT
#define _O_U8TEXT 0x00040000
#endif
#endif
#include <filesystem>
namespace fs = std::filesystem;
namespace megacmd {
std::string pathAsUtf8(const fs::path& path);
extern std::atomic<uint64_t> sInvalidUtf8Incidences;
bool isValidUtf8(const char* data, size_t size);
bool isValidUtf8(const std::string &str);
struct StdoutMutexGuard
{
inline static std::recursive_mutex sSetmodeMtx;
std::lock_guard<std::recursive_mutex> mGuard;
StdoutMutexGuard() : mGuard(sSetmodeMtx) {}
};
/* platform dependent */
#ifdef _WIN32
#define OUTSTREAMTYPE std::wostream
#define OUTFSTREAMTYPE std::wofstream
#define OUTSTRINGSTREAM std::wostringstream
#define OUTSTRING std::wstring
#define COUT std::wcout
#define CERR std::wcerr
//override << operators for wostream for string and const char *
std::wostream & operator<< ( std::wostream & ostr, std::string const & str );
std::wostream & operator<< ( std::wostream & ostr, const char * str );
// UTF-8 to wstrings (UTF-16) conversions:
void stringtolocalw(const char* path, std::wstring* local);
void stringtolocalw(const char* path, size_t lenutf8, std::wstring* local);
std::wstring utf8StringToUtf16WString(const char* str, size_t lenutf8);
std::wstring utf8StringToUtf16WString(const char* path);
// convert Utf-16 wide chars to UTF-8 std::strings
void localwtostring(const std::wstring* wide, std::string *multibyte);
void utf16ToUtf8(const wchar_t* utf16data, int utf16size, std::string* utf8string);
std::string utf16ToUtf8(const wchar_t *ws);
std::string utf16ToUtf8(const std::wstring &ws);
std::wstring nonMaxPathLimitedWstring(const fs::path &localpath);
fs::path nonMaxPathLimitedPath(const fs::path &localpath);
/***
* operator<< overloads to ensure proper handling of paths and widestrings
* This header would need to be included first in all project as a general rule, so that these are used
* As a way to ensure this, we could only define fs namespace here.
*
* Note: beyond these, operator<< overloads for logging can be found at megacmdlogger.h
**/
//// This is expected to be used when trying to << a wstring (supposedly in UTF-16, into a ostream (string/file/cout/...)
template <typename T>
inline std::enable_if_t<std::is_same_v<std::decay_t<T>, std::wstring>, std::ostream&>
operator<<(std::ostream& oss, const T& wstr)
{
static_assert(false); // Let's forbid this to better control that we just write utf8 std::strings in non wide streams (e.g cout)
// Notice that in the end, in stdout we want to write widestrings (utf16) to wcout instead, to have console rendering properly.
// If we were to automatically support this we should convert them to utf8 string as follows:
oss << megacmd::utf16ToUtf8(wstr);
return oss;
}
} // end of namespace megacmd
namespace std::filesystem {
// overload that may be used when building some stringstream.
// Note: LOG_xxx << path should are handled by SimpleLogger overloads, not this one
inline std::ostream &operator<<(std::ostream& oss, const fs::path& path)
{
// caveat: outputting its contents (utf-8) to stdout would need to be done converting to utf-16 and using wcout
// and a valid mode to stdout (See WindowsUtf8StdoutGuard)
assert(&oss != &std::cout);
assert(&oss != &std::cerr);
oss << megacmd::pathAsUtf8(path);
return oss;
}
} // end of namespace std::filesystem
namespace megacmd {
/**
* @brief This class is used to:
* - guard no meddling while writting/setting output mode on stdout/stderr
* - ensure setting the output modes to mOutputMode
*/
class OutputsModeGuard : public StdoutMutexGuard
{
unsigned int mOutputMode;
int mOldModeStdout;
int mOldModeStderr;
public:
OutputsModeGuard(unsigned int outputMode)
: mOutputMode(outputMode)
{
fflush(stdout);
fflush(stderr);
mOldModeStdout = _setmode(_fileno(stdout), mOutputMode);
mOldModeStderr = _setmode(_fileno(stderr), mOutputMode);
assert(mOldModeStdout != -1);
assert(mOldModeStderr != -1);
}
virtual ~OutputsModeGuard()
{
fflush(stdout);
fflush(stderr);
_setmode(_fileno(stdout), mOldModeStdout);
_setmode(_fileno(stderr), mOldModeStderr);
}
};
template <unsigned int OUTPUT_MODE>
class WindowsOutputsModeGuardGeneric : public OutputsModeGuard
{
public:
WindowsOutputsModeGuardGeneric()
: OutputsModeGuard(OUTPUT_MODE)
{}
};
using WindowsUtf8StdoutGuard = WindowsOutputsModeGuardGeneric<_O_U8TEXT>;
using WindowsNarrowStdoutGuard = WindowsOutputsModeGuardGeneric<_O_TEXT>;
using WindowsBinaryStdoutGuard = WindowsOutputsModeGuardGeneric<O_BINARY>;
class InterceptStreamBuffer : public std::streambuf
{
private:
std::streambuf* mOriginalStreamBuffer; // Store the original buffer
std::ostream& mNarrowStream; // Reference to the original stream (e.g., std::cout)
std::wostream& mWideOstream; // Reference to the original stream (e.g., std::cout)
bool hasNonAscii(const char* str, size_t length)
{
for (size_t i = 0; i < length; ++i)
{
if (static_cast<unsigned char>(str[i]) > 127)
{
return true;
}
}
return false;
}
public:
InterceptStreamBuffer(std::ostream& outStream, std::wostream &wideStream)
: mNarrowStream(outStream), mWideOstream(wideStream)
{
mOriginalStreamBuffer = mNarrowStream.rdbuf(); // Save the original buffer
mNarrowStream.rdbuf(this); // Replace with this buffer
}
~InterceptStreamBuffer()
{
mNarrowStream.rdbuf(mOriginalStreamBuffer); // Restore the original buffer on destruction
}
protected:
virtual int overflow(int c) override
{
char cc = char(c);
xsputn(&cc, 1);
return c;
}
virtual std::streamsize xsputn(const char* s, std::streamsize count) override
{
if (hasNonAscii(s, count)) // why cannot:
{
WindowsUtf8StdoutGuard utf8Guard;
// assert(false && "This should ideally be controlled in calling code"); //TODO: enable this assert to fix cases in origin (assumed better performance)
mWideOstream << utf8StringToUtf16WString(s, count);
return count;
}
else
{
WindowsNarrowStdoutGuard narrowGuard;
return mOriginalStreamBuffer->sputn(s, count); // This is protesting when having _setmode and doing cout << "odd" (odd number of chars)
}
}
};
class WindowsConsoleController
{
std::unique_ptr<megacmd::InterceptStreamBuffer> mInterceptCout;
std::unique_ptr<megacmd::InterceptStreamBuffer> mInterceptCerr;
public:
WindowsConsoleController();
void enableInterceptors(bool enable);
};
#else
#define OUTSTREAMTYPE std::ostream
#define OUTFSTREAMTYPE std::ofstream
#define OUTSTRINGSTREAM std::ostringstream
#define OUTSTRING std::string
#define COUT std::cout
#define CERR std::cerr
#endif
}//end namespace

View File

@ -45,99 +45,14 @@
#include <regex> //split
#include <random>
#ifdef _WIN32
namespace mega {
//override for the log. This is required for compiling, otherwise SimpleLog won't compile.
std::ostringstream & operator<< ( std::ostringstream & ostr, const std::wstring & str)
{
std::string s;
megacmd::localwtostring(&str,&s);
ostr << s;
return ( ostr );
}
}
#endif
namespace megacmd {
using namespace std;
#ifdef _WIN32
std::wostream & operator<< ( std::wostream & ostr, std::string const & str )
std::string errorCodeStr(const std::error_code& ec)
{
std::wstring toout;
stringtolocalw(str.c_str(),&toout);
ostr << toout;
return ( ostr );
return ec ? "(error: " + ec.message() + ")" : "";
}
std::wostream & operator<< ( std::wostream & ostr, const char * str )
{
std::wstring toout;
stringtolocalw(str,&toout);
ostr << toout;
return ( ostr );
}
// convert UTF-8 to Windows Unicode wstring
void stringtolocalw(const char* path, std::wstring* local)
{
// make space for the worst case
local->resize((strlen(path) + 1) * sizeof(wchar_t));
int wchars_num = MultiByteToWideChar(CP_UTF8, 0, path,-1, NULL,0);
local->resize(wchars_num);
int len = MultiByteToWideChar(CP_UTF8, 0, path,-1, (wchar_t*)local->data(), wchars_num);
if (len)
{
local->resize(len-1);
}
else
{
local->clear();
}
}
//widechar to utf8 string
void localwtostring(const std::wstring* wide, std::string *multibyte)
{
if( !wide->empty() )
{
int size_needed = WideCharToMultiByte(CP_UTF8, 0, wide->data(), (int)wide->size(), NULL, 0, NULL, NULL);
multibyte->resize(size_needed);
WideCharToMultiByte(CP_UTF8, 0, wide->data(), (int)wide->size(), (char*)multibyte->data(), size_needed, NULL, NULL);
}
}
// convert Windows Unicode to UTF-8
void utf16ToUtf8(const wchar_t* utf16data, int utf16size, string* utf8string)
{
if(!utf16size)
{
utf8string->clear();
return;
}
utf8string->resize((utf16size + 1) * 4);
utf8string->resize(WideCharToMultiByte(CP_UTF8, 0, utf16data,
utf16size,
(char*)utf8string->data(),
int(utf8string->size() + 1),
NULL, NULL));
}
std::string getutf8fromUtf16(const wchar_t *ws)
{
string utf8s;
utf16ToUtf8(ws, int(wcslen(ws)), &utf8s);
return utf8s;
}
#endif
bool canWrite(string path)
{
#ifdef _WIN32
@ -750,7 +665,8 @@ string toLower(const std::string& str)
return lower;
}
void printCenteredLine(OUTSTREAMTYPE &os, string msj, unsigned int width, bool encapsulated)
template <typename Stream_T>
void printCenteredLine(Stream_T &os, string msj, unsigned int width, bool encapsulated)
{
unsigned int msjsize = getstringutf8size(msj);
bool overflowed = false;
@ -771,6 +687,10 @@ void printCenteredLine(OUTSTREAMTYPE &os, string msj, unsigned int width, bool e
os << endl;
}
// Instantiate those that can be used:
template void printCenteredLine<OUTSTREAMTYPE>(OUTSTREAMTYPE &os, string msj, unsigned int width, bool encapsulated);
template void printCenteredLine<std::ostringstream>(std::ostringstream &os, string msj, unsigned int width, bool encapsulated);
void printCenteredContents(OUTSTREAMTYPE &os, string msj, unsigned int width, bool encapsulated)
{
string headfoot = " ";
@ -859,6 +779,9 @@ void printCenteredLine(string msj, unsigned int width, bool encapsulated)
{
OUTSTRINGSTREAM os;
printCenteredLine(os, msj, width, encapsulated);
#ifdef _WIN32
WindowsUtf8StdoutGuard utf8Guard;
#endif
COUT << os.str();
}
@ -866,6 +789,12 @@ void printCenteredContents(string msj, unsigned int width, bool encapsulated)
{
OUTSTRINGSTREAM os;
printCenteredContents(os, msj, width, encapsulated);
#ifdef _WIN32
WindowsUtf8StdoutGuard utf8Guard;
#else
StdoutMutexGuard stdoutGuard;
#endif
COUT << os.str();
}
@ -873,6 +802,11 @@ void printCenteredContentsCerr(string msj, unsigned int width, bool encapsulated
{
OUTSTRINGSTREAM os;
printCenteredContents(os, msj, width, encapsulated);
#ifdef _WIN32
WindowsUtf8StdoutGuard utf8Guard;
#else
StdoutMutexGuard stdoutGuard;
#endif
CERR << os.str();
}
@ -912,6 +846,13 @@ void printPercentageLineCerr(const char *title, long long completed, long long t
*ptr++ = '#';
}
#ifdef _WIN32
WindowsUtf8StdoutGuard utf8Guard;
#else
StdoutMutexGuard stdoutGuard;
#endif
// TODO: should this be CERR ? (`\r`) may not behave as wanted
if (cleanLineAfter)
{
cerr << outputString << '\r' << flush;
@ -1250,9 +1191,9 @@ string &trimProperty(string &what)
return what;
}
string getPropertyFromFile(const char *configFile, const char *propertyName)
string getPropertyFromFile(const fs::path &configFilePath, const char *propertyName)
{
ifstream infile(configFile);
ifstream infile(configFilePath);
string line;
while (getline(infile, line))
@ -1555,33 +1496,25 @@ std::unique_ptr<PlatformDirectories> PlatformDirectories::getPlatformSpecificDir
}
#ifdef _WIN32
std::string WindowsDirectories::configDirPath()
fs::path WindowsDirectories::configDirPath()
{
TCHAR szPath[MAX_PATH];
std::string folder;
wchar_t szPath[MAX_PATH];
if (!SUCCEEDED(GetModuleFileName(NULL, szPath, MAX_PATH)))
if (GetModuleFileNameW(NULL, szPath, MAX_PATH) == 0)
{
return std::string();
}
else
{
if (SUCCEEDED(PathRemoveFileSpec(szPath)))
{
if (PathAppend(szPath, TEXT(".megaCmd")))
{
utf16ToUtf8(szPath, lstrlen(szPath), &folder);
}
}
return {};
}
auto suffix = getenv("MEGACMD_WORKING_FOLDER_SUFFIX");
fs::path folder = fs::path(szPath).parent_path() / ".megaCmd";
auto suffix = _wgetenv(L"MEGACMD_WORKING_FOLDER_SUFFIX");
if (suffix != nullptr)
{
folder += "_";
folder += suffix;
}
folder = nonMaxPathLimitedPath(folder); // prepend //?/
return folder;
}
@ -1626,7 +1559,7 @@ std::string PosixDirectories::homeDirPath()
return std::string(pwd.pw_dir);
}
std::string PosixDirectories::configDirPath()
fs::path PosixDirectories::configDirPath()
{
std::string home = homeDirPath();
if (home.empty())
@ -1646,7 +1579,7 @@ string PosixDirectories::noHomeFallbackFolder()
}
#ifdef __APPLE__
std::string MacOSDirectories::runtimeDirPath()
fs::path MacOSDirectories::runtimeDirPath()
{
std::string home = homeDirPath();
if (home.empty())
@ -1678,7 +1611,7 @@ std::string getOrCreateSocketPath(bool createDirectory)
static auto MAX_SOCKET_PATH = sizeof(sockaddr_un::sun_path) / sizeof(decltype(sockaddr_un::sun_path[0]));
if ((socketFolder.size() + 1 + sockname.size()) >= (MAX_SOCKET_PATH - 1))
if ((socketFolder.string().size() + 1 + sockname.size()) >= (MAX_SOCKET_PATH - 1))
{
if (createDirectory)
{
@ -1708,7 +1641,7 @@ std::string getOrCreateSocketPath(bool createDirectory)
}
}
return socketFolder.append("/").append(sockname);
return (socketFolder / sockname).string();
}
#endif // ifdef(_WIN32) else
} //end namespace

View File

@ -19,6 +19,8 @@
#ifndef MEGACMDCOMMONUTILS_H
#define MEGACMDCOMMONUTILS_H
#include "megacmd_utf8.h"
#include <memory>
#ifndef _WIN32
#include <pwd.h>
@ -38,6 +40,7 @@
#include <condition_variable>
#include <cassert>
#include <optional>
#include <thread>
#ifndef UNUSED
#define UNUSED(x) (void)(x)
@ -50,52 +53,12 @@
using std::setw;
using std::left;
#ifdef _WIN32
namespace mega{
// Note: these was in megacmd namespace, but after one overload of operator<< was created within mega,
// ADL did not seem to be able to find it when solving template resolution in loggin.h (namespace mega),
// even for code coming from megacmd namespace.
// placing this operator in mega namespace eases ADL lookup and allows compilation
std::ostringstream & operator<< ( std::ostringstream & ostr, std::wstring const &str); //override for the log, otherwise SimpleLog won't compile.
}
#endif
namespace megacmd {
/* platform dependent */
#ifdef _WIN32
#define OUTSTREAMTYPE std::wostream
#define OUTFSTREAMTYPE std::wofstream
#define OUTSTRINGSTREAM std::wostringstream
#define OUTSTRING std::wstring
#define COUT std::wcout
#define CERR std::wcerr
//override << operators for wostream for string and const char *
std::wostream & operator<< ( std::wostream & ostr, std::string const & str );
std::wostream & operator<< ( std::wostream & ostr, const char * str );
void stringtolocalw(const char* path, std::wstring* local);
void localwtostring(const std::wstring* wide, std::string *multibyte);
std::string getutf8fromUtf16(const wchar_t *ws);
void utf16ToUtf8(const wchar_t* utf16data, int utf16size, std::string* utf8string);
#else
#define OUTSTREAMTYPE std::ostream
#define OUTFSTREAMTYPE std::ofstream
#define OUTSTRINGSTREAM std::ostringstream
#define OUTSTRING std::string
#define COUT std::cout
#define CERR std::cerr
#endif
#ifndef _WIN32
#define ARRAYSIZE(a) (sizeof((a)) / sizeof(*(a)))
#endif
namespace megacmd {
/* commands */
static std::vector<std::string> validGlobalParameters {"v", "help"};
static std::vector<std::string> localremotefolderpatterncommands {"sync", "fuse-add"};
@ -131,11 +94,8 @@ static std::vector<std::string> loginInValidCommands { "log", "debug", "speedlim
static std::vector<std::string> allValidCommands { "login", "signup", "confirm", "session", "mount", "ls", "cd", "log", "debug", "pwd", "lcd", "lpwd", "import", "masterkey",
"put", "get", "attr", "userattr", "mkdir", "rm", "du", "mv", "cp", "sync", "sync-ignore", "export", "share", "invite", "ipc", "df",
"showpcr", "users", "speedlimit", "killsession", "whoami", "help", "passwd", "reload", "logout", "version", "quit",
"thumbnail", "preview", "find", "completion", "clear", "https", "sync-issues"
#ifdef HAVE_DOWNLOADS_COMMAND
, "downloads"
#endif
, "transfers", "exclude", "exit", "errorcode", "graphics",
"thumbnail", "preview", "find", "completion", "clear", "https", "sync-issues",
"transfers", "exclude", "exit", "errorcode", "graphics",
"cancel", "confirmcancel", "cat", "tree", "psa", "proxy"
, "mediainfo"
#ifdef HAVE_LIBUV
@ -168,6 +128,8 @@ static std::vector<std::string> allValidCommands { "login", "signup", "confirm",
static const int RESUME_SESSION_TIMEOUT = 10;
std::string errorCodeStr(const std::error_code& ec);
/* Files and folders */
//tests if a path is writable //TODO: move to fsAccess
@ -259,7 +221,10 @@ OUTSTRING getRightAlignedStr(T what, int n)
void printCenteredLine(std::string msj, unsigned int width, bool encapsulated = true);
void printCenteredContents(std::string msj, unsigned int width, bool encapsulated = true);
void printCenteredContentsCerr(std::string msj, unsigned int width, bool encapsulated = true);
void printCenteredLine(OUTSTREAMTYPE &os, std::string msj, unsigned int width, bool encapsulated = true);
template <typename Stream_T>
void printCenteredLine(Stream_T &os, std::string msj, unsigned int width, bool encapsulated = true);
void printCenteredContents(OUTSTREAMTYPE &os, std::string msj, unsigned int width, bool encapsulated = true);
template <typename WHERE>
@ -319,11 +284,12 @@ std::string getCurrentExecPath();
std::string &ltrimProperty(std::string &s, const char &c);
std::string &rtrimProperty(std::string &s, const char &c);
std::string &trimProperty(std::string &what);
std::string getPropertyFromFile(const char *configFile, const char *propertyName);
std::string getPropertyFromFile(const fs::path &configFilePath, const char *propertyName);
template <typename T>
T getValueFromFile(const char *configFile, const char *propertyName, T defaultValue)
T getValueFromFile(const fs::path &configFilePath, const char *propertyName, T defaultValue)
{
std::string propValue = getPropertyFromFile(configFile, propertyName);
std::string propValue = getPropertyFromFile(configFilePath, propertyName);
if (!propValue.size()) return defaultValue;
T i;
@ -403,12 +369,14 @@ class PlatformDirectories
{
public:
static std::unique_ptr<PlatformDirectories> getPlatformSpecificDirectories();
virtual ~PlatformDirectories() = default;
/**
* @brief runtimeDirPath returns the base path for storing runtime files:
*
* Meant for sockets, named pipes, file locks, command history, etc.
*/
virtual std::string runtimeDirPath()
virtual fs::path runtimeDirPath()
{
return configDirPath();
}
@ -418,7 +386,7 @@ public:
* Meant for user-editable configuration files, data files that should not be deleted
* (session credentials, SDK workding directory, logs, etc).
*/
virtual std::string configDirPath() = 0;
virtual fs::path configDirPath() = 0;
};
template <typename T> size_t numberOfDigits(T num)
@ -435,7 +403,7 @@ template <typename T> size_t numberOfDigits(T num)
#ifdef _WIN32
class WindowsDirectories : public PlatformDirectories
{
std::string configDirPath() override;
fs::path configDirPath() override;
};
std::wstring getNamedPipeName();
#else // !defined(_WIN32)
@ -443,7 +411,7 @@ class PosixDirectories : public PlatformDirectories
{
public:
std::string homeDirPath();
virtual std::string configDirPath() override;
virtual fs::path configDirPath() override;
static std::string noHomeFallbackFolder();
@ -451,7 +419,7 @@ public:
#ifdef __APPLE__
class MacOSDirectories : public PosixDirectories
{
std::string runtimeDirPath() override;
fs::path runtimeDirPath() override;
};
#endif // defined(__APPLE__)
std::string getOrCreateSocketPath(bool createDirectory);
@ -563,5 +531,39 @@ public:
~ScopeGuard() { mExitCb(); }
};
template <typename _Rep, typename _Period, typename _Rep2, typename _Period2, typename Condition, typename What>
void timelyRetry(const std::chrono::duration<_Rep, _Period> &maxTime, const std::chrono::duration<_Rep2, _Period2> &step
, Condition&& endCondition, What&& what)
{
using Step_t = std::chrono::duration<_Rep2, _Period2>;
for (auto timeLeft = std::chrono::duration_cast<Step_t>(maxTime); !endCondition() && timeLeft > Step_t(0); timeLeft -= step)
{
std::this_thread::sleep_for(step);
what();
}
}
class HammeringLimiter
{
int mLimitSecs;
std::optional<std::chrono::steady_clock::time_point> mLastCall;
public:
HammeringLimiter(int seconds) : mLimitSecs(seconds) {}
// Returns true if run recently (or sets the last call to current time otherwise)
bool runRecently()
{
auto now = std::chrono::steady_clock::now();
if (mLastCall && std::chrono::duration_cast<std::chrono::seconds>(now - *mLastCall).count() <= mLimitSecs)
{
return true;
}
mLastCall = now;
return false;
}
};
}//end namespace
#endif // MEGACMDCOMMONUTILS_H

View File

@ -22,7 +22,6 @@
#include "megacmdutils.h"
#include "megacmdcommonutils.h"
#include "megacmdtransfermanager.h"
#include "configurationmanager.h"
#include "megacmdlogger.h"
#include "comunicationsmanager.h"
@ -39,7 +38,6 @@
#include <limits>
#include <string>
#include <ctime>
#include <filesystem>
#include <set>
#include <signal.h>
@ -49,7 +47,6 @@
using TI = TestInstruments;
#endif
namespace fs = std::filesystem;
using namespace mega;
using namespace std;
@ -799,7 +796,7 @@ MegaNode * MegaCmdExecuter::getBaseNode(string thepath, string &rest, bool *isre
}
else if (thepath == "//in")
{
baseNode = api->getInboxNode();
baseNode = api->getVaultNode();
rest = "";
}
else if (thepath == "/")
@ -814,7 +811,7 @@ MegaNode * MegaCmdExecuter::getBaseNode(string thepath, string &rest, bool *isre
}
else if (thepath.find("//in/") == 0 )
{
baseNode = api->getInboxNode();
baseNode = api->getVaultNode();
rest = thepath.substr(5);
}
else if (thepath.find("/") == 0 && !(thepath.find("//from/") == 0 ))
@ -1628,9 +1625,11 @@ void MegaCmdExecuter::createOrModifyBackup(string local, string remote, string s
{
if (establishBackup(local, n.get(), period, speriod, numBackups))
{
mtxBackupsMap.lock();
ConfigurationManager::saveBackups(&ConfigurationManager::configuredBackups);
mtxBackupsMap.unlock();
{
std::lock_guard g(mtxBackupsMap);
ConfigurationManager::saveBackups(&ConfigurationManager::configuredBackups);
}
OUTSTREAM << "Backup established: " << local << " into " << remote << " period="
<< ((period != -1)?getReadablePeriod(period/10):"\""+speriod+"\"")
<< " Number-of-Backups=" << numBackups << endl;
@ -2229,7 +2228,7 @@ void MegaCmdExecuter::actUponGetExtendedAccountDetails(std::unique_ptr<::mega::M
<< getFixLengthString(SSTR(storageDetails->getNumFolders(n->getHandle())), 5, ' ', true) << " folder(s)" << endl;
}
n = std::unique_ptr<MegaNode>(api->getInboxNode());
n = std::unique_ptr<MegaNode>(api->getVaultNode());
if (n)
{
OUTSTREAM << " In INBOX: " << getFixLengthString(sizeToText(storageDetails->getStorageUsed(n->getHandle())), 9, ' ', true) << "ytes in "
@ -2612,13 +2611,6 @@ int MegaCmdExecuter::actUponLogin(SynchronousRequestListener *srl, int timeout)
}
#endif
#ifdef HAVE_DOWNLOADS_COMMAND
bool downloads_tracking_enabled = ConfigurationManager::getConfigurationValue("downloads_tracking_enabled", false);
if (downloads_tracking_enabled)
{
DownloadsManager::Instance().start();
}
#endif
ConfigurationManager::migrateSyncConfig(api);
LOG_info << "Fetching nodes ... ";
@ -2890,39 +2882,6 @@ void MegaCmdExecuter::fetchNodes(MegaApi *api, int clientID)
#endif
}
void MegaCmdExecuter::cleanSlateTranfers()
{
#ifdef HAVE_DOWNLOADS_COMMAND
bool downloads_cleanslate = ConfigurationManager::getConfigurationValue("downloads_cleanslate_enabled", false);
if (downloads_cleanslate)
{
auto megaCmdListener = std::make_unique<MegaCmdListener>(nullptr);
api->cancelTransfers(MegaTransfer::TYPE_DOWNLOAD, megaCmdListener.get());
megaCmdListener->wait();
if (checkNoErrors(megaCmdListener->getError(), "cancel all download transfers"))
{
LOG_debug << "Download transfers cancelled successfully.";
}
megaCmdListener.reset(new MegaCmdListener(nullptr));
api->cancelTransfers(MegaTransfer::TYPE_UPLOAD, megaCmdListener.get());
megaCmdListener->wait();
if (checkNoErrors(megaCmdListener->getError(), "cancel all upload transfers"))
{
LOG_debug << "Upload transfers cancelled successfully.";
}
{
globalTransferListener->completedTransfersMutex.lock();
globalTransferListener->completedTransfers.clear();
globalTransferListener->completedTransfersMutex.unlock();
}
DownloadsManager::Instance().purge();
}
#endif
}
void MegaCmdExecuter::actUponLogout(SynchronousRequestListener *srl, bool keptSession, int timeout)
{
if (!timeout)
@ -2954,9 +2913,6 @@ void MegaCmdExecuter::actUponLogout(SynchronousRequestListener *srl, bool keptSe
}
ConfigurationManager::clearConfigurationFile();
#ifdef HAVE_DOWNLOADS_COMMAND
DownloadsManager::Instance().shutdown(true);
#endif
mtxSyncMap.unlock();
// clear greetings (asuming they are account-related)
@ -3465,9 +3421,9 @@ void MegaCmdExecuter::exportNode(MegaNode *n, int64_t expireTime, const std::opt
"You are strictly prohibited from using the MEGA cloud service to infringe copyright.\n"
"You may not upload, download, store, share, display, stream, distribute, email, link to, "
"transmit or otherwise make available any files, data or content that infringes any copyright "
"or other proprietary rights of any person or entity.");
"or other proprietary rights of any person or entity.\n");
confirmationQuery += " Do you accept this terms? (Yes/No): ";
confirmationQuery += "Do you accept these terms? (Yes/No): ";
const int confirmationResponse = askforConfirmation(confirmationQuery);
if (confirmationResponse != MCMDCONFIRM_YES && confirmationResponse != MCMDCONFIRM_ALL)
@ -4331,7 +4287,7 @@ void MegaCmdExecuter::printTransferColumnDisplayer(ColumnDisplayer *cd, MegaTran
//Direction
string type;
#ifdef _WIN32
type += getutf8fromUtf16((transfer->getType() == MegaTransfer::TYPE_DOWNLOAD)?L"\u25bc":L"\u25b2");
type += utf16ToUtf8((transfer->getType() == MegaTransfer::TYPE_DOWNLOAD)?L"\u25bc":L"\u25b2");
#else
type += (transfer->getType() == MegaTransfer::TYPE_DOWNLOAD)?"\u21d3":"\u21d1";
#endif
@ -4341,7 +4297,7 @@ void MegaCmdExecuter::printTransferColumnDisplayer(ColumnDisplayer *cd, MegaTran
if (transfer->isSyncTransfer())
{
#ifdef _WIN32
type += getutf8fromUtf16(L"\u21a8");
type += utf16ToUtf8(L"\u21a8");
#else
type += "\u21f5";
#endif
@ -4349,7 +4305,7 @@ void MegaCmdExecuter::printTransferColumnDisplayer(ColumnDisplayer *cd, MegaTran
else if (transfer->isBackupTransfer())
{
#ifdef _WIN32
type += getutf8fromUtf16(L"\u2191");
type += utf16ToUtf8(L"\u2191");
#else
type += "\u23eb";
#endif
@ -5014,43 +4970,55 @@ bool MegaCmdExecuter::establishBackup(string pathToBackup, MegaNode *n, int64_t
LOG_err << " Failed to expanse path";
}
MegaCmdListener *megaCmdListener = new MegaCmdListener(api, NULL);
api->setScheduledCopy(expansedAbsolutePath.toPath(false).c_str(), n, attendpastbackups, period, speriod.c_str(), numBackups, megaCmdListener);
auto megaCmdListener = std::make_unique<MegaCmdListener>(api, nullptr);
api->setScheduledCopy(expansedAbsolutePath.toPath(false).c_str(), n, attendpastbackups, period, speriod.c_str(), numBackups, megaCmdListener.get());
megaCmdListener->wait();
if (checkNoErrors(megaCmdListener->getError(), "establish backup"))
{
mtxBackupsMap.lock();
backup_struct *thebackup = NULL;
if (ConfigurationManager::configuredBackups.find(megaCmdListener->getRequest()->getFile()) != ConfigurationManager::configuredBackups.end())
backup_struct *thebackup = nullptr;
bool sendBackupEvent = false;
{
thebackup = ConfigurationManager::configuredBackups[megaCmdListener->getRequest()->getFile()];
if (thebackup->id == -1)
std::lock_guard g(mtxBackupsMap);
if (ConfigurationManager::configuredBackups.find(megaCmdListener->getRequest()->getFile()) != ConfigurationManager::configuredBackups.end())
{
thebackup = ConfigurationManager::configuredBackups[megaCmdListener->getRequest()->getFile()];
if (thebackup->id == -1)
{
thebackup->id = backupcounter++;
}
}
else
{
thebackup = new backup_struct;
thebackup->id = backupcounter++;
ConfigurationManager::configuredBackups[megaCmdListener->getRequest()->getFile()] = thebackup;
sendBackupEvent = true;
}
thebackup->active = true;
thebackup->handle = megaCmdListener->getRequest()->getNodeHandle();
thebackup->localpath = string(megaCmdListener->getRequest()->getFile());
thebackup->numBackups = numBackups;
thebackup->period = period;
thebackup->speriod = speriod;
thebackup->failed = false;
thebackup->tag = megaCmdListener->getRequest()->getTransferTag();
}
if (sendBackupEvent)
{
auto wasFirstBackupConfiguredOpt = ConfigurationManager::savePropertyValue("firstBackupConfigured", true);
if (!wasFirstBackupConfiguredOpt || !*wasFirstBackupConfiguredOpt)
{
sendEvent(StatsManager::MegacmdEvent::FIRST_CONFIGURED_SCHEDULED_BACKUP, api, false);
}
else
{
sendEvent(StatsManager::MegacmdEvent::SUBSEQUENT_CONFIGURED_SCHEDULED_BACKUP, api, false);
}
}
else
{
thebackup = new backup_struct;
thebackup->id = backupcounter++;
ConfigurationManager::configuredBackups[megaCmdListener->getRequest()->getFile()] = thebackup;
}
thebackup->active = true;
thebackup->handle = megaCmdListener->getRequest()->getNodeHandle();
thebackup->localpath = string(megaCmdListener->getRequest()->getFile());
thebackup->numBackups = numBackups;
thebackup->period = period;
thebackup->speriod = speriod;
thebackup->failed = false;
thebackup->tag = megaCmdListener->getRequest()->getTransferTag();
char * nodepath = api->getNodePath(n);
std::unique_ptr<char[]> nodepath(api->getNodePath(n));
LOG_info << "Added backup: " << megaCmdListener->getRequest()->getFile() << " to " << nodepath;
mtxBackupsMap.unlock();
delete []nodepath;
delete megaCmdListener;
return true;
}
else
@ -5088,33 +5056,34 @@ bool MegaCmdExecuter::establishBackup(string pathToBackup, MegaNode *n, int64_t
}
}
}
delete megaCmdListener;
return false;
}
void MegaCmdExecuter::confirmCancel(const char* confirmlink, const char* pass)
{
MegaCmdListener *megaCmdListener = new MegaCmdListener(NULL);
api->confirmCancelAccount(confirmlink, pass, megaCmdListener);
auto megaCmdListener = std::make_unique<MegaCmdListener>(nullptr);
api->confirmCancelAccount(confirmlink, pass, megaCmdListener.get());
megaCmdListener->wait();
if (megaCmdListener->getError()->getErrorCode() == MegaError::API_ETOOMANY)
{
LOG_err << "Confirm cancel account failed: too many attempts";
}
else if (megaCmdListener->getError()->getErrorCode() == MegaError::API_ENOENT
|| megaCmdListener->getError()->getErrorCode() == MegaError::API_EKEY)
else if (megaCmdListener->getError()->getErrorCode() == MegaError::API_ENOENT ||
megaCmdListener->getError()->getErrorCode() == MegaError::API_EKEY)
{
LOG_err << "Confirm cancel account failed: invalid link/password";
}
else if (checkNoErrors(megaCmdListener->getError(), "confirm cancel account"))
// We consider ESID (bad session ID) as successful because of a data race in the SDK
else if (megaCmdListener->getError()->getErrorCode() == MegaError::API_ESID ||
checkNoErrors(megaCmdListener->getError(), "confirm cancel account"))
{
OUTSTREAM << "CONFIRM Account cancelled succesfully" << endl;
MegaCmdListener *megaCmdListener2 = new MegaCmdListener(NULL);
api->localLogout(megaCmdListener2);
actUponLogout(megaCmdListener2, false);
delete megaCmdListener2;
megaCmdListener = std::make_unique<MegaCmdListener>(nullptr);
api->localLogout(megaCmdListener.get());
actUponLogout(megaCmdListener.get(), false);
}
delete megaCmdListener;
}
void MegaCmdExecuter::processPath(string path, bool usepcre, bool& firstone, void (*nodeprocessor)(MegaCmdExecuter *, MegaNode *, bool), MegaCmdExecuter *context)
@ -5200,20 +5169,31 @@ void MegaCmdExecuter::removeWebdavLocation(MegaNode *n, bool firstone, string na
void MegaCmdExecuter::addWebdavLocation(MegaNode *n, bool firstone, string name)
{
char *actualNodePath = api->getNodePath(n);
char *l = api->httpServerGetLocalWebDavLink(n);
OUTSTREAM << "Serving via webdav " << (name.size()?name:actualNodePath) << ": " << l << endl;
std::unique_ptr<char[]> actualNodePath(api->getNodePath(n));
std::unique_ptr<char[]> l(api->httpServerGetLocalWebDavLink(n));
mtxWebDavLocations.lock();
list<string> servedpaths = ConfigurationManager::getConfigurationValueList("webdav_served_locations");
servedpaths.push_back(actualNodePath);
servedpaths.sort();
servedpaths.unique();
ConfigurationManager::savePropertyValueList("webdav_served_locations", servedpaths);
mtxWebDavLocations.unlock();
OUTSTREAM << "Serving via webdav " << (name.size() ? name : actualNodePath.get()) << ": " << l.get() << endl;
delete []l;
delete []actualNodePath;
{
std::lock_guard g(mtxWebDavLocations);
list<string> servedpaths = ConfigurationManager::getConfigurationValueList("webdav_served_locations");
if (!ConfigurationManager::getConfigurationValue("firstWebDavConfigured", false))
{
sendEvent(StatsManager::MegacmdEvent::FIRST_CONFIGURED_WEBDAV, api, false);
ConfigurationManager::savePropertyValue("firstWebDavConfigured", true);
}
else if (std::find(servedpaths.begin(), servedpaths.end(), actualNodePath.get()) == servedpaths.end())
{
// Send event only if not already on the list
sendEvent(StatsManager::MegacmdEvent::SUBSEQUENT_CONFIGURED_WEBDAV, api, false);
}
servedpaths.push_back(actualNodePath.get());
servedpaths.sort();
servedpaths.unique();
ConfigurationManager::savePropertyValueList("webdav_served_locations", servedpaths);
}
}
void MegaCmdExecuter::removeFtpLocation(MegaNode *n, bool firstone, string name)
@ -5248,20 +5228,31 @@ void MegaCmdExecuter::removeFtpLocation(MegaNode *n, bool firstone, string name)
void MegaCmdExecuter::addFtpLocation(MegaNode *n, bool firstone, string name)
{
char *actualNodePath = api->getNodePath(n);
char *l = api->ftpServerGetLocalLink(n);
OUTSTREAM << "Serving via ftp " << (name.size()?name:n->getName()) << ": " << l << endl;
std::unique_ptr<char[]> actualNodePath(api->getNodePath(n));
std::unique_ptr<char[]> l(api->ftpServerGetLocalLink(n));
mtxFtpLocations.lock();
list<string> servedpaths = ConfigurationManager::getConfigurationValueList("ftp_served_locations");
servedpaths.push_back(actualNodePath);
servedpaths.sort();
servedpaths.unique();
ConfigurationManager::savePropertyValueList("ftp_served_locations", servedpaths);
mtxFtpLocations.unlock();
OUTSTREAM << "Serving via ftp " << (name.size() ? name : n->getName()) << ": " << l.get() << endl;
delete []l;
delete []actualNodePath;
{
std::lock_guard g(mtxFtpLocations);
list<string> servedpaths = ConfigurationManager::getConfigurationValueList("ftp_served_locations");
if (!ConfigurationManager::getConfigurationValue("firstFtpConfigured", false))
{
sendEvent(StatsManager::MegacmdEvent::FIRST_CONFIGURED_FTP, api, false);
ConfigurationManager::savePropertyValue("firstFtpConfigured", true);
}
else if (std::find(servedpaths.begin(), servedpaths.end(), actualNodePath.get()) == servedpaths.end())
{
// Send event only if not already on the list
sendEvent(StatsManager::MegacmdEvent::SUBSEQUENT_CONFIGURED_FTP, api, false);
}
servedpaths.push_back(actualNodePath.get());
servedpaths.sort();
servedpaths.unique();
ConfigurationManager::savePropertyValueList("ftp_served_locations", servedpaths);
}
}
#endif
@ -6674,18 +6665,7 @@ void MegaCmdExecuter::executecommand(vector<string> words, map<string, int> *clf
}
}
if (background) //TODO: do the same for uploads?
{
#ifdef HAVE_DOWNLOADS_COMMAND
megaCmdMultiTransferListener->waitMultiStart();
for (auto & dlId : megaCmdMultiTransferListener->getStartedTransfers())
{
OUTSTREAM << "Started background transfer <" << dlId.mPath << ">. Tag = " << dlId.mTag << ". Object Identifier: " << dlId.getObjectID() << endl;
}
#endif
}
else
if (!background)
{
megaCmdMultiTransferListener->waitMultiEnd();
@ -7013,53 +6993,49 @@ void MegaCmdExecuter::executecommand(vector<string> words, map<string, int> *clf
}
else if (words[0] == "log")
{
const bool cmdFlag = getFlag(clflags, "c");
const bool sdkFlag = getFlag(clflags, "s");
const bool noFlags = !cmdFlag && !sdkFlag;
if (words.size() == 1)
{
if (!getFlag(clflags, "s") && !getFlag(clflags, "c"))
if (cmdFlag || noFlags)
{
OUTSTREAM << "MEGAcmd log level = " << getLogLevelStr(loggerCMD->getCmdLoggerLevel()) << endl;
OUTSTREAM << "SDK log level = " << getLogLevelStr(loggerCMD->getSdkLoggerLevel()) << endl;
}
else if (getFlag(clflags, "s"))
if (sdkFlag || noFlags)
{
OUTSTREAM << "SDK log level = " << getLogLevelStr(loggerCMD->getSdkLoggerLevel()) << endl;
}
else if (getFlag(clflags, "c"))
{
OUTSTREAM << "MEGAcmd log level = " << getLogLevelStr(loggerCMD->getCmdLoggerLevel()) << endl;
}
}
else
{
int newLogLevel = getLogLevelNum(words[1].c_str());
if (newLogLevel == -1)
auto newLogLevelOpt = getLogLevelNum(words[1].c_str());
if (!newLogLevelOpt)
{
setCurrentThreadOutCode(MCMD_EARGS);
LOG_err << "Invalid log level";
return;
}
newLogLevel = max(newLogLevel, (int)MegaApi::LOG_LEVEL_FATAL);
newLogLevel = min(newLogLevel, (int)MegaApi::LOG_LEVEL_MAX);
if (!getFlag(clflags, "s") && !getFlag(clflags, "c"))
const int newLogLevel = *newLogLevelOpt;
if (cmdFlag || noFlags)
{
loggerCMD->setCmdLoggerLevel(newLogLevel);
loggerCMD->setSdkLoggerLevel(newLogLevel);
ConfigurationManager::savePropertyValue("cmdLogLevel", newLogLevel);
OUTSTREAM << "MEGAcmd log level = " << getLogLevelStr(loggerCMD->getCmdLoggerLevel()) << endl;
OUTSTREAM << "SDK log level = " << getLogLevelStr(loggerCMD->getSdkLoggerLevel()) << endl;
}
else if (getFlag(clflags, "s"))
if (sdkFlag || noFlags)
{
loggerCMD->setSdkLoggerLevel(newLogLevel);
ConfigurationManager::savePropertyValue("sdkLogLevel", newLogLevel);
OUTSTREAM << "SDK log level = " << getLogLevelStr(loggerCMD->getSdkLoggerLevel()) << endl;
}
else if (getFlag(clflags, "c"))
{
loggerCMD->setCmdLoggerLevel(newLogLevel);
OUTSTREAM << "MEGAcmd log level = " << getLogLevelStr(loggerCMD->getCmdLoggerLevel()) << endl;
}
}
return;
}
else if (words[0] == "pwd")
{
@ -9335,7 +9311,7 @@ void MegaCmdExecuter::executecommand(vector<string> words, map<string, int> *clf
long long storageMax = details->getStorageMax();
unique_ptr<MegaNode> root(api->getRootNode());
unique_ptr<MegaNode> inbox(api->getInboxNode());
unique_ptr<MegaNode> inbox(api->getVaultNode());
unique_ptr<MegaNode> rubbish(api->getRubbishNode());
unique_ptr<MegaNodeList> inShares(api->getInShares());
@ -10040,7 +10016,7 @@ void MegaCmdExecuter::executecommand(vector<string> words, map<string, int> *clf
}
for (int i = 0; i < ocrl->size(); i++)
{
MegaContactRequest * cr = ocrl->get(i);
auto cr = ocrl->get(i);
OUTSTREAM << " " << getLeftAlignedStr(cr->getTargetEmail(),22);
char * sid = api->userHandleToBase64(cr->getHandle());
@ -10068,7 +10044,7 @@ void MegaCmdExecuter::executecommand(vector<string> words, map<string, int> *clf
for (int i = 0; i < icrl->size(); i++)
{
MegaContactRequest * cr = icrl->get(i);
auto cr = icrl->get(i);
OUTSTREAM << " " << getLeftAlignedStr(cr->getSourceEmail(), 22);
MegaHandle id = cr->getHandle();
@ -10142,101 +10118,6 @@ void MegaCmdExecuter::executecommand(vector<string> words, map<string, int> *clf
return;
}
#ifdef HAVE_DOWNLOADS_COMMAND
else if (words[0] == "downloads")
{
if (getFlag(clflags, "purge"))
{
OUTSTREAM << "Cancelling and cleaning all transfers and history ..." << endl;
cleanSlateTranfers();
OUTSTREAM << "... done" << endl;
return;
}
if (getFlag(clflags, "enable-clean-slate"))
{
bool downloads_cleanslate_enabled_before = ConfigurationManager::getConfigurationValue("downloads_cleanslate_enabled", false);
if (!downloads_cleanslate_enabled_before)
{
ConfigurationManager::savePropertyValue("downloads_cleanslate_enabled", true);
}
OUTSTREAM << "Enabled clean slate: transfers from previous executions will be discarded upon restart" << endl;
return;
}
else if (getFlag(clflags, "disable-clean-slate"))
{
bool downloads_cleanslate_enabled_before = ConfigurationManager::getConfigurationValue("downloads_cleanslate_enabled", false);
if (downloads_cleanslate_enabled_before)
{
ConfigurationManager::savePropertyValue("downloads_cleanslate_enabled", false);
}
OUTSTREAM << "Disabled clean slate: transfers from previous executions will not be discarded upon restart" << endl;
return;
}
bool queryEnabled = getFlag(clflags, "query-enabled");
if (getFlag(clflags, "enable-tracking"))
{
bool downloads_tracking_enabled_before = ConfigurationManager::getConfigurationValue("downloads_tracking_enabled", false);
if (!downloads_tracking_enabled_before)
{
ConfigurationManager::savePropertyValue("downloads_tracking_enabled", true);
DownloadsManager::Instance().start();
}
queryEnabled = true;
}
else if (getFlag(clflags, "disable-tracking"))
{
bool downloads_tracking_enabled_before = ConfigurationManager::getConfigurationValue("downloads_tracking_enabled", false);
if (downloads_tracking_enabled_before)
{
ConfigurationManager::savePropertyValue("downloads_tracking_enabled", false);
DownloadsManager::Instance().shutdown(true);
}
queryEnabled = true;
}
if (queryEnabled)
{
bool downloads_tracking_enabled = ConfigurationManager::getConfigurationValue("downloads_tracking_enabled", false);
OUTSTREAM << "Download tracking is " << (downloads_tracking_enabled ? "enabled" : "disabled") << endl;
return;
}
if (getFlag(clflags, "report-all"))
{
OUTSTRINGSTREAM oss;
DownloadsManager::Instance().printAll(oss, clflags, cloptions);
OUTSTREAM << oss.str();
return;
}
/// report:
if (words.size() < 2)
{
setCurrentThreadOutCode(MCMD_EARGS);
LOG_err << " " << getUsageStr(words[0].c_str());
return;
}
for (unsigned i = 1 ; i < words.size(); i++)
{
if (!words[i].empty())
{
OUTSTRINGSTREAM oss;
DownloadsManager::Instance().printOne(oss, words[i], clflags, cloptions);
OUTSTREAM << oss.str();
}
}
}
#endif
else if (words[0] == "transfers")
{
bool showcompleted = getFlag(clflags, "show-completed");
@ -10800,13 +10681,28 @@ void MegaCmdExecuter::executecommand(vector<string> words, map<string, int> *clf
return;
}
auto syncIssues = mSyncIssuesManager.getSyncIssues();
#ifdef MEGACMD_TESTING_CODE
// Do not trust empty results (SDK may send them after spurious scans delayed 20ds. SDK-4813)
timelyRetry(std::chrono::milliseconds(2300), std::chrono::milliseconds(200),
[&syncIssues]() { return !syncIssues.empty(); },
[this, &syncIssues, firstTime{true}]() mutable
{
if (firstTime)
{
LOG_warn << "sync-issues first retrieval returned empty";
firstTime = false;
}
syncIssues = mSyncIssuesManager.getSyncIssues();
LOG_warn << "sync-issues retrieval returned empty. Retried returned = " << syncIssues.size();
});
#endif
ColumnDisplayer cd(clflags, cloptions);
bool detailSyncIssue = getFlag(clflags, "detail");
if (detailSyncIssue) // get the details of one or more issues
{
auto syncIssues = mSyncIssuesManager.getSyncIssues();
bool showAll = getFlag(clflags, "all");
if (showAll)
{
@ -10840,7 +10736,6 @@ void MegaCmdExecuter::executecommand(vector<string> words, map<string, int> *clf
}
else // show all sync issues
{
auto syncIssues = mSyncIssuesManager.getSyncIssues();
if (syncIssues.empty())
{
OUTSTREAM << "There are no sync issues" << endl;

View File

@ -19,8 +19,6 @@
#ifndef MEGACMDEXECUTER_H
#define MEGACMDEXECUTER_H
#include "megacmdtransfermanager.h"
#include "megacmdlogger.h"
#include "megacmdsandbox.h"
#include "listeners.h"
@ -240,8 +238,7 @@ public:
bool setProxy(const std::string &url, const std::string &username, const std::string &password, int proxyType);
void fetchNodes(mega::MegaApi *api = nullptr, int clientID = -27);
void cleanSlateTranfers();
void mayExecutePendingStuffInWorkerThread();
};
}//end namespace

View File

@ -21,23 +21,9 @@
#include "megacmd_src_file_list.h"
#include <map>
#include <filesystem>
#include <sys/types.h>
#ifdef _WIN32
#include <fcntl.h>
#include <io.h>
#include <stdio.h>
#ifndef _O_U16TEXT
#define _O_U16TEXT 0x00020000
#endif
#ifndef _O_U8TEXT
#define _O_U8TEXT 0x00040000
#endif
#endif
namespace fs = std::filesystem;
using namespace mega;
namespace megacmd {
@ -160,13 +146,12 @@ MegaCmdLogger::MegaCmdLogger() :
{
}
OUTSTRING MegaCmdLogger::getDefaultFilePath()
fs::path MegaCmdLogger::getDefaultFilePath()
{
auto dirs = PlatformDirectories::getPlatformSpecificDirectories();
assert(!dirs->configDirPath().empty());
auto logFilePath = fs::path(dirs->configDirPath()) / "megacmdserver.log";
return logFilePath.native();
assert(!dirs->configDirPath().empty());
return dirs->configDirPath() / "megacmdserver.log";
}
bool MegaCmdLogger::isMegaCmdSource(const std::string &source)
@ -180,14 +165,47 @@ bool MegaCmdLogger::isMegaCmdSource(const std::string &source)
return megaCmdSourceFiles.find(filename) != megaCmdSourceFiles.end();
}
void MegaCmdLogger::formatLogToStream(LoggedStream &stream, std::string_view time, int logLevel, const char *source, const char *message)
const char * loglevelToShortPaddedString(int loglevel)
{
stream << "[";
static constexpr std::array<const char*, 6> logLevels = {
"CRIT ", // LOG_LEVEL_FATAL
"ERR ", // LOG_LEVEL_ERROR
"WARN ", // LOG_LEVEL_WARNING
"INFO ", // LOG_LEVEL_INFO
"DBG ", // LOG_LEVEL_DEBUG
"DTL " // LOG_LEVEL_MAX
};
assert (loglevel >= 0 && loglevel < static_cast<int>(logLevels.size()));
return logLevels[static_cast<size_t>(loglevel)];
}
void MegaCmdLogger::formatLogToStream(LoggedStream &stream, std::string_view time, int logLevel, const char *source, const char *message, bool surround)
{
if (surround)
{
stream << "[";
}
stream << time;
if (!isMegaCmdSource(source))
{
stream << "SDK:";
stream << " sdk ";
}
stream << SimpleLogger::toStr(LogLevel(logLevel)) << ": " << time << "] " << message << '\n';
else
{
stream << " cmd ";
}
stream << loglevelToShortPaddedString(logLevel) << message;
if (surround)
{
stream << "]";
}
else
{
stream << " [" << source << "]";
}
stream << '\n';
if (logLevel <= mFlushOnLevel)
{
@ -259,6 +277,13 @@ int MegaCmdSimpleLogger::getMaxLogLevel() const
void MegaCmdSimpleLogger::log(const char * /*time*/, int logLevel, const char *source, const char *message)
{
if (!isValidUtf8(message, strlen(message)))
{
constexpr const char* invalid = "<invalid utf8>";
message = invalid;
assert(false && "Attempt to log invalid utf8 string");
}
if (shouldIgnoreMessage(logLevel, source, message))
{
return;
@ -266,29 +291,23 @@ void MegaCmdSimpleLogger::log(const char * /*time*/, int logLevel, const char *s
if (shouldLogToStream(logLevel, source))
{
// log to _file_ (e.g: FileRotatingLoggedStream)
const std::string nowTimeStr = getNowTimeStr();
formatLogToStream(mLoggedStream, nowTimeStr, logLevel, source, message);
if (mLogToOutStream)
if (mLogToOutStream) // log to stdout
{
#ifdef _WIN32
std::lock_guard<std::mutex> g(mSetmodeMtx);
int oldmode = _setmode(_fileno(stdout), _O_U8TEXT);
WindowsUtf8StdoutGuard utf8Guard;
#endif
formatLogToStream(mOutStream, nowTimeStr, logLevel, source, message);
#ifdef _WIN32
assert(oldmode != -1);
_setmode(_fileno(stdout), oldmode);
#endif
}
}
if (shouldLogToClient(logLevel, source))
{
const std::string nowTimeStr = getNowTimeStr();
assert(isMegaCmdSource(source)); // if this happens in the sdk thread, this shall be false
formatLogToStream(OUTSTREAM, nowTimeStr, logLevel, source, message);
formatLogToStream(OUTSTREAM, nowTimeStr, logLevel, source, message, true);
}
}

View File

@ -19,12 +19,49 @@
#ifndef MEGACMDLOGGER_H
#define MEGACMDLOGGER_H
#include "megacmdcommonutils.h"
#include "megacmd.h"
#include "comunicationsmanager.h"
#define OUTSTREAM getCurrentThreadOutStream()
namespace megacmd {
#ifdef WIN32
inline ::mega::SimpleLogger &operator<<(::mega::SimpleLogger& sl, const fs::path& path)
{
return sl << megacmd::pathAsUtf8(path);
}
template <typename T>
inline std::enable_if_t<std::is_same_v<std::decay_t<T>, std::wstring>, ::mega::SimpleLogger &>
operator<<(::mega::SimpleLogger& sl, const T& wstr)
{
return sl << megacmd::utf16ToUtf8(wstr);
}
#endif
// String used to transmit binary data
class BinaryStringView
{
public:
BinaryStringView(char *buffer, size_t size)
: mValue(buffer, size)
{}
const std::string_view& get() const {
return mValue;
}
std::string_view& get() {
return mValue;
}
private:
std::string_view mValue;
};
class LoggedStream
{
public:
@ -40,6 +77,7 @@ public:
virtual const LoggedStream& operator<<(std::wstring v) const = 0;
#endif
virtual const LoggedStream& operator<<(std::string v) const = 0;
virtual const LoggedStream& operator<<(BinaryStringView v) const = 0;
virtual const LoggedStream& operator<<(std::string_view v) const = 0;
virtual const LoggedStream& operator<<(int v) const = 0;
virtual const LoggedStream& operator<<(unsigned int v) const = 0;
@ -66,6 +104,7 @@ public:
#endif
const LoggedStream& operator<<(std::string v) const override { return *this; }
const LoggedStream& operator<<(BinaryStringView v) const override { return *this; }
const LoggedStream& operator<<(std::string_view v) const override { return *this; }
const LoggedStream& operator<<(int v) const override { return *this; }
const LoggedStream& operator<<(unsigned int v) const override { return *this; }
@ -119,6 +158,15 @@ public:
virtual const LoggedStream& operator<<(std::string_view v) const override { *out << v;return *this; }
#endif
virtual const LoggedStream& operator<<(std::string v) const override { *out << v;return *this; }
virtual const LoggedStream& operator<<(BinaryStringView v) const override {
#ifdef _WIN32
assert(false && "wostream cannot take binary data directly");
#else
*out << v.get();
#endif
return *this;
}
virtual const LoggedStream& operator<<(int v) const override { *out << v;return *this; }
virtual const LoggedStream& operator<<(unsigned int v) const override { *out << v;return *this; }
virtual const LoggedStream& operator<<(long unsigned int v) const override { *out << v;return *this; }
@ -144,7 +192,7 @@ class LoggedStreamPartialOutputs : public LoggedStream
{
public:
LoggedStreamPartialOutputs(ComunicationsManager *_cm, CmdPetition *_inf) : cm(_cm), inf(_inf) {}
virtual bool isClientConnected() { return inf && !inf->clientDisconnected; }
virtual bool isClientConnected() override { return inf && !inf->clientDisconnected; }
virtual const LoggedStream& operator<<(const char& v) const override { OUTSTRINGSTREAM os; os << v; OUTSTRING s = os.str(); cm->sendPartialOutput(inf, &s); return *this; }
virtual const LoggedStream& operator<<(const char* v) const override { OUTSTRINGSTREAM os; os << v; OUTSTRING s = os.str(); cm->sendPartialOutput(inf, &s); return *this; }
@ -155,6 +203,7 @@ public:
#else
virtual const LoggedStream& operator<<(std::string v) const override { cm->sendPartialOutput(inf, &v); return *this; }
#endif
virtual const LoggedStream& operator<<(BinaryStringView v) const override { cm->sendPartialOutput(inf, (char*) v.get().data(), v.get().size(), true); return *this; }
virtual const LoggedStream& operator<<(std::string_view v) const override { cm->sendPartialOutput(inf, (char*) v.data(), v.size()); return *this; }
virtual const LoggedStream& operator<<(int v) const override { OUTSTRINGSTREAM os; os << v; OUTSTRING s = os.str(); cm->sendPartialOutput(inf, &s); return *this; }
@ -216,7 +265,7 @@ class MegaCmdLogger : public mega::MegaLogger
protected:
static bool isMegaCmdSource(const std::string &source);
void formatLogToStream(LoggedStream& stream, std::string_view time, int logLevel, const char *source, const char *message);
void formatLogToStream(LoggedStream& stream, std::string_view time, int logLevel, const char *source, const char *message, bool surround = false);
bool shouldIgnoreMessage(int logLevel, const char *source, const char *message) const;
public:
@ -235,16 +284,13 @@ public:
virtual int getMaxLogLevel() const { return std::max(mSdkLoggerLevel, mCmdLoggerLevel); }
static OUTSTRING getDefaultFilePath();
static fs::path getDefaultFilePath();
};
class MegaCmdSimpleLogger final : public MegaCmdLogger
{
#ifdef _WIN32
std::mutex mSetmodeMtx;
#endif
LoggedStream &mLoggedStream;
LoggedStreamOutStream mOutStream;
LoggedStream &mLoggedStream; // to log into files (e.g. FileRotatingLoggedStream)
LoggedStreamOutStream mOutStream; // to log into stdout
bool mLogToOutStream;
bool shouldLogToStream(int logLevel, const char *source) const;

View File

@ -52,18 +52,6 @@
#include <sys/types.h>
#include <errno.h>
#else
#include <fcntl.h>
#include <io.h>
#include <stdio.h>
#ifndef _O_U16TEXT
#define _O_U16TEXT 0x00020000
#endif
#ifndef _O_U8TEXT
#define _O_U8TEXT 0x00040000
#endif
#endif
#if defined(_WIN32)
#define strdup _strdup
#endif
@ -168,8 +156,8 @@ void console_setecho(bool echo)
#endif
}
bool alreadyFinished = false; //flag to show progress
float percentDowloaded = 0.0; // to show progress
std::atomic_bool alreadyFinished = false; //flag to show progress
std::atomic<float> percentDowloaded = 0.0; // to show progress
// password change-related state information
string oldpasswd;
@ -182,10 +170,9 @@ static std::mutex handlerInstallerMutex;
static std::atomic_bool requirepromptinstall(true);
bool procesingline = false;
bool promptreinstalledwhenprocessingline = false;
bool serverTryingToLog = false;
std::atomic_bool procesingline = false;
std::atomic_bool promptreinstalledwhenprocessingline = false;
std::atomic_bool serverTryingToLog = false;
static char dynamicprompt[PROMPT_MAX_SIZE];
@ -253,7 +240,6 @@ void statechangehandle(string statestring, MegaCmdShellCommunications &comsManag
{
if (serverTryingToLog)
{
std::lock_guard<std::mutex> stdOutLockGuard(comsManager.getStdoutLockGuard());
printCenteredContentsCerr(string("MEGAcmd Server is still trying to log in. Still, some commands are available.\n"
"Type \"help\", to list them.").c_str(), width);
}
@ -279,11 +265,8 @@ void statechangehandle(string statestring, MegaCmdShellCommunications &comsManag
#ifdef _WIN32
wstring wbuffer;
stringtolocalw((const char*)os.str().data(),&wbuffer);
int oldmode;
std::lock_guard<std::mutex> stdOutLockGuard(comsManager.getStdoutLockGuard());
oldmode = _setmode(_fileno(stdout), _O_U8TEXT);
WindowsUtf8StdoutGuard utf8Guard;
OUTSTREAM << wbuffer << flush;
_setmode(_fileno(stdout), oldmode);
#else
OUTSTREAM << os.str();
#endif
@ -297,21 +280,22 @@ void statechangehandle(string statestring, MegaCmdShellCommunications &comsManag
{
serverTryingToLog = true;
std::lock_guard<std::mutex> stdOutLockGuard(comsManager.getStdoutLockGuard());
printCenteredContentsCerr(string("Resuming session ... ").c_str(), width, false);
}
else if (newstate.compare(0, strlen("message:"), "message:") == 0)
{
if (notRepeatedMessage(newstate)) //to avoid repeating messages
{
std::lock_guard<std::mutex> stdOutLockGuard(comsManager.getStdoutLockGuard());
#ifdef _WIN32
int oldmode = _setmode(_fileno(stdout), _O_U8TEXT);
#endif
string contents = newstate.substr(strlen("message:"));
std::string_view messageContents = std::string_view(newstate).substr(strlen("message:"));
string contents(messageContents);
replaceAll(contents, "%mega-%", "");
if (contents.find("-----") != 0)
#ifdef _WIN32
WindowsUtf8StdoutGuard utf8Guard;
#else
StdoutMutexGuard stdoutGuard;
#endif
if (messageContents.rfind("-----", 0) != 0)
{
if (!procesingline || promptreinstalledwhenprocessingline || shown_partial_progress)
{
@ -332,10 +316,6 @@ void statechangehandle(string statestring, MegaCmdShellCommunications &comsManag
requirepromptinstall = true;
OUTSTREAM << endl << contents << endl;
}
#ifdef _WIN32
_setmode(_fileno(stdout), oldmode);
#endif
}
}
else if (newstate.compare(0, strlen("clientID:"), "clientID:") == 0)
@ -370,7 +350,6 @@ void statechangehandle(string statestring, MegaCmdShellCommunications &comsManag
shown_partial_progress = false;
}
std::lock_guard<std::mutex> stdOutLockGuard(comsManager.getStdoutLockGuard());
long long completed = received == SPROGRESS_COMPLETE ? PROGRESS_COMPLETE : charstoll(received.c_str());
const char * progressTitle = title.empty() ? "TRANSFERRING" : title.c_str();
printprogress(completed, charstoll(total.c_str()), progressTitle);
@ -631,48 +610,11 @@ void install_rl_handler(const char *theprompt, bool external)
promptreinstalledwhenprocessingline = true;
}
#ifdef _WIN32
wstring wswhat;
stringtolocalw(theprompt,&wswhat);
const wchar_t *what = wswhat.c_str();
// escape characters that break readline input (e.g. Chinese ones. e.g \x242ee)
wstring output = escapereadlinebreakers(what);
// give readline something it understands
what = output.c_str();
size_t buffer_size;
#ifdef _TRUNCATE
wcstombs_s(&buffer_size, NULL, 0, what, _TRUNCATE);
#else
buffer_size=output.size()*sizeof(wchar_t)*2;
#endif
if (buffer_size) //coversion is ok
{
// do the actual conversion
char *buffer = new char[buffer_size];
#ifdef _TRUNCATE
wcstombs_s(&buffer_size, buffer, buffer_size,what, _TRUNCATE);
#else
wcstombs(buffer, what, buffer_size);
#endif
rl_callback_handler_install(buffer, store_line);
}
else
{
rl_callback_handler_install("INVALID_PROMPT: ", store_line);
}
#else
rl_restore_prompt();
rl_callback_handler_install(theprompt, store_line);
handlerOverridenByExternalThread = external;
requirepromptinstall = false;
#endif
}
void redisplay_prompt()
@ -868,7 +810,6 @@ void changedir(const string& where)
#endif
}
#ifndef NO_READLINE
char* remote_completion(const char* text, int state)
{
@ -888,16 +829,7 @@ char* remote_completion(const char* text, int state)
string outputcommand;
#ifdef _WIN32
#ifdef __MINGW32__
wstring soss=oss.str();
localwtostring(&soss,&outputcommand);
#else
localwtostring(&oss.str(),&outputcommand);
#endif
#else
outputcommand = oss.str();
#endif
outputcommand = oss.str();
if (outputcommand == "MEGACMD_USE_LOCAL_COMPLETION")
{
@ -967,78 +899,6 @@ void printHistory()
}
}
#ifdef _WIN32
/**
* @brief getcharacterreadlineUTF16support
* while this works, somehow arrows and other readline stuff is disabled using this one.
* @param stream
* @return
*/
int getcharacterreadlineUTF16support (FILE *stream)
{
int result;
char b[10];
memset(b,0,10);
while (1)
{
int oldmode = _setmode(_fileno(stream), _O_U16TEXT);
result = read (fileno (stream), &b, 10);
_setmode(_fileno(stream), oldmode);
if (result == 0)
{
return (EOF);
}
// convert the UTF16 string to widechar
size_t wbuffer_size;
#ifdef _TRUNCATE
mbstowcs_s(&wbuffer_size, NULL, 0, b, _TRUNCATE);
#else
wbuffer_size=10;
#endif
wchar_t *wbuffer = new wchar_t[wbuffer_size];
#ifdef _TRUNCATE
mbstowcs_s(&wbuffer_size, wbuffer, wbuffer_size, b, _TRUNCATE);
#else
mbstowcs(wbuffer, b, wbuffer_size);
#endif
// convert the UTF16 widechar to UTF8 string
string receivedutf8;
utf16ToUtf8(wbuffer, wbuffer_size,&receivedutf8);
if (strlen(receivedutf8.c_str()) > 1) //multi byte utf8 sequence: place the UTF8 characters into rl buffer one by one
{
for (unsigned int i=0;i< strlen(receivedutf8.c_str());i++)
{
rl_line_buffer[rl_end++] = receivedutf8.c_str()[i];
rl_point=rl_end;
}
rl_line_buffer[rl_end] = '\0';
return 0;
}
if (result =! 0)
{
return (b[0]);
}
/* If zero characters are returned, then the file that we are
reading from is empty! Return EOF in that case. */
if (result == 0)
{
return (EOF);
}
}
}
#endif
void wait_for_input(int readline_fd)
{
fd_set fds;
@ -1051,17 +911,13 @@ void wait_for_input(int readline_fd)
{
if (ERRNO != EINTR) //syscall
{
#ifdef _WIN32
if (ERRNO != WSAENOTSOCK) // it enters here since it is not a socket. Alt: Use WaitForMultipleObjectsEx
#endif
cerr << "Error at select at wait_for_input errno: " << ERRNO << endl;
cerr << "Error at select at wait_for_input errno: " << ERRNO << endl;
return;
}
}
}
#else
vector<autocomplete::ACState::Completion> remote_completion(string linetocomplete)
{
using namespace autocomplete;
@ -1600,33 +1456,6 @@ void process_line(const char * line)
#endif
return;
}
#ifdef HAVE_DOWNLOADS_COMMAND
else if ( (words[0] == "downloads"))
{
string toexec;
if (!strstr (commandtoexec,"path-display-size"))
{
unsigned int width = getNumberOfCols(75);
int pathSize = int((width-46)/2);
toexec+=words[0];
toexec+=" --path-display-size=";
toexec+=SSTR(pathSize);
toexec+=" ";
if (strlen(commandtoexec)>(words[0].size()+1))
{
toexec+=commandtoexec+words[0].size()+1;
}
}
else
{
toexec+=commandtoexec;
}
comms->executeCommand(toexec.c_str(), readresponse);
}
#endif
else if ( (words[0] == "transfers"))
{
string toexec;
@ -2057,42 +1886,63 @@ void printWelcomeMsg(unsigned int width)
width = getNumberOfCols(75);
}
COUT << endl;
COUT << ".";
for (unsigned int i = 0; i < width; i++)
COUT << "=" ;
COUT << ".";
COUT << endl;
printCenteredLine(" __ __ _____ ____ _ _ ",width);
printCenteredLine("| \\/ | ___|/ ___| / \\ ___ _ __ ___ __| |",width);
printCenteredLine("| |\\/| | \\ / | _ / _ \\ / __| '_ ` _ \\ / _` |",width);
printCenteredLine("| | | | /__\\ |_| |/ ___ \\ (__| | | | | | (_| |",width);
printCenteredLine("|_| |_|____|\\____/_/ \\_\\___|_| |_| |_|\\__,_|",width);
std::ostringstream oss;
COUT << "|";
oss << endl;
oss << ".";
for (unsigned int i = 0; i < width; i++)
COUT << " " ;
COUT << "|";
COUT << endl;
printCenteredLine("Welcome to MEGAcmd! A Command Line Interactive and Scriptable",width);
printCenteredLine("Application to interact with your MEGA account.",width);
printCenteredLine("Please write to support@mega.nz if you find any issue or",width);
printCenteredLine("have any suggestion concerning its functionalities.",width);
printCenteredLine("Enter \"help --non-interactive\" to learn how to use MEGAcmd with scripts.",width);
printCenteredLine("Enter \"help\" for basic info and a list of available commands.",width);
oss << "=" ;
oss << ".";
oss << endl;
printCenteredLine(oss, " __ __ _____ ____ _ _ ",width);
printCenteredLine(oss, "| \\/ | ___|/ ___| / \\ ___ _ __ ___ __| |",width);
printCenteredLine(oss, "| |\\/| | \\ / | _ / _ \\ / __| '_ ` _ \\ / _` |",width);
printCenteredLine(oss, "| | | | /__\\ |_| |/ ___ \\ (__| | | | | | (_| |",width);
printCenteredLine(oss, "|_| |_|____|\\____/_/ \\_\\___|_| |_| |_|\\__,_|",width);
oss << "|";
for (unsigned int i = 0; i < width; i++)
oss << " " ;
oss << "|";
oss << endl;
printCenteredLine(oss, "Welcome to MEGAcmd! A Command Line Interactive and Scriptable",width);
printCenteredLine(oss, "Application to interact with your MEGA account.",width);
printCenteredLine(oss, "Please write to support@mega.nz if you find any issue or",width);
printCenteredLine(oss, "have any suggestion concerning its functionalities.",width);
printCenteredLine(oss, "Enter \"help --non-interactive\" to learn how to use MEGAcmd with scripts.",width);
printCenteredLine(oss, "Enter \"help\" for basic info and a list of available commands.",width);
#if defined(_WIN32) && defined(NO_READLINE)
printCenteredLine("Unicode support in the console is improved, see \"help --unicode\"", width);
printCenteredLine(oss, "Unicode support in the console is improved, see \"help --unicode\"", width);
#elif defined(_WIN32)
printCenteredLine("Enter \"help --unicode\" for info regarding non-ASCII support.",width);
printCenteredLine(oss, "Enter \"help --unicode\" for info regarding non-ASCII support.",width);
#endif
COUT << "`";
oss << "`";
for (unsigned int i = 0; i < width; i++)
COUT << "=" ;
COUT << "´";
COUT << endl;
{
oss << "=" ;
}
#ifndef _WIN32
oss << "\u00b4\n";
COUT << oss.str() << std::flush;
#else
WindowsUtf8StdoutGuard utf8Guard;
// So far, all is ASCII.
COUT << oss.str();
// Now let's tray the non ascii forward acute. Note: codepage should have been set to UTF-8
// set via console->setShellConsole(CP_UTF8, GetConsoleOutputCP());
assert(GetConsoleOutputCP() == CP_UTF8);
if (!(COUT << L"\u00b4")) // still, Windows 7 or depending on the fonts, the console may struggle to render this
{
COUT << "/"; //fallback character
}
COUT << endl;
#endif
}
int quote_detector(char *line, int index)
@ -2122,52 +1972,6 @@ bool runningInBackground()
return false;
}
#ifdef _WIN32
void mycompletefunct(char **c, int num_matches, int max_length)
{
int cols = 80;
#if defined( RL_ISSTATE ) && defined( RL_STATE_INITIALIZED )
int rows = 1;
if (RL_ISSTATE(RL_STATE_INITIALIZED))
{
rl_resize_terminal();
rl_get_screen_size(&rows, &cols);
}
#endif
// max_length is not trustworthy
for (int i=1; i <= num_matches; i++) //contrary to what the documentation says, num_matches is not the size of c (but num_matches+1), current text is preappended in c[0]
{
max_length = max(max_length,(int)strlen(c[i]));
}
OUTSTREAM << endl;
int nelements_per_col = max(1,(cols-1)/(max_length+1));
for (int i=1; i <= num_matches; i++) //contrary to what the documentation says, num_matches is not the size of c (but num_matches+1), current text is preappended in c[0]
{
string option = c[i];
{
std::lock_guard<std::mutex> stdOutLockGuard(comms->getStdoutLockGuard());
OUTSTREAM << setw(min(cols-1,max_length+1)) << left;
int oldmode = _setmode(_fileno(stdout), _O_U16TEXT);
OUTSTREAM << c[i];
_setmode(_fileno(stdout), oldmode);
}
if ( (i%nelements_per_col == 0) && (i != num_matches))
{
OUTSTREAM << endl;
}
}
OUTSTREAM << endl;
}
#endif
#ifndef NO_READLINE
std::string readresponse(const char* question)
{
@ -2187,8 +1991,22 @@ std::string readresponse(const char* question)
#else
std::string readresponse(const char* question)
{
COUT << question << flush;
console->updateInputPrompt(question);
std::string questionStr(question);
size_t pos = questionStr.rfind('\n');
if (pos != std::string::npos)
{
std::string questionPrev = questionStr.substr(0, pos);
std::string prompt = questionStr.substr(pos + 1);
COUT << questionPrev << std::endl;
console->updateInputPrompt(prompt);
}
else
{
console->updateInputPrompt(questionStr);
}
for (;;)
{
if (char* line = console->checkForCompletedInputLine())
@ -2213,12 +2031,6 @@ using namespace megacmd;
int main(int argc, char* argv[])
{
#if defined(_WIN32) && !defined(NO_READLINE)
// Set Environment's default locale
setlocale(LC_ALL, "en-US");
rl_completion_display_matches_hook = mycompletefunct;
#endif
// intialize the comms object
#if defined(_WIN32)
comms = new MegaCmdShellCommunicationsNamedPipes();

View File

@ -31,17 +31,6 @@
#ifdef _WIN32
#include <shlobj.h> //SHGetFolderPath
#include <Shlwapi.h> //PathAppend
#include <fcntl.h>
#include <io.h>
#include <stdio.h>
#ifndef _O_U16TEXT
#define _O_U16TEXT 0x00020000
#endif
#ifndef _O_U8TEXT
#define _O_U8TEXT 0x00040000
#endif
#else
#include <fcntl.h>
@ -67,31 +56,28 @@
#define ENOTCONN 107
#endif
namespace megacmd {
using namespace std;
namespace megacmd {
#ifndef _WIN32
string createAndRetrieveConfigFolder()
{
auto dirs = PlatformDirectories::getPlatformSpecificDirectories();
#ifdef _WIN32
// We don't create the folder: Windows is currently using the folder
// of the executable.
return dirs->configDirPath();
#else
auto dir = dirs->configDirPath();
struct stat st = {};
auto dir = dirs->configDirPath().string();
struct stat st = {};
if (stat(dir.c_str(), &st) == -1)
{
mkdir(dir.c_str(), 0700);
}
return dir;
#endif
}
#endif
#ifndef _WIN32
#include <sys/wait.h>
bool is_pid_running(pid_t pid) {
while(waitpid(-1, 0, WNOHANG) > 0) {
@ -179,6 +165,7 @@ SOCKET MegaCmdShellCommunicationsPosix::createSocket(int number, bool initialize
std::vector<const char*> argsVector{
executable,
"--do-not-log-to-stdout",
nullptr
};
@ -434,7 +421,7 @@ int MegaCmdShellCommunicationsPosix::executeCommand(string command, std::string
n = recv(thesock, (char *)&partialoutsize, sizeof(partialoutsize), MSG_NOSIGNAL);
if (n && partialoutsize > 0)
{
std::lock_guard<std::mutex> stdOutLockGuard(getStdoutLockGuard());
StdoutMutexGuard stdOutLockGuard;
do{
char *buffer = new char[partialoutsize+1];
n = recv(thesock, (char *)buffer, partialoutsize, MSG_NOSIGNAL);
@ -512,7 +499,7 @@ int MegaCmdShellCommunicationsPosix::executeCommand(string command, std::string
{
if (n != 1 || buffer[0] != 0) //To avoid outputing 0 char in binary outputs
{
std::lock_guard<std::mutex> stdOutLockGuard(getStdoutLockGuard());
StdoutMutexGuard stdOutLockGuard;
output << string(buffer,n) << flush;
}
}
@ -664,6 +651,7 @@ bool MegaCmdShellCommunications::registerForStateChanges(bool interactive, State
mListenerThread->join();
}
mClientIdPromise = std::promise<std::string>();
auto resultRegistration = registerForStateChangesImpl(interactive, initiateServer);
if (!resultRegistration)
{
@ -790,9 +778,19 @@ void MegaCmdShellCommunications::setForRegisterAgain(bool dontWait)
}
}
std::lock_guard<std::mutex> MegaCmdShellCommunications::getStdoutLockGuard()
void MegaCmdShellCommunications::setClientIdPromise(const std::string& clientId)
{
return std::lock_guard<std::mutex>(mStdoutMutex);
mClientIdPromise.set_value(clientId);
}
std::optional<std::string> MegaCmdShellCommunications::tryToGetClientId(std::chrono::seconds waitForSecs)
{
auto f = mClientIdPromise.get_future();
if (f.wait_for(waitForSecs) == std::future_status::timeout)
{
return std::nullopt;
}
return f.get();
}
MegaCmdShellCommunications::~MegaCmdShellCommunications()

View File

@ -140,6 +140,9 @@ public:
bool registerRequired();
void setForRegisterAgain(bool dontWait = false);
void setClientIdPromise(const std::string& clientId);
std::optional<std::string> tryToGetClientId(std::chrono::seconds waitForSecs = std::chrono::seconds(15));
std::lock_guard<std::mutex> getStdoutLockGuard();
private:
@ -149,6 +152,8 @@ private:
std::mutex mStdoutMutex;
std::promise<std::string> mClientIdPromise;
std::unique_ptr<std::thread> mListenerThread;
std::mutex mRegistrationMutex;

View File

@ -34,16 +34,6 @@
#include <algorithm>
#include <fcntl.h>
#include <io.h>
#include <stdio.h>
#ifndef _O_U16TEXT
#define _O_U16TEXT 0x00020000
#endif
#ifndef _O_U8TEXT
#define _O_U8TEXT 0x00040000
#endif
namespace megacmd {
bool MegaCmdShellCommunicationsNamedPipes::confirmResponse; //TODO: do all this only in parent class
@ -494,6 +484,8 @@ int MegaCmdShellCommunicationsNamedPipes::executeCommand(string command, std::st
closeNamedPipe(theNamedPipe);
});
bool isCat = command.rfind("cat", 0) == 0 || wcommand.rfind(L"cat", 0) == 0;
if (interactiveshell)
{
command="X"+command;
@ -545,7 +537,8 @@ int MegaCmdShellCommunicationsNamedPipes::executeCommand(string command, std::st
return -1;
}
bool binaryoutput = !wcommand.compare(0, 3, L"cat") && redirectedstdout;
bool binaryoutput = isCat && redirectedstdout;
bool shouldPrintAdditionalLine = false;
while (outcode == MCMD_REQCONFIRM || outcode == MCMD_REQSTRING || outcode == MCMD_PARTIALOUT)
{
@ -558,16 +551,16 @@ int MegaCmdShellCommunicationsNamedPipes::executeCommand(string command, std::st
return -1;
}
if (partialoutsize > 0)
{
std::lock_guard<std::mutex> stdOutLockGuard(getStdoutLockGuard());
int oldmode = 0;
std::unique_ptr<OutputsModeGuard> outputModeGuard;
if (binaryoutput)
{
oldmode = _setmode(_fileno(stdout), O_BINARY);
outputModeGuard.reset(new WindowsBinaryStdoutGuard());
}
else
{
outputModeGuard.reset(new WindowsUtf8StdoutGuard());
}
size_t BUFFERSIZE = 10024;
@ -577,10 +570,11 @@ int MegaCmdShellCommunicationsNamedPipes::executeCommand(string command, std::st
readok = ReadFile(newNamedPipe, buffer, DWORD(std::min(BUFFERSIZE,partialoutsize)),&n,NULL);
if (readok)
{
if (binaryoutput)
{
Instance<WindowsConsoleController>::Get().enableInterceptors(false);
std::cout << string(buffer,n) << flush;
Instance<WindowsConsoleController>::Get().enableInterceptors(true);
}
else
{
@ -588,18 +582,15 @@ int MegaCmdShellCommunicationsNamedPipes::executeCommand(string command, std::st
wstring wbuffer;
stringtolocalw((const char*)&buffer,&wbuffer);
int oldmode;
oldmode = _setmode(_fileno(stdout), _O_U8TEXT);
output << wbuffer << flush;
_setmode(_fileno(stdout), oldmode);
}
partialoutsize-=n;
}
} while(n != 0 && partialoutsize && n !=SOCKET_ERROR);
if (binaryoutput)
if (isCat && !binaryoutput && interactiveshell)
{
_setmode(_fileno(stdout), oldmode);
shouldPrintAdditionalLine = true;
}
}
else
@ -680,25 +671,8 @@ int MegaCmdShellCommunicationsNamedPipes::executeCommand(string command, std::st
stringtolocalw((const char*)&buffer,&wbuffer);
int oldmode;
std::lock_guard<std::mutex> stdOutLockGuard(getStdoutLockGuard());
// if (interactiveshell || outputtobinaryorconsole())
// {
// In non-interactive mode, at least in powershell, when outputting to a file/pipe, things get rough
// Powershell tries to interpret the output as a string and would meddle with the UTF16 encoding, resulting
// in unusable output, So we disable the UTF-16 in such cases (this might cause that the output could be truncated!).
// oldmode = _setmode(_fileno(stdout), _O_U16TEXT);
// }
oldmode = _setmode(_fileno(stdout), _O_U8TEXT);
WindowsUtf8StdoutGuard utf8Guard;
output << wbuffer << flush;
_setmode(_fileno(stdout), oldmode);
// if (interactiveshell || outputtobinaryorconsole() || true)
// {
// _setmode(_fileno(stdout), oldmode);
// }
}
if (readok && n == BUFFERSIZE)
{
@ -720,6 +694,12 @@ int MegaCmdShellCommunicationsNamedPipes::executeCommand(string command, std::st
return -1;
}
if (shouldPrintAdditionalLine)
{
WindowsUtf8StdoutGuard utf8Guard;
output << std::endl;
}
return outcode;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,703 +0,0 @@
/**
* @file src/megacmdtransfermanager.h
* @brief MEGAcmd: Executer of the commands
*
* (c) 2013 by Mega Limited, Auckland, New Zealand
*
* This file is part of the MEGAcmd.
*
* MEGAcmd is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* @copyright Simplified (2-clause) BSD License.
*
* You should have received a copy of the license along with this
* program.
*/
#ifdef HAVE_DOWNLOADS_COMMAND
#pragma once
#include "megacmdcommonutils.h"
#include "mega/types.h" //make_unique
#include "megaapi.h"
#include <memory>
#include <sqlite3.h> //TODO: move all these to a separate source file
#include <condition_variable>
#include <thread>
using namespace mega;
using std::map;
using std::string;
namespace megacmd {
static void printTransferColumnDisplayer(ColumnDisplayer *cd, mega::MegaTransfer *transfer,
const std::string &source, bool printstate=true);
class DownloadId
{
public:
int mTag; //tag for active/finished transfers in current execution
std::string mPath; // the path used to initiate the dl (or the objectId if loaded from db)
DownloadId(int tag, const std::string &path)
: mTag(tag), mPath(path){}
DownloadId() : DownloadId(-1,""){}
bool operator<(const DownloadId& r) const
{
return std::tie(mTag, mPath)
< std::tie(r.mTag, r.mPath);
}
// this returns an id that is always the same for the same path
std::string getObjectID() const;
static bool isObjectID(const string &what);
};
class DataBaseEntry
{
public:
constexpr static int INVALID_DB_ID = 0;
int64_t dbid() const;
void setDbid(const int64_t &dbid);
private:
int64_t mDbid = INVALID_DB_ID;
};
/**
* @brief The information we want to keep of a transfer
*/
class TransferInfo : public DataBaseEntry
{
long mSubTransfersStarted = 0;
long mSubTransfersFinishedOk = 0;
long mSubTransfersFinishedWithFailure = 0;
int mFinalError = API_OK;
string mSourcePath; //full path for files
map<int, std::shared_ptr<TransferInfo>> mSubTransfersInfo; //subtransferInfo by tag
TransferInfo *mParent = nullptr; //for child transfers
std::mutex mTransferMutex;
std::unique_ptr<MegaTransfer> mTransfer; // a copy of a transfer
DownloadId mId; //For main transfers
int64_t mLastUpdate; //timestamp of the last update
//MegaTransfer interface
int getType() const;
int64_t getStartTime() const;
long long getTransferredBytes() const;
long long getTotalBytes() const;
const char *getPath() const;
const char *getParentPath() const;
MegaHandle getNodeHandle() const;
MegaHandle getParentHandle() const;
long long getStartPos() const;
long long getEndPos() const;
const char *getFileName() const;
int getNumRetry() const;
int getMaxRetries() const;
int getTag() const;
long long getSpeed() const;
long long getMeanSpeed() const;
long long getDeltaSize() const;
int64_t getUpdateTime() const;
MegaNode *getPublicMegaNode() const;
bool isSyncTransfer() const;
bool isStreamingTransfer() const;
bool isFinished() const;
bool isBackupTransfer() const;
bool isForeignOverquota() const;
bool isForceNewUpload() const;
char *getLastBytes() const;
MegaError getLastError() const;
const MegaError *getLastErrorExtended() const;
bool isFolderTransfer() const;
int getFolderTransferTag() const;
const char *getAppData() const;
int getState() const;
unsigned long long getPriority() const;
long long getNotificationNumber() const;
bool getTargetOverride() const;
void addToColumnDisplayer(ColumnDisplayer &cd);
void initialize(MegaApi *api, MegaTransfer *transfer, DownloadId *id);
public:
//regular ctors
//Despite receiving transfer object here, updateTransfer(transfer, ...) will be required afterwards
// Reason: updateTransfer will trigger IO writer update, and that requires a shared pointer from this class,
// which is not available in ctor.
TransferInfo(MegaApi * api, MegaTransfer *transfer, DownloadId *id = nullptr);
TransferInfo(MegaApi * api, MegaTransfer *transfer, TransferInfo *parent); //ctor for subtransfers
//ctor for loading from db
TransferInfo(const std::string &serializedTransfer, int64_t lastUpdate, TransferInfo *parent, const std::string &objectId);
// updates TransferInfo, requires a shared pointer to it
void updateTransfer(MegaTransfer *transfer, const std::shared_ptr<TransferInfo> &transferInfo, MegaError *error = nullptr);
void addSubTransfer(const std::shared_ptr<TransferInfo> &transferInfo);
void onSubTransferStarted(MegaApi *api, MegaTransfer *subtransfer);
void onSubTransferFinish(MegaTransfer *subtransfer, MegaError *error);
void onSubTransferUpdate(MegaTransfer *subtransfer);
void print(OUTSTREAMTYPE &os, std::map<std::string, int> *clflags, std::map<std::string, std::string> *cloptions, bool printHeader = true);
std::string serializedTransferData();
DownloadId getId() const;
int64_t getParentDbId() const;
int64_t getLastUpdate() const;
void onPersisted();
};
OUTSTREAMTYPE &operator<<(OUTSTREAMTYPE &os, const DownloadId &p);
using MapOfDlTransfers = std::map<DownloadId, std::shared_ptr<TransferInfo>>;
class DownloadsManager
{
private:
std::recursive_mutex mTransfersMutex;
MapOfDlTransfers mTransfers; //here's the ownership of the objects
std::map<int, MapOfDlTransfers::iterator> mActiveTransfers; //All active transfers added
std::map<int, MapOfDlTransfers::iterator> mFinishedTransfers; //All finished transfers in current run
std::queue<int> mFinishedTransfersQueue; //Finished transfers in order of insertion
//Map betwen OID -> TransferInfo
// since 2 transfer can have the same OID, it will be keep the last recently updated
std::map<std::string, MapOfDlTransfers::iterator> mTransfersInMemory;
//a collection of transfers that were initiated, but still are not added
// we need to store this because onTransferFinish of the listener created in downloadNode happens
// after the global onTransferFinish listener. i.e: we cannot tell if these transfers will
// be handled by the second or were added elswhere (from resumption) and have no associated path
std::map<int, std::unique_ptr<MegaTransfer>> mNewUnHandledTransfers;
unsigned mMaxAllowedTransfer = 9999999;
unsigned mLowthresholdMaxAllowedTransfers = 999999;
public:
static DownloadsManager& Instance();
void start();
void shutdown(bool loginout);
void recoverUnHandleTransfer(MegaApi *api, MegaTransfer *transfer);
MapOfDlTransfers::iterator addNewTopLevelTransfer(MegaApi *api, MegaTransfer *transfer,int tag, const std::string &path);
void onTransferStart(MegaApi *api, MegaTransfer *transfer);
void onTransferUpdate(MegaApi *api, MegaTransfer *transfer);
void onTransferFinish(MegaApi *api, ::mega::MegaTransfer *transfer, ::mega::MegaError* error);
void printAll(OUTSTREAMTYPE &os, map<std::string, int> *clflags, map<std::string, std::string> *cloptions);
void printOne(OUTSTREAMTYPE &os, std::string objectIDorTag, map<string, int> *clflags, map<string, string> *cloptions);
void purge();
};
/**
* @brief Extract parameters from a serialized string
*
*/
class ParamReader
{
private:
char *mStart; //starting of the buffer
char *mP; //position of the buffer
char *mEnd; //end of the buffer
bool mDuplicateConstCharPointers; //whether to dup const char * or just use pointers to the buffer
public:
ParamReader(const string &params, bool duplicateConstCharPointer = false);
void advance(size_t size);
void advanceString(); //advances while != \0;
const char *read(size_t size);
size_t sizeRead()
{
assert (mP>=mStart);
return mP-mStart;
}
friend ParamReader& operator>> (ParamReader&, MegaTransfer *&);
// friend ParamReader& operator>> (ParamReader&, MegaError *&);
friend ParamReader& operator>> (ParamReader&, const char *&);
friend ParamReader& operator>> (ParamReader&, char *&);
friend ParamReader& operator>> (ParamReader&, string &);
template <typename T>
friend ParamReader& operator>> (ParamReader&, std::unique_ptr<T>&);
template <typename T>
friend ParamReader& operator>> (ParamReader&, T &);
};
template <typename T>
ParamReader& operator>>(ParamReader& x, std::unique_ptr<T>& n)
{
#ifdef DEBUG
auto prev = x.mDuplicateConstCharPointers;
x.mDuplicateConstCharPointers = true;
#endif
T *pointer = nullptr;
x >> pointer;
n.reset(pointer);
#ifdef DEBUG
x.mDuplicateConstCharPointers = prev;
#endif
return x;
}
template <typename T>
ParamReader& operator>> (ParamReader& x, T &o)
{
if (x.mP + + sizeof(T) <= x.mEnd)
{
memcpy(&o,x.mP, sizeof(T));
x.advance(sizeof(T));
}
return x;
}
class ParamWriter
{
private:
string &mOut;
public:
ParamWriter(string &where);
friend ParamWriter& operator<<(ParamWriter&, MegaTransfer *&);
friend ParamWriter& operator<<(ParamWriter&, const char *);
friend ParamWriter& operator<<(ParamWriter&, char *);
friend ParamWriter& operator<<(ParamWriter&, const string&);
void write(const char *buffer, size_t size);
template <typename T>
friend ParamWriter& operator<<(ParamWriter&, const T &s);
};
template <typename T>
ParamWriter& operator<<(ParamWriter& x, const T &s)
{
static_assert(!std::is_pointer<T>::value, "Param writer not implemented for this type of pointer");
x.mOut.append(reinterpret_cast<const char *>(&s), sizeof(T));
return x;
}
class MegaErrorWithCtor : public MegaError
{
public:
MegaErrorWithCtor() : MegaError(API_OK){};
};
class MegaTransferHeldInString : public MegaTransfer
{
private:
string mSerialized;
int mType;
const char * mTransferString = nullptr;
// const char * mtoString = nullptr;
// const char * m__str__ = nullptr;
// const char * m__toString = nullptr;
int64_t mStartTime;
long long mTransferredBytes;
long long mTotalBytes;
const char * mPath = nullptr;
const char * mParentPath = nullptr;
MegaHandle mNodeHandle;
MegaHandle mParentHandle;
long long mStartPos;
long long mEndPos;
const char * mFileName = nullptr;
// MegaTransferListener * mListener = nullptr;
int mNumRetry;
int mMaxRetries;
int mTag;
long long mSpeed;
long long mMeanSpeed;
long long mDeltaSize;
int64_t mUpdateTime;
// MegaNode * mPublicMegaNode = nullptr;
bool misSyncTransfer;
bool misBackupTransfer;
bool misForeignOverquota;
bool misForceNewUpload;
bool misStreamingTransfer;
bool misFinished;
char * mLastBytes = nullptr;
// MegaError mLastError;
// const MegaError * mLastErrorExtended = nullptr;
bool misFolderTransfer;
int mFolderTransferTag;
const char * mAppData = nullptr;
int mState;
unsigned long long mPriority;
long long mNotificationNumber;
bool mTarOverride;
public:
MegaTransferHeldInString(const string &s, size_t *size_read = nullptr);
virtual MegaTransfer *copy() override
{
return new MegaTransferHeldInString(mSerialized);
}
virtual int getType() const override
{
return mType;
}
virtual const char *getTransferString() const override
{
return mTransferString;
}
virtual const char *toString() const override
{
assert(false && "unimplemented");
return nullptr;
}
virtual const char *__str__() const override
{
assert(false && "unimplemented");
return nullptr;
}
virtual const char *__toString() const override
{
assert(false && "unimplemented");
return nullptr;
}
virtual int64_t getStartTime() const override
{
return mStartTime;
}
virtual long long getTransferredBytes() const override
{
return mTransferredBytes;
}
virtual long long getTotalBytes() const override
{
return mTotalBytes;
}
virtual const char *getPath() const override
{
return mPath;
}
virtual const char *getParentPath() const override
{
return mParentPath;
}
virtual MegaHandle getNodeHandle() const override
{
return mNodeHandle;
}
virtual MegaHandle getParentHandle() const override
{
return mParentHandle;
}
virtual long long getStartPos() const override
{
return mStartPos;
}
virtual long long getEndPos() const override
{
return mEndPos;
}
virtual const char *getFileName() const override
{
return mFileName;
}
virtual MegaTransferListener *getListener() const override
{
assert(false && "unimplemented");
return nullptr;
}
virtual int getNumRetry() const override
{
return mNumRetry;
}
virtual int getMaxRetries() const override
{
return mMaxRetries;
}
virtual int getTag() const override
{
return mTag;
}
virtual long long getSpeed() const override
{
return mSpeed;
}
virtual long long getMeanSpeed() const override
{
return mMeanSpeed;
}
virtual long long getDeltaSize() const override
{
return mDeltaSize;
}
virtual int64_t getUpdateTime() const override
{
return mUpdateTime;
}
virtual MegaNode *getPublicMegaNode() const override
{
assert(false && "unimplemented");
return nullptr;
}
virtual bool isSyncTransfer() const override
{
return misSyncTransfer;
}
virtual bool isBackupTransfer() const override
{
return misBackupTransfer;
}
virtual bool isForeignOverquota() const override
{
return misForeignOverquota;
}
virtual bool isForceNewUpload() const override
{
return misForceNewUpload;
}
virtual bool isStreamingTransfer() const override
{
return misStreamingTransfer;
}
virtual bool isFinished() const override
{
return misFinished;
}
virtual char *getLastBytes() const override
{
return mLastBytes;
}
virtual MegaError getLastError() const override
{
assert(false && "unimplemented");
return MegaErrorWithCtor(); //TODO: remove this and do actually serialize the error (not too costly)
}
virtual const MegaError *getLastErrorExtended() const override
{
assert(false && "unimplemented");
return nullptr;
}
virtual bool isFolderTransfer() const override
{
return misFolderTransfer;
}
virtual int getFolderTransferTag() const override
{
return mFolderTransferTag;
}
virtual const char *getAppData() const override
{
return mAppData;
}
virtual int getState() const override
{
return mState;
}
virtual unsigned long long getPriority() const override
{
return mPriority;
}
virtual long long getNotificationNumber() const override
{
return mNotificationNumber;
}
virtual bool getTargetOverride() const override
{
return mTarOverride;
}
};
class CommitGuard
{
private:
sqlite3 *mDb = nullptr;
bool mVacuum = false;
public:
CommitGuard(sqlite3 *db, bool shrinkDb = false)
:mDb(db), mVacuum(shrinkDb)
{
sqlite3_exec(mDb, "BEGIN", 0, 0, NULL);
}
~CommitGuard()
{
sqlite3_exec(mDb, "COMMIT", 0, 0, NULL);
if (mVacuum)
{
sqlite3_exec(mDb, "VACUUM", 0, 0, NULL);
}
}
};
/**
* @brief Transfer Info persistency action
*/
class TransferInfoIOAction
{
public:
enum Action
{
Write = 0,
Remove = 1,
};
private:
Action mAction;
std::weak_ptr<TransferInfo> mTransferInfo;
std::shared_ptr<TransferInfo> mTransferInfoOwned;
public:
TransferInfoIOAction(Action action, std::shared_ptr<TransferInfo> transferInfo, bool giveOwnership = false)
: mAction(action), mTransferInfo(transferInfo)
{
if (giveOwnership)
{
mTransferInfoOwned = transferInfo; //thus, we keep a reference of the transferInfo
}
}
Action action() const;
std::weak_ptr<TransferInfo> transferInfo() const;
};
/**
* @brief Class for persisting data transferInfos
*/
class TransferInfoIOWriter
{
private:
std::deque<TransferInfoIOAction> mActions;
TransferInfoIOAction getNextAction();
bool hasActions();
std::mutex mActionsMutex;
std::mutex mIOMutex;
std::condition_variable mIOcv;
bool mFinished = false;
int64_t mIOScheduleMs = 0;
uint64_t mIOMaxActionBeforeNotifying = 0;
std::unique_ptr<std::thread> mThreadIoProcessor;
std::string mTransferInfoDbPath;
// std::shared_ptr<LRUListCache<TransferInfo, std::string>> mTransferInfoCache;
//sqlite3 specific:
bool initializeSqlite();
bool doWrite(std::shared_ptr<TransferInfo> transferInfo);
std::shared_ptr<std::string> doRead(std::shared_ptr<TransferInfo> transferInfo);
bool doRemove(std::shared_ptr<TransferInfo> transferInfo);
sqlite3 *db = nullptr;
int64_t mLastId = 0;
bool mInitialized = false;
std::shared_ptr<TransferInfo> loadTransferInfo(const std::string &objectId);
std::vector<std::shared_ptr<TransferInfo>> loadSubTransfers(TransferInfo *parent);
// Initiates mThreadIoProcessor thread loop finish.
void end();
public:
static TransferInfoIOWriter& Instance();
bool start();
void shutdown(bool loginout = false);
void loopIOActionProcessor();
std::string transferInfoDbPath() const;
~TransferInfoIOWriter();
/**
* @brief queues writting a transferInfo
* @param transferInfo
* @return
*/
bool write(std::shared_ptr<TransferInfo> transferInfo);
/**
* @brief queues removing a transferInfo
* @param transferInfo
* @return
*/
bool remove(std::shared_ptr<TransferInfo> transferInfo, bool delayNotification = false);
void forceExecution();
/**
* @brief reads synchronously from db
* @param transferInfo
* @return
*/
std::shared_ptr<TransferInfo> read(const std::string &objectId);
// clean queues and empties db
bool purge();
};
}//end namespace
#endif

View File

@ -223,7 +223,7 @@ const char * getLogLevelStr(int loglevel)
}
}
int getLogLevelNum(const char* level)
std::optional<int> getLogLevelNum(const char* level)
{
if (!strcmp(level, "FATAL") || !strcmp(level, "fatal"))
{
@ -251,13 +251,14 @@ int getLogLevelNum(const char* level)
}
int i = -1;
istringstream is(level);
is >> i;
if (i == 0 && strcmp(level,"0"))
std::istringstream is(level);
if (!(is >> i))
{
return -1;
return {};
}
return i;
return std::clamp(i, (int) MegaApi::LOG_LEVEL_FATAL, (int) MegaApi::LOG_LEVEL_MAX);
}
@ -1250,15 +1251,4 @@ mega::MegaHandle base64ToSyncBackupId(const std::string &shandle)
{
return MegaApi::base64ToUserHandle(shandle.c_str());
}
bool pathIsExistingDir(std::string path)
{
#ifdef _WIN32
replaceAll(path, "/", "\\");
#endif
LocalPath abs = LocalPath::fromAbsolutePath(path);
::mega::MegaFileSystemAccess fsa;
std::unique_ptr<::mega::FileAccess> fa = fsa.newfileaccess();
return fa->isfolder(abs);
}
}//end namespace

View File

@ -42,7 +42,6 @@ const char* getAccessLevelStr(int level);
GENERATOR_MACRO(RUNSTATE_PENDING, "Pending", "Sync config has loaded but we have not attempted to start it yet")\
GENERATOR_MACRO(RUNSTATE_LOADING, "Loading", "Sync is in the process of loading from disk")\
GENERATOR_MACRO(RUNSTATE_RUNNING, "Running", "Sync loaded and active")\
GENERATOR_MACRO(RUNSTATE_PAUSED, "Paused", "Sync loaded but sync logic is suspended for now.")\
GENERATOR_MACRO(RUNSTATE_SUSPENDED, "Suspended", "Sync is not loaded, but it is on disk with the last known sync state")\
GENERATOR_MACRO(RUNSTATE_DISABLED, "Disabled", "Sync has been disabled (no state cached). Starting it is like configuring a brand new sync with those settings")\
@ -72,7 +71,7 @@ const char * getErrorCodeStr(mega::MegaError *e);
const char * getLogLevelStr(int loglevel);
int getLogLevelNum(const char* level);
std::optional<int> getLogLevelNum(const char* level);
const char * getShareLevelStr(int sharelevel);
@ -152,7 +151,5 @@ bool getMinAndMaxSize(std::string sizestring, int64_t *minSize, int64_t *maxSize
std::string readablePermissions(int permvalue);
int permissionsFromReadable(std::string permissions);
bool pathIsExistingDir(std::string path);
}//end namespace
#endif // MEGACMDUTILS_H

View File

@ -25,13 +25,12 @@
namespace megacmd {
const char * const megacmdchangelog =
"Improved startup time""\n"
"Reduced memory consumption: cached metadata is no longer loaded at startup""\n"
"Fixes and improvements in whoami, ls, backup and export commands""\n"
"Fixed several memory leaks and improved overall memory consumption""\n"
"Fixed file permissions on Unix""\n"
"Added support for the Apple silicon (M1)""\n"
"Many other fixes and improvements"
"New Sync Engine: See sync-issues and sync-ignore commands""\n"
"Rotating Logger: Introduced a robust rotating logging system across all platforms for better performance and debugging""\n"
"Platform-specific enhancements: Addressed various file descriptor issues on Linux and macOS, and improved non-ascii support on Windows""\n"
"Improved overall reliability: Fixed memory leaks, resolved potential data races, and eliminated deadlock scenarios""\n"
"Fixed an issue when handling double-quoted arguments""\n"
"Various fixes and refinements to enhance usability and performance"
;
}//end namespace

View File

@ -71,7 +71,7 @@ void printSyncHeader(ColumnDisplayer &cd)
cd.addHeader("REMOTEPATH", false);
}
void printSingleSync(mega::MegaApi& api, mega::MegaSync& sync, mega::MegaNode& node, long long nFiles, long long nFolders, ColumnDisplayer &cd, bool showHandle, int syncIssuesCount)
void printSingleSync(mega::MegaApi& api, mega::MegaSync& sync, mega::MegaNode* node, long long nFiles, long long nFolders, ColumnDisplayer &cd, bool showHandle, int syncIssuesCount)
{
cd.addValue("ID", getSyncId(sync));
cd.addValue("LOCALPATH", sync.getLocalFolder());
@ -106,7 +106,7 @@ void printSingleSync(mega::MegaApi& api, mega::MegaSync& sync, mega::MegaNode& n
cd.addValue("ERROR", syncIssuesMsg);
}
cd.addValue("SIZE", sizeToText(api.getSize(&node)));
cd.addValue("SIZE", sizeToText(node ? api.getSize(node) : 0));
cd.addValue("FILES", std::to_string(nFiles));
cd.addValue("DIRS", std::to_string(nFolders));
}
@ -176,7 +176,7 @@ void printSync(mega::MegaApi& api, ColumnDisplayer& cd, bool showHandle, mega::M
printSyncHeader(cd);
unsigned int syncIssuesCount = syncIssues.getSyncIssuesCount(sync);
printSingleSync(api, sync, *node, nFiles, nFolders, cd, showHandle, syncIssuesCount);
printSingleSync(api, sync, node.get(), nFiles, nFolders, cd, showHandle, syncIssuesCount);
}
void printSyncList(mega::MegaApi& api, ColumnDisplayer& cd, bool showHandles, const mega::MegaSyncList& syncList, const SyncIssueList& syncIssues)
@ -204,7 +204,7 @@ void printSyncList(mega::MegaApi& api, ColumnDisplayer& cd, bool showHandles, co
}
unsigned int syncIssuesCount = syncIssues.getSyncIssuesCount(sync);
printSingleSync(api, sync, *node, nFiles, nFolders, cd, showHandles, syncIssuesCount);
printSingleSync(api, sync, node.get(), nFiles, nFolders, cd, showHandles, syncIssuesCount);
}
}

View File

@ -16,13 +16,11 @@
#pragma once
#include <memory>
#include <filesystem>
#include "megacmdcommonutils.h"
#include "sync_issues.h"
using namespace megacmd;
namespace fs = std::filesystem;
namespace SyncCommand
{

View File

@ -18,13 +18,11 @@
#include <fstream>
#include <cstring>
#include <regex>
#include <filesystem>
#include "megacmdcommonutils.h"
#include "megacmdlogger.h"
using namespace megacmd;
namespace fs = std::filesystem;
namespace {
@ -46,13 +44,13 @@ void trimSpaces(std::string& str)
str.erase(end, str.end());
}
std::unique_lock<std::mutex> getFileLock(const std::string& str)
std::unique_lock<std::mutex> getFileLock(const fs::path& path)
{
static std::mutex mapMutex;
static std::map<std::string, std::mutex> fileMutexMap;
static std::map<fs::path, std::mutex> fileMutexMap;
std::lock_guard mapLock(mapMutex);
return std::unique_lock(fileMutexMap[str]);
return std::unique_lock(fileMutexMap[path]);
}
void executeAdd(MegaIgnoreFile& megaIgnoreFile, const std::set<std::string>& filters)
@ -138,7 +136,7 @@ void executeCommand(const Args& args)
return;
}
std::string megaIgnoreFilePath;
fs::path megaIgnoreFilePath;
bool isDefault = true;
if (args.mMegaIgnoreDirPath.empty())
{
@ -146,21 +144,24 @@ void executeCommand(const Args& args)
}
else
{
megaIgnoreFilePath = args.mMegaIgnoreDirPath + "/.megaignore";
megaIgnoreFilePath = args.mMegaIgnoreDirPath / ".megaignore";
isDefault = false;
}
if (!fs::exists(megaIgnoreFilePath))
std::error_code ec;
if (!fs::exists(megaIgnoreFilePath, ec))
{
setCurrentThreadOutCode(MCMD_NOTFOUND);
if (isDefault)
{
// For the default file to be created, a sync that DOES NOT already contain a .megaignore file has to be added
LOG_err << "Default .megaignore file does not exist (will be created when a new sync is added)";
LOG_err << "Default .megaignore file does not exist (will be created when a new sync is added)"
<< ( ec ? std::string(": ").append(errorCodeStr(ec).c_str()) : "");
}
else
{
LOG_err << "Mega ignore file \"" << megaIgnoreFilePath << "\" does not exist";
LOG_err << "Mega ignore file \"" << megaIgnoreFilePath << "\" does not exist"
<< ( ec ? std::string(": ").append(errorCodeStr(ec).c_str()) : "");
}
return;
}
@ -211,11 +212,10 @@ void MegaIgnoreFile::loadFilters(std::ifstream& file)
}
}
std::string MegaIgnoreFile::getDefaultPath()
fs::path MegaIgnoreFile::getDefaultPath()
{
auto platformDirs = megacmd::PlatformDirectories::getPlatformSpecificDirectories();
auto configDirPath = platformDirs->configDirPath();
return configDirPath + "/.megaignore.default";
return platformDirs->configDirPath() / ".megaignore.default";
}
bool MegaIgnoreFile::isValidFilter(const std::string& filter)
@ -224,15 +224,21 @@ bool MegaIgnoreFile::isValidFilter(const std::string& filter)
return std::regex_match(filter, filterRegex);
}
MegaIgnoreFile::MegaIgnoreFile(const std::string& path) :
MegaIgnoreFile::MegaIgnoreFile(const fs::path& path) :
mPath(path),
mValid(false)
{
auto fileLock = getFileLock(mPath);
if (fs::exists(mPath))
std::error_code ec;
if (fs::exists(mPath, ec))
{
loadFromPath();
}
else if (ec)
{
LOG_err << "MegaIgnoreFile existence check failure: " << mPath << ": " << errorCodeStr(ec);
return;
}
else
{
createWithBOM();

Some files were not shown because too many files have changed in this diff Show More