]> git.saurik.com Git - apple/libc.git/blobdiff - darwin/proc_listpidspath.c
Libc-997.1.1.tar.gz
[apple/libc.git] / darwin / proc_listpidspath.c
diff --git a/darwin/proc_listpidspath.c b/darwin/proc_listpidspath.c
deleted file mode 100644 (file)
index 2ee883f..0000000
+++ /dev/null
@@ -1,612 +0,0 @@
-/*
- * Copyright (c) 2007, 2008 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/fcntl.h>
-#include <sys/errno.h>
-#include <sys/param.h>
-#include <sys/mount.h>
-#include <libproc.h>
-
-
-typedef struct {
-       // process IDs
-       int                             *pids;
-       int                             pids_count;
-       size_t                          pids_size;
-
-       // threads
-       uint64_t                        *threads;
-       int                             thr_count;
-       size_t                          thr_size;
-
-       // open file descriptors
-       struct proc_fdinfo              *fds;
-       int                             fds_count;
-       size_t                          fds_size;
-
-       // file/volume of interest
-       struct stat                     match_stat;
-
-       // flags
-       uint32_t                        flags;
-
-} fdOpenInfo, *fdOpenInfoRef;
-
-
-/*
- * check_init
- */
-static fdOpenInfoRef
-check_init(const char *path, uint32_t flags)
-{
-       fdOpenInfoRef   info;
-       int             status;
-
-       info = malloc(sizeof(*info));
-       if (!info)
-               return NULL;
-
-       info->pids              = NULL;
-       info->pids_count        = 0;
-       info->pids_size         = 0;
-
-       info->threads           = NULL;
-       info->thr_count         = 0;
-       info->thr_size          = 0;
-
-       info->fds               = NULL;
-       info->fds_count         = 0;
-       info->fds_size          = 0;
-
-       status = stat(path, &info->match_stat);
-       if (status == -1) {
-               goto fail;
-       }
-
-       info->flags             = flags;
-
-       return info;
-
-    fail :
-
-       free(info);
-       return NULL;
-}
-
-
-/*
- * check_free
- */
-static void
-check_free(fdOpenInfoRef info)
-{
-       if (info->pids != NULL) {
-               free(info->pids);
-       }
-
-       if (info->threads != NULL) {
-               free(info->threads);
-       }
-
-       if (info->fds != NULL) {
-               free(info->fds);
-       }
-
-       free(info);
-
-       return;
-}
-
-
-/*
- * check_file
- *   check if a process vnode is of interest
- *
- *   in  : vnode stat(2)
- *   out : -1 if error
- *          0 if no match
- *          1 if match
- */
-static int
-check_file(fdOpenInfoRef info, struct vinfo_stat *sb)
-{
-       if (sb->vst_dev == 0) {
-               // if no info
-               return 0;
-       }
-
-       if (sb->vst_dev != info->match_stat.st_dev) {
-               // if not the requested filesystem
-               return 0;
-       }
-
-       if (!(info->flags & PROC_LISTPIDSPATH_PATH_IS_VOLUME) &&
-           (sb->vst_ino != info->match_stat.st_ino)) {
-               // if not the requested file
-               return 0;
-       }
-
-       return 1;
-}
-
-
-/*
- * check_process_vnodes
- *   check [process] current working directory
- *   check [process] root directory
- *
- *   in  : pid
- *   out : -1 if error
- *          0 if no match
- *          1 if match
- */
-static int
-check_process_vnodes(fdOpenInfoRef info, int pid)
-{
-       int                             buf_used;
-       int                             status;
-       struct proc_vnodepathinfo       vpi;
-
-       buf_used = proc_pidinfo(pid, PROC_PIDVNODEPATHINFO, 0, &vpi, sizeof(vpi));
-       if (buf_used <= 0) {
-               if (errno == ESRCH) {
-                       // if the process is gone
-                       return 0;
-               }
-               return -1;
-       } else if (buf_used < sizeof(vpi)) {
-               // if we didn't get enough information
-               return -1;
-       }
-
-       // processing current working directory
-       status = check_file(info, &vpi.pvi_cdir.vip_vi.vi_stat);
-       if (status != 0) {
-               // if error or match
-               return status;
-       }
-
-       // processing root directory
-       status = check_file(info, &vpi.pvi_rdir.vip_vi.vi_stat);
-       if (status != 0) {
-               // if error or match
-               return status;
-       }
-
-       return 0;
-}
-
-
-/*
- * check_process_text
- *   check [process] text (memory)
- *
- *   in  : pid
- *   out : -1 if error
- *          0 if no match
- *          1 if match
- */
-static int
-check_process_text(fdOpenInfoRef info, int pid)
-{
-       uint64_t        a       = 0;
-       int             status;
-
-       while (1) {     // for all memory regions
-               int                             buf_used;
-               struct proc_regionwithpathinfo  rwpi;
-
-               // processing next address
-               buf_used = proc_pidinfo(pid, PROC_PIDREGIONPATHINFO, a, &rwpi, sizeof(rwpi));
-               if (buf_used <= 0) {
-                       if ((errno == ESRCH) || (errno == EINVAL)) {
-                               // if no more text information is available for this process.
-                               break;
-                       }
-                       return -1;
-               } else if (buf_used < sizeof(rwpi)) {
-                       // if we didn't get enough information
-                       return -1;
-               }
-
-               status = check_file(info, &rwpi.prp_vip.vip_vi.vi_stat);
-               if (status != 0) {
-                       // if error or match
-                       return status;
-               }
-
-               a = rwpi.prp_prinfo.pri_address + rwpi.prp_prinfo.pri_size;
-       }
-
-       return 0;
-}
-
-
-/*
- * check_process_fds
- *   check [process] open file descriptors
- *
- *   in  : pid
- *   out : -1 if error
- *          0 if no match
- *          1 if match
- */
-static int
-check_process_fds(fdOpenInfoRef info, int pid)
-{
-       int     buf_used;
-       int     i;
-       int     status;
-
-       // get list of open file descriptors
-       buf_used = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0);
-       if (buf_used <= 0) {
-               return -1;
-       }
-
-       while (1) {
-               if (buf_used > info->fds_size) {
-                       // if we need to allocate [more] space
-                       while (buf_used > info->fds_size) {
-                               info->fds_size += (sizeof(struct proc_fdinfo) * 32);
-                       }
-
-                       if (info->fds == NULL) {
-                               info->fds = malloc(info->fds_size);
-                       } else {
-                               info->fds = reallocf(info->fds, info->fds_size);
-                       }
-                       if (info->fds == NULL) {
-                               return -1;
-                       }
-               }
-
-               buf_used = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, info->fds, info->fds_size);
-               if (buf_used <= 0) {
-                       return -1;
-               }
-
-               if ((buf_used + sizeof(struct proc_fdinfo)) >= info->fds_size) {
-                       // if not enough room in the buffer for an extra fd
-                       buf_used = info->fds_size + sizeof(struct proc_fdinfo);
-                       continue;
-               }
-
-               info->fds_count = buf_used / sizeof(struct proc_fdinfo);
-               break;
-       }
-
-       // iterate through each file descriptor
-       for (i = 0; i < info->fds_count; i++) {
-               struct proc_fdinfo      *fdp;
-
-               fdp = &info->fds[i];
-               switch (fdp->proc_fdtype) {
-                       case PROX_FDTYPE_VNODE : {
-                               int                     buf_used;
-                               struct vnode_fdinfo     vi;
-
-                               buf_used = proc_pidfdinfo(pid, fdp->proc_fd, PROC_PIDFDVNODEINFO, &vi, sizeof(vi));
-                               if (buf_used <= 0) {
-                                       if (errno == ENOENT) {
-                                               /*
-                                                * The file descriptor's vnode may have been revoked. This is a
-                                                * bit of a hack, since an ENOENT error might not always mean the
-                                                * descriptor's vnode has been revoked. As the libproc API
-                                                * matures, this code may need to be revisited.
-                                                */
-                                               continue;
-                                       }
-                                       return -1;
-                               } else if (buf_used < sizeof(vi)) {
-                                       // if we didn't get enough information
-                                       return -1;
-                               }
-
-                               if ((info->flags & PROC_LISTPIDSPATH_EXCLUDE_EVTONLY) &&
-                                   (vi.pfi.fi_openflags & O_EVTONLY)) {
-                                       // if this file should be excluded
-                                       continue;
-                               }
-
-                               status = check_file(info, &vi.pvi.vi_stat);
-                               if (status != 0) {
-                                       // if error or match
-                                       return status;
-                               }
-                               break;
-                       }
-                       default :
-                               break;
-               }
-       }
-
-       return 0;
-}
-
-
-/*
- * check_process_threads
- *   check [process] thread working directories
- *
- *   in  : pid
- *   out : -1 if error
- *          0 if no match
- *          1 if match
- */
-static int
-check_process_threads(fdOpenInfoRef info, int pid)
-{
-       int                             buf_used;
-       int                             status;
-       struct proc_taskallinfo         tai;
-
-       buf_used = proc_pidinfo(pid, PROC_PIDTASKALLINFO, 0, &tai, sizeof(tai));
-       if (buf_used <= 0) {
-               if (errno == ESRCH) {
-                       // if the process is gone
-                       return 0;
-               }
-               return -1;
-       } else if (buf_used < sizeof(tai)) {
-               // if we didn't get enough information
-               return -1;
-       }
-
-       // check thread info
-       if (tai.pbsd.pbi_flags & PROC_FLAG_THCWD) {
-               int     i;
-
-               // get list of threads
-               buf_used = tai.ptinfo.pti_threadnum * sizeof(uint64_t);
-
-               while (1) {
-                       if (buf_used > info->thr_size) {
-                               // if we need to allocate [more] space
-                               while (buf_used > info->thr_size) {
-                                       info->thr_size += (sizeof(uint64_t) * 32);
-                               }
-
-                               if (info->threads == NULL) {
-                                       info->threads = malloc(info->thr_size);
-                               } else {
-                                       info->threads = reallocf(info->threads, info->thr_size);
-                               }
-                               if (info->threads == NULL) {
-                                       return -1;
-                               }
-                       }
-
-                       buf_used = proc_pidinfo(pid, PROC_PIDLISTTHREADS, 0, info->threads, info->thr_size);
-                       if (buf_used <= 0) {
-                               return -1;
-                       }
-
-                       if ((buf_used + sizeof(uint64_t)) >= info->thr_size) {
-                               // if not enough room in the buffer for an extra thread
-                               buf_used = info->thr_size + sizeof(uint64_t);
-                               continue;
-                       }
-
-                       info->thr_count = buf_used / sizeof(uint64_t);
-                       break;
-               }
-
-               // iterate through each thread
-               for (i = 0; i < info->thr_count; i++) {
-                       uint64_t                        thr     = info->threads[i];
-                       struct proc_threadwithpathinfo  tpi;
-
-                       buf_used = proc_pidinfo(pid, PROC_PIDTHREADPATHINFO, thr, &tpi, sizeof(tpi));
-                       if (buf_used <= 0) {
-                               if ((errno == ESRCH) || (errno == EINVAL)) {
-                                       // if the process or thread is gone
-                                       continue;
-                               }
-                       } else if (buf_used < sizeof(tai)) {
-                               // if we didn't get enough information
-                               return -1;
-                       }
-
-                       status = check_file(info, &tpi.pvip.vip_vi.vi_stat);
-                       if (status != 0) {
-                               // if error or match
-                               return status;
-                       }
-               }
-       }
-
-       return 0;
-}
-
-
-/*
- * check_process
- *   check [process] current working and root directories
- *   check [process] text (memory)
- *   check [process] open file descriptors
- *
- *   in  : pid
- *   out : -1 if error
- *          0 if no match
- *          1 if match
- */
-static int
-check_process(fdOpenInfoRef info, int pid)
-{
-       int     status;
-
-       // check root and current working directory
-       status = check_process_vnodes(info, pid);
-       if (status != 0) {
-               // if error or match
-               return status;
-       }
-
-       // check process text (memory)
-       status = check_process_text(info, pid);
-       if (status != 0) {
-               // if error or match
-               return status;
-       }
-
-       // check open file descriptors
-       status = check_process_fds(info, pid);
-       if (status != 0) {
-               // if error or match
-               return status;
-       }
-
-       // check per-thread working directories
-       status = check_process_threads(info, pid);
-       if (status != 0) {
-               // if error or match
-               return status;
-       }
-
-       return 0;
-}
-
-
-/*
- * proc_listpidspath
- *
- *   in  : type
- *       : typeinfo
- *       : path
- *       : pathflags
- *       : buffer
- *       : buffersize
- *   out : buffer filled with process IDs that have open file
- *         references that match the specified path or volume;
- *         return value is the bytes of the returned buffer
- *         that contains valid information.
- */
-int
-proc_listpidspath(uint32_t     type,
-                 uint32_t      typeinfo,
-                 const char    *path,
-                 uint32_t      pathflags,
-                 void          *buffer,
-                 int           buffersize)
-{
-       int             buf_used;
-       int             *buf_next       = (int *)buffer;
-       int             i;
-       fdOpenInfoRef   info;
-       int             status          = -1;
-
-       if (buffer == NULL) {
-               // if this is a sizing request
-               return proc_listpids(type, typeinfo, NULL, 0);
-       }
-
-       buffersize -= (buffersize % sizeof(int)); // make whole number of ints
-       if (buffersize < sizeof(int)) {
-               // if we can't even return a single PID
-               errno = ENOMEM;
-               return -1;
-       }
-
-       // init
-       info = check_init(path, pathflags);
-       if (info == NULL) {
-               return -1;
-       }
-
-       // get list of processes
-       buf_used = proc_listpids(type, typeinfo, NULL, 0);
-       if (buf_used <= 0) {
-               goto done;
-       }
-
-       while (1) {
-               if (buf_used > info->pids_size) {
-                       // if we need to allocate [more] space
-                       while (buf_used > info->pids_size) {
-                               info->pids_size += (sizeof(int) * 32);
-                       }
-
-                       if (info->pids == NULL) {
-                               info->pids = malloc(info->pids_size);
-                       } else {
-                               info->pids = reallocf(info->pids, info->pids_size);
-                       }
-                       if (info->pids == NULL) {
-                               goto done;
-                       }
-               }
-
-               buf_used = proc_listpids(type, typeinfo, info->pids, info->pids_size);
-               if (buf_used <= 0) {
-                       goto done;
-               }
-
-               if ((buf_used + sizeof(int)) >= info->pids_size) {
-                       // if not enough room in the buffer for an extra pid
-                       buf_used = info->pids_size + sizeof(int);
-                       continue;
-               }
-
-               info->pids_count = buf_used / sizeof(int);
-               break;
-       }
-
-       // iterate through each process
-       buf_used = 0;
-       for (i = info->pids_count - 1; i >= 0; i--) {
-               int     pid;
-               int     status;
-
-               pid = info->pids[i];
-               if (pid == 0) {
-                       continue;
-               }
-
-               status = check_process(info, pid);
-               if (status != 1) {
-                       // if not a match
-                       continue;
-               }
-
-               *buf_next++ = pid;
-               buf_used += sizeof(int);
-
-               if (buf_used >= buffersize) {
-                       // if we have filled the buffer
-                       break;
-               }
-       }
-
-       status = buf_used;
-
-    done :
-
-       // cleanup
-       check_free(info);
-
-       return status;
-}