void phantom_unix_fs_init() { hal_mutex_init( &mm, "rootfs" ); add_mount( "/dev", "devfs", &dev_fs ); add_mount( "/proc", "procfs", &proc_fs ); add_mount( "udp://", "udpfs", &udp_fs ); add_mount( "tcp://", "tcpfs", &tcp_fs ); }
int usys_mount( int *err, uuprocess_t *u, const char *source, const char *target, const char *fstype, int flags, const void *data ) { (void) u; (void) flags; (void) fstype; uufs_t *fs = 0; if( strcmp( data, "procfs" ) ) fs = &proc_fs; if( strcmp( data, "devfs" ) ) fs = &dev_fs; // TODO connect to real FS code and devices if( fs == 0 ) { *err = ENOTBLK; return -1; } *err = add_mount( target, source, fs ); return *err ? -1 : 0; }
static int add_root_mount(void) { _cleanup_free_ char *what = NULL; const char *opts; if (isempty(arg_root_what)) { log_debug("Could not find a root= entry on the kernel command line."); return 0; } what = fstab_node_to_udev_node(arg_root_what); if (!path_is_absolute(what)) { log_debug("Skipping entry what=%s where=/sysroot type=%s", what, strna(arg_root_fstype)); return 0; } if (!arg_root_options) opts = arg_root_rw > 0 ? "rw" : "ro"; else if (arg_root_rw >= 0 || !fstab_test_option(arg_root_options, "ro\0" "rw\0")) opts = strjoina(arg_root_options, ",", arg_root_rw > 0 ? "rw" : "ro"); else opts = arg_root_options; log_debug("Found entry what=%s where=/sysroot type=%s", what, strna(arg_root_fstype)); return add_mount(what, "/sysroot", arg_root_fstype, opts, 1, false, false, false, SPECIAL_INITRD_ROOT_FS_TARGET, "/proc/cmdline"); }
static int probe_and_add_mount( const char *id, const char *what, const char *where, bool rw, const char *description, const char *post) { _cleanup_blkid_free_probe_ blkid_probe b = NULL; const char *fstype; int r; assert(id); assert(what); assert(where); assert(description); if (path_is_mount_point(where, true) <= 0 && dir_is_empty(where) <= 0) { log_debug("%s already populated, ignoring.", where); return 0; } /* Let's check the partition type here, so that we know * whether to do LUKS magic. */ errno = 0; b = blkid_new_probe_from_filename(what); if (!b) { if (errno == 0) return log_oom(); log_error_errno(errno, "Failed to allocate prober: %m"); return -errno; } blkid_probe_enable_superblocks(b, 1); blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE); errno = 0; r = blkid_do_safeprobe(b); if (r == -2 || r == 1) /* no result or uncertain */ return 0; else if (r != 0) { if (errno == 0) errno = EIO; log_error_errno(errno, "Failed to probe %s: %m", what); return -errno; } blkid_probe_lookup_value(b, "TYPE", &fstype, NULL); return add_mount( id, what, where, fstype, rw, description, post); }
static int parse_fstab(void) { FILE *f; int r = 0; struct mntent *me; errno = 0; f = setmntent("/etc/fstab", "r"); if (!f) { if (errno == ENOENT) return 0; log_error("Failed to open /etc/fstab: %m"); return -errno; } while ((me = getmntent(f))) { char _cleanup_free_ *where = NULL, *what = NULL; int k; what = fstab_node_to_udev_node(me->mnt_fsname); where = strdup(me->mnt_dir); if (!what || !where) { r = log_oom(); goto finish; } if (is_path(where)) path_kill_slashes(where); log_debug("Found entry what=%s where=%s type=%s", what, where, me->mnt_type); if (streq(me->mnt_type, "swap")) k = add_swap(what, me); else { bool noauto, nofail, automount, isbind, isnetwork; noauto = !!hasmntopt(me, "noauto"); nofail = !!hasmntopt(me, "nofail"); automount = hasmntopt(me, "comment=systemd.automount") || hasmntopt(me, "x-systemd.automount"); isbind = mount_is_bind(me); isnetwork = mount_is_network(me); k = add_mount(what, where, me->mnt_type, me->mnt_opts, me->mnt_passno, false, noauto, nofail, automount, isbind, isnetwork, "/etc/fstab"); } if (k < 0) r = k; } finish: endmntent(f); return r; }
static int add_usr_mount(void) { _cleanup_free_ char *what = NULL; const char *opts; if (!arg_usr_what && !arg_usr_fstype && !arg_usr_options) return 0; if (arg_root_what && !arg_usr_what) { arg_usr_what = strdup(arg_root_what); if (!arg_usr_what) return log_oom(); } if (arg_root_fstype && !arg_usr_fstype) { arg_usr_fstype = strdup(arg_root_fstype); if (!arg_usr_fstype) return log_oom(); } if (arg_root_options && !arg_usr_options) { arg_usr_options = strdup(arg_root_options); if (!arg_usr_options) return log_oom(); } if (!arg_usr_what) return 0; what = fstab_node_to_udev_node(arg_usr_what); if (!path_is_absolute(what)) { log_debug("Skipping entry what=%s where=/sysroot/usr type=%s", what, strna(arg_usr_fstype)); return -1; } if (!arg_usr_options) opts = arg_root_rw > 0 ? "rw" : "ro"; else if (!fstab_test_option(arg_usr_options, "ro\0" "rw\0")) opts = strjoina(arg_usr_options, ",", arg_root_rw > 0 ? "rw" : "ro"); else opts = arg_usr_options; log_debug("Found entry what=%s where=/sysroot/usr type=%s", what, strna(arg_usr_fstype)); return add_mount(what, "/sysroot/usr", arg_usr_fstype, opts, 1, false, false, false, SPECIAL_INITRD_ROOT_FS_TARGET, "/proc/cmdline"); }
static void add_mount_inside(char *base, char *src, char *dst, char *type, unsigned long f, void *d) { int rc; _free_ char *target = NULL; rc = asprintf(&target, "%s%s", base, dst); if (rc < 0) fail_printf("OOM"); add_mount(src, target, type, f, d); }
static int parse_fstab(void) { FILE *f; int r = 0; struct mntent *me; errno = 0; f = setmntent("/etc/fstab", "r"); if (!f) { if (errno == ENOENT) return 0; log_error("Failed to open /etc/fstab: %m"); return -errno; } while ((me = getmntent(f))) { char *where, *what; int k; what = fstab_node_to_udev_node(me->mnt_fsname); if (!what) { r = log_oom(); goto finish; } where = strdup(me->mnt_dir); if (!where) { r = log_oom(); free(what); goto finish; } if (is_path(where)) path_kill_slashes(where); log_debug("Found entry what=%s where=%s type=%s", what, where, me->mnt_type); if (streq(me->mnt_type, "swap")) k = add_swap(what, me); else k = add_mount(what, where, me); free(what); free(where); if (k < 0) r = k; } finish: endmntent(f); return r; }
int mount_all(const char *jailroot) { struct library *l; struct mount *m; avl_for_each_element(&libraries, l, avl) add_mount(l->path, 1, -1); avl_for_each_element(&mounts, m, avl) if (mount_bind(jailroot, m->path, m->readonly, m->error)) return -1; return 0; }
int fuse_mnt_add_mount(const char *progname, const char *fsname, const char *mnt, const char *type, const char *opts) { int res; if (!mtab_needs_update(mnt)) return 0; res = add_mount(progname, fsname, mnt, type, opts); if (res == -1) res = add_mount_legacy(progname, fsname, mnt, type, opts); return res; }
static int mount_fuse(const char *mnt, int flags) { int res; int fd; const char *dev = FUSE_DEV; const char *type = "fuse"; struct stat stbuf; res = check_perm(mnt, &stbuf); if(res == -1) return -1; fd = open(dev, O_RDWR); if(fd == -1) { int status; pid_t pid = fork(); if(pid == 0) { setuid(0); execl("/sbin/modprobe", "/sbin/modprobe", "fuse", NULL); exit(1); } if(pid != -1) waitpid(pid, &status, 0); fd = open(dev, O_RDWR); } if(fd == -1) { fprintf(stderr, "%s: unable to open fuse device %s: %s\n", progname, dev, strerror(errno)); return -1; } res = do_mount(dev, mnt, type, stbuf.st_mode & S_IFMT, fd, flags); if(res == -1) return -1; res = add_mount(dev, mnt, type); if(res == -1) { umount(mnt); return -1; } return fd; }
errno_t auto_mount( const char *name, uufs_t *fs, char *out_mnt_path, size_t outsz, int flags ) { static int am_index = 0; static char mpath[32]; snprintf( mpath, sizeof(mpath), "/amnt%d", am_index ++ ); SHOW_INFO( 0, "Partition %s mounted @ %s", name, mpath ); if( outsz && out_mnt_path ) strlcpy( out_mnt_path, mpath, outsz ); errno_t rc = add_mount( mpath, name, fs ); if( !rc && (flags & AUTO_MOUNT_FLAG_AUTORUN) ) hal_start_kernel_thread_arg( auto_run_thread, strdup(mpath) ); return rc; }
static void hal_property_modified(LibHalContext *ctx, const char *udi, const char *key, dbus_bool_t is_removed, dbus_bool_t is_added) { if (!strcmp(key, "volume.is_mounted")) { if (libhal_device_get_property_bool(ctx, udi, "volume.is_mounted", NULL)) { char *mountpoint = libhal_device_get_property_string( ctx, udi, "volume.mount_point", NULL); if (!strncmp(MEDIA_DIR, mountpoint, strlen(MEDIA_DIR))) { add_mount(udi, mountpoint); } if (mountpoint) libhal_free_string(mountpoint); } else { remove_mount(udi); } update_status(); } }
static int parse_fstab(const char *prefix, bool initrd) { _cleanup_free_ char *fstab_path = NULL; FILE *f; int r = 0; struct mntent *me; fstab_path = strjoin(strempty(prefix), "/etc/fstab", NULL); if (!fstab_path) return log_oom(); f = setmntent(fstab_path, "r"); if (!f) { if (errno == ENOENT) return 0; log_error("Failed to open %s/etc/fstab: %m", strempty(prefix)); return -errno; } while ((me = getmntent(f))) { _cleanup_free_ char *where = NULL, *what = NULL; int k; if (initrd && !mount_in_initrd(me)) continue; what = fstab_node_to_udev_node(me->mnt_fsname); where = strjoin(strempty(prefix), me->mnt_dir, NULL); if (!what || !where) { r = log_oom(); goto finish; } if (is_path(where)) path_kill_slashes(where); log_debug("Found entry what=%s where=%s type=%s", what, where, me->mnt_type); if (streq(me->mnt_type, "swap")) k = add_swap(what, me); else { bool noauto, nofail, automount, isbind; const char *pre, *pre2, *post, *online; noauto = !!hasmntopt(me, "noauto"); nofail = !!hasmntopt(me, "nofail"); automount = hasmntopt(me, "comment=systemd.automount") || hasmntopt(me, "x-systemd.automount"); isbind = mount_is_bind(me); if (initrd) { pre = pre2 = online = NULL; post = SPECIAL_INITRD_FS_TARGET; } else if (mount_in_initrd(me)) { pre = pre2 = online = NULL; post = SPECIAL_INITRD_ROOT_FS_TARGET; } else if (mount_is_network(me)) { pre = SPECIAL_REMOTE_FS_PRE_TARGET; pre2 = SPECIAL_NETWORK_TARGET; online = SPECIAL_NETWORK_ONLINE_TARGET; post = SPECIAL_REMOTE_FS_TARGET; } else { pre = SPECIAL_LOCAL_FS_PRE_TARGET; pre2 = online = NULL; post = SPECIAL_LOCAL_FS_TARGET; } k = add_mount(what, where, me->mnt_type, me->mnt_opts, me->mnt_passno, noauto, nofail, automount, isbind, pre, pre2, online, post, fstab_path); } if (k < 0) r = k; } finish: endmntent(f); return r; }
static int mount_fuse(const char *mnt, const char *opts, char *devfd) { int res; int fd; char *dev; struct stat stbuf; char *type = NULL; char *source = NULL; char *mnt_opts = NULL; const char *real_mnt = mnt; int mountpoint_fd = -1; fd = devfd ? check_fuse_device(devfd, &dev) : open_fuse_device(&dev); if (fd == -1) return -1; drop_privs(); read_conf(); if (getuid() != 0 && mount_max != -1) { int mount_count = count_fuse_fs(); if (mount_count >= mount_max) { fprintf(stderr, "%s: too many FUSE filesystems mounted; mount_max=N can be set in /etc/fuse.conf\n", progname); goto fail_close_fd; } } res = check_version(dev); if (res != -1) { res = check_perm(&real_mnt, &stbuf, &mountpoint_fd); restore_privs(); if (res != -1) res = do_mount(real_mnt, &type, stbuf.st_mode & S_IFMT, fd, opts, dev, &source, &mnt_opts, stbuf.st_size); } else restore_privs(); if (mountpoint_fd != -1) close(mountpoint_fd); if (res == -1) goto fail_close_fd; res = chdir("/"); if (res == -1) { fprintf(stderr, "%s: failed to chdir to '/'\n", progname); goto fail_close_fd; } if (geteuid() == 0) { res = add_mount(source, mnt, type, mnt_opts); if (res == -1) { /* Can't clean up mount in a non-racy way */ goto fail_close_fd; } } out_free: free(source); free(type); free(mnt_opts); free(dev); return fd; fail_close_fd: close(fd); fd = -1; goto out_free; }
void add_mount_from_spec(char *spec) { int rc; size_t c; _free_ char **opts = NULL; _free_ char *tmp = strdup(spec); if (tmp == NULL) fail_printf("OOM"); c = split_str(tmp, &opts, ","); if (c == 0) fail_printf("Invalid mount spec '%s'", spec); if (strncmp(opts[0], "bind", 4) == 0) { _free_ char *src = NULL; _free_ char *dst = NULL; if (c < 3) fail_printf("Invalid mount spec '%s'", spec); src = realpath(opts[1], NULL); if (src == NULL) sysf_printf("realpath()"); dst = realpath(opts[2], NULL); if (dst == NULL) sysf_printf("realpath()"); add_mount(src, dst, NULL, MS_BIND, NULL); if (strncmp(opts[0], "bind-ro", 8) == 0) add_mount(src, dst, NULL, MS_REMOUNT | MS_BIND | MS_RDONLY, NULL); } else if (strncmp(opts[0], "aufs", 5) == 0) { _free_ char *dst = NULL; _free_ char *overlay = NULL; _free_ char *aufs_opts = NULL; if (c < 3) fail_printf("Invalid mount spec '%s'", spec); overlay = realpath(opts[1], NULL); if (overlay == NULL) sysf_printf("realpath()"); dst = realpath(opts[2], NULL); if (dst == NULL) sysf_printf("realpath()"); rc = asprintf(&aufs_opts, "br:%s=rw:%s=ro", overlay, dst); if (rc < 0) fail_printf("OOM"); add_mount(NULL, dst, "aufs", 0, aufs_opts); } else if (strncmp(opts[0], "overlay", 8) == 0) { _free_ char *dst = NULL; _free_ char *overlay = NULL; _free_ char *workdir = NULL; _free_ char *overlayfs_opts = NULL; if (c < 4) fail_printf("Invalid mount spec '%s'", spec); overlay = realpath(opts[1], NULL); if (overlay == NULL) sysf_printf("realpath()"); dst = realpath(opts[2], NULL); if (dst == NULL) sysf_printf("realpath()"); workdir = realpath(opts[3], NULL); if (workdir == NULL) sysf_printf("realpath()"); #ifdef HAVE_AUFS rc = asprintf(&overlayfs_opts, "br:%s=rw:%s=ro", overlay, dst); if (rc < 0) fail_printf("OOM"); add_mount(NULL, dst, "aufs", 0, overlayfs_opts); #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) rc = asprintf(&overlayfs_opts, "upperdir=%s,lowerdir=%s,workdir=%s", overlay, dst, workdir); if (rc < 0) fail_printf("OOM"); add_mount(NULL, dst, "overlay", 0, overlayfs_opts); #else fail_printf("The 'overlay' mount type is not supported"); #endif } else if (strncmp(opts[0], "tmp", 4) == 0) { _free_ char *dst = NULL; if (c < 2) fail_printf("Invalid mount spec '%s'", spec); dst = realpath(opts[1], NULL); if (dst == NULL) sysf_printf("realpath()"); add_mount("tmpfs", dst, "tmpfs", 0, NULL); } else { fail_printf("Invalid mount type '%s'", opts[0]); } }
void add_mount_from_spec(const char *spec) { int rc; size_t c; _free_ char **opts = NULL; _free_ char *tmp = strdup(spec); if (tmp == NULL) fail_printf("OOM"); c = split_str(tmp, &opts, ","); if (c == 0) fail_printf("Invalid mount spec '%s'", spec); if (strncmp(opts[0], "bind", 4) == 0) { _free_ char *src = NULL; _free_ char *dst = NULL; if (c < 3) fail_printf("Invalid mount spec '%s'", spec); src = realpath(opts[1], NULL); if (src == NULL) sysf_printf("realpath()"); dst = realpath(opts[2], NULL); if (dst == NULL) sysf_printf("realpath()"); add_mount(&mounts, src, dst, "bind", MS_BIND, NULL); if (strncmp(opts[0], "bind-ro", 8) == 0) add_mount(&mounts, src, dst, "bind-ro", MS_REMOUNT | MS_BIND | MS_RDONLY, NULL); } else if (strncmp(opts[0], "aufs", 5) == 0) { _free_ char *dst = NULL; _free_ char *overlay = NULL; _free_ char *aufs_opts = NULL; if (c < 3) fail_printf("Invalid mount spec '%s'", spec); overlay = realpath(opts[1], NULL); if (overlay == NULL) sysf_printf("realpath()"); dst = realpath(opts[2], NULL); if (dst == NULL) sysf_printf("realpath()"); rc = asprintf(&aufs_opts, "br:%s=rw:%s=ro", overlay, dst); if (rc < 0) fail_printf("OOM"); add_mount(&mounts, NULL, dst, "aufs", 0, aufs_opts); } else if (strncmp(opts[0], "overlay", 8) == 0) { _free_ char *dst = NULL; _free_ char *overlay = NULL; _free_ char *workdir = NULL; if (c < 4) fail_printf("Invalid mount spec '%s'", spec); overlay = realpath(opts[1], NULL); if (overlay == NULL) sysf_printf("realpath()"); dst = realpath(opts[2], NULL); if (dst == NULL) sysf_printf("realpath()"); workdir = realpath(opts[3], NULL); if (workdir == NULL) sysf_printf("realpath()"); add_overlay_mount(&mounts, overlay, dst, workdir); } else if (strncmp(opts[0], "tmp", 4) == 0) { _free_ char *dst = NULL; if (c < 2) fail_printf("Invalid mount spec '%s'", spec); dst = realpath(opts[1], NULL); if (dst == NULL) sysf_printf("realpath()"); add_mount(&mounts, "tmpfs", dst, "tmpfs", 0, NULL); } else { fail_printf("Invalid mount type '%s'", opts[0]); } }
static int parse_fstab(bool initrd) { _cleanup_endmntent_ FILE *f = NULL; const char *fstab_path; struct mntent *me; int r = 0; fstab_path = initrd ? "/sysroot/etc/fstab" : "/etc/fstab"; f = setmntent(fstab_path, "re"); if (!f) { if (errno == ENOENT) return 0; log_error_errno(errno, "Failed to open %s: %m", fstab_path); return -errno; } while ((me = getmntent(f))) { _cleanup_free_ char *where = NULL, *what = NULL; bool noauto, nofail; int k; if (initrd && !mount_in_initrd(me)) continue; what = fstab_node_to_udev_node(me->mnt_fsname); if (!what) return log_oom(); if (is_device_path(what) && path_is_read_only_fs("sys") > 0) { log_info("Running in a container, ignoring fstab device entry for %s.", what); continue; } where = initrd ? strappend("/sysroot/", me->mnt_dir) : strdup(me->mnt_dir); if (!where) return log_oom(); if (is_path(where)) path_kill_slashes(where); noauto = fstab_test_yes_no_option(me->mnt_opts, "noauto\0" "auto\0"); nofail = fstab_test_yes_no_option(me->mnt_opts, "nofail\0" "fail\0"); log_debug("Found entry what=%s where=%s type=%s nofail=%s noauto=%s", what, where, me->mnt_type, yes_no(noauto), yes_no(nofail)); if (streq(me->mnt_type, "swap")) k = add_swap(what, me, noauto, nofail); else { bool automount; const char *post; automount = fstab_test_option(me->mnt_opts, "comment=systemd.automount\0" "x-systemd.automount\0"); if (initrd) post = SPECIAL_INITRD_FS_TARGET; else if (mount_in_initrd(me)) post = SPECIAL_INITRD_ROOT_FS_TARGET; else if (mount_is_network(me)) post = SPECIAL_REMOTE_FS_TARGET; else post = SPECIAL_LOCAL_FS_TARGET; k = add_mount(what, where, me->mnt_type, me->mnt_opts, me->mnt_passno, noauto, nofail, automount, post, fstab_path); } if (k < 0) r = k; } return r; }
static int add_automount( const char *id, const char *what, const char *where, const char *fstype, bool rw, const char *options, const char *description, usec_t timeout) { _cleanup_free_ char *unit = NULL, *lnk = NULL; _cleanup_free_ char *opt, *p = NULL; _cleanup_fclose_ FILE *f = NULL; int r; assert(id); assert(where); assert(description); if (options) opt = strjoin(options, ",noauto", NULL); else opt = strdup("noauto"); if (!opt) return log_oom(); r = add_mount(id, what, where, fstype, rw, opt, description, NULL); if (r < 0) return r; r = unit_name_from_path(where, ".automount", &unit); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); p = strjoin(arg_dest, "/", unit, NULL); if (!p) return log_oom(); f = fopen(p, "wxe"); if (!f) return log_error_errno(errno, "Failed to create unit file %s: %m", unit); fprintf(f, "# Automatically generated by systemd-gpt-auto-generator\n\n" "[Unit]\n" "Description=%s\n" "Documentation=man:systemd-gpt-auto-generator(8)\n" "[Automount]\n" "Where=%s\n" "TimeoutIdleSec=%lld\n", description, where, (unsigned long long)timeout / USEC_PER_SEC); r = fflush_and_check(f); if (r < 0) return log_error_errno(r, "Failed to write unit file %s: %m", p); lnk = strjoin(arg_dest, "/" SPECIAL_LOCAL_FS_TARGET ".wants/", unit, NULL); if (!lnk) return log_oom(); mkdir_parents_label(lnk, 0755); if (symlink(p, lnk) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", lnk); return 0; }
static int mount_fuse(const char *mnt, const char *opts) { int res; int fd; char *dev; struct stat stbuf; char *type = NULL; char *source = NULL; char *mnt_opts = NULL; const char *real_mnt = mnt; int currdir_fd = -1; int mountpoint_fd = -1; fd = open_fuse_device(&dev); if (fd == -1) return -1; drop_privs(); read_conf(); if (getuid() != 0 && mount_max != -1) { int mount_count = count_fuse_fs(); if (mount_count >= mount_max) { fprintf(stderr, "%s: too many FUSE filesystems mounted; mount_max=N can be set in /etc/fuse.conf\n", progname); close(fd); return -1; } } res = check_version(dev); if (res != -1) { res = check_perm(&real_mnt, &stbuf, &currdir_fd, &mountpoint_fd); restore_privs(); if (res != -1) res = do_mount(real_mnt, &type, stbuf.st_mode & S_IFMT, fd, opts, dev, &source, &mnt_opts, stbuf.st_size); } else restore_privs(); if (currdir_fd != -1) { fchdir(currdir_fd); close(currdir_fd); } if (mountpoint_fd != -1) close(mountpoint_fd); if (res == -1) { close(fd); return -1; } if (geteuid() == 0) { res = add_mount(source, mnt, type, mnt_opts); if (res == -1) { umount2(mnt, 2); /* lazy umount */ close(fd); return -1; } } free(source); free(type); free(mnt_opts); free(dev); return fd; }
int add_path_and_deps(const char *path, int readonly, int error, int lib) { assert(path != NULL); if (lib == 0 && path[0] != '/') { ERROR("%s is not an absolute path\n", path); return error; } char *map = NULL; int fd, ret = -1; if (path[0] == '/') { if (avl_find(&mounts, path)) return 0; fd = open(path, O_RDONLY|O_CLOEXEC); if (fd == -1) return error; add_mount(path, readonly, error); } else { if (avl_find(&libraries, path)) return 0; char *fullpath; fd = lib_open(&fullpath, path); if (fd == -1) return error; if (fullpath) { alloc_library(fullpath, path); free(fullpath); } } struct stat s; if (fstat(fd, &s) == -1) { ERROR("fstat(%s) failed: %s\n", path, strerror(errno)); ret = error; goto out; } if (!S_ISREG(s.st_mode)) { ret = 0; goto out; } /* too small to be an ELF or a script -> "normal" file */ if (s.st_size < 4) { ret = 0; goto out; } map = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (map == MAP_FAILED) { ERROR("failed to mmap %s\n", path); ret = -1; goto out; } if (map[0] == '#' && map[1] == '!') { ret = add_script_interp(path, map, s.st_size); goto out; } if (map[0] == ELFMAG0 && map[1] == ELFMAG1 && map[2] == ELFMAG2 && map[3] == ELFMAG3) { ret = elf_load_deps(path, map); goto out; } ret = 0; out: if (fd >= 0) close(fd); if (map) munmap(map, s.st_size); return ret; }