Skip to content

Instantly share code, notes, and snippets.

@error454
Created December 17, 2019 20:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save error454/324d63ba8263376507c91ba4ca3710e7 to your computer and use it in GitHub Desktop.
Save error454/324d63ba8263376507c91ba4ca3710e7 to your computer and use it in GitHub Desktop.
Dropbox FS Fix
#!/bin/bash
##############################################################################
# Workaround for Dropbox daemon
# -----------------------------
# Verified on Dropbox v77.4.131
# Just make it executable (if need, using
# $ chmod a+x fix_dropbox
# ) and run it.
# Author: Здравко
# www.dropboxforum.com/t5/user/viewprofilepage/user-id/422790
##############################################################################
# Figure out the target places.
USR_HOME=`realpath ~`
USR_LOCAL="$USR_HOME/.local"
USR_LOCAL_BIN="$USR_LOCAL/bin"
USR_LOCAL_LIB="$USR_LOCAL/lib"
DRB_REPLACEMENT="$USR_LOCAL_BIN/dropbox"
DRB_FIX_LIB="$USR_LOCAL_LIB/libdropbox_ext4.so"
USR_PROFILE="$USR_HOME/.profile"
# Dropbox's components
DBX_SHELL_BASE="/usr/bin"
DBX_SHELL="$DBX_SHELL_BASE/dropbox"
DBX_WEB_SRC_BASE="https://www.dropbox.com/download?dl=packages"
DBX_SCRIPT_ALT="dropbox.py"
DBX_WEB_src="$DBX_WEB_SRC_BASE/$DBX_SCRIPT_ALT"
DBX_SHELL_ALT="$USR_LOCAL_BIN/$DBX_SCRIPT_ALT"
##############################################################################
# Precheck and fix up some prerequisites.
# Ensure target directories are on their place.
if [[ ! -d $USR_LOCAL_BIN ]]
then
echo "The Directory \"$USR_LOCAL_BIN\" doesn't exist, going to create it."
mkdir -p $USR_LOCAL_BIN
if [[ $? -ne 0 || ! -d $USR_LOCAL_BIN ]]
then
echo "Directory \"$USR_LOCAL_BIN\" creation fail! Exit."
exit 1
fi
fi
if [[ ! -d $USR_LOCAL_LIB ]]
then
echo "The Directory \"$USR_LOCAL_LIB\" doesn't exist, going to create it."
mkdir -p $USR_LOCAL_LIB
if [[ $? -ne 0 || ! -d $USR_LOCAL_LIB ]]
then
echo "Directory \"$USR_LOCAL_LIB\" creation fail! Exit."
exit 1
fi
fi
# Ensure backup for any existing files.
if [[ -e $DRB_REPLACEMENT ]]
then
if [[ -f $DRB_REPLACEMENT ]]
then
echo "\"$DRB_REPLACEMENT\" already exist, going to back it up."
mv --backup=t -T $DRB_REPLACEMENT "${DRB_REPLACEMENT}.backup"
if [[ $? -ne 0 || -e $DRB_REPLACEMENT ]]
then
echo "Error backing up \"$DRB_REPLACEMENT\" file! Exit."
exit 1
fi
else
echo "$DRB_REPLACEMENT is not regular file! Exit."
exit 1
fi
fi
if [[ -e $DRB_FIX_LIB ]]
then
if [[ -f $DRB_FIX_LIB ]]
then
echo "\"$DRB_FIX_LIB\" already exist, going to back it up."
mv --backup=t -T $DRB_FIX_LIB "${DRB_FIX_LIB}.backup"
if [[ $? -ne 0 || -e $DRB_FIX_LIB ]]
then
echo "Error backing up \"$DRB_FIX_LIB\" file! Exit."
exit 1
fi
else
echo "$DRB_FIX_LIB is not regular file! Exit."
exit 1
fi
fi
# Ensure writing permissions.
if [[ ! -w $USR_LOCAL_BIN || ! -x $USR_LOCAL_BIN ]]
then
chmod u+rwx $USR_LOCAL_BIN
if [[ $? -ne 0 ]]
then
echo "The Directory \"$USR_LOCAL_BIN\" is inaccessible! Exit."
exit 1
fi
fi
if [[ ! -w $USR_LOCAL_LIB || ! -x $USR_LOCAL_LIB ]]
then
chmod u+rwx $USR_LOCAL_LIB
if [[ $? -ne 0 ]]
then
echo "The Directory \"$USR_LOCAL_LIB\" is inaccessible! Exit."
exit 1
fi
fi
# Check for preinstalled dropbox shell script.
if [[ ! -e $DBX_SHELL || ! -x $DBX_SHELL ]]
then
echo "Cannot find pre installed \"$DBX_SHELL\". Will trying alternative."
DBX_SHELL_BASE="$USR_LOCAL_BIN"
DBX_SHELL="$DBX_SHELL_ALT"
# Ensure backup for existing control script.
if [[ -e $DBX_SHELL_ALT ]]
then
if [[ -f $DBX_SHELL_ALT ]]
then
echo "\"$DBX_SHELL_ALT\" already exist, going to back it up."
mv --backup=t -T $DBX_SHELL_ALT "${DBX_SHELL_ALT}.backup"
if [[ $? -ne 0 || -e $DBX_SHELL_ALT ]]
then
echo "Error backing up \"$DBX_SHELL_ALT\" file! Exit."
exit 1
fi
else
echo "$DBX_SHELL_ALT is not regular file! Exit."
exit 1
fi
fi
fi
##############################################################################
# Generate actual workaround components.
# Fetch Dropbox control script (if need).
if [[ "$DBX_SHELL" == "$DBX_SHELL_ALT" ]]
then
if ! wget -q -O "$DBX_SHELL_ALT" "$DBX_WEB_SRC"
then
echo "Error while download \"$DBX_SHELL_ALT\" from \"$DBX_WEB_SRC\"! Exit."
exit 1
fi
chmod a+x $DBX_SHELL_ALT
echo "Dropbox control script: \"$DBX_SHELL_ALT\" - ready for use."
fi
# Fixer - source and building.
gcc -shared -fPIC -ldl -xc -o $DRB_FIX_LIB - << EndOfSrc
// Functions replacements
#define _GNU_SOURCE
#include <stdlib.h>
#include <sys/vfs.h>
#include <linux/magic.h>
#include <dlfcn.h>
#include <sys/statvfs.h>
#include <stdarg.h>
static int (*orig_statfs)(const char *path, struct statfs *buf) = NULL;
static int (*orig_statfs64)(const char *path, struct statfs64 *buf) = NULL;
static int (*orig_open64)(const char *pathname, int flags, ...) = NULL;
int statfs(const char *path, struct statfs *buf) {
if (orig_statfs == NULL) {
orig_statfs = dlsym(RTLD_NEXT, "statfs");
}
register int retval = orig_statfs(path, buf);
if (retval == 0) {
buf->f_type = EXT4_SUPER_MAGIC;
}
return retval;
}
int statfs64(const char *path, struct statfs64 *buf) {
if (orig_statfs64 == NULL) {
orig_statfs64 = dlsym(RTLD_NEXT, "statfs64");
}
register int retval = orig_statfs64(path, buf);
if (retval == 0) {
buf->f_type = EXT4_SUPER_MAGIC;
}
return retval;
}
int open64(const char *pathname, int flags, ...) {
if (orig_open64 == NULL) {
orig_open64 = dlsym(RTLD_NEXT, "open64");
}
register const char *p0 = "/proc/filesystems", *p1 = pathname;
while(*p0 && *p1 && *p0 == *p1) ++p0, ++p1;
if (*p0 == '\0' && *p1 == '\0') {
return -1;
}
va_list arg;
va_start(arg, flags);
mode_t mode = va_arg (arg, int);
va_end(arg);
return orig_open64(pathname, flags, mode);
}
EndOfSrc
if [[ $? -ne 0 ]]
then
echo "Error building \"$DRB_FIX_LIB\"! Exit."
exit 2
fi
echo "\"$DRB_FIX_LIB\" - build and ready."
# Wrapper generating.
cat > $DRB_REPLACEMENT << WrapperHead
#!/bin/bash
if [ \$1 == "start" ]
then
sleep 1
patchpath=\`realpath \$0\`
if echo \$(for i in \`ps -C dropbox -o pid\`
do ls -l /proc/\$i/exe 2>/dev/null | grep -v \$patchpath
done) | grep dropbox > /dev/null
then
timeout=300
# Make sure there isn't any concurrent start operation in progress.
$DBX_SHELL running
while [[ \$? -eq 0 && \$timeout -ne 0 ]]
do
sleep 1
((--timeout))
if echo \$(for i in \`ps -C dropbox -o pid\`
do ls -l /proc/\$i/exe 2>/dev/null | grep -v \$patchpath
done) | grep dropbox > /dev/null
then
$DBX_SHELL running
fi
done
# If there is running application instance, force its stop.
$DBX_SHELL running
while [[ \$? -ne 0 && \$timeout -ne 0 ]]
do
$DBX_SHELL stop
sleep 1
((--timeout))
$DBX_SHELL running
done
# If something goes wrong...
if [[ \$timeout -eq 0 ]]
then
# ...notify somehow about.
title="Problem launching Dropbox"
mainmsg="Possible existing application instance dead"
submsg="Check that, clear and try start again"
if which notify-send > /dev/null
then notify-send --icon=dropbox "\$title" "<b>\$mainmsg\!</b>\n\$submsg."
elif which zenity > /dev/null
then zenity --error --title="\$title" --timeout=10 --width=380 \\
--text="<span size=\"xx-large\"><b>\$mainmsg\!</b>\n\$submsg.</span>" \\
2> /dev/null
else echo " \$title!"
echo "\$mainmsg."
echo "\$submsg."
fi
exit 1
fi
else sleep 100
fi
fi
WrapperHead
declare -p | grep "declare -x LD_PRELOAD" > /dev/null
if [[ $? -ne 0 ]]
then
echo "export LD_PRELOAD=$DRB_FIX_LIB" >> $DRB_REPLACEMENT
else
echo "LD_PRELOAD=$DRB_FIX_LIB:\$LD_PRELOAD" >> $DRB_REPLACEMENT
fi
echo "$DBX_SHELL \$@" >> $DRB_REPLACEMENT
chmod a+x $DRB_REPLACEMENT
echo "\"$DRB_REPLACEMENT\" - generated."
# Environment check and fixup (if need).
echo ""
echo ""
(
IFS=:
for a in $PATH
do
if [[ "$a" == "$USR_LOCAL_BIN" ]]
then
exit 0
elif [[ "$a" == "$DBX_SHELL_BASE" ]]
then
break
fi
done
exit 1
)
if [[ $? -ne 0 ]]
then
echo "" >> $USR_PROFILE
echo "" >> $USR_PROFILE
echo "# Add $USR_LOCAL_BIN to \$PATH environment variable." >> $USR_PROFILE
echo "# This addition is dedicated for Dropbox Workaround." >> $USR_PROFILE
echo "# Remove theses lines when they are no more needed." >> $USR_PROFILE
echo "PATH=\"$USR_LOCAL_BIN:\$PATH\"" >> $USR_PROFILE
echo "" >> $USR_PROFILE
echo "Your Dropbox is almost patched. You have to logout and login"
echo " (or on Your opinion - restart), so all changes to take effect."
echo "After Your next account login:"
fi
echo "Your Dropbox is already patched."
if [[ "$DBX_SHELL_BASE" == "$USR_LOCAL_BIN" ]]
then echo "Just type:"
else echo "Just start it from desktop GUI or type:"
fi
echo "\$ dropbox start"
echo "in console (append option -i, when launch for first time)."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment