diff options
author | Andy Fiddaman <omnios@citrus-it.co.uk> | 2019-11-19 11:04:46 +0000 |
---|---|---|
committer | Andy Fiddaman <omnios@citrus-it.co.uk> | 2020-01-24 08:04:05 +0000 |
commit | a02120c4550735e4c33259ff2671a5ef9d06c5cc (patch) | |
tree | b3e98992c422f4688a44e7e76ffee23c0c92c7fb /usr/src/lib/libproc | |
parent | e3bf7d5a53699b06ef4e776789b585322c4bf8ed (diff) | |
download | illumos-gate-a02120c4550735e4c33259ff2671a5ef9d06c5cc.tar.gz |
12046 Provide /proc/<PID>/fdinfo/
Reviewed by: John Levon <john.levon@joyent.com>
Reviewed by: Robert Mustacchi <rm@fingolfin.org>
Approved by: Dan McDonald <danmcd@joyent.com>
Diffstat (limited to 'usr/src/lib/libproc')
-rw-r--r-- | usr/src/lib/libproc/Makefile | 6 | ||||
-rw-r--r-- | usr/src/lib/libproc/Makefile.com | 7 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/Pcontrol.c | 2 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/Pcontrol.h | 3 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/Pcore.c | 12 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/Pfdinfo.c | 113 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/Pgcore.c | 15 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/libproc.h | 19 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/mapfile-vers | 7 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/proc_fd.c | 350 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/proc_fd.h | 32 |
11 files changed, 472 insertions, 94 deletions
diff --git a/usr/src/lib/libproc/Makefile b/usr/src/lib/libproc/Makefile index 1e42afebbb..ad175b0e9d 100644 --- a/usr/src/lib/libproc/Makefile +++ b/usr/src/lib/libproc/Makefile @@ -22,6 +22,7 @@ # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # +# Copyright 2020 OmniOS Community Edition (OmniOSce) Association. # include ../Makefile.lib @@ -34,11 +35,10 @@ clean := TARGET= clean clobber := TARGET= clobber delete := TARGET= delete install := TARGET= install -lint := TARGET= lint _msg := TARGET= _msg package := TARGET= package -LIBRARY= libproc.a +LIBRARY= libproc.a TEXT_DOMAIN= SUNW_OST_OSLIB XGETFLAGS= -a POFILE= $(LIBRARY:.a=.po) @@ -61,7 +61,7 @@ $(ROOTHDRDIR)/%: common/% .KEEP_STATE: -all clean clobber delete install lint package: $(SUBDIRS) +all clean clobber delete install package: $(SUBDIRS) install_h: $(ROOTHDRS) diff --git a/usr/src/lib/libproc/Makefile.com b/usr/src/lib/libproc/Makefile.com index 7ed72f97ed..9bc99f1b40 100644 --- a/usr/src/lib/libproc/Makefile.com +++ b/usr/src/lib/libproc/Makefile.com @@ -24,6 +24,7 @@ # Copyright (c) 2013 by Delphix. All rights reserved. # # Copyright (c) 2018, Joyent, Inc. +# Copyright 2020 OmniOS Community Edition (OmniOSce) Association. LIBRARY = libproc.a VERS = .1 @@ -70,6 +71,7 @@ CMNOBJS = \ proc_get_info.o \ proc_names.o \ proc_arg.o \ + proc_fd.o \ proc_set.o \ proc_stdio.o @@ -84,13 +86,12 @@ include ../../Makefile.rootfs SRCS = $(CMNOBJS:%.o=../common/%.c) $(ISAOBJS:%.o=%.c) -LIBS = $(DYNLIB) $(LINTLIB) +LIBS = $(DYNLIB) LDLIBS += -lrtld_db -lelf -lctf -lc CSTD = $(CSTD_GNU99) CPPFLAGS += $($(MACH64)_CPPFLAGS) SRCDIR = ../common -$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC) CFLAGS += $(CCVERBOSE) CPPFLAGS += -I$(SRCDIR) @@ -114,8 +115,6 @@ DYNFLAGS += $(BNODIRECT) $(ZDIRECT) $(ZLAZYLOAD) all: $(LIBS) -lint: lintcheck - # include library targets include ../../Makefile.targ diff --git a/usr/src/lib/libproc/common/Pcontrol.c b/usr/src/lib/libproc/common/Pcontrol.c index 9af5026014..5a135aef17 100644 --- a/usr/src/lib/libproc/common/Pcontrol.c +++ b/usr/src/lib/libproc/common/Pcontrol.c @@ -27,6 +27,7 @@ * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. * Copyright (c) 2013 by Delphix. All rights reserved. * Copyright 2015, Joyent, Inc. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ #include <assert.h> @@ -1201,6 +1202,7 @@ Pfree(struct ps_prochandle *P) while (P->num_fd > 0) { fd_info_t *fip = list_next(&P->fd_head); list_unlink(fip); + proc_fdinfo_free(fip->fd_info); free(fip); P->num_fd--; } diff --git a/usr/src/lib/libproc/common/Pcontrol.h b/usr/src/lib/libproc/common/Pcontrol.h index e05ff8b430..a2a875e145 100644 --- a/usr/src/lib/libproc/common/Pcontrol.h +++ b/usr/src/lib/libproc/common/Pcontrol.h @@ -26,6 +26,7 @@ * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. * Copyright (c) 2013 by Delphix. All rights reserved. * Copyright 2018 Joyent, Inc. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ #ifndef _PCONTROL_H @@ -147,7 +148,7 @@ typedef struct lwp_info { /* per-lwp information from core file */ typedef struct fd_info { plist_t fd_list; /* linked list */ - prfdinfo_t fd_info; /* fd info */ + prfdinfo_t *fd_info; /* fd info */ } fd_info_t; typedef struct core_info { /* information specific to core files */ diff --git a/usr/src/lib/libproc/common/Pcore.c b/usr/src/lib/libproc/common/Pcore.c index dadda5b2a7..0532346922 100644 --- a/usr/src/lib/libproc/common/Pcore.c +++ b/usr/src/lib/libproc/common/Pcore.c @@ -27,6 +27,7 @@ * Copyright (c) 2018, Joyent, Inc. All rights reserved. * Copyright (c) 2013 by Delphix. All rights reserved. * Copyright 2015 Gary Mills + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ #include <sys/types.h> @@ -50,6 +51,7 @@ #include "Pcontrol.h" #include "P32ton.h" #include "Putil.h" +#include "proc_fd.h" #ifdef __x86 #include "Pcore_linux.h" #endif @@ -754,7 +756,7 @@ err: static int note_fdinfo(struct ps_prochandle *P, size_t nbytes) { - prfdinfo_t prfd; + prfdinfo_core_t prfd; fd_info_t *fip; if ((nbytes < sizeof (prfd)) || @@ -767,7 +769,13 @@ note_fdinfo(struct ps_prochandle *P, size_t nbytes) dprintf("Pgrab_core: failed to add NT_FDINFO\n"); return (-1); } - (void) memcpy(&fip->fd_info, &prfd, sizeof (prfd)); + if (fip->fd_info == NULL) { + if (proc_fdinfo_from_core(&prfd, &fip->fd_info) != 0) { + dprintf("Pgrab_core: failed to convert NT_FDINFO\n"); + return (-1); + } + } + return (0); } diff --git a/usr/src/lib/libproc/common/Pfdinfo.c b/usr/src/lib/libproc/common/Pfdinfo.c index 27264091f8..c822ec8434 100644 --- a/usr/src/lib/libproc/common/Pfdinfo.c +++ b/usr/src/lib/libproc/common/Pfdinfo.c @@ -14,6 +14,7 @@ */ /* * Copyright (c) 2013 Joyent, Inc. All Rights reserved. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ #include <limits.h> @@ -27,6 +28,7 @@ #include "libproc.h" #include "Pcontrol.h" +#include "proc_fd.h" /* * Pfdinfo.c - obtain open file information. @@ -51,10 +53,13 @@ Pfd2info(struct ps_prochandle *P, int fd) } for (i = 0; i < P->num_fd; i++, fip = list_next(fip)) { - if (fip->fd_info.pr_fd == fd) { + if (fip->fd_info == NULL) + continue; + + if (fip->fd_info->pr_fd == fd) { return (fip); } - if (fip->fd_info.pr_fd < fd) { + if (fip->fd_info->pr_fd < fd) { break; } } @@ -63,12 +68,34 @@ Pfd2info(struct ps_prochandle *P, int fd) if ((fip = calloc(1, sizeof (*fip))) == NULL) return (NULL); - fip->fd_info.pr_fd = fd; list_link(fip, next ? next : (void *)&(P->fd_head)); P->num_fd++; return (fip); } +static int +fdwalk_cb(const prfdinfo_t *info, void *arg) +{ + struct ps_prochandle *P = arg; + fd_info_t *fip; + + fip = Pfd2info(P, info->pr_fd); + if (fip == NULL) { + errno = ENOMEM; + return (-1); + } + + if (fip->fd_info == NULL) + fip->fd_info = proc_fdinfo_dup(info); + + if (fip->fd_info == NULL) { + errno = ENOMEM; + return (-1); + } + + return (0); +} + /* * Attempt to load the open file information from a live process. */ @@ -81,83 +108,13 @@ load_fdinfo(struct ps_prochandle *P) * This is an edge case it isn't worth adding additional state to * to eliminate. */ - if (P->num_fd > 0) { + if (P->num_fd > 0) return; - } - if (P->state != PS_DEAD && P->state != PS_IDLE) { - char dir_name[PATH_MAX]; - char path[PATH_MAX]; - struct dirent *ent; - DIR *dirp; - int fd; - - /* - * Try to get the path information first. - */ - (void) snprintf(dir_name, sizeof (dir_name), - "%s/%d/path", procfs_path, (int)P->pid); - dirp = opendir(dir_name); - if (dirp == NULL) { - return; - } - ent = NULL; - while ((ent = readdir(dirp)) != NULL) { - fd_info_t *fip; - prfdinfo_t *info; - int len; - struct stat64 stat; - - if (!isdigit(ent->d_name[0])) - continue; - - fd = atoi(ent->d_name); - - fip = Pfd2info(P, fd); - info = &fip->fd_info; - info->pr_fd = fd; - - if (pr_fstat64(P, fd, &stat) == 0) { - info->pr_mode = stat.st_mode; - info->pr_uid = stat.st_uid; - info->pr_gid = stat.st_gid; - info->pr_major = major(stat.st_dev); - info->pr_minor = minor(stat.st_dev); - info->pr_rmajor = major(stat.st_rdev); - info->pr_rminor = minor(stat.st_rdev); - info->pr_size = stat.st_size; - info->pr_ino = stat.st_ino; - } - - info->pr_fileflags = pr_fcntl(P, fd, F_GETXFL, 0); - info->pr_fdflags = pr_fcntl(P, fd, F_GETFD, 0); - info->pr_offset = pr_llseek(P, fd, 0, SEEK_CUR); - - /* attempt to determine the path to it */ - switch (info->pr_mode & S_IFMT) { - case S_IFDOOR: - case S_IFSOCK: - /* not applicable */ - len = -1; - break; - default: - (void) snprintf(path, sizeof (path), - "%s/%d/path/%d", procfs_path, (int)P->pid, - fd); - len = readlink(path, info->pr_path, - sizeof (info->pr_path) - 1); - break; - } - - if (len < 0) { - info->pr_path[0] = 0; - } else { - info->pr_path[len] = 0; - } - } - (void) closedir(dirp); + if (P->state == PS_DEAD || P->state == PS_IDLE) + return; - } + proc_fdwalk(P->pid, fdwalk_cb, P); } int @@ -174,7 +131,7 @@ Pfdinfo_iter(struct ps_prochandle *P, proc_fdinfo_f *func, void *cd) for (fip = list_prev(&P->fd_head); fip != (void *)&P->fd_head && fip != NULL; fip = list_prev(fip)) { - if ((rv = func(cd, &fip->fd_info)) != 0) + if ((rv = func(cd, fip->fd_info)) != 0) return (rv); } return (0); diff --git a/usr/src/lib/libproc/common/Pgcore.c b/usr/src/lib/libproc/common/Pgcore.c index 64ef98065b..e4d4437baa 100644 --- a/usr/src/lib/libproc/common/Pgcore.c +++ b/usr/src/lib/libproc/common/Pgcore.c @@ -27,6 +27,7 @@ * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. * Copyright 2018 Joyent, Inc. * Copyright (c) 2013 by Delphix. All rights reserved. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ #define _STRUCTURED_PROC 1 @@ -49,6 +50,7 @@ #include "Pcontrol.h" #include "P32ton.h" +#include "proc_fd.h" typedef enum { STR_NONE, @@ -611,12 +613,19 @@ new_per_lwp(void *data, const lwpstatus_t *lsp, const lwpsinfo_t *lip) } static int -iter_fd(void *data, prfdinfo_t *fdinfo) +iter_fd(void *data, const prfdinfo_t *fdinfo) { fditer_t *iter = data; + prfdinfo_core_t core; + int ret = 0; - if (write_note(iter->fd_fd, NT_FDINFO, fdinfo, - sizeof (*fdinfo), iter->fd_doff) != 0) + if (proc_fdinfo_to_core(fdinfo, &core) != 0) + return (1); + + ret = write_note(iter->fd_fd, NT_FDINFO, &core, + sizeof (core), iter->fd_doff); + + if (ret != 0) return (1); return (0); } diff --git a/usr/src/lib/libproc/common/libproc.h b/usr/src/lib/libproc/common/libproc.h index f783026060..cdf789a621 100644 --- a/usr/src/lib/libproc/common/libproc.h +++ b/usr/src/lib/libproc/common/libproc.h @@ -28,7 +28,7 @@ * Copyright 2019 Joyent, Inc. * Copyright (c) 2013 by Delphix. All rights reserved. * Copyright 2019, Carlos Neira <cneirabustos@gmail.com> - * Copyright 2019 OmniOS Community Edition (OmniOSce) Association. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ /* @@ -469,6 +469,18 @@ extern int proc_walk(proc_walk_f *, void *, int); #define PR_WALK_INCLUDE_SYS 0x80000000 /* include SSYS processes */ /* + * File descriptor iteration. + */ +typedef int proc_fdwalk_f(const prfdinfo_t *, void *); +extern int proc_fdwalk(pid_t, proc_fdwalk_f *, void *); + +/* + * fdinfo iteration. + */ +typedef int proc_fdinfowalk_f(uint_t, const void *, size_t, void *); +extern int proc_fdinfowalk(const prfdinfo_t *, proc_fdinfowalk_f *, void *); + +/* * Determine if an lwp is in a set as returned from proc_arg_xgrab(). */ extern int proc_lwp_in_set(const char *, lwpid_t); @@ -706,6 +718,9 @@ extern void proc_free_priv(prpriv_t *); extern int proc_get_psinfo(pid_t, psinfo_t *); extern int proc_get_status(pid_t, pstatus_t *); extern int proc_get_secflags(pid_t, prsecflags_t **); +extern prfdinfo_t *proc_get_fdinfo(pid_t, int); +extern const void *proc_fdinfo_misc(const prfdinfo_t *, uint_t, size_t *); +extern void proc_fdinfo_free(prfdinfo_t *); /* * Utility functions for debugging tools to convert numeric fault, @@ -774,7 +789,7 @@ extern int proc_finistdio(void); /* * Iterate over all open files. */ -typedef int proc_fdinfo_f(void *, prfdinfo_t *); +typedef int proc_fdinfo_f(void *, const prfdinfo_t *); extern int Pfdinfo_iter(struct ps_prochandle *, proc_fdinfo_f *, void *); #ifdef __cplusplus diff --git a/usr/src/lib/libproc/common/mapfile-vers b/usr/src/lib/libproc/common/mapfile-vers index 6e5ff2c21a..1da5918393 100644 --- a/usr/src/lib/libproc/common/mapfile-vers +++ b/usr/src/lib/libproc/common/mapfile-vers @@ -24,7 +24,7 @@ # Copyright 2018 Joyent, Inc. # Copyright (c) 2013 by Delphix. All rights reserved. # Copyright (c) 2019 Carlos Neira <cneirabustos@gmail.com> -# Copyright 2019 OmniOS Community Edition (OmniOSce) Association. +# Copyright 2020 OmniOS Community Edition (OmniOSce) Association. # # @@ -207,6 +207,10 @@ SYMBOL_VERSION SUNWprivate_1.1 { proc_arg_xpsinfo; proc_content2str; proc_dmodelname; + proc_fdinfo_free; + proc_fdinfo_misc; + proc_fdinfowalk; + proc_fdwalk; proc_finistdio; proc_fltname; proc_fltset2str; @@ -214,6 +218,7 @@ SYMBOL_VERSION SUNWprivate_1.1 { proc_free_priv; proc_get_auxv; proc_get_cred; + proc_get_fdinfo; proc_get_priv; proc_get_psinfo; proc_get_secflags; diff --git a/usr/src/lib/libproc/common/proc_fd.c b/usr/src/lib/libproc/common/proc_fd.c new file mode 100644 index 0000000000..e491934c16 --- /dev/null +++ b/usr/src/lib/libproc/common/proc_fd.c @@ -0,0 +1,350 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/proc.h> +#include <sys/sysmacros.h> + +#include <libgen.h> +#include <limits.h> +#include <alloca.h> +#include <unistd.h> +#include <string.h> +#include <strings.h> +#include <fcntl.h> +#include <ctype.h> +#include <errno.h> +#include <dirent.h> + +#include "Pcontrol.h" + +/* + * Walk all file descriptors open for a process and call func() for each. + */ +int +proc_fdwalk(pid_t pid, proc_fdwalk_f *func, void *arg) +{ + struct dirent *dirent; + DIR *fddir; + char *dir; + int ret = 0; + + if (asprintf(&dir, "%s/%d/fd", procfs_path, (int)pid) == -1) + return (-1); + + if ((fddir = opendir(dir)) == NULL) { + free(dir); + return (-1); + } + + free(dir); + + while ((dirent = readdir(fddir)) != NULL) { + prfdinfo_t *info; + char *errptr; + int fd; + + if (!isdigit(dirent->d_name[0])) + continue; + + fd = (int)strtol(dirent->d_name, &errptr, 10); + if (errptr != NULL && *errptr != '\0') + continue; + + if ((info = proc_get_fdinfo(pid, fd)) == NULL) + continue; + + ret = func(info, arg); + + free(info); + + if (ret != 0) + break; + } + + (void) closedir(fddir); + return (ret); +} + +int +proc_fdinfowalk(const prfdinfo_t *info, proc_fdinfowalk_f *func, void *arg) +{ + off_t off = offsetof(prfdinfo_t, pr_misc); + int ret = 0; + + for (;;) { + const pr_misc_header_t *misc; + uint_t type; + size_t size; + + misc = (pr_misc_header_t *)((uint8_t *)info + off); + + /* Found terminating record */ + if (misc->pr_misc_size == 0) + break; + + off += misc->pr_misc_size; + + type = misc->pr_misc_type; + size = misc->pr_misc_size - sizeof (pr_misc_header_t); + misc++; + + ret = func(type, misc, size, arg); + + if (ret != 0) + break; + } + + return (ret); +} + +prfdinfo_t * +proc_get_fdinfo(pid_t pid, int fd) +{ + prfdinfo_t *info = NULL; + char *fname; + uint_t retries; + int ifd, err = EIO; + + if (asprintf(&fname, "%s/%d/fdinfo/%d", + procfs_path, (int)pid, fd) == -1) { + return (NULL); + } + + if ((ifd = open(fname, O_RDONLY)) == -1) { + free(fname); + return (NULL); + } + + free(fname); + + /* + * There is a race between stat()-ing the file and reading from + * it where the size may change. To protect against that, we + * walk the returned data to ensure that it is properly + * terminated. If not, increase the buffer size and try again. + */ + + for (retries = 1; retries < 5; retries++) { + struct stat st; + off_t off; + size_t l; + + if (fstat(ifd, &st) == -1) { + err = errno; + break; + } + + st.st_size *= retries; + + if ((info = reallocf(info, st.st_size)) == NULL) { + err = errno; + break; + } + + if ((l = read(ifd, info, st.st_size)) == -1) { + err = errno; + break; + } + + /* Walk the data to check that is properly terminated. */ + + off = offsetof(prfdinfo_t, pr_misc); + + while (off <= l - sizeof (pr_misc_header_t)) { + pr_misc_header_t *misc; + + misc = (pr_misc_header_t *)((uint8_t *)info + off); + + if (misc->pr_misc_size == 0) { + /* Found terminator record */ + (void) close(ifd); + return (info); + } + + /* Next record */ + off += misc->pr_misc_size; + } + } + + (void) close(ifd); + free(info); + + errno = err; + + return (NULL); +} + +typedef struct proc_fdinfo_misc_cbdata { + uint_t type; + const void *data; + size_t len; +} pfm_data_t; + +static int +proc_fdinfo_misc_cb(uint_t type, const void *data, size_t len, void *datap) +{ + pfm_data_t *cb = (pfm_data_t *)datap; + + if (type == cb->type) { + cb->data = data; + cb->len = len; + return (1); + } + return (0); +} + +const void * +proc_fdinfo_misc(const prfdinfo_t *info, uint_t type, size_t *buflen) +{ + pfm_data_t cb; + + cb.data = NULL; + cb.type = type; + + (void) proc_fdinfowalk(info, proc_fdinfo_misc_cb, (void *)&cb); + + if (cb.data != NULL) { + if (buflen != NULL) + *buflen = cb.len; + + return (cb.data); + } + + return (NULL); +} + +static int +proc_fdinfo_dup_cb(uint_t type, const void *data, size_t len, void *datap) +{ + size_t *sz = (size_t *)datap; + + *sz += len + sizeof (pr_misc_header_t); + return (0); +} + + +prfdinfo_t * +proc_fdinfo_dup(const prfdinfo_t *old) +{ + prfdinfo_t *new; + size_t sz = offsetof(prfdinfo_t, pr_misc); + + /* Determine the size of the miscellaneous items */ + (void) proc_fdinfowalk(old, proc_fdinfo_dup_cb, (void *)&sz); + + /* Add the size of the terminator record */ + sz += sizeof (pr_misc_header_t); + + if ((new = calloc(1, sz)) == NULL) + return (NULL); + + bcopy(old, new, sz); + + return (new); +} + +void +proc_fdinfo_free(prfdinfo_t *info) +{ + free(info); +} + +/* + * Convert a prfdinfo_core_t to prfdinfo_t + */ +int +proc_fdinfo_from_core(const prfdinfo_core_t *core, prfdinfo_t **infop) +{ + prfdinfo_t *info; + size_t len, slen = 0; + + len = offsetof(prfdinfo_t, pr_misc) + sizeof (pr_misc_header_t); + if (*core->pr_path != '\0') { + slen = strlen(core->pr_path) + 1; + len += PRFDINFO_ROUNDUP(slen) + sizeof (pr_misc_header_t); + } + + if ((info = calloc(1, len)) == NULL) + return (-1); + + *infop = info; + + info->pr_fd = core->pr_fd; + info->pr_mode = core->pr_mode; + info->pr_uid = core->pr_uid; + info->pr_gid = core->pr_gid; + info->pr_major = core->pr_major; + info->pr_minor = core->pr_minor; + info->pr_rmajor = core->pr_rmajor; + info->pr_rminor = core->pr_rminor; + info->pr_size = core->pr_size; + info->pr_ino = core->pr_ino; + info->pr_fileflags = core->pr_fileflags; + info->pr_fdflags = core->pr_fdflags; + info->pr_offset = core->pr_offset; + + if (slen != 0) { + pr_misc_header_t *misc; + + misc = (pr_misc_header_t *)&info->pr_misc; + + misc->pr_misc_size = sizeof (*misc) + PRFDINFO_ROUNDUP(slen); + misc->pr_misc_type = PR_PATHNAME; + misc++; + bcopy(core->pr_path, misc, slen); + } + + return (0); +} + +/* + * Convert a prfdinfo_t to prfdinfo_core_t + */ +int +proc_fdinfo_to_core(const prfdinfo_t *info, prfdinfo_core_t *core) +{ + const char *path; + size_t pathl; + + bzero(core, sizeof (*core)); + + core->pr_fd = info->pr_fd; + core->pr_mode = info->pr_mode; + core->pr_uid = info->pr_uid; + core->pr_gid = info->pr_gid; + core->pr_major = info->pr_major; + core->pr_minor = info->pr_minor; + core->pr_rmajor = info->pr_rmajor; + core->pr_rminor = info->pr_rminor; + core->pr_size = info->pr_size; + core->pr_ino = info->pr_ino; + core->pr_fileflags = info->pr_fileflags; + core->pr_fdflags = info->pr_fdflags; + core->pr_offset = info->pr_offset; + + path = proc_fdinfo_misc(info, PR_PATHNAME, &pathl); + if (path != NULL) { + /* + * Rather than provide a truncated path in the pr_path field + * just leave it empty if the path will not fit. + */ + if (pathl <= sizeof (core->pr_path) - 1) + bcopy(path, core->pr_path, pathl + 1); + } + + return (0); +} diff --git a/usr/src/lib/libproc/common/proc_fd.h b/usr/src/lib/libproc/common/proc_fd.h new file mode 100644 index 0000000000..0ada83fca7 --- /dev/null +++ b/usr/src/lib/libproc/common/proc_fd.h @@ -0,0 +1,32 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. + */ + +#ifndef _PROC_FD_H +#define _PROC_FD_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Private functions */ +extern int proc_fdinfo_from_core(const prfdinfo_core_t *, prfdinfo_t **); +extern int proc_fdinfo_to_core(const prfdinfo_t *, prfdinfo_core_t *); +extern prfdinfo_t *proc_fdinfo_dup(const prfdinfo_t *); + +#ifdef __cplusplus +} +#endif + +#endif /* _PROC_FD_H */ |