From 00b43eb17434ea5c3ae5d3920c24020a858a95bc Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Thu, 4 Feb 2016 19:16:37 +0100 Subject: [PATCH] loooots of bugfixes and changes: check changelog. Most noticeably: libudev is now mandatory. --- Changelog | 13 ++ PKGBUILD | 7 +- README.md | 15 +-- inc/declarations.h | 2 - inc/mount.h | 11 +- inc/string_constants.h | 8 +- makefile | 12 +- src/log.c | 4 - src/main.c | 24 +--- src/mount.c | 297 ++++++++++++++++++----------------------- src/quit_functions.c | 2 +- src/string_constants.c | 21 ++- src/timer.c | 16 +-- src/ui_functions.c | 10 +- 14 files changed, 200 insertions(+), 242 deletions(-) diff --git a/Changelog b/Changelog index 1ec114e..d3c1e11 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,16 @@ +02 / 05 / 2016 +* fixed iso files mounting. Now works fine and reliably. +* removed is_mounted and relying on mntent function (get_mount_points) +* fixed check_cwd function and moved those checks to mount_fs (only when unmounting), to make them useful even when unmounting an iso. +* fixed is_iso_mounted check: it will now perform check to see if a loop device with the same backingfile is unmounted (but already present...created by user or another program), and mount the iso on this loop dev, instead of creating another loop dev. +* moved SetAutoclear on loopdevices to its own function: it has to be called after add_device mounts the loop_dev. +* fixed a bug if compiled with clang ( uint8_t bytes = '\0' was const, with gcc worked fine, but not with clang) +* fixed add_device: relying on some udev dev property values instead of is_mounted function. +* fixed print_info: if info_win is not present, it won't do anything. +* helper_string (helper_win) content will now change together with compile time options, hiding the useless ones. +* libudev is now mandatory +* fixes in add_device: checking if a "size" property is really available for current dev. + 02 / 02 / 2016 * using basename() and dirname() functions instead of manually strrchr path strings. Way cleaner and probably more reliable. * using change_dir when creating new_tab to check for chdir errors and reuse more code. diff --git a/PKGBUILD b/PKGBUILD index 7d7e596..be39163 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -13,10 +13,11 @@ optdepends=('xdg-utils: xdg-open support' 'udisks2: mountable drives and ISO mount support' 'packagekit: package installation support' 'upower: AC (dis)connection events support') -# libcups, libconfig, libx11, openssl, and systemd are optional build dep. +# libcups, libconfig, libx11, and openssl are optional build dep. # If compiled without them, the program will run just fine; -# but that would disable xdg-open, config file read, printing, shasum, powermanagement inhibition, -# drives/iso mount, local packages installation and upower AC (dis)connection signals support. +# but that would disable xdg-open, config file read, printing, and shasum support. +# systemd too is an optdep. But in arch libudev is packaged together with it, +# and libudev is a mandatory dep. makedepends=('git') source=("git://github.com/FedeDP/${_gitname}.git") backup=('etc/default/ncursesFM.conf') diff --git a/README.md b/README.md index 12510c9..4a0f21a 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ It can be built with a very small set of dependencies, as i tried to make as man * Every feature you would expect by a basic FM. * Terminal window resize support. * 2 tabs support. Their content is kept in sync. Jump between tabs with arrow keys (left/right). -* Simple sysinfo monitor that will refresh every 30s: clock, battery and some system info; battery monitor needs libudev. +* Simple sysinfo monitor that will refresh every 30s: clock, battery and some system info. If you've got Upower installed, AC (dis)connection will refresh battery status instantly, instead of waiting up to 30s until next refresh. * Fast browse mode: enable it with ','. It lets you jump between files by just typing their names. * '.' to change files/dirs sorting mode: alphabetically (default), by size, by last modified or by type. @@ -37,7 +37,7 @@ You can add whatever type of file you wish as bookmark from within ncursesFM. Yo * Powermanagement inhibition while processing a job (eg: while pasting a file) to avoid data loss. * Internal udisks2 monitor, to poll for new devices. It can automount new connected devices too. Device monitor will list only mountable devices, eg: dvd reader will not be listed until a cd/dvd is inserted. -* Drives/usb sticks/ISO files (un)mount through udisks2. For drives/usb sticks mount, you also need libudev. +* Drives/usb sticks/ISO files (un)mount through udisks2. * Distro package files installation. * It can reveice AC (dis)connection events from upower, to instantly update battery monitor. @@ -72,11 +72,12 @@ Log file is located at "$HOME/.ncursesfm.log". It is overwritten each time ncurs * 3 : log disabled. ## Build requirements -* linux>=3.4 -> pipe2() O_DIRECT flag. See: http://man7.org/linux/man-pages/man2/pipe.2.html +* linux >= 3.4 -> pipe2() O_DIRECT flag. See: http://man7.org/linux/man-pages/man2/pipe.2.html * ncurses -> UI * libarchive -> archiving/extracting support * pkg-config -> to manage libraries link in makefile -* glibc -> to set locale, for inotify, and for mntent functions (useful only if compiled with libudev too) +* glibc -> to set locale, for inotify, and for mntent functions. +* libudev -> needed for devices/iso mount, and batteries polling. * git -> to clone repo ## Optional compile time dependencies @@ -84,7 +85,6 @@ Log file is located at "$HOME/.ncursesfm.log". It is overwritten each time ncurs * libconfig -> config file parsing. * libx11 -> check whether ncursesFM is started in a X environment or not, and xdg-open support. * sd-bus -> needed for powermanagement inhibition functions, devices/iso mount and packages installation. -* libudev -> needed for devices/iso mount, and batteries polling. * openssl -> for shasum function support. **Build options (to be passed to make)** @@ -92,7 +92,6 @@ Log file is located at "$HOME/.ncursesfm.log". It is overwritten each time ncurs * DISABLE_LIBX11=1 to disable libx11 support. * DISABLE_LIBCONFIG=1 to disable libconfig support. * DISABLE_LIBSYSTEMD=1 to disable libsystemd (sd-bus) support. -* DISABLE_LIBUDEV=1 to disable libudev support. * DISABLE_LIBOPENSSL=1 ti disable openssl support. * DISABLE_LIBCUPS=1 to disable libcups support. @@ -114,11 +113,11 @@ Log file is located at "$HOME/.ncursesfm.log". It is overwritten each time ncurs On Ubuntu install required packages: - # apt-get install libncursesw5-dev libarchive-dev pkg-config git build-essential + # apt-get install libncursesw5-dev libarchive-dev pkg-config git build-essential libudev-dev Optional: - # apt-get install libcups2-dev libconfig-dev libx11-dev libsystemd-dev libudev-dev libssl-dev + # apt-get install libcups2-dev libconfig-dev libx11-dev libsystemd-dev libssl-dev Clone the repo and move inside new dir, then: diff --git a/inc/declarations.h b/inc/declarations.h index d5009a0..56924f2 100644 --- a/inc/declarations.h +++ b/inc/declarations.h @@ -74,9 +74,7 @@ struct conf { int second_tab_starting_dir; #ifdef SYSTEMD_PRESENT int inhibit; -#ifdef LIBUDEV_PRESENT int automount; -#endif #endif int starting_helper; int loglevel; diff --git a/inc/mount.h b/inc/mount.h index 4f13b83..2e68fae 100644 --- a/inc/mount.h +++ b/inc/mount.h @@ -1,15 +1,12 @@ -#ifdef SYSTEMD_PRESENT - #include "fm_functions.h" -#include - -void isomount(const char *str); -#ifdef LIBUDEV_PRESENT +#ifdef SYSTEMD_PRESENT +#include #include #include +void isomount(const char *str); int start_monitor(void); void devices_bus_process(void); void show_devices_tab(void); @@ -17,5 +14,5 @@ void manage_mount_device(void); void manage_enter_device(void); void leave_device_mode(void); void free_device_monitor(void); -#endif + #endif diff --git a/inc/string_constants.h b/inc/string_constants.h index 628e8bd..38b24e3 100644 --- a/inc/string_constants.h +++ b/inc/string_constants.h @@ -1,4 +1,9 @@ +#ifdef SYSTEMD_PRESENT #define HELPER_HEIGHT 14 +#else +#define HELPER_HEIGHT 12 +#endif + #define LONG_FILE_OPERATIONS 5 #define SHORT_FILE_OPERATIONS 3 @@ -67,9 +72,6 @@ const char *helper_string[HELPER_HEIGHT - 2]; const char *pkg_quest; const char *install_th_wait; const char *package_warn; -#endif - -#ifdef LIBUDEV_PRESENT const char *device_mode_str; #endif const char *bookmarks_mode_str; diff --git a/makefile b/makefile index 27f2669..879f484 100644 --- a/makefile +++ b/makefile @@ -1,4 +1,4 @@ -LIBS =-lpthread $(shell pkg-config --silence-errors --libs libarchive ncurses) +LIBS =-lpthread $(shell pkg-config --silence-errors --libs libarchive ncurses libudev) CFLAGS =-D_GNU_SOURCE RM = rm INSTALL = install -p @@ -24,14 +24,11 @@ endif ifneq ("$(DISABLE_LIBSYSTEMD)","1") LIBSYSTEMD=$(shell pkg-config --silence-errors --libs libsystemd) endif -ifneq ("$(DISABLE_LIBUDEV)","1") -LIBUDEV=$(shell pkg-config --silence-errors --libs libudev) -endif ifneq ("$(DISABLE_OPENSSL)","1") LIBOPENSSL=$(shell pkg-config --silence-errors --libs openssl) endif -LIBS+=$(LIBX11) $(LIBCONFIG) $(LIBSYSTEMD) $(LIBUDEV) $(LIBOPENSSL) +LIBS+=$(LIBX11) $(LIBCONFIG) $(LIBSYSTEMD) $(LIBOPENSSL) ifneq ("$(LIBX11)","") CFLAGS+=-DLIBX11_PRESENT @@ -61,11 +58,6 @@ CFLAGS+=-DSYSTEMD_PRESENT $(info libsystemd support enabled.) endif -ifneq ("$(LIBUDEV)","") -CFLAGS+=-DLIBUDEV_PRESENT -$(info libudev support enabled.) -endif - endif all: ncursesFM clean diff --git a/src/log.c b/src/log.c index 70c9646..5d9f99d 100644 --- a/src/log.c +++ b/src/log.c @@ -37,16 +37,12 @@ static void log_current_options(void) { fprintf(log_file, "* Second tab starting dir: %d\n", config.second_tab_starting_dir); #ifdef SYSTEMD_PRESENT fprintf(log_file, "* Inhibition: %d\n", config.inhibit); -#ifdef LIBUDEV_PRESENT fprintf(log_file, "* Automount: %d\n", config.automount); -#endif #endif fprintf(log_file, "* Starting with helper window: %d\n", config.starting_helper); fprintf(log_file, "* Log level: %d\n", config.loglevel); fprintf(log_file, "* Log persistency: %d\n", config.persistent_log); -#ifdef LIBUDEV_PRESENT fprintf(log_file, "* Low battery threshold: %d\n\n", config.bat_low_level); -#endif } void log_message(const char *filename, int lineno, const char *funcname, const char *log_msg, char type, int log_level) { diff --git a/src/main.c b/src/main.c index 0475ede..94bdb63 100644 --- a/src/main.c +++ b/src/main.c @@ -38,7 +38,7 @@ static void read_config_file(void); #endif static void config_checks(void); static void main_loop(void); -#if defined SYSTEMD_PRESENT && LIBUDEV_PRESENT +#ifdef SYSTEMD_PRESENT static void check_device_mode(void); #endif static void manage_enter(struct stat current_file_stat); @@ -91,7 +91,7 @@ static void set_signals(void) { } static void set_pollfd(void) { -#if defined SYSTEMD_PRESENT && LIBUDEV_PRESENT +#ifdef SYSTEMD_PRESENT nfds = 6; #else nfds = 5; @@ -122,7 +122,7 @@ static void set_pollfd(void) { .fd = info_fd[0], .events = POLLIN, }; -#if defined SYSTEMD_PRESENT && LIBUDEV_PRESENT +#ifdef SYSTEMD_PRESENT main_p[DEVMON_IX] = (struct pollfd) { .fd = start_monitor(), .events = POLLIN, @@ -157,11 +157,9 @@ static void sigsegv_handler(int signum) { static void helper_function(int argc, const char *argv[]) { /* default value for starting_helper, bat_low_level and device_mode */ config.starting_helper = 1; -#ifdef LIBUDEV_PRESENT config.bat_low_level = 15; #ifdef SYSTEMD_PRESENT device_mode = DEVMON_STARTING; -#endif #endif if ((argc > 1) && (!strcmp(argv[1], "--help"))) { @@ -190,11 +188,7 @@ static void helper_function(int argc, const char *argv[]) { static void parse_cmd(int argc, const char *argv[]) { int j = 1; #ifdef SYSTEMD_PRESENT -#ifdef LIBUDEV_PRESENT const char *cmd_switch[] = {"--editor", "--starting_dir", "--helper_win", "--loglevel", "--persistent_log", "--low_level", "--inhibit", "--automount"}; -#else - const char *cmd_switch[] = {"--editor", "--starting_dir", "--helper_win", "--loglevel", "--persistent_log", "--low_level", "--inhibit"}; -#endif #else const char *cmd_switch[] = {"--editor", "--starting_dir", "--helper_win", "--loglevel", "--persistent_log", "--low_level"}; #endif @@ -217,11 +211,9 @@ static void parse_cmd(int argc, const char *argv[]) { else if ((!strcmp(cmd_switch[6], argv[j])) && (argv[j + 1])) { config.inhibit = atoi(argv[j + 1]); } -#ifdef LIBUDEV_PRESENT else if ((!strcmp(cmd_switch[7], argv[j])) && (argv[j + 1])) { config.automount = atoi(argv[j + 1]); } -#endif #endif else { break; @@ -253,9 +245,7 @@ static void read_config_file(void) { config_lookup_int(&cfg, "starting_helper", &config.starting_helper); #ifdef SYSTEMD_PRESENT config_lookup_int(&cfg, "inhibit", &config.inhibit); -#ifdef LIBUDEV_PRESENT config_lookup_int(&cfg, "automount", &config.automount); -#endif #endif config_lookup_int(&cfg, "loglevel", &config.loglevel); config_lookup_int(&cfg, "persistent_log", &config.persistent_log); @@ -398,7 +388,7 @@ static void main_loop(void) { } break; #endif -#if defined SYSTEMD_PRESENT && LIBUDEV_PRESENT +#ifdef SYSTEMD_PRESENT case 'm': // m to mount/unmount fs check_device_mode(); break; @@ -447,7 +437,7 @@ static void main_loop(void) { } } -#if defined SYSTEMD_PRESENT && LIBUDEV_PRESENT +#ifdef SYSTEMD_PRESENT static void check_device_mode(void) { if (sv.searching == 3 + active || bookmarks_mode[active]) { return; @@ -472,7 +462,7 @@ static void manage_enter(struct stat current_file_stat) { sv.found_searched[ps[active].curr_pos][index] = '\0'; leave_search_mode(sv.found_searched[ps[active].curr_pos]); } -#if defined SYSTEMD_PRESENT && LIBUDEV_PRESENT +#ifdef SYSTEMD_PRESENT else if (device_mode == 1 + active) { manage_enter_device(); } @@ -492,7 +482,7 @@ static void manage_quit(void) { if (sv.searching == 3 + active) { leave_search_mode(ps[active].my_cwd); } -#if defined SYSTEMD_PRESENT && LIBUDEV_PRESENT +#ifdef SYSTEMD_PRESENT else if (device_mode == 1 + active) { leave_device_mode(); } diff --git a/src/mount.c b/src/mount.c index b590e45..dd88ed0 100644 --- a/src/mount.c +++ b/src/mount.c @@ -1,11 +1,8 @@ #include "../inc/mount.h" #ifdef SYSTEMD_PRESENT -static int mount_fs(const char *str, const char *method, int mount); - -static char mount_str[PATH_MAX + 1]; - -#ifdef LIBUDEV_PRESENT +static int mount_fs(const char *str, int mount); +static void set_autoclear(const char *loopname); static int is_iso_mounted(const char *filename, char *loop_dev); static void iso_backing_file(char *s, const char *name); static int init_mbus(void); @@ -15,8 +12,7 @@ static int remove_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_ static int change_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error); static int change_power_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error); static void enumerate_block_devices(void); -static int is_mounted(const char *dev_path); -static void get_mount_point(const char *dev_path, char *path); +static int get_mount_point(const char *dev_path, char *path); static int check_cwd(char *mounted_path); static void change_mounted_status(int pos, const char *name); static int add_device(struct udev_device *dev, const char *name); @@ -24,32 +20,45 @@ static int remove_device(const char *name); static int is_present(const char *name); static void *safe_realloc(const size_t size); +static char mount_str[PATH_MAX + 1]; static struct udev *udev; static int number_of_devices; char (*my_devices)[PATH_MAX + 1]; static sd_bus *bus; -#endif -#endif - -#ifdef SYSTEMD_PRESENT /* * Open the bus, and call "method" string on UDisks2.Filesystem. */ -static int mount_fs(const char *str, const char *method, int mount) { +static int mount_fs(const char *str, int mount) { sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus_message *mess = NULL; sd_bus *mount_bus = NULL; const char *path; char obj_path[PATH_MAX + 1] = "/org/freedesktop/UDisks2/block_devices/"; - char tmp[30]; + char tmp[30], method[10]; int r, ret = -1; + char mounted_path[PATH_MAX + 1] = {0}, old_cwd[PATH_MAX + 1]; + int win; r = sd_bus_open_system(&mount_bus); if (r < 0) { print_and_warn(strerror(-r), ERR_LINE); goto finish; } + if (mount) { + /* + * before unmount, save old cwd as we'll need + * to chdir anyway to another dir if current cwd + * is inside mounted path. + * If unmount fails, we'll restore our previous cwd. + */ + strcpy(old_cwd, ps[active].my_cwd); + get_mount_point(str, mounted_path); + win = check_cwd(mounted_path); + strcpy(method, "Unmount"); + } else { + strcpy(method, "Mount"); + } strcat(obj_path, strrchr(str, '/') + 1); sprintf(tmp, "calling %s on bus.", method); INFO(tmp); @@ -63,6 +72,8 @@ static int mount_fs(const char *str, const char *method, int mount) { "a{sv}", NULL); if (r < 0) { + /* if it was not succesful, restore old_cwd */ + chdir(old_cwd); print_and_warn(error.message, ERR_LINE); goto finish; } @@ -71,13 +82,29 @@ static int mount_fs(const char *str, const char *method, int mount) { sd_bus_message_read(mess, "s", &path); sprintf(mount_str, "%s mounted in: %s.", str, path); INFO("Mounted."); + /* if it's a loop dev, set autoclear after mounting it */ + if (!strncmp(str, "/dev/loop", strlen("/dev/loop"))) { + set_autoclear(str); + } } else { + /* + * if not active tab was inside mountpoint, move it away: + * check_cwd will return summation of (1 + win) + * for each win inside mountpoint, so r here means + * that OR both win were inside path, or only !active. + */ + if (win == 1 + !active || win == 3) { + change_dir(mounted_path, !active); + } + /* + * here we don't care about unmount success: + * save back in ps[active].my_cwd, process' check_cwd + * to be sure we carry the right cwd + */ + getcwd(ps[active].my_cwd, PATH_MAX); sprintf(mount_str, "%s unmounted.", str); INFO("Unmounted."); } -#ifndef LIBUDEV_PRESENT - print_info(mount_str, INFO_LINE); -#endif finish: close_bus(&error, mess, mount_bus); @@ -95,15 +122,19 @@ void isomount(const char *str) { sd_bus *iso_bus = NULL; const char *obj_path; int r, fd; - -#ifdef LIBUDEV_PRESENT char loop_dev[PATH_MAX + 1]; - if (is_iso_mounted(str, loop_dev)) { - mount_fs(loop_dev, "Unmount", 1); + int mount = is_iso_mounted(str, loop_dev); + /* it was already present */ + if (mount != -1) { + /* + * if it was mounted, then unmount it. + * if it is was unmounted, just mount it (ie: someone else + * created this loop dev probably without autoclear true) + */ + mount_fs(loop_dev, mount); return; } -#endif fd = open(str, O_RDONLY); r = sd_bus_open_system(&iso_bus); if (r < 0) { @@ -121,39 +152,51 @@ void isomount(const char *str) { "ha{sv}", fd, NULL); - close(fd); if (r < 0) { print_and_warn(error.message, ERR_LINE); goto finish; } sd_bus_message_read(mess, "o", &obj_path); - sd_bus_flush(iso_bus); - mount_fs(obj_path, "Mount", 0); - INFO("calling SetAutoClear on bus."); - r = sd_bus_call_method(iso_bus, - "org.freedesktop.UDisks2", - obj_path, - "org.freedesktop.UDisks2.Loop", - "SetAutoclear", - &error, - NULL, - "ba{sv}", - TRUE, - NULL); - if (r < 0) { - print_and_warn(error.message, ERR_LINE); - } finish: + close(fd); close_bus(&error, mess, iso_bus); } -#ifdef LIBUDEV_PRESENT +static void set_autoclear(const char *loopname) { + sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus_message *mess = NULL; + sd_bus *iso_bus = NULL; + char obj_path[PATH_MAX + 1] = "/org/freedesktop/UDisks2/block_devices/"; + int r; + + r = sd_bus_open_system(&iso_bus); + if (r < 0) { + print_and_warn(strerror(-r), ERR_LINE); + } else { + strcat(obj_path, strrchr(loopname, '/') + 1); + INFO("calling SetAutoClear on bus."); + r = sd_bus_call_method(iso_bus, + "org.freedesktop.UDisks2", + obj_path, + "org.freedesktop.UDisks2.Loop", + "SetAutoclear", + &error, + NULL, + "ba{sv}", + TRUE, + NULL); + if (r < 0) { + print_and_warn(error.message, ERR_LINE); + } + } + close_bus(&error, mess, iso_bus); +} /* * Check if iso is already mounted. * For each /dev/loop device present, calls iso_backing_file on bus. * As soon as it finds a matching backing_file with current file's filename, - * it breaks the cycle and returns 1; + * it breaks the cycle and returns its mounted status; */ static int is_iso_mounted(const char *filename, char loop_dev[PATH_MAX + 1]) { struct udev *tmp_udev; @@ -162,8 +205,8 @@ static int is_iso_mounted(const char *filename, char loop_dev[PATH_MAX + 1]) { struct udev_device *dev; char s[PATH_MAX + 1] = {0}; char resolved_path[PATH_MAX + 1]; - int mount = 0; - + int mount = -1; + realpath(filename, resolved_path); tmp_udev = udev_new(); enumerate = udev_enumerate_new(tmp_udev); @@ -178,7 +221,7 @@ static int is_iso_mounted(const char *filename, char loop_dev[PATH_MAX + 1]) { iso_backing_file(s, loop_dev); udev_device_unref(dev); if (!strcmp(s, resolved_path)) { - mount = 1; + mount = get_mount_point(loop_dev, NULL); break; } } @@ -195,9 +238,9 @@ static void iso_backing_file(char *s, const char *name) { sd_bus_message *mess = NULL; sd_bus *iso_bus = NULL; int r; - const uint8_t bytes = '\0'; + uint8_t bytes = '\0'; char obj_path[PATH_MAX + 1] = "/org/freedesktop/UDisks2/block_devices/"; - + r = sd_bus_open_system(&iso_bus); if (r < 0) { print_and_warn(strerror(-r), ERR_LINE); @@ -248,14 +291,10 @@ int start_monitor(void) { goto fail; } device_mode = DEVMON_READY; - sd_bus_process(bus, NULL); INFO("started device monitor."); return sd_bus_get_fd(bus); fail: - if (!quit) { /* else it is called by program_quit */ - free_device_monitor(); - } device_mode = DEVMON_OFF; return -1; } @@ -346,7 +385,7 @@ static int add_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_err const char *obj = "/org/freedesktop/UDisks2/block_devices/"; char devname[PATH_MAX + 1]; char name[NAME_MAX + 1]; - struct udev_device *dev = NULL; + struct udev_device *dev; r = sd_bus_message_read(m, "o", &path); if (r < 0) { @@ -360,7 +399,6 @@ static int add_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_err sprintf(devname, "/dev/%s", name); r = add_device(dev, devname); udev_device_unref(dev); - print_info("New device connected.", INFO_LINE); if (!quit && device_mode > DEVMON_READY && r != -1) { update_special_mode(number_of_devices, device_mode - 1, my_devices); } @@ -424,7 +462,7 @@ static int change_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_ int present = is_present(devname); if (present != -1) { change_mounted_status(present, devname); - if (!quit && device_mode > DEVMON_READY) { + if (device_mode > DEVMON_READY) { update_special_mode(number_of_devices, device_mode - 1, NULL); } } @@ -496,78 +534,30 @@ static void enumerate_block_devices(void) { udev_enumerate_unref(enumerate); } -/* - * Check through udisks2 for at least 1 mountpoint. - * If there is no mountpoint, device is not mounted. - * If sd_bus_get_property failes with "-EINVAL" error code, - * it means there's no a mountable fs on the device and i won't list it. - */ -static int is_mounted(const char *dev_path) { - sd_bus_error error = SD_BUS_ERROR_NULL; - sd_bus_message *mess = NULL; - int r, ret = 0; - char obj_path[PATH_MAX + 1] = "/org/freedesktop/UDisks2/block_devices/"; - const uint8_t bytes; - - strcat(obj_path, strrchr(dev_path, '/') + 1); - INFO("getting MountPoints property on bus."); - r = sd_bus_get_property(bus, - "org.freedesktop.UDisks2", - obj_path, - "org.freedesktop.UDisks2.Filesystem", - "MountPoints", - &error, - &mess, - "aay"); - if (r < 0) { - ret = -1; - if (r == -EINVAL) { - INFO("not mountable fs. Discarded."); - } else { - WARN(error.message); - } - goto finish; - } - r = sd_bus_message_enter_container(mess, SD_BUS_TYPE_ARRAY, "ay"); - if (r < 0) { - goto fail; - } - r = sd_bus_message_enter_container(mess, SD_BUS_TYPE_ARRAY, "y"); - if (r < 0) { - goto fail; - } - if (sd_bus_message_read(mess, "y", &bytes) > 0) { - ret = 1; - } - goto finish; - -fail: - print_and_warn(strerror(-r), ERR_LINE); - -finish: - close_bus(&error, mess, NULL); - return ret; -} - /* * Getting mountpoint for a device through mtab. */ -static void get_mount_point(const char *dev_path, char *path) { +static int get_mount_point(const char *dev_path, char *path) { struct mntent *part; FILE *mtab; + int ret = 0; if (!(mtab = setmntent("/proc/mounts", "r"))) { WARN("could not find /proc/mounts"); print_info("could not find /proc/mounts.", ERR_LINE); - return; + return -1; } while ((part = getmntent(mtab))) { if ((part->mnt_fsname) && (!strcmp(part->mnt_fsname, dev_path))) { - strcpy(path, part->mnt_dir); + if (path) { + strcpy(path, part->mnt_dir); + } + ret = 1; break; } } endmntent(mtab); + return ret; } /* @@ -579,50 +569,16 @@ static void get_mount_point(const char *dev_path, char *path) { * it moves the tab to the path just before the mountpoint. */ void manage_mount_device(void) { - int mount, r = -1; + int mount; int pos = ps[active].curr_pos; int len = strlen(my_devices[pos]); char *ptr = strchr(my_devices[pos], ','); - char name[PATH_MAX + 1], old_cwd[PATH_MAX + 1]; - char mounted_path[PATH_MAX + 1] = {0}; + char name[PATH_MAX + 1]; - mount = my_devices[pos][len - 1] - '0'; strcpy(name, my_devices[pos]); name[len - strlen(ptr)] = '\0'; - get_mount_point(name, mounted_path); - if (!strcmp(mounted_path, "/")) { - print_info("Cannot unmount root.", ERR_LINE); - } else { - if (mount) { - /* - * before unmount, save old cwd as we'll need - * to chdir anyway to another dir if current cwd - * is inside mounted path. - * If unmount fails, we'll restore our previous cwd. - */ - strcpy(old_cwd, ps[active].my_cwd); - r = check_cwd(mounted_path); - int ret = mount_fs(name, "Unmount", mount); - /* if unmounting was succesful */ - if (ret != -1) { - /* if not active tab was inside mountpoint, move it away */ - if (r) { - change_dir(mounted_path, !active); - } - /* if it was not succesful, restore old_cwd */ - } else { - chdir(old_cwd); - } - /* - * here we don't care about unmount success: - * save back in ps[active].my_cwd, process' check_cwd - * to be sure we carry the right cwd - */ - getcwd(ps[active].my_cwd, PATH_MAX); - } else { - mount_fs(name, "Mount", mount); - } - } + mount = my_devices[pos][len - 1] - '0'; + mount_fs(name, mount); } /* @@ -635,12 +591,19 @@ static int check_cwd(char *mounted_path) { for (int i = 0; i < cont; i++) { if (!strncmp(ps[i].my_cwd, mounted_path, strlen(mounted_path))) { - if (i == active) { - strcpy(mounted_path, dirname(mounted_path)); - chdir(mounted_path); - } else { - ret = 1; - } + ret += 1 + i; + } + } + if (ret) { + strcpy(mounted_path, dirname(mounted_path)); + /* + * if ret == 1 + active means that active tab only + * was inside mounted_path. + * if ret == 3 means that every tab was inside mounted_path; + * in both case we need to change process' cwd. + */ + if (ret == 1 + active || ret == 3) { + chdir(mounted_path); } } return ret; @@ -661,10 +624,9 @@ void manage_enter_device(void) { strcpy(dev_path, my_devices[pos]); dev_path[len - strlen(ptr)] = '\0'; if (!mount) { - ret = mount_fs(dev_path, "Mount", mount); + ret = mount_fs(dev_path, mount); } - if (ret == 1) { - get_mount_point(dev_path, name); + if (ret == 1 && get_mount_point(dev_path, name) != -1) { strcpy(ps[active].my_cwd, name); leave_device_mode(); } @@ -708,27 +670,30 @@ void free_device_monitor(void) { * Check if dev must be ignored, then * check if it is a mountable fs (eg: a dvd reader without a dvd inserted, is NOT a moutable fs), * and its mount status. Then add the device to my_devices. - * If the dev is a loop_dev or if config.automount is == 1 and the dev is not mounted, + * If the dev is not mounted and it is a loop_dev or if config.automount is == 1, * it will mount the device. */ static int add_device(struct udev_device *dev, const char *name) { int mount; uint64_t size; - char s[20]; + char s[20] = {0}; const char *ignore = udev_device_get_property_value(dev, "UDISKS_IGNORE"); + const char *fs_type = udev_device_get_property_value(dev, "ID_FS_TYPE"); - if (ignore && !strcmp(ignore, "1")) { + if (!fs_type || (ignore && !strcmp(ignore, "1"))) { mount = -1; } else { - mount = is_mounted(name); + mount = get_mount_point(name, NULL); } if (mount != -1) { my_devices = safe_realloc((PATH_MAX + 1) * (number_of_devices + 1)); if (!quit) { /* calculates current device size */ - size = strtol(udev_device_get_sysattr_value(dev, "size"), NULL, 10); - size = (size / (uint64_t) 2) * 1024; - change_unit((float)size, s); + if (udev_device_get_sysattr_value(dev, "size")) { + size = strtol(udev_device_get_sysattr_value(dev, "size"), NULL, 10); + size = (size / (uint64_t) 2) * 1024; + change_unit((float)size, s); + } if (udev_device_get_property_value(dev, "ID_MODEL")) { sprintf(my_devices[number_of_devices], "%s, %s, Size: %s, Mounted: %d", name, udev_device_get_property_value(dev, "ID_MODEL"), s, mount); @@ -738,8 +703,10 @@ static int add_device(struct udev_device *dev, const char *name) { } number_of_devices++; INFO("added device."); - if ((device_mode != DEVMON_STARTING) && (!mount && config.automount)) { - mount_fs(name, "Mount", mount); + print_info("New device connected.", INFO_LINE); + int is_loop_dev = !strncmp(name, "/dev/loop", strlen("/dev/loop")); + if (device_mode != DEVMON_STARTING && (!mount && (config.automount || is_loop_dev))) { + mount_fs(name, mount); } } } @@ -780,6 +747,4 @@ static void *safe_realloc(const size_t size) { } return tmp; } - -#endif #endif \ No newline at end of file diff --git a/src/quit_functions.c b/src/quit_functions.c index fc14fec..b435027 100644 --- a/src/quit_functions.c +++ b/src/quit_functions.c @@ -26,7 +26,7 @@ int program_quit(void) { } static void free_everything(void) { -#if defined SYSTEMD_PRESENT && LIBUDEV_PRESENT +#ifdef SYSTEMD_PRESENT free_device_monitor(); #endif free_timer(); diff --git a/src/string_constants.c b/src/string_constants.c index 6a86ace..29f0f0e 100644 --- a/src/string_constants.c +++ b/src/string_constants.c @@ -61,27 +61,40 @@ const char *selected_mess = "There are selected files."; const char *thread_running = "There's already a thread working. This thread will be queued."; const char *quit_with_running_thread = "Queued jobs still running. Waiting..."; -const char *helper_string[] = { "Enter to surf between folders or to open files.", +const char *helper_string[] = { +#ifdef SYSTEMD_PRESENT + "Enter to surf between folders or to open files.", "It will eventually extract your archives, (un)mount your ISO files or install your distro downloaded packages.", +#else + "Enter to surf between folders or to open files. It will eventually extract your archives.", +#endif "',' to enable fast browse mode: it lets you jump between files by just typing their name.", "'h' to trigger the showing of hidden files; 's' to see stat about files in current folder.", "'.' to change files/dirs sorting function: alphabetically (default), by size, by last modified or by type.", +#ifdef OPENSSL_PRESENT "Space to select files. Twice to remove the file from selected files. 'u' to check shasum of current file.", +#else + "Space to select files. Twice to remove the file from selected files.", +#endif +#ifdef LIBCUPS_PRESENT "'v'/'x' to paste/cut, 'b' to compress and 'r' to remove selected files. 'p' to print a file.", +#else + "'v'/'x' to paste/cut, 'b' to compress and 'r' to remove selected files.", +#endif "'g' to switch to bookmarks window. 'e' to add current file to bookmarks/remove it if in bookmarks_mode.", "'o' to rename current file/dir; 'n'/'d' to create new file/dir. 'f' to search (case sensitive) for a file.", "'t' to create new tab (at most one more). 'w' to close tab. Arrow left or right to switch between tabs.", +#ifdef SYSTEMD_PRESENT "'m' to switch to devices tab. 'm' on a device to (un)mount it, enter to move to its mountpoint, mounting it if necessary.", +#endif "You can't close first tab. Use 'q' to quit/leave current mode."}; - + #ifdef SYSTEMD_PRESENT const char *pkg_quest = "Do you really want to install this package? y/N:> "; const char *install_th_wait = "Waiting for package installation to finish..."; const char *package_warn = "Currently there is no check against wrong package arch: it will crash packagekit and ncursesfm."; -#ifdef LIBUDEV_PRESENT const char *device_mode_str = "Choose your desired device to (un)mount it"; #endif -#endif const char *bookmarks_mode_str = "Bookmarks:"; const char *special_mode_title = "q to return to normal mode"; \ No newline at end of file diff --git a/src/timer.c b/src/timer.c index 9803aa6..7a27c9e 100644 --- a/src/timer.c +++ b/src/timer.c @@ -1,15 +1,11 @@ #include "../inc/timer.h" -#ifdef LIBUDEV_PRESENT static void poll_batteries(void); -#endif static int timerfd; -#ifdef LIBUDEV_PRESENT static int num_of_batt; static char ac_path[PATH_MAX + 1], (*batt)[PATH_MAX + 1]; static struct udev *udev; -#endif /* * Create 30s timer and returns its fd to @@ -22,10 +18,8 @@ int start_timer(void) { if (timerfd == -1) { WARN("could not start timer."); } else { -#ifdef LIBUDEV_PRESENT udev = udev_new(); poll_batteries(); -#endif timerValue.it_value.tv_sec = 30; timerValue.it_value.tv_nsec = 0; timerValue.it_interval.tv_sec = 30; @@ -39,7 +33,6 @@ int start_timer(void) { void timer_func(void) { update_time(); -#ifdef LIBUDEV_PRESENT struct udev_device *dev; int perc[num_of_batt]; char name[num_of_batt][10]; @@ -64,22 +57,16 @@ void timer_func(void) { } } update_batt(online, perc, num_of_batt, name); -#else - update_batt(-1, NULL, 0, NULL); -#endif } void free_timer(void) { close(timerfd); -#ifdef LIBUDEV_PRESENT if (batt) { free(batt); } udev_unref(udev); -#endif } -#ifdef LIBUDEV_PRESENT static void poll_batteries(void) { struct udev_enumerate *enumerate; struct udev_list_entry *devices, *dev_list_entry; @@ -104,5 +91,4 @@ static void poll_batteries(void) { udev_device_unref(dev); } udev_enumerate_unref(enumerate); -} -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/src/ui_functions.c b/src/ui_functions.c index 8abdce9..33410c8 100644 --- a/src/ui_functions.c +++ b/src/ui_functions.c @@ -101,6 +101,12 @@ void screen_end(void) { delete_tab(i); } delwin(info_win); + /* + * needed: this way any print_info won't do anything: + * to avoid a print_info from a worker thread while we're leaving + * or after we left the program. + */ + info_win = NULL; if (helper_win) { delwin(helper_win); } @@ -585,7 +591,7 @@ static void info_print(const char *str, int i) { * then writes on the pipe the address of its heap-allocated struct info_msg. */ void print_info(const char *str, int line) { - if (!quit) { + if (info_win) { struct info_msg *info; int len = 1 + strlen(info_win_str[line]); @@ -714,7 +720,7 @@ int main_poll(WINDOW *win) { /* we received an event from pipe to print a info msg */ info_refresh(main_p[i].fd); break; -#if defined SYSTEMD_PRESENT && LIBUDEV_PRESENT +#ifdef SYSTEMD_PRESENT case DEVMON_IX: /* we received a bus event */ devices_bus_process();