CAMLprim value caml_extunix_readlinkat(value v_dirfd, value v_name) { CAMLparam2(v_dirfd, v_name); CAMLlocal1(v_link); char* res; char* p = caml_stat_alloc(caml_string_length(v_name) + 1); strcpy(p, String_val(v_name)); caml_enter_blocking_section(); res = readlinkat_malloc(Int_val(v_dirfd), p); caml_leave_blocking_section(); caml_stat_free(p); if (res == NULL) uerror("readlinkat", v_name); v_link = caml_copy_string(res); free(res); CAMLreturn(v_link); }
static int fd_copy_symlink(int df, const char *from, const struct stat *st, int dt, const char *to) { _cleanup_free_ char *target = NULL; int r; assert(from); assert(st); assert(to); r = readlinkat_malloc(df, from, &target); if (r < 0) return r; if (symlinkat(target, dt, to) < 0) return -errno; if (fchownat(dt, to, st->st_uid, st->st_gid, AT_SYMLINK_NOFOLLOW) < 0) return -errno; return 0; }
/* Joins /proc/[pid]/fd/ and /proc/[pid]/fdinfo/ into the following lines: * 0:/dev/pts/23 * pos: 0 * flags: 0100002 * * 1:/dev/pts/23 * pos: 0 * flags: 0100002 * * 2:/dev/pts/23 * pos: 0 * flags: 0100002 * EOF */ static int compose_open_fds(pid_t pid, char **open_fds) { _cleanup_closedir_ DIR *proc_fd_dir = NULL; _cleanup_close_ int proc_fdinfo_fd = -1; _cleanup_free_ char *buffer = NULL; _cleanup_fclose_ FILE *stream = NULL; const char *fddelim = "", *path; struct dirent *dent = NULL; size_t size = 0; int r = 0; assert(pid >= 0); assert(open_fds != NULL); path = procfs_file_alloca(pid, "fd"); proc_fd_dir = opendir(path); if (!proc_fd_dir) return -errno; proc_fdinfo_fd = openat(dirfd(proc_fd_dir), "../fdinfo", O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC|O_PATH); if (proc_fdinfo_fd < 0) return -errno; stream = open_memstream(&buffer, &size); if (!stream) return -ENOMEM; FOREACH_DIRENT(dent, proc_fd_dir, return -errno) { _cleanup_fclose_ FILE *fdinfo = NULL; _cleanup_free_ char *fdname = NULL; char line[LINE_MAX]; int fd; r = readlinkat_malloc(dirfd(proc_fd_dir), dent->d_name, &fdname); if (r < 0) return r; fprintf(stream, "%s%s:%s\n", fddelim, dent->d_name, fdname); fddelim = "\n"; /* Use the directory entry from /proc/[pid]/fd with /proc/[pid]/fdinfo */ fd = openat(proc_fdinfo_fd, dent->d_name, O_NOFOLLOW|O_CLOEXEC|O_RDONLY); if (fd < 0) continue; fdinfo = fdopen(fd, "re"); if (fdinfo == NULL) { close(fd); continue; } FOREACH_LINE(line, fdinfo, break) { fputs(line, stream); if (!endswith(line, "\n")) fputc('\n', stream); } } errno = 0; stream = safe_fclose(stream); if (errno != 0) return -errno; *open_fds = buffer; buffer = NULL; return 0; }