<commit_before>#include <stdio.h>
#include <fcntl.h>
#include <malloc.h>
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
#include <string.h>
#include <signal.h>
#include <syslog.h>
#include <poll.h>
#include <pwd.h>
#include <libudev.h>
#include <mntent.h>
#include <sys/inotify.h>
#include <sys/wait.h>
#include <libmount/libmount.h>
#include <errno.h>

#define VERSION_STR "0.4.1"

enum {
    DEVICE_VOLUME,
    DEVICE_CD,
    DEVICE_UNK
};

enum {
    QUIRK_NONE = 0,
    QUIRK_OWNER_FIX = (1<<0),
    QUIRK_UTF8_FLAG = (1<<1)
};

typedef struct device_t  {
    int                  type;
    char                *filesystem;
    char                *devnode;
    char                *mountpoint;
    struct udev_device  *udev;
} device_t;

typedef struct fs_quirk_t {
    char *name;
    int quirks;
} fs_quirk_t;

typedef struct blacklist_entry_t {
    char *uuid;  
} blacklist_entry_t;

#define MOUNT_PATH      "/media/"
#define CALLBACK_PATH   NULL
#define OPT_FMT         "uid=%i,gid=%i"
#define MAX_DEVICES     20

/* Static global structs */

static struct libmnt_table     *g_fstab;
static struct libmnt_table     *g_mtab;
static struct device_t         *g_devices[MAX_DEVICES];
static FILE                    *g_lockfd;
static int                      g_running;
static int                      g_uid;
static int                      g_gid;

/* Functions declaration */
char * s_strdup(const char *str);
int lock_create(int pid);
int lock_remove(void);
int lock_exist(void);
struct libmnt_fs * fstab_search (struct libmnt_table *tab, struct udev_device *device);
int device_has_media(struct device_t *device);
int filesystem_needs_id_fix(char *fs);
char * device_create_mountpoint(struct device_t *device);
void device_list_clear(void);
int device_register(struct device_t *dev);
void device_destroy(struct device_t *dev);
struct device_t * device_search(char *devnode);
struct device_t * device_new(struct udev_device *dev);
int device_mount(struct udev_device *dev);
int device_unmount(struct udev_device *dev);
int device_change(struct udev_device *dev);
int force_reload_table (struct libmnt_table **table, const char *path);
void mount_plugged_devices(struct udev *udev);
void sig_handler(int signal);
int daemonize(void);

/* A less stupid s_strdup */

char *
s_strdup(const char *str)
{
    if (!str)
        return NULL;
    return (char *)strdup(str);
}

/* Locking functions */

#define LOCK_PATH "/run/ldm.pid"

int
lock_create (int pid)
{
    g_lockfd = fopen(LOCK_PATH, "w+");
    if (!g_lockfd)
        return 0;
    fprintf(g_lockfd, "%d", pid);
    fclose(g_lockfd);
    return 1;
}

int
lock_remove (void)
{
    return (remove(LOCK_PATH) == 0);
}

int
lock_exist (void)
{
    FILE *f = fopen(LOCK_PATH, "r");
    if (f)
        fclose(f);
    return (f != NULL);
}

/* Spawn helper */

int
spawn_helper (const char *helper, const char *action, char *mountpoint)
{
    pid_t child_pid;
    int ret;

    if (!helper)
        return 0;

    child_pid = fork();

    if (child_pid < 0)
        return 0;

    if (child_pid > 0) {
        wait(&ret);
        /* Return the exit code or 0 if something went wrong */
        return WIFEXITED(ret) ? WEXITSTATUS(ret) : 0;
    }

    execvp(helper, (char *[]){ (char *)helper, (char *)action, mountpoint, NULL });
    /* Should never reach this */
    syslog(LOG_ERR, "Could not execute \"%s\"", helper);

    return 0;
}

/* Convenience function for fstab handling */

#define FSTAB_PATH  "/etc/fstab"
#define MTAB_PATH   "/proc/self/mounts"

struct libmnt_fs *
fstab_search (struct libmnt_table *tab, struct udev_device *udev)
{
    struct libmnt_fs *ret;
    const char *tmp;

    /* Try matching the /dev node */
    tmp = udev_device_get_devnode(udev);
    ret = mnt_table_find_source(tab, tmp? tmp: "", MNT_ITER_FORWARD);
    if (ret) return ret;
    /* Try matching the uuid */
    tmp = udev_device_get_property_value(udev, "ID_FS_UUID");
    ret = mnt_table_find_tag(tab, "UUID", tmp? tmp: "", MNT_ITER_FORWARD);
    if (tmp && ret) return ret;
    /* Try matching the label */
    tmp = udev_device_get_property_value(udev, "ID_FS_LABEL");
    ret = mnt_table_find_tag(tab, "LABEL", tmp? tmp: "", MNT_ITER_FORWARD);
    if (tmp && ret) return ret;

    return NULL;
}
<commit_msg>Drop root permissions before executing the callback. Handle execvp failure properly. Cherrypicked from @JohnJocoo pull request.<commit_after>#include <stdio.h>
#include <fcntl.h>
#include <malloc.h>
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
#include <string.h>
#include <signal.h>
#include <syslog.h>
#include <poll.h>
#include <pwd.h>
#include <libudev.h>
#include <mntent.h>
#include <sys/inotify.h>
#include <sys/wait.h>
#include <libmount/libmount.h>
#include <errno.h>

#define VERSION_STR "0.4.1"

enum {
    DEVICE_VOLUME,
    DEVICE_CD,
    DEVICE_UNK
};

enum {
    QUIRK_NONE = 0,
    QUIRK_OWNER_FIX = (1<<0),
    QUIRK_UTF8_FLAG = (1<<1)
};

typedef struct device_t  {
    int                  type;
    char                *filesystem;
    char                *devnode;
    char                *mountpoint;
    struct udev_device  *udev;
} device_t;

typedef struct fs_quirk_t {
    char *name;
    int quirks;
} fs_quirk_t;

typedef struct blacklist_entry_t {
    char *uuid;  
} blacklist_entry_t;

#define MOUNT_PATH      "/media/"
#define CALLBACK_PATH   NULL
#define OPT_FMT         "uid=%i,gid=%i"
#define MAX_DEVICES     20

/* Static global structs */

static struct libmnt_table     *g_fstab;
static struct libmnt_table     *g_mtab;
static struct device_t         *g_devices[MAX_DEVICES];
static FILE                    *g_lockfd;
static int                      g_running;
static int                      g_uid;
static int                      g_gid;

/* Functions declaration */
char * s_strdup(const char *str);
int lock_create(int pid);
int lock_remove(void);
int lock_exist(void);
struct libmnt_fs * fstab_search (struct libmnt_table *tab, struct udev_device *device);
int device_has_media(struct device_t *device);
int filesystem_needs_id_fix(char *fs);
char * device_create_mountpoint(struct device_t *device);
void device_list_clear(void);
int device_register(struct device_t *dev);
void device_destroy(struct device_t *dev);
struct device_t * device_search(char *devnode);
struct device_t * device_new(struct udev_device *dev);
int device_mount(struct udev_device *dev);
int device_unmount(struct udev_device *dev);
int device_change(struct udev_device *dev);
int force_reload_table (struct libmnt_table **table, const char *path);
void mount_plugged_devices(struct udev *udev);
void sig_handler(int signal);
int daemonize(void);

/* A less stupid s_strdup */

char *
s_strdup(const char *str)
{
    if (!str)
        return NULL;
    return (char *)strdup(str);
}

/* Locking functions */

#define LOCK_PATH "/run/ldm.pid"

int
lock_create (int pid)
{
    g_lockfd = fopen(LOCK_PATH, "w+");
    if (!g_lockfd)
        return 0;
    fprintf(g_lockfd, "%d", pid);
    fclose(g_lockfd);
    return 1;
}

int
lock_remove (void)
{
    return (remove(LOCK_PATH) == 0);
}

int
lock_exist (void)
{
    FILE *f = fopen(LOCK_PATH, "r");
    if (f)
        fclose(f);
    return (f != NULL);
}

/* Spawn helper */

int
spawn_helper (const char *helper, const char *action, char *mountpoint)
{
    pid_t child_pid;
    int ret;

    if (!helper)
        return 0;

    child_pid = fork();

    if (child_pid < 0)
        return 0;

    if (child_pid > 0) {
        wait(&ret);
        /* Return the exit code or 0 if something went wrong */
        return WIFEXITED(ret) ? WEXITSTATUS(ret) : 0;
    }

    /* Drop the root priviledges. Oh and the bass too. */
    setgid(g_gid);
    setuid(g_uid);

    execvp(helper, (char *[]){ (char *)helper, (char *)action, mountpoint, NULL });
    /* Should never reach this */
    syslog(LOG_ERR, "Could not execute \"%s\"", helper);
    /* Die */
    _Exit(1);

    return 0xdeadbeef;
}

/* Convenience function for fstab handling */

#define FSTAB_PATH  "/etc/fstab"
#define MTAB_PATH   "/proc/self/mounts"

struct libmnt_fs *
fstab_search (struct libmnt_table *tab, struct udev_device *udev)
{
    struct libmnt_fs *ret;
    const char *tmp;

    /* Try matching the /dev node */
    tmp = udev_device_get_devnode(udev);
    ret = mnt_table_find_source(tab, tmp? tmp: "", MNT_ITER_FORWARD);
    if (ret) return ret;
    /* Try matching the uuid */
    tmp = udev_device_get_property_value(udev, "ID_FS_UUID");
    ret = mnt_table_find_tag(tab, "UUID", tmp? tmp: "", MNT_ITER_FORWARD);
    if (tmp && ret) return ret;
    /* Try matching the label */
    tmp = udev_device_get_property_value(udev, "ID_FS_LABEL");
    ret = mnt_table_find_tag(tab, "LABEL", tmp? tmp: "", MNT_ITER_FORWARD);
    if (tmp && ret) return ret;

    return NULL;
}

{'fraction_non_alphanumeric': 0.12221464301955434, 'fraction_numerical': 0.0048885857207821735, 'mean_word_length': 3.195040534096328, 'pattern_counts': {'":': 0, '<': 47, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1123246', 'n_tokens_mistral': 3269, 'n_tokens_neox': 3165, 'n_words': 824}