GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/fstat/fuser.c Lines: 0 50 0.0 %
Date: 2016-12-06 Branches: 0 43 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: fuser.c,v 1.6 2015/01/16 06:40:08 deraadt Exp $	*/
2
3
/*
4
 * Copyright (c) 2009 Todd C. Miller <Todd.Miller@courtesan.com>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
/*
20
 * Copyright (c) 2002 Peter Werner <peterw@ifost.org.au>
21
 * All rights reserved.
22
 *
23
 * Redistribution and use in source and binary forms, with or without
24
 * modification, are permitted provided that the following conditions
25
 * are met:
26
 *
27
 * 1. Redistributions of source code must retain the above copyright
28
 *    notice, this list of conditions and the following disclaimer.
29
 * 2. The name of the author may not be used to endorse or promote products
30
 *    derived from this software without specific prior written permission.
31
 *
32
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
33
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
34
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
35
 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
36
 * EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,
37
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
38
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
39
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
40
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42
 */
43
44
#include <sys/queue.h>
45
#include <sys/stat.h>
46
#include <sys/sysctl.h>
47
#include <sys/ucred.h>
48
#define _KERNEL /* for DTYPE_VNODE */
49
#include <sys/file.h>
50
#undef _KERNEL
51
52
#include <err.h>
53
#include <fcntl.h>
54
#include <pwd.h>
55
#include <signal.h>
56
#include <stdio.h>
57
#include <stdlib.h>
58
#include <string.h>
59
#include <unistd.h>
60
61
#include "fstat.h"
62
63
/*
64
 * Returns 1 if the file watched (fa) is equivalent
65
 * to a file held by a process (kf), else 0.
66
 */
67
static int
68
match(struct filearg *fa, struct kinfo_file *kf)
69
{
70
	if (fa->dev == kf->va_fsid) {
71
		if (cflg)
72
			return (1);
73
		if (fa->ino == kf->va_fileid)
74
			return (1);
75
	}
76
	return (0);
77
}
78
79
/*
80
 * Examine kinfo_file struct and record the details if they
81
 * match a watched file.
82
 */
83
void
84
fuser_check(struct kinfo_file *kf)
85
{
86
	struct filearg *fa;
87
	struct fuser *fu;
88
89
	if (kf->f_type != DTYPE_VNODE)
90
		return;
91
92
	SLIST_FOREACH(fa, &fileargs, next) {
93
		if (!match(fa, kf))
94
			continue;
95
96
		/*
97
		 * This assumes that kinfo_files2 returns all files
98
		 * associated with a process in a contiguous block.
99
		 */
100
		if (TAILQ_EMPTY(&fa->fusers) || kf->p_pid !=
101
		    (fu = TAILQ_LAST(&fa->fusers, fuserhead))->pid) {
102
			fu = malloc(sizeof(*fu));
103
			if (fu == NULL)
104
				err(1, NULL);
105
			fu->pid = kf->p_pid;
106
			fu->uid = kf->p_uid;
107
			fu->flags = 0;
108
			TAILQ_INSERT_TAIL(&fa->fusers, fu, tq);
109
		}
110
		switch (kf->fd_fd) {
111
		case KERN_FILE_CDIR:
112
			fu->flags |= F_CWD;
113
			break;
114
		case KERN_FILE_RDIR:
115
			fu->flags |= F_ROOT;
116
			break;
117
		case KERN_FILE_TEXT:
118
			fu->flags |= F_TEXT;
119
			break;
120
		case KERN_FILE_TRACE:
121
			/* ignore */
122
			break;
123
		default:
124
			fu->flags |= F_OPEN;
125
			break;
126
		}
127
	}
128
}
129
130
/*
131
 * Print out the specfics for a given file/filesystem
132
 */
133
static void
134
printfu(struct fuser *fu)
135
{
136
	struct passwd *pwd;
137
138
	printf("%d", fu->pid);
139
	fflush(stdout);
140
141
	if (fu->flags & F_CWD)
142
		fprintf(stderr, "c");
143
144
	if (fu->flags & F_ROOT)
145
		fprintf(stderr, "r");
146
147
	if (fu->flags & F_TEXT)
148
		fprintf(stderr, "t");
149
150
	if (uflg) {
151
		pwd = getpwuid(fu->uid);
152
		if (pwd != NULL)
153
			fprintf(stderr, "(%s)", pwd->pw_name);
154
		else
155
			fprintf(stderr, "(%d)", fu->uid);
156
	}
157
158
	putchar(' ');
159
}
160
161
/*
162
 * For each file, print matching process info and optionally send a signal.
163
 */
164
void
165
fuser_run(void)
166
{
167
	struct filearg *fa;
168
	struct fuser *fu;
169
	pid_t mypid = getpid();
170
171
	SLIST_FOREACH(fa, &fileargs, next) {
172
		fprintf(stderr, "%s: ", fa->name);
173
		TAILQ_FOREACH(fu, &fa->fusers, tq) {
174
			printfu(fu);
175
			if (sflg && fu->pid != mypid) {
176
				kill(fu->pid, signo);
177
			}
178
		}
179
		fflush(stdout);
180
		fprintf(stderr, "\n");
181
	}
182
}