+
+void
+fs_usage_fd_set(thread, fd)
+ unsigned int thread;
+ unsigned int fd;
+{
+ int n;
+ fd_threadmap *fdmap;
+
+ if(!(fdmap = find_fd_thread_map(thread)))
+ return;
+
+ /* If the map is not allocated, then now is the time */
+ if (fdmap->fd_setptr == (unsigned long *)0)
+ {
+ fdmap->fd_setptr = (unsigned long *)malloc(FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE));
+ if (fdmap->fd_setptr)
+ {
+ fdmap->fd_setsize = FS_USAGE_FD_SETSIZE;
+ bzero(fdmap->fd_setptr,(FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE)));
+ }
+ else
+ return;
+ }
+
+ /* If the map is not big enough, then reallocate it */
+ while (fdmap->fd_setsize < fd)
+ {
+ printf("reallocating bitmap for threadid %d, fd = %d, setsize = %d\n",
+ thread, fd, fdmap->fd_setsize);
+ n = fdmap->fd_setsize * 2;
+ fdmap->fd_setptr = (unsigned long *)realloc(fdmap->fd_setptr, (FS_USAGE_NFDBYTES(n)));
+ bzero(&fdmap->fd_setptr[(fdmap->fd_setsize/FS_USAGE_NFDBITS)], (FS_USAGE_NFDBYTES(fdmap->fd_setsize)));
+ fdmap->fd_setsize = n;
+ }
+
+ /* set the bit */
+ fdmap->fd_setptr[fd/FS_USAGE_NFDBITS] |= (1 << ((fd) % FS_USAGE_NFDBITS));
+
+ return;
+}
+
+/*
+ Return values:
+ 0 : File Descriptor bit is not set
+ 1 : File Descriptor bit is set
+*/
+
+int
+fs_usage_fd_isset(thread, fd)
+ unsigned int thread;
+ unsigned int fd;
+{
+ int ret = 0;
+ fd_threadmap *fdmap;
+
+ if(!(fdmap = find_fd_thread_map(thread)))
+ return(ret);
+
+ if (fdmap->fd_setptr == (unsigned long *)0)
+ return (ret);
+
+ if (fd < fdmap->fd_setsize)
+ ret = fdmap->fd_setptr[fd/FS_USAGE_NFDBITS] & (1 << (fd % FS_USAGE_NFDBITS));
+
+ return (ret);
+}
+
+void
+fs_usage_fd_clear(thread, fd)
+ unsigned int thread;
+ unsigned int fd;
+{
+ fd_threadmap *map;
+
+ if (!(map = find_fd_thread_map(thread)))
+ return;
+
+ if (map->fd_setptr == (unsigned long *)0)
+ return;
+
+ /* clear the bit */
+ if (fd < map->fd_setsize)
+ map->fd_setptr[fd/FS_USAGE_NFDBITS] &= ~(1 << (fd % FS_USAGE_NFDBITS));
+
+ return;
+}
+
+
+/*
+ * ret = 1 means print the entry
+ * ret = 0 means don't print the entry
+ */
+int
+check_filter_mode(struct th_info * ti, int type, int error, int retval)
+{
+ int ret = 0;
+ int network_fd_isset = 0;
+ unsigned int fd;
+
+ if (filter_mode == DEFAULT_DO_NOT_FILTER)
+ return(1);
+
+ if (ti == (struct th_info *)0)
+ {
+ if(filter_mode & FILESYS_FILTER)
+ ret = 1;
+ else
+ ret = 0;
+ return(ret);
+ }
+
+
+ switch (type) {
+ case BSC_close:
+ fd = ti->arg1;
+ network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
+ if (error == 0)
+ {
+ fs_usage_fd_clear(ti->thread,fd);
+ }
+
+ if (network_fd_isset)
+ {
+ if (filter_mode & NETWORK_FILTER)
+ ret = 1;
+ }
+ else if (filter_mode & FILESYS_FILTER)
+ ret = 1;
+ break;
+ case BSC_read:
+ case BSC_write:
+ /* we don't care about error in this case */
+ fd = ti->arg1;
+ network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
+ if (network_fd_isset)
+ {
+ if (filter_mode & NETWORK_FILTER)
+ ret = 1;
+ }
+ else if (filter_mode & FILESYS_FILTER)
+ ret = 1;
+ break;
+ case BSC_accept:
+ case BSC_socket:
+ fd = retval;
+ if (error == 0)
+ fs_usage_fd_set(ti->thread, fd);
+ if (filter_mode & NETWORK_FILTER)
+ ret = 1;
+ break;
+ case BSC_recvfrom:
+ case BSC_sendto:
+ case BSC_recvmsg:
+ case BSC_sendmsg:
+ case BSC_connect:
+ case BSC_bind:
+ case BSC_listen:
+ fd = ti->arg1;
+ if (error == 0)
+ fs_usage_fd_set(ti->thread, fd);
+ if (filter_mode & NETWORK_FILTER)
+ ret = 1;
+ break;
+ case BSC_select:
+ case BSC_socketpair:
+ /* Cannot determine info about file descriptors */
+ if (filter_mode & NETWORK_FILTER)
+ ret = 1;
+ break;
+ case BSC_dup:
+ case BSC_dup2:
+ ret=0; /* We track these cases for fd state only */
+ fd = ti->arg1; /* oldd */
+ network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
+ if (error == 0 && network_fd_isset)
+ {
+ /* then we are duping a socket descriptor */
+ fd = retval; /* the new fd */
+ fs_usage_fd_set(ti->thread, fd);
+ }
+ break;
+
+ default:
+ if (filter_mode & FILESYS_FILTER)
+ ret = 1;
+ break;
+ }
+
+ return(ret);
+}
+
+/*
+ * Allocate a buffer that is large enough to hold the maximum arguments
+ * to execve(). This is used when getting the arguments to programs
+ * when we see LaunchCFMApps. If this fails, it is not fatal, we will
+ * simply not resolve the command name.
+ */
+
+void
+init_arguments_buffer()
+{
+
+ int mib[2];
+ size_t size;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_ARGMAX;
+ size = sizeof(argmax);
+ if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1)
+ return;
+
+#if 1
+ /* Hack to avoid kernel bug. */
+ if (argmax > 8192) {
+ argmax = 8192;
+ }
+#endif
+
+ arguments = (char *)malloc(argmax);
+
+ return;
+}
+
+
+int
+get_real_command_name(int pid, char *cbuf, int csize)
+{
+ /*
+ * Get command and arguments.
+ */
+ char *cp;
+ int mib[4];
+ char *command_beg, *command, *command_end;
+
+ if (cbuf == NULL) {
+ return(0);
+ }
+
+ if (arguments)
+ bzero(arguments, argmax);
+ else
+ return(0);
+
+ /*
+ * A sysctl() is made to find out the full path that the command
+ * was called with.
+ */
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROCARGS;
+ mib[2] = pid;
+ mib[3] = 0;
+
+ if (sysctl(mib, 3, arguments, (size_t *)&argmax, NULL, 0) < 0) {
+ return(0);
+ }
+
+ /* Skip the saved exec_path. */
+ for (cp = arguments; cp < &arguments[argmax]; cp++) {
+ if (*cp == '\0') {
+ /* End of exec_path reached. */
+ break;
+ }
+ }
+ if (cp == &arguments[argmax]) {
+ return(0);
+ }
+
+ /* Skip trailing '\0' characters. */
+ for (; cp < &arguments[argmax]; cp++) {
+ if (*cp != '\0') {
+ /* Beginning of first argument reached. */
+ break;
+ }
+ }
+ if (cp == &arguments[argmax]) {
+ return(0);
+ }
+ command_beg = cp;
+
+ /*
+ * Make sure that the command is '\0'-terminated. This protects
+ * against malicious programs; under normal operation this never
+ * ends up being a problem..
+ */
+ for (; cp < &arguments[argmax]; cp++) {
+ if (*cp == '\0') {
+ /* End of first argument reached. */
+ break;
+ }
+ }
+ if (cp == &arguments[argmax]) {
+ return(0);
+ }
+ command_end = command = cp;
+
+ /* Get the basename of command. */
+ for (command--; command >= command_beg; command--) {
+ if (*command == '/') {
+ command++;
+ break;
+ }
+ }
+
+ (void) strncpy(cbuf, (char *)command, csize);
+ cbuf[csize-1] = '\0';
+
+ return(1);
+}