forked from pool/psmisc
.
OBS-URL: https://build.opensuse.org/package/show/Base:System/psmisc?expand=0&rev=21
This commit is contained in:
parent
d57396fe8d
commit
27d2e910a5
269
psmisc-22.12-leaks.patch
Normal file
269
psmisc-22.12-leaks.patch
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
--- src/fuser.c
|
||||||
|
+++ src/fuser.c 2010-07-13 14:42:02.762926098 +0000
|
||||||
|
@@ -148,18 +148,12 @@ scan_procs(struct names *names_head, str
|
||||||
|
{
|
||||||
|
DIR *topproc_dir;
|
||||||
|
struct dirent *topproc_dent;
|
||||||
|
- char *fd_dirpath, *fd_pathname;
|
||||||
|
struct inode_list *ino_tmp;
|
||||||
|
struct device_list *dev_tmp;
|
||||||
|
pid_t pid, my_pid;
|
||||||
|
uid_t uid;
|
||||||
|
struct stat *cwd_stat, *exe_stat, *root_stat;
|
||||||
|
|
||||||
|
- if ((fd_dirpath = malloc(MAX_PATHNAME)) == NULL)
|
||||||
|
- return;
|
||||||
|
- if ((fd_pathname = malloc(MAX_PATHNAME)) == NULL)
|
||||||
|
- return;
|
||||||
|
-
|
||||||
|
if ((topproc_dir = opendir("/proc")) == NULL) {
|
||||||
|
fprintf(stderr, _("Cannot open /proc directory: %s\n"),
|
||||||
|
strerror(errno));
|
||||||
|
@@ -219,6 +213,9 @@ scan_procs(struct names *names_head, str
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ if (root_stat) free(root_stat);
|
||||||
|
+ if (cwd_stat) free(cwd_stat);
|
||||||
|
+ if (exe_stat) free(exe_stat);
|
||||||
|
check_dir(pid, "lib", dev_head, ino_head, uid, ACCESS_MMAP,
|
||||||
|
sockets, netdev);
|
||||||
|
check_dir(pid, "mmap", dev_head, ino_head, uid, ACCESS_MMAP,
|
||||||
|
@@ -237,10 +234,9 @@ add_inode(struct inode_list **ino_list,
|
||||||
|
{
|
||||||
|
struct inode_list *ino_tmp, *ino_head;
|
||||||
|
|
||||||
|
- ino_head = *ino_list;
|
||||||
|
-
|
||||||
|
- if ((ino_tmp = malloc(sizeof(struct inode_list))) == NULL)
|
||||||
|
+ if ((ino_tmp = (struct inode_list*)malloc(sizeof(struct inode_list))) == NULL)
|
||||||
|
return;
|
||||||
|
+ ino_head = *ino_list;
|
||||||
|
ino_tmp->name = this_name;
|
||||||
|
ino_tmp->device = device;
|
||||||
|
ino_tmp->inode = inode;
|
||||||
|
@@ -254,10 +250,10 @@ add_device(struct device_list **dev_list
|
||||||
|
struct device_list *dev_tmp, *dev_head;
|
||||||
|
|
||||||
|
/*printf("Adding device %s %d\n", this_name->filename, device); */
|
||||||
|
- dev_head = *dev_list;
|
||||||
|
|
||||||
|
- if ((dev_tmp = malloc(sizeof(struct device_list))) == NULL)
|
||||||
|
+ if ((dev_tmp = (struct device_list*)malloc(sizeof(struct device_list))) == NULL)
|
||||||
|
return;
|
||||||
|
+ dev_head = *dev_list;
|
||||||
|
dev_tmp->name = this_name;
|
||||||
|
dev_tmp->device = device;
|
||||||
|
dev_tmp->next = dev_head;
|
||||||
|
@@ -271,10 +267,9 @@ add_ip_conn(struct ip_connections **ip_l
|
||||||
|
{
|
||||||
|
struct ip_connections *ip_tmp, *ip_head;
|
||||||
|
|
||||||
|
- ip_head = *ip_list;
|
||||||
|
-
|
||||||
|
- if ((ip_tmp = malloc(sizeof(struct ip_connections))) == NULL)
|
||||||
|
+ if ((ip_tmp = (struct ip_connections*)malloc(sizeof(struct ip_connections))) == NULL)
|
||||||
|
return;
|
||||||
|
+ ip_head = *ip_list;
|
||||||
|
ip_tmp->name = this_name;
|
||||||
|
ip_tmp->lcl_port = lcl_port;
|
||||||
|
ip_tmp->rmt_port = rmt_port;
|
||||||
|
@@ -292,10 +287,9 @@ add_ip6_conn(struct ip6_connections **ip
|
||||||
|
{
|
||||||
|
struct ip6_connections *ip_tmp, *ip_head;
|
||||||
|
|
||||||
|
- ip_head = *ip_list;
|
||||||
|
-
|
||||||
|
- if ((ip_tmp = malloc(sizeof(struct ip6_connections))) == NULL)
|
||||||
|
+ if ((ip_tmp = (struct ip6_connections*)malloc(sizeof(struct ip6_connections))) == NULL)
|
||||||
|
return;
|
||||||
|
+ ip_head = *ip_list;
|
||||||
|
ip_tmp->name = this_name;
|
||||||
|
ip_tmp->lcl_port = lcl_port;
|
||||||
|
ip_tmp->rmt_port = rmt_port;
|
||||||
|
@@ -326,7 +320,7 @@ add_matched_proc(struct names *name_list
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Not found */
|
||||||
|
- if ((pptr = malloc(sizeof(struct procs))) == NULL) {
|
||||||
|
+ if ((pptr = (struct procs*)malloc(sizeof(struct procs))) == NULL) {
|
||||||
|
fprintf(stderr,
|
||||||
|
_("Cannot allocate memory for matched proc: %s\n"),
|
||||||
|
strerror(errno));
|
||||||
|
@@ -339,10 +333,13 @@ add_matched_proc(struct names *name_list
|
||||||
|
pptr->next = NULL;
|
||||||
|
/* set command name */
|
||||||
|
pptr->command = NULL;
|
||||||
|
+
|
||||||
|
+ fp = NULL;
|
||||||
|
+ pathname = NULL;
|
||||||
|
if ((asprintf(&pathname, "/proc/%d/stat", pid) > 0) &&
|
||||||
|
((fp = fopen(pathname, "r")) != NULL) &&
|
||||||
|
(fscanf(fp, "%*d (%100[^)]", cmdname) == 1))
|
||||||
|
- if ((pptr->command = malloc(MAX_CMDNAME + 1)) != NULL) {
|
||||||
|
+ if ((pptr->command = (char*)malloc(MAX_CMDNAME + 1)) != NULL) {
|
||||||
|
cmdlen = 0;
|
||||||
|
for (cptr = cmdname; cmdlen < MAX_CMDNAME && *cptr;
|
||||||
|
cptr++) {
|
||||||
|
@@ -359,6 +356,10 @@ add_matched_proc(struct names *name_list
|
||||||
|
name_list->matched_procs = pptr;
|
||||||
|
else
|
||||||
|
last_proc->next = pptr;
|
||||||
|
+ if (pathname)
|
||||||
|
+ free(pathname);
|
||||||
|
+ if (fp)
|
||||||
|
+ fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adds a knfsd etc process */
|
||||||
|
@@ -680,7 +681,7 @@ find_net_sockets(struct inode_list **ino
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
- return;
|
||||||
|
+ fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_IPV6
|
||||||
|
@@ -753,6 +754,7 @@ find_net6_sockets(struct inode_list **in
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ fclose(fp);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@@ -1253,13 +1255,15 @@ static struct stat *get_pidstat(const pi
|
||||||
|
char pathname[256];
|
||||||
|
struct stat *st;
|
||||||
|
|
||||||
|
- if ((st = malloc(sizeof(struct stat))) == NULL)
|
||||||
|
+ if ((st = (struct stat*)malloc(sizeof(struct stat))) == NULL)
|
||||||
|
return NULL;
|
||||||
|
snprintf(pathname, 256, "/proc/%d/%s", pid, filename);
|
||||||
|
if (stat(pathname, st) != 0)
|
||||||
|
- return NULL;
|
||||||
|
- else
|
||||||
|
- return st;
|
||||||
|
+ goto out;
|
||||||
|
+ return st;
|
||||||
|
+out:
|
||||||
|
+ free(st);
|
||||||
|
+ return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
@@ -1267,7 +1271,7 @@ check_dir(const pid_t pid, const char *d
|
||||||
|
struct inode_list *ino_head, const uid_t uid, const char access,
|
||||||
|
struct unixsocket_list *sockets, dev_t netdev)
|
||||||
|
{
|
||||||
|
- char *dirpath, *filepath;
|
||||||
|
+ char *dirpath = NULL, *filepath = NULL;
|
||||||
|
DIR *dirp;
|
||||||
|
struct dirent *direntry;
|
||||||
|
struct inode_list *ino_tmp;
|
||||||
|
@@ -1275,14 +1279,14 @@ check_dir(const pid_t pid, const char *d
|
||||||
|
struct unixsocket_list *sock_tmp;
|
||||||
|
struct stat st, lst;
|
||||||
|
|
||||||
|
- if ((dirpath = malloc(MAX_PATHNAME)) == NULL)
|
||||||
|
- return;
|
||||||
|
- if ((filepath = malloc(MAX_PATHNAME)) == NULL)
|
||||||
|
- return;
|
||||||
|
+ if ((dirpath = (char*)malloc(MAX_PATHNAME)) == NULL)
|
||||||
|
+ goto out;
|
||||||
|
+ if ((filepath = (char*)malloc(MAX_PATHNAME)) == NULL)
|
||||||
|
+ goto out;
|
||||||
|
|
||||||
|
snprintf(dirpath, MAX_PATHNAME, "/proc/%d/%s", pid, dirname);
|
||||||
|
if ((dirp = opendir(dirpath)) == NULL)
|
||||||
|
- return;
|
||||||
|
+ goto out;
|
||||||
|
while ((direntry = readdir(dirp)) != NULL) {
|
||||||
|
if (direntry->d_name[0] < '0' || direntry->d_name[0] > '9')
|
||||||
|
continue;
|
||||||
|
@@ -1341,6 +1345,11 @@ check_dir(const pid_t pid, const char *d
|
||||||
|
}
|
||||||
|
} /* while fd_dent */
|
||||||
|
closedir(dirp);
|
||||||
|
+out:
|
||||||
|
+ if (dirpath)
|
||||||
|
+ free(dirpath);
|
||||||
|
+ if (filepath)
|
||||||
|
+ free(filepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
@@ -1400,7 +1409,6 @@ void fill_unix_cache(struct unixsocket_l
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
char line[BUFSIZ];
|
||||||
|
- char *scanned_path;
|
||||||
|
int scanned_inode;
|
||||||
|
struct stat st;
|
||||||
|
struct unixsocket_list *newsocket;
|
||||||
|
@@ -1411,24 +1419,38 @@ void fill_unix_cache(struct unixsocket_l
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (fgets(line, BUFSIZ, fp) != NULL) {
|
||||||
|
+ char * path;
|
||||||
|
+ char * scanned_path = NULL;
|
||||||
|
if (sscanf(line, "%*x: %*x %*x %*x %*x %*d %d %as",
|
||||||
|
- &scanned_inode, &scanned_path) != 2)
|
||||||
|
+ &scanned_inode, &scanned_path) != 2) {
|
||||||
|
+ if (scanned_path)
|
||||||
|
+ free(scanned_path);
|
||||||
|
continue;
|
||||||
|
+ }
|
||||||
|
+ if (scanned_path == NULL)
|
||||||
|
+ continue;
|
||||||
|
+ path = scanned_path;
|
||||||
|
+ if (*scanned_path == '@')
|
||||||
|
+ scanned_path++;
|
||||||
|
if (stat(scanned_path, &st) < 0) {
|
||||||
|
- free(scanned_path);
|
||||||
|
+ free(path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
- if ((newsocket =
|
||||||
|
- malloc(sizeof(struct unixsocket_list))) == NULL)
|
||||||
|
+ if ((newsocket = (struct unixsocket_list*)
|
||||||
|
+ malloc(sizeof(struct unixsocket_list))) == NULL) {
|
||||||
|
+ free(path);
|
||||||
|
continue;
|
||||||
|
+ }
|
||||||
|
newsocket->sun_name = strdup(scanned_path);
|
||||||
|
newsocket->inode = st.st_ino;
|
||||||
|
newsocket->dev = st.st_dev;
|
||||||
|
newsocket->net_inode = scanned_inode;
|
||||||
|
newsocket->next = *unixsocket_head;
|
||||||
|
*unixsocket_head = newsocket;
|
||||||
|
+ free(path);
|
||||||
|
} /* while */
|
||||||
|
|
||||||
|
+ fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
@@ -1567,6 +1589,7 @@ scan_knfsd(struct names *names_head, str
|
||||||
|
line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
@@ -1610,6 +1633,7 @@ scan_mounts(struct names *names_head, st
|
||||||
|
find_mountp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
@@ -1656,4 +1680,5 @@ scan_swaps(struct names *names_head, str
|
||||||
|
line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ fclose(fp);
|
||||||
|
}
|
903
psmisc-22.12-nfs4fuser.patch
Normal file
903
psmisc-22.12-nfs4fuser.patch
Normal file
@ -0,0 +1,903 @@
|
|||||||
|
--- doc/fuser.1
|
||||||
|
+++ doc/fuser.1 2010-07-13 11:19:41.000000000 +0000
|
||||||
|
@@ -88,8 +88,14 @@ List all known signal names.
|
||||||
|
\fINAME\fR specifies a file on a mounted file system or a block device that
|
||||||
|
is mounted. All processes accessing files on that file system are listed.
|
||||||
|
If a directory file is specified, it is automatically changed to
|
||||||
|
-\fINAME\fR/. to use any file system that might be mounted on that
|
||||||
|
-directory.
|
||||||
|
+\fINAME\fR/. To use any file system that might be mounted on that
|
||||||
|
+directory. Please note that due the required device ID comparision all
|
||||||
|
+mounted file systems the
|
||||||
|
+.BR stat (2)
|
||||||
|
+system call will applied to every file system even on network file system
|
||||||
|
+(NFS). If the NFS server does not respond or the network is down the
|
||||||
|
+.BR stat (2)
|
||||||
|
+may hang forever.
|
||||||
|
.TP
|
||||||
|
\fB\-M\f, \fB\-\-ismountpoint\fR
|
||||||
|
Request will be fulfilled only if \fINAME\fR specifies a mountpoint.
|
||||||
|
@@ -174,10 +180,13 @@ The \fB\-k\fR option only works on proce
|
||||||
|
\fBfuser\fR will print an advice, but take no action beyond that.
|
||||||
|
.SH BUGS
|
||||||
|
.PP
|
||||||
|
-fuser \-m /dev/sgX will show (or kill with the \-k flag) all processes, even
|
||||||
|
+\fBfuser \-m \fI/dev/sgX\fR will show (or kill with the \fB\-k\fR flag) all processes, even
|
||||||
|
if you don't have that device configured. There may be other devices it
|
||||||
|
does this for too.
|
||||||
|
.PP
|
||||||
|
+\fBfuser \-m \fIname\fR may hang forever if there are NFS file systems mounted
|
||||||
|
+and one of the NFS servers do not respond or the corresponding network is down.
|
||||||
|
+.PP
|
||||||
|
.B fuser
|
||||||
|
cannot report on any processes that it doesn't have permission to look at
|
||||||
|
the file descriptor table for. The most common time this problem occurs
|
||||||
|
--- src/fuser.c
|
||||||
|
+++ src/fuser.c 2010-07-13 16:28:32.051424747 +0000
|
||||||
|
@@ -32,9 +32,11 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
+#include <sys/param.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
+#include <sys/wait.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
@@ -45,6 +47,7 @@
|
||||||
|
#include <mntent.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
+#include <setjmp.h>
|
||||||
|
|
||||||
|
#include "fuser.h"
|
||||||
|
#include "signals.h"
|
||||||
|
@@ -67,7 +70,8 @@ static void check_map(const pid_t pid, c
|
||||||
|
struct device_list *dev_head,
|
||||||
|
struct inode_list *ino_head, const uid_t uid,
|
||||||
|
const char access);
|
||||||
|
-static struct stat *get_pidstat(const pid_t pid, const char *filename);
|
||||||
|
+static struct stat *get_pidstat(const opt_type opts, const pid_t pid,
|
||||||
|
+ const char *filename, char *real);
|
||||||
|
static uid_t getpiduid(const pid_t pid);
|
||||||
|
static int print_matches(struct names *names_head, const opt_type opts,
|
||||||
|
const int sig_number);
|
||||||
|
@@ -79,12 +83,12 @@ static void add_device(struct device_lis
|
||||||
|
struct names *this_name, dev_t device);
|
||||||
|
void fill_unix_cache(struct unixsocket_list **unixsocket_head);
|
||||||
|
static dev_t find_net_dev(void);
|
||||||
|
-static void scan_procs(struct names *names_head, struct inode_list *ino_head,
|
||||||
|
- struct device_list *dev_head,
|
||||||
|
+static void scan_procs(const opt_type opts, struct names *names_head,
|
||||||
|
+ struct inode_list *ino_head, struct device_list *dev_head,
|
||||||
|
struct unixsocket_list *sockets, dev_t netdev);
|
||||||
|
static void scan_knfsd(struct names *names_head, struct inode_list *ino_head,
|
||||||
|
struct device_list *dev_head);
|
||||||
|
-static void scan_mounts(struct names *names_head,
|
||||||
|
+static void scan_mounts(struct names *names_head, struct mount_list *mounts,
|
||||||
|
struct inode_list *ino_head,
|
||||||
|
struct device_list *dev_head);
|
||||||
|
static void scan_swaps(struct names *names_head, struct inode_list *ino_head,
|
||||||
|
@@ -95,6 +99,13 @@ static void debug_match_lists(struct nam
|
||||||
|
struct device_list *dev_head);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+static struct nfs_points *mnts;
|
||||||
|
+static void clear_mnt(void);
|
||||||
|
+static int check4nfs(const char * path, char * real);
|
||||||
|
+
|
||||||
|
+typedef int (*stat_t)(const char*, struct stat*);
|
||||||
|
+static int nfssafe(stat_t func, const char *path, struct stat *buf);
|
||||||
|
+
|
||||||
|
static void usage(const char *errormsg)
|
||||||
|
{
|
||||||
|
if (errormsg != NULL)
|
||||||
|
@@ -141,8 +152,15 @@ void print_version()
|
||||||
|
"For more information about these matters, see the files named COPYING.\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int islocatedon(const char * path, const char * loc)
|
||||||
|
+{
|
||||||
|
+ if (!path || *path == '\0')
|
||||||
|
+ return 0;
|
||||||
|
+ return (strstr(path, loc) == path);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void
|
||||||
|
-scan_procs(struct names *names_head, struct inode_list *ino_head,
|
||||||
|
+scan_procs(const opt_type opts, struct names *names_head, struct inode_list *ino_head,
|
||||||
|
struct device_list *dev_head, struct unixsocket_list *sockets,
|
||||||
|
dev_t netdev)
|
||||||
|
{
|
||||||
|
@@ -153,6 +171,9 @@ scan_procs(struct names *names_head, str
|
||||||
|
pid_t pid, my_pid;
|
||||||
|
uid_t uid;
|
||||||
|
struct stat *cwd_stat, *exe_stat, *root_stat;
|
||||||
|
+ char root_real[PATH_MAX+1];
|
||||||
|
+ char cwd_real[PATH_MAX+1];
|
||||||
|
+ char exe_real[PATH_MAX+1];
|
||||||
|
|
||||||
|
if ((topproc_dir = opendir("/proc")) == NULL) {
|
||||||
|
fprintf(stderr, _("Cannot open /proc directory: %s\n"),
|
||||||
|
@@ -169,9 +190,10 @@ scan_procs(struct names *names_head, str
|
||||||
|
continue;
|
||||||
|
uid = getpiduid(pid);
|
||||||
|
|
||||||
|
- root_stat = get_pidstat(pid, "root");
|
||||||
|
- cwd_stat = get_pidstat(pid, "cwd");
|
||||||
|
- exe_stat = get_pidstat(pid, "exe");
|
||||||
|
+ root_real[0] = cwd_real[0] = exe_real[0] = '\0';
|
||||||
|
+ root_stat = get_pidstat(opts, pid, "root", root_real);
|
||||||
|
+ cwd_stat = get_pidstat(opts, pid, "cwd", cwd_real);
|
||||||
|
+ exe_stat = get_pidstat(opts, pid, "exe", exe_real);
|
||||||
|
/* Scan the devices */
|
||||||
|
for (dev_tmp = dev_head; dev_tmp != NULL;
|
||||||
|
dev_tmp = dev_tmp->next) {
|
||||||
|
@@ -187,6 +209,17 @@ scan_procs(struct names *names_head, str
|
||||||
|
&& cwd_stat->st_dev == dev_tmp->device)
|
||||||
|
add_matched_proc(dev_tmp->name, pid, uid,
|
||||||
|
ACCESS_CWD);
|
||||||
|
+ if ((dev_tmp->name->name_space & NAMESPACE_NFS) == 0)
|
||||||
|
+ continue;
|
||||||
|
+ if (islocatedon(&exe_real[0], dev_tmp->name->filename))
|
||||||
|
+ add_matched_proc(dev_tmp->name, pid, uid,
|
||||||
|
+ ACCESS_EXE);
|
||||||
|
+ if (islocatedon(&root_real[0], dev_tmp->name->filename))
|
||||||
|
+ add_matched_proc(dev_tmp->name, pid, uid,
|
||||||
|
+ ACCESS_ROOT);
|
||||||
|
+ if (islocatedon(&cwd_real[0], dev_tmp->name->filename))
|
||||||
|
+ add_matched_proc(dev_tmp->name, pid, uid,
|
||||||
|
+ ACCESS_CWD);
|
||||||
|
}
|
||||||
|
for (ino_tmp = ino_head; ino_tmp != NULL;
|
||||||
|
ino_tmp = ino_tmp->next) {
|
||||||
|
@@ -212,14 +245,27 @@ scan_procs(struct names *names_head, str
|
||||||
|
uid, ACCESS_CWD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ if ((ino_tmp->name->name_space & NAMESPACE_NFS) == 0)
|
||||||
|
+ continue;
|
||||||
|
+ if (islocatedon(&exe_real[0], ino_tmp->name->filename))
|
||||||
|
+ add_matched_proc(ino_tmp->name, pid, uid,
|
||||||
|
+ ACCESS_EXE);
|
||||||
|
+ if (islocatedon(&root_real[0], ino_tmp->name->filename))
|
||||||
|
+ add_matched_proc(ino_tmp->name, pid, uid,
|
||||||
|
+ ACCESS_ROOT);
|
||||||
|
+ if (islocatedon(&cwd_real[0], ino_tmp->name->filename))
|
||||||
|
+ add_matched_proc(ino_tmp->name, pid, uid,
|
||||||
|
+ ACCESS_CWD);
|
||||||
|
}
|
||||||
|
if (root_stat) free(root_stat);
|
||||||
|
if (cwd_stat) free(cwd_stat);
|
||||||
|
if (exe_stat) free(exe_stat);
|
||||||
|
+#ifndef __linux__
|
||||||
|
check_dir(pid, "lib", dev_head, ino_head, uid, ACCESS_MMAP,
|
||||||
|
sockets, netdev);
|
||||||
|
check_dir(pid, "mmap", dev_head, ino_head, uid, ACCESS_MMAP,
|
||||||
|
sockets, netdev);
|
||||||
|
+#endif
|
||||||
|
check_dir(pid, "fd", dev_head, ino_head, uid, ACCESS_FILE,
|
||||||
|
sockets, netdev);
|
||||||
|
check_map(pid, "maps", dev_head, ino_head, uid, ACCESS_MMAP);
|
||||||
|
@@ -394,6 +440,23 @@ add_special_proc(struct names *name_list
|
||||||
|
|
||||||
|
int parse_file(struct names *this_name, struct inode_list **ino_list)
|
||||||
|
{
|
||||||
|
+ char real[PATH_MAX+1] = "";
|
||||||
|
+
|
||||||
|
+ real[0] = '\0';
|
||||||
|
+ if (check4nfs(this_name->filename, real)) {
|
||||||
|
+ if (this_name->filename)
|
||||||
|
+ free(this_name->filename);
|
||||||
|
+ this_name->filename = strdup(real);
|
||||||
|
+ this_name->name_space |= NAMESPACE_NFS;
|
||||||
|
+ add_inode(ino_list, this_name, (dev_t)-1, (ino_t)-1);
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ if (real[0] != '\0') {
|
||||||
|
+ if (this_name->filename)
|
||||||
|
+ free(this_name->filename);
|
||||||
|
+ this_name->filename = strdup(real);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (stat(this_name->filename, &(this_name->st)) != 0) {
|
||||||
|
if (errno == ENOENT)
|
||||||
|
fprintf(stderr, _("Specified filename %s does not exist.\n"), this_name->filename);
|
||||||
|
@@ -411,12 +474,12 @@ int parse_file(struct names *this_name,
|
||||||
|
|
||||||
|
int
|
||||||
|
parse_unixsockets(struct names *this_name, struct inode_list **ino_list,
|
||||||
|
- struct unixsocket_list *sun_head)
|
||||||
|
+ struct unixsocket_list *sun_head, dev_t net_dev)
|
||||||
|
{
|
||||||
|
struct unixsocket_list *sun_tmp;
|
||||||
|
- dev_t net_dev;
|
||||||
|
|
||||||
|
- net_dev = find_net_dev();
|
||||||
|
+ if (this_name->name_space & NAMESPACE_NFS)
|
||||||
|
+ return 0;
|
||||||
|
|
||||||
|
for (sun_tmp = sun_head; sun_tmp != NULL; sun_tmp = sun_tmp->next) {
|
||||||
|
if (sun_tmp->dev == this_name->st.st_dev && sun_tmp->inode == this_name->st.st_ino) {
|
||||||
|
@@ -429,10 +492,14 @@ parse_unixsockets(struct names *this_nam
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
-parse_mounts(struct names *this_name, struct device_list **dev_list,
|
||||||
|
- const char opts)
|
||||||
|
+parse_mounts(struct names *this_name, struct mount_list *mounts,
|
||||||
|
+ struct device_list **dev_list)
|
||||||
|
{
|
||||||
|
dev_t match_device;
|
||||||
|
+ struct mount_list *mountptr;
|
||||||
|
+
|
||||||
|
+ if (this_name->name_space & NAMESPACE_NFS)
|
||||||
|
+ goto skip;
|
||||||
|
|
||||||
|
if (S_ISBLK(this_name->st.st_mode))
|
||||||
|
match_device = this_name->st.st_rdev;
|
||||||
|
@@ -440,6 +507,13 @@ parse_mounts(struct names *this_name, st
|
||||||
|
match_device = this_name->st.st_dev;
|
||||||
|
add_device(dev_list, this_name, match_device);
|
||||||
|
return 0;
|
||||||
|
+skip:
|
||||||
|
+ match_device = -1;
|
||||||
|
+ for (mountptr = mounts ; mountptr != NULL ; mountptr = mountptr->next) {
|
||||||
|
+ if (strcmp(mountptr->mountpoint, this_name->filename) == 0)
|
||||||
|
+ add_device(dev_list, this_name, match_device);
|
||||||
|
+ }
|
||||||
|
+ return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_IPV6
|
||||||
|
@@ -758,34 +832,101 @@ find_net6_sockets(struct inode_list **in
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+static inline int isnetfs(const char * type)
|
||||||
|
+{
|
||||||
|
+ static const char* netfs[] = {"nfs", "nfs4", "smbfs", "cifs", "afs", "ncpfs", (char*)0};
|
||||||
|
+ int n;
|
||||||
|
+ for (n = 0; netfs[n]; n++)
|
||||||
|
+ if (!strcasecmp(netfs[n], type))
|
||||||
|
+ return 1;
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void
|
||||||
|
read_proc_mounts(struct mount_list **mnt_list)
|
||||||
|
{
|
||||||
|
- FILE *fp;
|
||||||
|
- char line[BUFSIZ];
|
||||||
|
- char *find_mountp;
|
||||||
|
- char *find_space;
|
||||||
|
- struct mount_list *mnt_tmp;
|
||||||
|
+ FILE *mntfp;
|
||||||
|
+ struct mntent *mnt_ptr;
|
||||||
|
+ struct stat st;
|
||||||
|
+ const char * mtab;
|
||||||
|
+
|
||||||
|
+ if (stat("/proc/version", &st) < 0)
|
||||||
|
+ mtab = PROC_MOUNTS;
|
||||||
|
+ else
|
||||||
|
+ mtab = "/etc/mtab";
|
||||||
|
|
||||||
|
- if ((fp = fopen(PROC_MOUNTS, "r")) == NULL) {
|
||||||
|
- fprintf(stderr, "Cannot open %s\n", PROC_MOUNTS);
|
||||||
|
+ if ( (mntfp = setmntent(mtab,"r")) == NULL) {
|
||||||
|
+ fprintf(stderr, _("Cannot open %s: %s\n"), mtab,
|
||||||
|
+ strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
- while (fgets(line, BUFSIZ, fp) != NULL) {
|
||||||
|
- if ((find_mountp = strchr(line, ' ')) == NULL)
|
||||||
|
- continue;
|
||||||
|
- find_mountp++;
|
||||||
|
- if ((find_space = strchr(find_mountp, ' ')) == NULL)
|
||||||
|
- continue;
|
||||||
|
- *find_space = '\0';
|
||||||
|
- if ((mnt_tmp = malloc(sizeof(struct mount_list))) == NULL)
|
||||||
|
+ while ((mnt_ptr = getmntent(mntfp)) != NULL) {
|
||||||
|
+ struct mount_list *mnt_tmp;
|
||||||
|
+ if (isnetfs(mnt_ptr->mnt_type)) {
|
||||||
|
+ /*
|
||||||
|
+ * Remember all NFS typed partitions, required to make check4nfs() work.
|
||||||
|
+ */
|
||||||
|
+ size_t nlen = strlen(mnt_ptr->mnt_dir);
|
||||||
|
+ struct nfs_points *restrict p;
|
||||||
|
+ if (posix_memalign((void*)&p, sizeof(void*), alignof(struct nfs_points)+(nlen+1)) != 0)
|
||||||
|
+ goto out;
|
||||||
|
+ p->name = ((char*)p)+alignof(struct nfs_points);
|
||||||
|
+ p->nlen = nlen;
|
||||||
|
+ p->shadow = (struct shadow_list*)0;
|
||||||
|
+
|
||||||
|
+ strcpy(p->name, mnt_ptr->mnt_dir);
|
||||||
|
+ if (mnts)
|
||||||
|
+ mnts->prev = p;
|
||||||
|
+ p->next = mnts;
|
||||||
|
+ p->prev = (struct nfs_points*)0;
|
||||||
|
+ mnts = p;
|
||||||
|
+ }
|
||||||
|
+ if ((mnt_tmp = (struct mount_list*)malloc(sizeof(struct mount_list))) == NULL)
|
||||||
|
continue;
|
||||||
|
- if ((mnt_tmp->mountpoint = strdup(find_mountp)) == NULL)
|
||||||
|
+ if ((mnt_tmp->mountpoint = strdup(mnt_ptr->mnt_dir)) == NULL)
|
||||||
|
continue;
|
||||||
|
mnt_tmp->next = *mnt_list;
|
||||||
|
*mnt_list = mnt_tmp;
|
||||||
|
}
|
||||||
|
- fclose(fp);
|
||||||
|
+ endmntent(mntfp);
|
||||||
|
+
|
||||||
|
+ if (!mnts)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ if ((mntfp = setmntent(mtab, "r")) == NULL) {
|
||||||
|
+ fprintf(stderr, _("Cannot open %s: %s\n"), mtab,
|
||||||
|
+ strerror(errno));
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ while ((mnt_ptr = getmntent(mntfp)) != NULL) {
|
||||||
|
+ struct nfs_points *p;
|
||||||
|
+
|
||||||
|
+ for (p = mnts; p; p = p->next) {
|
||||||
|
+ struct shadow_list *s;
|
||||||
|
+ size_t nlen;
|
||||||
|
+
|
||||||
|
+ if (strcmp(mnt_ptr->mnt_dir, p->name) == 0)
|
||||||
|
+ continue;
|
||||||
|
+ if (strncmp(mnt_ptr->mnt_dir, p->name, p->nlen) != 0)
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ nlen = strlen(mnt_ptr->mnt_dir);
|
||||||
|
+ if (posix_memalign((void*)&s, sizeof(void*), alignof(struct shadow_list)+(nlen+1)) != 0)
|
||||||
|
+ goto out;
|
||||||
|
+ s->name = ((char*)s)+alignof(struct shadow_list);
|
||||||
|
+ s->nlen = nlen;
|
||||||
|
+
|
||||||
|
+ strcpy(s->name, mnt_ptr->mnt_dir);
|
||||||
|
+ if (p->shadow)
|
||||||
|
+ p->shadow->prev = s;
|
||||||
|
+ s->next = p->shadow;
|
||||||
|
+ s->prev = (struct shadow_list*)0;
|
||||||
|
+ p->shadow = s;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+out:
|
||||||
|
+ endmntent(mntfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
@@ -808,6 +949,150 @@ is_mountpoint(struct mount_list **mnt_li
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * Remove struct nfs_points and its sahdows from memory
|
||||||
|
+ */
|
||||||
|
+static void clear_shadow(struct shadow_list *restrict shadow)
|
||||||
|
+{
|
||||||
|
+ struct shadow_list *s, *n, *l;
|
||||||
|
+
|
||||||
|
+ n = shadow;
|
||||||
|
+ l = (struct shadow_list*)0;
|
||||||
|
+ for (s = shadow; n; s = n) {
|
||||||
|
+ l = s->prev;
|
||||||
|
+ n = s->next;
|
||||||
|
+ if (s == shadow) {
|
||||||
|
+ if (n) n->prev = (struct shadow_list*)0;
|
||||||
|
+ shadow = n;
|
||||||
|
+ } else if (l) {
|
||||||
|
+ if (n) n->prev = l;
|
||||||
|
+ l->next = n;
|
||||||
|
+ }
|
||||||
|
+ free(s);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void clear_mnt(void)
|
||||||
|
+{
|
||||||
|
+ struct nfs_points *p, *n, *l;
|
||||||
|
+
|
||||||
|
+ n = mnts;
|
||||||
|
+ l = (struct nfs_points*)0;
|
||||||
|
+ for (p = mnts; n; p = n) {
|
||||||
|
+ l = p->prev;
|
||||||
|
+ n = p->next;
|
||||||
|
+ if (p == mnts) {
|
||||||
|
+ if (n) n->prev = (struct nfs_points*)0;
|
||||||
|
+ mnts = n;
|
||||||
|
+ } else if (l) {
|
||||||
|
+ if (n) n->prev = l;
|
||||||
|
+ l->next = n;
|
||||||
|
+ }
|
||||||
|
+ if (p->shadow)
|
||||||
|
+ clear_shadow(p->shadow);
|
||||||
|
+ free(p);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Check if path is a shadow of a NFS partition.
|
||||||
|
+ */
|
||||||
|
+static int shadow(struct shadow_list *restrict this, const char *restrict name, const size_t nlen)
|
||||||
|
+{
|
||||||
|
+ struct shadow_list *s;
|
||||||
|
+
|
||||||
|
+ if (!this)
|
||||||
|
+ goto out;
|
||||||
|
+ for (s = this; s; s = s->next) {
|
||||||
|
+ if (nlen < s->nlen)
|
||||||
|
+ continue;
|
||||||
|
+ if (name[s->nlen] != '\0' && name[s->nlen] != '/')
|
||||||
|
+ continue;
|
||||||
|
+ if (strncmp(name, s->name, s->nlen) == 0)
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+out:
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Check path is located on a NFS partition.
|
||||||
|
+ */
|
||||||
|
+static int check4nfs(const char * path, char * real)
|
||||||
|
+{
|
||||||
|
+ char buf[PATH_MAX+1];
|
||||||
|
+ const char *curr;
|
||||||
|
+ int deep = MAXSYMLINKS;
|
||||||
|
+
|
||||||
|
+ if (!mnts) return 0;
|
||||||
|
+
|
||||||
|
+ curr = path;
|
||||||
|
+ do {
|
||||||
|
+ const char *prev;
|
||||||
|
+ int len;
|
||||||
|
+
|
||||||
|
+ if ((prev = strdupa(curr)) == NULL)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ errno = 0;
|
||||||
|
+ if ((len = readlink(curr, buf, PATH_MAX)) < 0)
|
||||||
|
+ break;
|
||||||
|
+ buf[len] = '\0'; /* Don't be fooled by readlink(2) */
|
||||||
|
+
|
||||||
|
+ if (strncmp(prev, "/proc/", 6) == 0) {
|
||||||
|
+ curr = &buf[0];
|
||||||
|
+ break; /* /proc/ provides the real path! */
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (len > 10) {
|
||||||
|
+ char *const ptr = &buf[len - 10];
|
||||||
|
+ if (strcmp(ptr, " (deleted)") == 0) {
|
||||||
|
+ *ptr = '\0';
|
||||||
|
+ curr = &buf[0];
|
||||||
|
+ break; /* Path is deleted from VFS cache */
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (buf[0] != '/') {
|
||||||
|
+ const char *slash;
|
||||||
|
+
|
||||||
|
+ if ((slash = strrchr(prev, '/'))) {
|
||||||
|
+ size_t off = slash - prev + 1;
|
||||||
|
+
|
||||||
|
+ if (off + len > PATH_MAX)
|
||||||
|
+ len = PATH_MAX - off;
|
||||||
|
+
|
||||||
|
+ memmove(&buf[off], &buf[0], len + 1);
|
||||||
|
+ memcpy(&buf[0], prev, off);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ curr = &buf[0];
|
||||||
|
+
|
||||||
|
+ if (deep-- <= 0) return 0;
|
||||||
|
+
|
||||||
|
+ } while (1);
|
||||||
|
+
|
||||||
|
+ if (real) strcpy(real, curr);
|
||||||
|
+
|
||||||
|
+ if (errno == EINVAL) {
|
||||||
|
+ const size_t nlen = strlen(curr);
|
||||||
|
+ struct nfs_points *p;
|
||||||
|
+ for (p = mnts; p; p = p->next) {
|
||||||
|
+ if (nlen < p->nlen)
|
||||||
|
+ continue;
|
||||||
|
+ if (curr[p->nlen] != '\0' && curr[p->nlen] != '/')
|
||||||
|
+ continue;
|
||||||
|
+ if (!strncmp(curr, p->name, p->nlen)) {
|
||||||
|
+ if (shadow(p->shadow, curr, nlen))
|
||||||
|
+ continue;
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
opt_type opts;
|
||||||
|
@@ -835,6 +1120,7 @@ int main(int argc, char *argv[])
|
||||||
|
struct option *optr;
|
||||||
|
char *nsptr;
|
||||||
|
int skip_argv;
|
||||||
|
+ size_t len;
|
||||||
|
|
||||||
|
struct option options[] = {
|
||||||
|
{"all", 0, NULL, 'a'},
|
||||||
|
@@ -931,7 +1217,6 @@ int main(int argc, char *argv[])
|
||||||
|
break;
|
||||||
|
case 'M':
|
||||||
|
opts |= OPT_ISMOUNTPOINT;
|
||||||
|
- read_proc_mounts(&mounts);
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
argc_cnt++;
|
||||||
|
@@ -979,6 +1264,9 @@ int main(int argc, char *argv[])
|
||||||
|
} /* an option */
|
||||||
|
/* Not an option, must be a file specification */
|
||||||
|
|
||||||
|
+ if (!mounts)
|
||||||
|
+ read_proc_mounts(&mounts);
|
||||||
|
+
|
||||||
|
if ((this_name = malloc(sizeof(struct names))) == NULL)
|
||||||
|
continue;
|
||||||
|
this_name->next = NULL;
|
||||||
|
@@ -1030,11 +1318,24 @@ int main(int argc, char *argv[])
|
||||||
|
break;
|
||||||
|
default: /* FILE */
|
||||||
|
this_name->filename = strdup(current_argv);
|
||||||
|
+ len = strlen(this_name->filename);
|
||||||
|
+ if (len > 1 && this_name->filename[len-1] == '/')
|
||||||
|
+ this_name->filename[len-1] = '\0';
|
||||||
|
+ if (len > 1 && this_name->filename[0] != '/') {
|
||||||
|
+ char pwd[MAX_PATHNAME];
|
||||||
|
+ if (getcwd(pwd, MAX_PATHNAME-1)) {
|
||||||
|
+ char *new, *old = this_name->filename;
|
||||||
|
+ if (asprintf(&new, "%s/%s", (strlen(pwd) > 1 ? pwd : ""), old) > 0) {
|
||||||
|
+ this_name->filename = new;
|
||||||
|
+ free(old);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
if (parse_file(this_name, &match_inodes) == 0) {
|
||||||
|
- parse_unixsockets(this_name, &match_inodes, unixsockets);
|
||||||
|
+ parse_unixsockets(this_name, &match_inodes, unixsockets, netdev);
|
||||||
|
if (opts & OPT_MOUNTS)
|
||||||
|
- parse_mounts(this_name, &match_devices, opts);
|
||||||
|
- }
|
||||||
|
+ parse_mounts(this_name, mounts, &match_devices);
|
||||||
|
+ }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1080,11 +1381,14 @@ int main(int argc, char *argv[])
|
||||||
|
#ifdef DEBUG
|
||||||
|
debug_match_lists(names_head, match_inodes, match_devices);
|
||||||
|
#endif
|
||||||
|
- scan_procs(names_head, match_inodes, match_devices, unixsockets,
|
||||||
|
- netdev);
|
||||||
|
- scan_knfsd(names_head, match_inodes, match_devices);
|
||||||
|
- scan_mounts(names_head, match_inodes, match_devices);
|
||||||
|
- scan_swaps(names_head, match_inodes, match_devices);
|
||||||
|
+ scan_procs(opts, names_head, match_inodes, match_devices,
|
||||||
|
+ unixsockets, netdev);
|
||||||
|
+ if (opts & OPT_VERBOSE) {
|
||||||
|
+ scan_knfsd(names_head, match_inodes, match_devices);
|
||||||
|
+ scan_mounts(names_head, mounts, match_inodes, match_devices);
|
||||||
|
+ scan_swaps(names_head, match_inodes, match_devices);
|
||||||
|
+ }
|
||||||
|
+ clear_mnt();
|
||||||
|
return print_matches(names_head, opts, sig_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1250,7 +1554,7 @@ print_matches(struct names *names_head,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
-static struct stat *get_pidstat(const pid_t pid, const char *filename)
|
||||||
|
+static struct stat *get_pidstat(const opt_type opts, const pid_t pid, const char *filename, char *real)
|
||||||
|
{
|
||||||
|
char pathname[256];
|
||||||
|
struct stat *st;
|
||||||
|
@@ -1258,6 +1562,10 @@ static struct stat *get_pidstat(const pi
|
||||||
|
if ((st = (struct stat*)malloc(sizeof(struct stat))) == NULL)
|
||||||
|
return NULL;
|
||||||
|
snprintf(pathname, 256, "/proc/%d/%s", pid, filename);
|
||||||
|
+ if (check4nfs(pathname, real)) {
|
||||||
|
+ if ((opts & OPT_MOUNTS) == 0)
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
if (stat(pathname, st) != 0)
|
||||||
|
goto out;
|
||||||
|
return st;
|
||||||
|
@@ -1309,6 +1617,16 @@ check_dir(const pid_t pid, const char *d
|
||||||
|
}
|
||||||
|
for (dev_tmp = dev_head; dev_tmp != NULL;
|
||||||
|
dev_tmp = dev_tmp->next) {
|
||||||
|
+ if (dev_tmp->name->name_space & NAMESPACE_NFS) {
|
||||||
|
+ char buf[PATH_MAX+1];
|
||||||
|
+ ssize_t len;
|
||||||
|
+ if ((len = readlink(filepath, buf, PATH_MAX)) < 0)
|
||||||
|
+ continue;
|
||||||
|
+ buf[len] = '\0'; /* Don't be fooled by readlink(2) */
|
||||||
|
+ if (islocatedon(buf, dev_tmp->name->filename))
|
||||||
|
+ add_matched_proc(dev_tmp->name, pid,uid, access);
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
if (st.st_dev == dev_tmp->device) {
|
||||||
|
if (access == ACCESS_FILE
|
||||||
|
&& (lstat(filepath, &lst) == 0)
|
||||||
|
@@ -1326,6 +1644,16 @@ check_dir(const pid_t pid, const char *d
|
||||||
|
}
|
||||||
|
for (ino_tmp = ino_head; ino_tmp != NULL;
|
||||||
|
ino_tmp = ino_tmp->next) {
|
||||||
|
+ if (ino_tmp->name->name_space & NAMESPACE_NFS) {
|
||||||
|
+ char buf[PATH_MAX+1];
|
||||||
|
+ ssize_t len;
|
||||||
|
+ if ((len = readlink(filepath, buf, PATH_MAX)) < 0)
|
||||||
|
+ continue;
|
||||||
|
+ buf[len] = '\0'; /* Don't be fooled by readlink(2) */
|
||||||
|
+ if (islocatedon(buf, ino_tmp->name->filename))
|
||||||
|
+ add_matched_proc(ino_tmp->name, pid,uid, access);
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
if (st.st_dev == ino_tmp->device
|
||||||
|
&& st.st_ino == ino_tmp->inode) {
|
||||||
|
if (access == ACCESS_FILE
|
||||||
|
@@ -1372,18 +1700,41 @@ check_map(const pid_t pid, const char *f
|
||||||
|
while (fgets(line, BUFSIZ, fp)) {
|
||||||
|
if (sscanf(line, "%*s %*s %*s %x:%x %lld",
|
||||||
|
&tmp_maj, &tmp_min, &tmp_inode) == 3) {
|
||||||
|
+ const char * filepath = strchr(line, '/');
|
||||||
|
tmp_device = tmp_maj * 256 + tmp_min;
|
||||||
|
for (dev_tmp = dev_head; dev_tmp != NULL;
|
||||||
|
- dev_tmp = dev_tmp->next)
|
||||||
|
+ dev_tmp = dev_tmp->next) {
|
||||||
|
+ if (dev_tmp->name->name_space & NAMESPACE_NFS) {
|
||||||
|
+ char *nl;
|
||||||
|
+ if (!filepath)
|
||||||
|
+ continue;
|
||||||
|
+ if ((nl = strchr(filepath, '\n')))
|
||||||
|
+ nl = '\0';
|
||||||
|
+ if (islocatedon(filepath, dev_tmp->name->filename))
|
||||||
|
+ add_matched_proc(dev_tmp->name, pid,uid, access);
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
if (dev_tmp->device == tmp_device)
|
||||||
|
add_matched_proc(dev_tmp->name, pid,
|
||||||
|
uid, access);
|
||||||
|
+ }
|
||||||
|
for (ino_tmp = ino_head; ino_tmp != NULL;
|
||||||
|
- ino_tmp = ino_tmp->next)
|
||||||
|
+ ino_tmp = ino_tmp->next) {
|
||||||
|
+ if (ino_tmp->name->name_space & NAMESPACE_NFS) {
|
||||||
|
+ char *nl;
|
||||||
|
+ if (!filepath)
|
||||||
|
+ continue;
|
||||||
|
+ if ((nl = strchr(filepath, '\n')))
|
||||||
|
+ nl = '\0';
|
||||||
|
+ if (islocatedon(filepath, ino_tmp->name->filename))
|
||||||
|
+ add_matched_proc(ino_tmp->name, pid,uid, access);
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
if (ino_tmp->device == tmp_device
|
||||||
|
&& ino_tmp->inode == tmp_inode)
|
||||||
|
add_matched_proc(ino_tmp->name, pid,
|
||||||
|
uid, access);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
@@ -1571,7 +1922,7 @@ scan_knfsd(struct names *names_head, str
|
||||||
|
if ((find_space = strpbrk(line, " \t")) == NULL)
|
||||||
|
continue;
|
||||||
|
*find_space = '\0';
|
||||||
|
- if (stat(line, &st) != 0) {
|
||||||
|
+ if (nfssafe(stat, line, &st) != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Scan the devices */
|
||||||
|
@@ -1580,6 +1931,11 @@ scan_knfsd(struct names *names_head, str
|
||||||
|
if (st.st_dev == dev_tmp->device)
|
||||||
|
add_special_proc(dev_tmp->name, PTYPE_KNFSD, 0,
|
||||||
|
line);
|
||||||
|
+ if ((dev_tmp->name->name_space & NAMESPACE_NFS) == 0)
|
||||||
|
+ continue;
|
||||||
|
+ if (strcmp(line, dev_tmp->name->filename))
|
||||||
|
+ continue;
|
||||||
|
+ add_special_proc(dev_tmp->name, PTYPE_MOUNT, 0, line);
|
||||||
|
}
|
||||||
|
for (ino_tmp = ino_head; ino_tmp != NULL;
|
||||||
|
ino_tmp = ino_tmp->next) {
|
||||||
|
@@ -1587,53 +1943,55 @@ scan_knfsd(struct names *names_head, str
|
||||||
|
&& st.st_ino == ino_tmp->inode)
|
||||||
|
add_special_proc(ino_tmp->name, PTYPE_KNFSD, 0,
|
||||||
|
line);
|
||||||
|
+ if ((ino_tmp->name->name_space & NAMESPACE_NFS) == 0)
|
||||||
|
+ continue;
|
||||||
|
+ if (strcmp(line, ino_tmp->name->filename))
|
||||||
|
+ continue;
|
||||||
|
+ add_special_proc(ino_tmp->name, PTYPE_MOUNT, 0, line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
-scan_mounts(struct names *names_head, struct inode_list *ino_head,
|
||||||
|
- struct device_list *dev_head)
|
||||||
|
+scan_mounts(struct names *names_head, struct mount_list *mounts,
|
||||||
|
+ struct inode_list *ino_head, struct device_list *dev_head)
|
||||||
|
{
|
||||||
|
struct device_list *dev_tmp;
|
||||||
|
struct inode_list *ino_tmp;
|
||||||
|
- FILE *fp;
|
||||||
|
- char line[BUFSIZ];
|
||||||
|
- char *find_mountp;
|
||||||
|
- char *find_space;
|
||||||
|
+ struct mount_list *mountptr;
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
- if ((fp = fopen(PROC_MOUNTS, "r")) == NULL) {
|
||||||
|
- fprintf(stderr, "Cannot open %s\n", PROC_MOUNTS);
|
||||||
|
- return;
|
||||||
|
- }
|
||||||
|
- while (fgets(line, BUFSIZ, fp) != NULL) {
|
||||||
|
- if ((find_mountp = strchr(line, ' ')) == NULL)
|
||||||
|
- continue;
|
||||||
|
- find_mountp++;
|
||||||
|
- if ((find_space = strchr(find_mountp, ' ')) == NULL)
|
||||||
|
+ for (mountptr = mounts ; mountptr != NULL ; mountptr = mountptr->next) {
|
||||||
|
+ if (nfssafe(stat, mountptr->mountpoint, &st) != 0)
|
||||||
|
continue;
|
||||||
|
- *find_space = '\0';
|
||||||
|
- if (stat(find_mountp, &st) != 0) {
|
||||||
|
- continue;
|
||||||
|
- }
|
||||||
|
/* Scan the devices */
|
||||||
|
for (dev_tmp = dev_head; dev_tmp != NULL;
|
||||||
|
dev_tmp = dev_tmp->next) {
|
||||||
|
if (st.st_dev == dev_tmp->device)
|
||||||
|
add_special_proc(dev_tmp->name, PTYPE_MOUNT, 0,
|
||||||
|
- find_mountp);
|
||||||
|
+ mountptr->mountpoint);
|
||||||
|
+ if ((dev_tmp->name->name_space & NAMESPACE_NFS) == 0)
|
||||||
|
+ continue;
|
||||||
|
+ if (strcmp(mountptr->mountpoint, dev_tmp->name->filename))
|
||||||
|
+ continue;
|
||||||
|
+ add_special_proc(dev_tmp->name, PTYPE_MOUNT, 0,
|
||||||
|
+ mountptr->mountpoint);
|
||||||
|
}
|
||||||
|
for (ino_tmp = ino_head; ino_tmp != NULL;
|
||||||
|
ino_tmp = ino_tmp->next) {
|
||||||
|
if (st.st_dev == ino_tmp->device
|
||||||
|
&& st.st_ino == ino_tmp->inode)
|
||||||
|
add_special_proc(ino_tmp->name, PTYPE_MOUNT, 0,
|
||||||
|
- find_mountp);
|
||||||
|
+ mountptr->mountpoint);
|
||||||
|
+ if ((ino_tmp->name->name_space & NAMESPACE_NFS) == 0)
|
||||||
|
+ continue;
|
||||||
|
+ if (strcmp(mountptr->mountpoint, ino_tmp->name->filename))
|
||||||
|
+ continue;
|
||||||
|
+ add_special_proc(ino_tmp->name, PTYPE_MOUNT, 0,
|
||||||
|
+ mountptr->mountpoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
@@ -1682,3 +2040,59 @@ scan_swaps(struct names *names_head, str
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+static sigjmp_buf jenv;
|
||||||
|
+static int timeout = 5;
|
||||||
|
+static void
|
||||||
|
+sigalarm(int sig)
|
||||||
|
+{
|
||||||
|
+ if (sig == SIGALRM)
|
||||||
|
+ siglongjmp(jenv, 1);
|
||||||
|
+}
|
||||||
|
+static int
|
||||||
|
+nfssafe(stat_t func, const char *path, struct stat *buf)
|
||||||
|
+{
|
||||||
|
+ pid_t pid = 0;
|
||||||
|
+ int ret = 0, pipes[4];
|
||||||
|
+
|
||||||
|
+ if (pipe(&pipes[0]) < 0)
|
||||||
|
+ goto err;
|
||||||
|
+ switch ((pid = fork ())) {
|
||||||
|
+ case -1:
|
||||||
|
+ close(pipes[0]);
|
||||||
|
+ close(pipes[1]);
|
||||||
|
+ goto err;
|
||||||
|
+ case 0:
|
||||||
|
+ (void) signal(SIGALRM, SIG_DFL);
|
||||||
|
+ close(pipes[0]);
|
||||||
|
+ if ((ret = func(path, buf)) == 0)
|
||||||
|
+ write(pipes[1], buf, sizeof(struct stat));
|
||||||
|
+ close(pipes[1]);
|
||||||
|
+ exit(ret);
|
||||||
|
+ default:
|
||||||
|
+ close(pipes[1]);
|
||||||
|
+ if (sigsetjmp(jenv, 1)) {
|
||||||
|
+ (void) alarm(0);
|
||||||
|
+ (void) signal(SIGALRM, SIG_DFL);
|
||||||
|
+ if (waitpid(0, (int*)0, WNOHANG) == 0)
|
||||||
|
+ kill(pid, SIGKILL);
|
||||||
|
+ errno = ETIMEDOUT;
|
||||||
|
+ timeout = 1;
|
||||||
|
+ goto err;
|
||||||
|
+ }
|
||||||
|
+ (void) signal(SIGALRM, sigalarm);
|
||||||
|
+ (void) alarm(timeout);
|
||||||
|
+ if (read(pipes[0], buf, sizeof(struct stat)) == 0) {
|
||||||
|
+ errno = EFAULT;
|
||||||
|
+ ret = -1;
|
||||||
|
+ }
|
||||||
|
+ (void) alarm(0);
|
||||||
|
+ (void) signal(SIGALRM, SIG_DFL);
|
||||||
|
+ close(pipes[0]);
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ return ret;
|
||||||
|
+err:
|
||||||
|
+ return -1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
--- src/fuser.h
|
||||||
|
+++ src/fuser.h 2010-07-13 12:53:15.000000000 +0000
|
||||||
|
@@ -66,6 +66,11 @@ struct inode_list {
|
||||||
|
struct inode_list *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
+struct mountdev_list {
|
||||||
|
+ char *dir;
|
||||||
|
+ struct mountdev_list *next;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
struct device_list {
|
||||||
|
struct names *name;
|
||||||
|
dev_t device;
|
||||||
|
@@ -85,9 +90,33 @@ struct mount_list {
|
||||||
|
struct mount_list *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
+struct shadow_list
|
||||||
|
+{
|
||||||
|
+ struct shadow_list *next;
|
||||||
|
+ struct shadow_list *prev;
|
||||||
|
+ size_t nlen;
|
||||||
|
+ char * name;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+struct nfs_points {
|
||||||
|
+ struct nfs_points *next, *prev;
|
||||||
|
+ struct shadow_list *shadow;
|
||||||
|
+ size_t nlen;
|
||||||
|
+ char * name;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
|
||||||
|
+# ifndef restrict
|
||||||
|
+# define restrict __restrict__
|
||||||
|
+# endif
|
||||||
|
+#endif
|
||||||
|
+#define alignof(type) ((sizeof(type)+(sizeof(void*)-1)) & ~(sizeof(void*)-1))
|
||||||
|
+
|
||||||
|
+
|
||||||
|
#define NAMESPACE_FILE 0
|
||||||
|
#define NAMESPACE_TCP 1
|
||||||
|
#define NAMESPACE_UDP 2
|
||||||
|
+#define NAMESPACE_NFS 4
|
||||||
|
|
||||||
|
#define MAX_PATHNAME 200
|
||||||
|
#define MAX_CMDNAME 16
|
74
psmisc-22.12-pstree.patch
Normal file
74
psmisc-22.12-pstree.patch
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
--- src/pstree.c
|
||||||
|
+++ src/pstree.c 2010-07-13 10:27:54.139239142 +0000
|
||||||
|
@@ -61,6 +61,7 @@ extern const char *__progname;
|
||||||
|
#define UTF_HD "\342\224\254" /* U+252C, Horizontal and down */
|
||||||
|
|
||||||
|
#define VT_BEG "\033(0\017" /* use graphic chars */
|
||||||
|
+#define VT_LEN 4
|
||||||
|
#define VT_END "\033(B" /* back to normal char set */
|
||||||
|
#define VT_V "x" /* see UTF definitions above */
|
||||||
|
#define VT_VR "t"
|
||||||
|
@@ -230,6 +231,27 @@ static void out_scontext(security_contex
|
||||||
|
}
|
||||||
|
#endif /*WITH_SELINUX */
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * Only affects vt100 line drawing mode: Do not count the strlen of
|
||||||
|
+ * VT_BEG to prevent doing end-of-line way too early:
|
||||||
|
+ */
|
||||||
|
+static void
|
||||||
|
+out_sym (const char *str)
|
||||||
|
+{
|
||||||
|
+ int seq = 0;
|
||||||
|
+ if (sym == &sym_vt100 && *str == '\033') {
|
||||||
|
+ seq = 1;
|
||||||
|
+ if (cur_x <= output_width || !trunc)
|
||||||
|
+ cur_x -= VT_LEN;
|
||||||
|
+ }
|
||||||
|
+ out_string(str);
|
||||||
|
+ if (seq) {
|
||||||
|
+ str = VT_END;
|
||||||
|
+ while (*str)
|
||||||
|
+ putchar (*str++);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
|
||||||
|
static void out_newline(void)
|
||||||
|
{
|
||||||
|
@@ -426,11 +448,12 @@ dump_tree(PROC * current, int level, int
|
||||||
|
for (lvl = 0; lvl < level; lvl++) {
|
||||||
|
for (i = width[lvl] + 1; i; i--)
|
||||||
|
out_char(' ');
|
||||||
|
- out_string(lvl ==
|
||||||
|
- level -
|
||||||
|
- 1 ? last ? sym->last_2 : sym->branch_2 : more[lvl +
|
||||||
|
- 1] ?
|
||||||
|
- sym->vert_2 : sym->empty_2);
|
||||||
|
+ /*
|
||||||
|
+ * Replace all three symbol-drawing calls with calls to out_sym()
|
||||||
|
+ * to handle VT100 line drawing sequences if VT100 mode is active:
|
||||||
|
+ */
|
||||||
|
+ out_sym(lvl == level - 1 ? last ? sym->last_2 : sym->branch_2 :
|
||||||
|
+ more[lvl + 1] ? sym->vert_2 : sym->empty_2);
|
||||||
|
}
|
||||||
|
if (rep < 2)
|
||||||
|
add = 0;
|
||||||
|
@@ -531,7 +554,7 @@ dump_tree(PROC * current, int level, int
|
||||||
|
}
|
||||||
|
width[level] = comm_len + cur_x - offset + add;
|
||||||
|
if (cur_x >= output_width && trunc) {
|
||||||
|
- out_string(sym->first_3);
|
||||||
|
+ out_sym(sym->first_3);
|
||||||
|
out_string("+");
|
||||||
|
out_newline();
|
||||||
|
return;
|
||||||
|
@@ -553,7 +576,7 @@ dump_tree(PROC * current, int level, int
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (first) {
|
||||||
|
- out_string(next ? sym->first_3 : sym->single_3);
|
||||||
|
+ out_sym(next ? sym->first_3 : sym->single_3);
|
||||||
|
first = 0;
|
||||||
|
}
|
||||||
|
dump_tree(walk->child, level + 1, count + 1,
|
11
psmisc-22.12-pstree_overflow.patch
Normal file
11
psmisc-22.12-pstree_overflow.patch
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
--- src/pstree.c
|
||||||
|
+++ src/pstree.c 2010-07-13 10:18:31.454925471 +0000
|
||||||
|
@@ -69,7 +69,7 @@ extern const char *__progname;
|
||||||
|
#define VT_HD "w"
|
||||||
|
|
||||||
|
typedef struct _proc {
|
||||||
|
- char comm[COMM_LEN + 1];
|
||||||
|
+ char comm[COMM_LEN + 2 + 1]; /* add another 2 for thread brackets */
|
||||||
|
char **argv; /* only used : argv[0] is 1st arg; undef if argc < 1 */
|
||||||
|
int argc; /* with -a : number of arguments, -1 if swapped */
|
||||||
|
pid_t pid;
|
11
psmisc-22.12-tigetstr.patch
Normal file
11
psmisc-22.12-tigetstr.patch
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
--- src/pstree.c
|
||||||
|
+++ src/pstree.c 2010-07-13 10:14:50.978925622 +0000
|
||||||
|
@@ -868,7 +868,7 @@ int main(int argc, char **argv)
|
||||||
|
} else if (isatty(1) && (termname = getenv("TERM")) &&
|
||||||
|
(strlen(termname) > 0) &&
|
||||||
|
(setupterm(NULL, 1 /* stdout */ , NULL) == OK) &&
|
||||||
|
- (tigetstr("acsc") > 0)) {
|
||||||
|
+ ((int)tigetstr("acsc") > 0)) {
|
||||||
|
/*
|
||||||
|
* Failing that, if TERM is defined, a non-null value, and the terminal
|
||||||
|
* has the VT100 graphics charset, use it.
|
129
psmisc-22.12-writeonly.patch
Normal file
129
psmisc-22.12-writeonly.patch
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
--- doc/fuser.1
|
||||||
|
+++ doc/fuser.1 2010-07-13 13:19:57.000000000 +0000
|
||||||
|
@@ -12,6 +12,7 @@ fuser \- identify processes using files
|
||||||
|
.RB [ \-k
|
||||||
|
.RB [ \-i ]
|
||||||
|
.RB [ \-M ]
|
||||||
|
+.RB [ \-w ]
|
||||||
|
.RB [ \- \fISIGNAL
|
||||||
|
] ]
|
||||||
|
.IR name " ..."
|
||||||
|
@@ -102,6 +103,10 @@ Request will be fulfilled only if \fINAM
|
||||||
|
This is an invaluable seatbelt which prevents you from killing the machine
|
||||||
|
if \fINAME\fR happens to not be a filesystem.
|
||||||
|
.TP
|
||||||
|
+\fB\-w\fP
|
||||||
|
+Kill only processes which have write access. This option is
|
||||||
|
+silently ignored if \fB\-k\fP is not present too.
|
||||||
|
+.TP
|
||||||
|
\fB\-n \fISPACE\fR, \fB\-\-namespace\fR \fISPACE\fR
|
||||||
|
Select a different name space. The name spaces \fBfile\fR (file names, the
|
||||||
|
default), \fBudp\fR (local UDP ports), and \fBtcp\fR (local TCP ports) are
|
||||||
|
--- src/fuser.c
|
||||||
|
+++ src/fuser.c 2010-07-13 13:25:44.000000000 +0000
|
||||||
|
@@ -75,7 +75,7 @@ static struct stat *get_pidstat(const op
|
||||||
|
static uid_t getpiduid(const pid_t pid);
|
||||||
|
static int print_matches(struct names *names_head, const opt_type opts,
|
||||||
|
const int sig_number);
|
||||||
|
-static void kill_matched_proc(struct procs *pptr, const opt_type opts,
|
||||||
|
+static int kill_matched_proc(struct procs *pptr, const opt_type opts,
|
||||||
|
const int sig_number);
|
||||||
|
|
||||||
|
/*int parse_mount(struct names *this_name, struct device_list **dev_list);*/
|
||||||
|
@@ -127,6 +127,7 @@ static void usage(const char *errormsg)
|
||||||
|
" -SIGNAL send this signal instead of SIGKILL\n"
|
||||||
|
" -u,--user display user IDs\n"
|
||||||
|
" -v,--verbose verbose output\n"
|
||||||
|
+ " -w,--writeonly kill only processes with write access\n"
|
||||||
|
" -V,--version display version information\n"));
|
||||||
|
#ifdef WITH_IPV6
|
||||||
|
fprintf(stderr, _(
|
||||||
|
@@ -1133,6 +1134,7 @@ int main(int argc, char *argv[])
|
||||||
|
{"silent", 0, NULL, 's'},
|
||||||
|
{"user", 0, NULL, 'u'},
|
||||||
|
{"verbose", 0, NULL, 'v'},
|
||||||
|
+ {"writeonly", 0, NULL, 'w'},
|
||||||
|
{"version", 0, NULL, 'V'},
|
||||||
|
#ifdef WITH_IPV6
|
||||||
|
{"ipv4", 0, NULL, '4'},
|
||||||
|
@@ -1244,6 +1246,9 @@ int main(int argc, char *argv[])
|
||||||
|
case 'v':
|
||||||
|
opts |= OPT_VERBOSE;
|
||||||
|
break;
|
||||||
|
+ case 'w':
|
||||||
|
+ opts |= OPT_WRITE;
|
||||||
|
+ break;
|
||||||
|
case 'V':
|
||||||
|
print_version();
|
||||||
|
return 0;
|
||||||
|
@@ -1406,6 +1411,7 @@ print_matches(struct names *names_head,
|
||||||
|
int len = 0;
|
||||||
|
struct passwd *pwent = NULL;
|
||||||
|
int have_match = 0;
|
||||||
|
+ int have_kill = 0;
|
||||||
|
int name_has_procs;
|
||||||
|
|
||||||
|
for (nptr = names_head; nptr != NULL; nptr = nptr->next) {
|
||||||
|
@@ -1546,8 +1552,8 @@ print_matches(struct names *names_head,
|
||||||
|
}
|
||||||
|
} /* be silent */
|
||||||
|
if (opts & OPT_KILL)
|
||||||
|
- kill_matched_proc(nptr->matched_procs, opts,
|
||||||
|
- sig_number);
|
||||||
|
+ have_kill = kill_matched_proc(nptr->matched_procs,
|
||||||
|
+ opts, sig_number);
|
||||||
|
|
||||||
|
} /* next name */
|
||||||
|
return (have_match == 1 ? 0 : 1);
|
||||||
|
@@ -1857,12 +1863,13 @@ static int ask(const pid_t pid)
|
||||||
|
} /* while */
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void
|
||||||
|
+static int
|
||||||
|
kill_matched_proc(struct procs *proc_head, const opt_type opts,
|
||||||
|
const int sig_number)
|
||||||
|
{
|
||||||
|
struct procs *pptr;
|
||||||
|
pid_t mypid;
|
||||||
|
+ int ret = 0;
|
||||||
|
|
||||||
|
mypid = getpid();
|
||||||
|
|
||||||
|
@@ -1871,13 +1878,18 @@ kill_matched_proc(struct procs *proc_hea
|
||||||
|
continue; /* dont kill myself */
|
||||||
|
if ( pptr->proc_type != PTYPE_NORMAL )
|
||||||
|
continue;
|
||||||
|
+ if ((opts & OPT_WRITE) && ((pptr->access & ACCESS_FILEWR) == 0))
|
||||||
|
+ continue;
|
||||||
|
if ((opts & OPT_INTERACTIVE) && (ask(pptr->pid) == 0))
|
||||||
|
continue;
|
||||||
|
if ( kill(pptr->pid, sig_number) < 0) {
|
||||||
|
fprintf(stderr, _("Could not kill process %d: %s\n"),
|
||||||
|
pptr->pid, strerror(errno));
|
||||||
|
+ continue;
|
||||||
|
}
|
||||||
|
+ ret = 1;
|
||||||
|
}
|
||||||
|
+ return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static dev_t find_net_dev(void)
|
||||||
|
--- src/fuser.h
|
||||||
|
+++ src/fuser.h 2010-07-13 13:26:15.000000000 +0000
|
||||||
|
@@ -1,6 +1,6 @@
|
||||||
|
|
||||||
|
/* Option Flags */
|
||||||
|
-typedef unsigned char opt_type;
|
||||||
|
+typedef unsigned short opt_type;
|
||||||
|
|
||||||
|
#define OPT_VERBOSE 1
|
||||||
|
#define OPT_ALLFILES 2
|
||||||
|
@@ -10,6 +10,7 @@ typedef unsigned char opt_type;
|
||||||
|
#define OPT_SILENT 32
|
||||||
|
#define OPT_USER 64
|
||||||
|
#define OPT_ISMOUNTPOINT 128
|
||||||
|
+#define OPT_WRITE 256
|
||||||
|
|
||||||
|
struct procs {
|
||||||
|
pid_t pid;
|
49
psmisc-22.12.dif
Normal file
49
psmisc-22.12.dif
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
--- configure.ac
|
||||||
|
+++ configure.ac 2010-07-13 13:54:30.000000000 +0000
|
||||||
|
@@ -66,7 +66,8 @@ AC_CHECK_MEMBERS([struct user_regs_struc
|
||||||
|
struct user_regs_struct.rdi,
|
||||||
|
struct user_regs_struct.rsi,
|
||||||
|
struct user_regs_struct.rdx], [],[],
|
||||||
|
- [#include <sys/user.h>])
|
||||||
|
+ [#include <sys/types.h>
|
||||||
|
+ #include <sys/user.h>])
|
||||||
|
AC_CHECK_MEMBERS([struct pt_regs.orig_gpr3,
|
||||||
|
struct pt_regs.gpr], [],[], [#include <linux/ptrace.h>])
|
||||||
|
AC_CHECK_MEMBERS([struct pt_regs.uregs],[],[], [#include <asm/ptrace.h>])
|
||||||
|
--- src/fuser.c
|
||||||
|
+++ src/fuser.c 2010-07-13 15:01:58.000000000 +0000
|
||||||
|
@@ -1120,7 +1120,8 @@ int main(int argc, char *argv[])
|
||||||
|
char option_buf[3];
|
||||||
|
struct option *optr;
|
||||||
|
char *nsptr;
|
||||||
|
- int skip_argv;
|
||||||
|
+ int skip_argv;
|
||||||
|
+ int seen_file;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
struct option options[] = {
|
||||||
|
@@ -1160,6 +1161,7 @@ int main(int argc, char *argv[])
|
||||||
|
netdev = find_net_dev();
|
||||||
|
fill_unix_cache(&unixsockets);
|
||||||
|
|
||||||
|
+ seen_file = 0;
|
||||||
|
for (argc_cnt = 1; argc_cnt < argc; argc_cnt++) {
|
||||||
|
current_argv = argv[argc_cnt];
|
||||||
|
if (current_argv[0] == '-') { /* its an option */
|
||||||
|
@@ -1291,6 +1293,7 @@ int main(int argc, char *argv[])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this_name->matched_procs = NULL;
|
||||||
|
+ seen_file = 1;
|
||||||
|
if (opts & (OPT_MOUNTS|OPT_ISMOUNTPOINT)
|
||||||
|
&& this_name->name_space != NAMESPACE_FILE)
|
||||||
|
usage(_
|
||||||
|
@@ -1350,7 +1353,7 @@ int main(int argc, char *argv[])
|
||||||
|
names_tail->next = this_name;
|
||||||
|
names_tail = this_name;
|
||||||
|
} /* for across the argvs */
|
||||||
|
- if (names_head == NULL)
|
||||||
|
+ if (names_head == NULL && !seen_file)
|
||||||
|
usage(_("No process specification given"));
|
||||||
|
|
||||||
|
if (opts & OPT_SILENT) {
|
3
psmisc-22.12.tar.bz2
Normal file
3
psmisc-22.12.tar.bz2
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:a496b4e684dc5cd5ed28ae296b071701d39845e0a799396dbc005f2736340b1d
|
||||||
|
size 298393
|
@ -1,18 +0,0 @@
|
|||||||
--- src/fuser.c
|
|
||||||
+++ src/fuser.c 2008-09-01 15:03:05.000000000 +0200
|
|
||||||
@@ -1404,6 +1404,7 @@ void fill_unix_cache(struct unixsocket_l
|
|
||||||
*unixsocket_head = newsocket;
|
|
||||||
} /* while */
|
|
||||||
|
|
||||||
+ fclose(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int isnetfs(const char * type)
|
|
||||||
@@ -1650,6 +1651,7 @@ static void scan_knfsd(struct names *nam
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
+ fclose(fp);
|
|
||||||
}
|
|
||||||
#endif /* NFSCHECKS */
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
|||||||
--- src/fuser.c
|
|
||||||
+++ src/fuser.c 2008-05-16 14:58:07.906452331 +0200
|
|
||||||
@@ -1310,12 +1310,21 @@ void fill_unix_cache(struct unixsocket_l
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
while (fgets(line, BUFSIZ, fp) != NULL) {
|
|
||||||
+ char * path;
|
|
||||||
+ scanned_path = (char*)0;
|
|
||||||
if (sscanf(line, "%*x: %*x %*x %*x %*x %*d %d %as",
|
|
||||||
- &scanned_inode,
|
|
||||||
- &scanned_path) != 2)
|
|
||||||
+ &scanned_inode, &scanned_path) != 2) {
|
|
||||||
+ if (scanned_path)
|
|
||||||
+ free(scanned_path);
|
|
||||||
continue;
|
|
||||||
+ }
|
|
||||||
+ if (scanned_path == (char*)0)
|
|
||||||
+ continue;
|
|
||||||
+ path = scanned_path;
|
|
||||||
+ if (*scanned_path == '@')
|
|
||||||
+ scanned_path++;
|
|
||||||
if (stat(scanned_path, &st) < 0) {
|
|
||||||
- free(scanned_path);
|
|
||||||
+ free(path);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ( (newsocket = malloc(sizeof(struct unixsocket_list))) == NULL)
|
|
||||||
@@ -1323,7 +1332,7 @@ void fill_unix_cache(struct unixsocket_l
|
|
||||||
newsocket->sun_name = strdup(scanned_path);
|
|
||||||
newsocket->inode = st.st_ino;
|
|
||||||
newsocket->dev = st.st_dev;
|
|
||||||
- newsocket->net_inode = scanned_inode;
|
|
||||||
+ newsocket->net_inode = scanned_inode;
|
|
||||||
newsocket->next = *unixsocket_head;
|
|
||||||
*unixsocket_head = newsocket;
|
|
||||||
} /* while */
|
|
@ -1,11 +0,0 @@
|
|||||||
--- src/pstree.c
|
|
||||||
+++ src/pstree.c 2008-10-09 16:24:23.000000000 +0200
|
|
||||||
@@ -912,7 +912,7 @@ main (int argc, char **argv)
|
|
||||||
} else if (isatty (1) && (termname = getenv ("TERM")) && \
|
|
||||||
(strlen (termname) > 0) && \
|
|
||||||
(setupterm (NULL, 1 /* stdout */, NULL) == OK) && \
|
|
||||||
- (tigetstr ("acsc") > 0)) {
|
|
||||||
+ ((int)tigetstr ("acsc") > 0)) {
|
|
||||||
/*
|
|
||||||
* Failing that, if TERM is defined, a non-null value, and the terminal
|
|
||||||
* has the VT100 graphics charset, use it.
|
|
@ -1,241 +0,0 @@
|
|||||||
--- src/fuser.c
|
|
||||||
+++ src/fuser.c 2009-08-10 11:30:01.674401417 +0200
|
|
||||||
@@ -225,6 +225,9 @@ static void scan_procs(const opt_type op
|
|
||||||
if (islocatedon(&cwd_real[0], ino_tmp->name->filename))
|
|
||||||
add_matched_proc(ino_tmp->name, pid, uid, ACCESS_CWD);
|
|
||||||
}
|
|
||||||
+ if (root_stat) free(root_stat);
|
|
||||||
+ if (cwd_stat) free(cwd_stat);
|
|
||||||
+ if (exe_stat) free(exe_stat);
|
|
||||||
#ifndef __linux__
|
|
||||||
check_dir(pid, "lib", dev_head, ino_head, uid, ACCESS_MMAP, sockets, netdev);
|
|
||||||
check_dir(pid, "mmap", dev_head, ino_head, uid, ACCESS_MMAP, sockets, netdev);
|
|
||||||
@@ -239,10 +242,9 @@ static void add_inode(struct inode_list
|
|
||||||
{
|
|
||||||
struct inode_list *ino_tmp, *ino_head;
|
|
||||||
|
|
||||||
- ino_head = *ino_list;
|
|
||||||
-
|
|
||||||
- if ( (ino_tmp = malloc(sizeof(struct inode_list))) == NULL)
|
|
||||||
+ if ( (ino_tmp = (struct inode_list*)malloc(sizeof(struct inode_list))) == NULL)
|
|
||||||
return;
|
|
||||||
+ ino_head = *ino_list;
|
|
||||||
ino_tmp->name = this_name;
|
|
||||||
ino_tmp->device = device;
|
|
||||||
ino_tmp->inode = inode;
|
|
||||||
@@ -250,15 +252,15 @@ static void add_inode(struct inode_list
|
|
||||||
*ino_list = ino_tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void add_device(struct device_list **dev_list, struct names *this_name, dev_t device)
|
|
||||||
+static void add_device(struct device_list **restrict dev_list, struct names *this_name, dev_t device)
|
|
||||||
{
|
|
||||||
struct device_list *dev_tmp, *dev_head;
|
|
||||||
|
|
||||||
/*printf("Adding device %s %d\n", this_name->filename, device);*/
|
|
||||||
- dev_head = *dev_list;
|
|
||||||
|
|
||||||
- if ( (dev_tmp = malloc(sizeof(struct device_list))) == NULL)
|
|
||||||
+ if ( (dev_tmp = (struct device_list*)malloc(sizeof(struct device_list))) == NULL)
|
|
||||||
return;
|
|
||||||
+ dev_head = *dev_list;
|
|
||||||
dev_tmp->name = this_name;
|
|
||||||
dev_tmp->device = device;
|
|
||||||
dev_tmp->next = dev_head;
|
|
||||||
@@ -269,16 +271,14 @@ static void add_ip_conn(struct ip_connec
|
|
||||||
{
|
|
||||||
struct ip_connections *ip_tmp, *ip_head;
|
|
||||||
|
|
||||||
- ip_head = *ip_list;
|
|
||||||
-
|
|
||||||
if ( (ip_tmp = malloc(sizeof(struct ip_connections))) == NULL)
|
|
||||||
return;
|
|
||||||
+ ip_head = *ip_list;
|
|
||||||
ip_tmp->name = this_name;
|
|
||||||
ip_tmp->lcl_port = lcl_port;
|
|
||||||
ip_tmp->rmt_port = rmt_port;
|
|
||||||
ip_tmp->rmt_address.s_addr = rmt_address;
|
|
||||||
ip_tmp->next = ip_head;
|
|
||||||
-
|
|
||||||
*ip_list = ip_tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -287,10 +287,9 @@ static void add_ip6_conn(struct ip6_conn
|
|
||||||
{
|
|
||||||
struct ip6_connections *ip_tmp, *ip_head;
|
|
||||||
|
|
||||||
- ip_head = *ip_list;
|
|
||||||
-
|
|
||||||
if ( (ip_tmp = malloc(sizeof(struct ip6_connections))) == NULL)
|
|
||||||
return;
|
|
||||||
+ ip_head = *ip_list;
|
|
||||||
ip_tmp->name = this_name;
|
|
||||||
ip_tmp->lcl_port = lcl_port;
|
|
||||||
ip_tmp->rmt_port = rmt_port;
|
|
||||||
@@ -319,7 +318,7 @@ static void add_matched_proc(struct name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Not found */
|
|
||||||
- if ( (pptr = malloc(sizeof (struct procs))) == NULL) {
|
|
||||||
+ if ( (pptr = (struct procs*)malloc(sizeof (struct procs))) == NULL) {
|
|
||||||
fprintf(stderr,_("Cannot allocate memory for matched proc: %s\n"), strerror(errno));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
@@ -329,10 +328,13 @@ static void add_matched_proc(struct name
|
|
||||||
pptr->next = NULL;
|
|
||||||
/* set command name */
|
|
||||||
pptr->command = NULL;
|
|
||||||
+
|
|
||||||
+ fp = NULL;
|
|
||||||
+ pathname = NULL;
|
|
||||||
if ( (asprintf(&pathname, "/proc/%d/stat", pid) > 0) &&
|
|
||||||
( (fp = fopen(pathname, "r")) != NULL) &&
|
|
||||||
( fscanf(fp, "%*d (%100[^)]", cmdname) == 1))
|
|
||||||
- if ( (pptr->command = malloc(MAX_CMDNAME+1)) != NULL) {
|
|
||||||
+ if ( (pptr->command = (char*)malloc(MAX_CMDNAME+1)) != NULL) {
|
|
||||||
cmdlen = 0;
|
|
||||||
for (cptr = cmdname; cmdlen < MAX_CMDNAME && *cptr ; cptr++) {
|
|
||||||
if (isprint(*cptr))
|
|
||||||
@@ -346,6 +348,10 @@ static void add_matched_proc(struct name
|
|
||||||
name_list->matched_procs = pptr;
|
|
||||||
else
|
|
||||||
last_proc->next = pptr;
|
|
||||||
+ if (pathname)
|
|
||||||
+ free(pathname);
|
|
||||||
+ if (fp)
|
|
||||||
+ fclose(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
int parse_mount(struct names *this_name, struct device_list **dev_list)
|
|
||||||
@@ -372,16 +378,16 @@ int parse_file(struct names *this_name,
|
|
||||||
|
|
||||||
real[0] = '\0';
|
|
||||||
if (check4nfs(this_name->filename, real)) {
|
|
||||||
- if ((opts & (OPT_MOUNTPOINT|OPT_MOUNTS)) == 0) {
|
|
||||||
+ if (this_name->filename)
|
|
||||||
free(this_name->filename);
|
|
||||||
- this_name->filename = strdup(real);
|
|
||||||
- this_name->name_space |= NAMESPACE_NFS;
|
|
||||||
- add_inode(ino_list, this_name, (dev_t)-1, (ino_t)-1);
|
|
||||||
- return 0;
|
|
||||||
- }
|
|
||||||
+ this_name->filename = strdup(real);
|
|
||||||
+ this_name->name_space |= NAMESPACE_NFS;
|
|
||||||
+ add_inode(ino_list, this_name, (dev_t)-1, (ino_t)-1);
|
|
||||||
+ return 0;
|
|
||||||
}
|
|
||||||
if (real[0] != '\0') {
|
|
||||||
- free(this_name->filename);
|
|
||||||
+ if (this_name->filename)
|
|
||||||
+ free(this_name->filename);
|
|
||||||
this_name->filename = strdup(real);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -662,7 +668,7 @@ void find_net_sockets(struct inode_list
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
- return ;
|
|
||||||
+ fclose(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef WITH_IPV6
|
|
||||||
@@ -725,6 +731,7 @@ void find_net6_sockets(struct inode_list
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+ fclose(fp);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1218,23 +1225,25 @@ static struct stat *get_pidstat(const op
|
|
||||||
char pathname[256];
|
|
||||||
struct stat *st;
|
|
||||||
|
|
||||||
- if ( (st = malloc(sizeof(struct stat))) == NULL)
|
|
||||||
+ if ( (st = (struct stat*)malloc(sizeof(struct stat))) == NULL)
|
|
||||||
return NULL;
|
|
||||||
snprintf(pathname, 256, "/proc/%d/%s", pid, filename);
|
|
||||||
if (check4nfs(pathname, real)) {
|
|
||||||
if ((opts & (OPT_MOUNTPOINT|OPT_MOUNTS)) == 0)
|
|
||||||
- return NULL;
|
|
||||||
+ goto out;
|
|
||||||
}
|
|
||||||
if (stat(pathname, st) != 0)
|
|
||||||
- return NULL;
|
|
||||||
- else
|
|
||||||
- return st;
|
|
||||||
+ goto out;
|
|
||||||
+ return st;
|
|
||||||
+out:
|
|
||||||
+ free(st);
|
|
||||||
+ return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void check_dir(const pid_t pid, const char *dirname, struct device_list *dev_head, struct inode_list *ino_head, const uid_t uid, const char access,
|
|
||||||
struct unixsocket_list *sockets, dev_t netdev)
|
|
||||||
{
|
|
||||||
- char *dirpath, *filepath;
|
|
||||||
+ char *dirpath = NULL, *filepath = NULL;
|
|
||||||
DIR *dirp;
|
|
||||||
struct dirent *direntry;
|
|
||||||
struct inode_list *ino_tmp;
|
|
||||||
@@ -1243,13 +1252,13 @@ static void check_dir(const pid_t pid, c
|
|
||||||
struct stat st, lst;
|
|
||||||
|
|
||||||
if ( (dirpath = malloc(MAX_PATHNAME)) == NULL)
|
|
||||||
- return;
|
|
||||||
+ goto out;
|
|
||||||
if ( (filepath = malloc(MAX_PATHNAME)) == NULL)
|
|
||||||
- return;
|
|
||||||
+ goto out;
|
|
||||||
|
|
||||||
snprintf(dirpath, MAX_PATHNAME, "/proc/%d/%s", pid, dirname);
|
|
||||||
if ( (dirp = opendir(dirpath)) == NULL)
|
|
||||||
- return;
|
|
||||||
+ goto out;
|
|
||||||
while ( (direntry = readdir(dirp)) != NULL) {
|
|
||||||
if (direntry->d_name[0] < '0' || direntry->d_name[0] > '9')
|
|
||||||
continue;
|
|
||||||
@@ -1293,8 +1302,11 @@ static void check_dir(const pid_t pid, c
|
|
||||||
}
|
|
||||||
} /* while fd_dent */
|
|
||||||
closedir(dirp);
|
|
||||||
- free(dirpath);
|
|
||||||
- free(filepath);
|
|
||||||
+out:
|
|
||||||
+ if (dirpath)
|
|
||||||
+ free(dirpath);
|
|
||||||
+ if (filepath)
|
|
||||||
+ free(filepath);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void check_map(const pid_t pid, const char *filename, struct device_list *dev_head, struct inode_list *ino_head, const uid_t uid, const char access)
|
|
||||||
@@ -1349,7 +1361,7 @@ void add_mount_device(struct mountdev_li
|
|
||||||
struct mountdev_list *newmount;
|
|
||||||
/*printf("Adding mount Path: %s Dir:%s dev:%0x\n",dir, fsname, device);*/
|
|
||||||
|
|
||||||
- if ( (newmount = malloc(sizeof(struct mountdev_list))) == NULL)
|
|
||||||
+ if ( (newmount = (struct mountdev_list*)malloc(sizeof(struct mountdev_list))) == NULL)
|
|
||||||
return;
|
|
||||||
newmount->fsname = strdup(fsname);
|
|
||||||
newmount->dir = strdup(dir);
|
|
||||||
@@ -1394,14 +1406,17 @@ void fill_unix_cache(struct unixsocket_l
|
|
||||||
free(path);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
- if ( (newsocket = malloc(sizeof(struct unixsocket_list))) == NULL)
|
|
||||||
+ if ( (newsocket = (struct unixsocket_list*)malloc(sizeof(struct unixsocket_list))) == NULL) {
|
|
||||||
+ free(path);
|
|
||||||
continue;
|
|
||||||
+ }
|
|
||||||
newsocket->sun_name = strdup(scanned_path);
|
|
||||||
newsocket->inode = st.st_ino;
|
|
||||||
newsocket->dev = st.st_dev;
|
|
||||||
newsocket->net_inode = scanned_inode;
|
|
||||||
newsocket->next = *unixsocket_head;
|
|
||||||
*unixsocket_head = newsocket;
|
|
||||||
+ free(path);
|
|
||||||
} /* while */
|
|
||||||
|
|
||||||
fclose(fp);
|
|
@ -1,796 +0,0 @@
|
|||||||
--- doc/fuser.1
|
|
||||||
+++ doc/fuser.1 2008-05-16 15:18:59.000000000 +0200
|
|
||||||
@@ -80,8 +80,14 @@ List all known signal names.
|
|
||||||
\fIname\fP specifies a file on a mounted file system or a block device that
|
|
||||||
is mounted. All processes accessing files on that file system are listed.
|
|
||||||
If a directory file is specified, it is automatically changed to
|
|
||||||
-\fIname\fP/. to use any file system that might be mounted on that
|
|
||||||
-directory.
|
|
||||||
+\fIname\fP/. To use any file system that might be mounted on that
|
|
||||||
+directory. Please note that due the required device ID comparision all
|
|
||||||
+mounted file systems the
|
|
||||||
+.BR stat (2)
|
|
||||||
+system call will applied to every file system even on network file system
|
|
||||||
+(NFS). If the NFS server does not respond or the network is down the
|
|
||||||
+.BR stat (2)
|
|
||||||
+may hang forever.
|
|
||||||
.IP \fB\-n\ \fIspace\fP
|
|
||||||
Select a different name space. The name spaces \fBfile\fP (file names, the
|
|
||||||
default), \fBudp\fP (local UDP ports), and \fBtcp\fP (local TCP ports) are
|
|
||||||
@@ -152,10 +158,13 @@ The \fB\-k\fP option only works on proce
|
|
||||||
\fBfuser\fP will print an advice, but take no action beyond that.
|
|
||||||
.SH BUGS
|
|
||||||
.PP
|
|
||||||
-fuser \-m /dev/sgX will show (or kill with the \-k flag) all processes, even
|
|
||||||
+\fBfuser \-m \fI/dev/sgX\fR will show (or kill with the \fB\-k\fR flag) all processes, even
|
|
||||||
if you don't have that device configured. There may be other devices it
|
|
||||||
does this for too.
|
|
||||||
.PP
|
|
||||||
+\fBfuser \-m \fIname\fR may hang forever if there are NFS file systems mounted
|
|
||||||
+and one of the NFS servers do not respond or the corresponding network is down.
|
|
||||||
+.PP
|
|
||||||
.B fuser
|
|
||||||
cannot report on any processes that it doesn't have permission to look at
|
|
||||||
the file descriptor table for. The most common time this problem occurs
|
|
||||||
--- src/fuser.c
|
|
||||||
+++ src/fuser.c 2009-10-12 17:14:23.228525394 +0200
|
|
||||||
@@ -32,9 +32,11 @@
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
+#include <sys/param.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
+#include <sys/wait.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <pwd.h>
|
|
||||||
@@ -45,6 +47,7 @@
|
|
||||||
#include <mntent.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
+#include <setjmp.h>
|
|
||||||
|
|
||||||
#include "fuser.h"
|
|
||||||
#include "signals.h"
|
|
||||||
@@ -63,7 +66,7 @@ static void add_matched_proc(struct name
|
|
||||||
static void check_dir(const pid_t pid, const char *dirname, struct device_list *dev_head, struct inode_list *ino_head, const uid_t uid, const char access,
|
|
||||||
struct unixsocket_list *sockets, dev_t netdev);
|
|
||||||
static void check_map(const pid_t pid, const char *filename, struct device_list *dev_head, struct inode_list *ino_head, const uid_t uid, const char access);
|
|
||||||
-static struct stat *get_pidstat(const pid_t pid, const char *filename);
|
|
||||||
+static struct stat *get_pidstat(const opt_type opts, const pid_t pid, const char *filename, char *real);
|
|
||||||
static uid_t getpiduid(const pid_t pid);
|
|
||||||
static int print_matches(struct names *names_head, const opt_type opts, const int sig_number);
|
|
||||||
static void kill_matched_proc(struct procs *pptr, const opt_type opts, const int sig_number);
|
|
||||||
@@ -73,13 +76,20 @@ static void add_device(struct device_lis
|
|
||||||
void scan_mount_devices(const opt_type opts, struct mountdev_list **mount_devices);
|
|
||||||
void fill_unix_cache(struct unixsocket_list **unixsocket_head);
|
|
||||||
static dev_t find_net_dev(void);
|
|
||||||
-static void scan_procs(struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head, struct unixsocket_list *sockets, dev_t netdev);
|
|
||||||
+static void scan_procs(const opt_type opts, struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head, struct unixsocket_list *sockets, dev_t netdev);
|
|
||||||
#ifdef NFS_CHECKS
|
|
||||||
static void scan_knfsd(struct names *names_head, struct device_list *dev_head);
|
|
||||||
#endif /* NFS_CHECKS */
|
|
||||||
#ifdef DEBUG
|
|
||||||
static void debug_match_lists(struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head);
|
|
||||||
#endif
|
|
||||||
+static struct nfs_points *mnts;
|
|
||||||
+static void clear_mnt(void);
|
|
||||||
+static int check4nfs(const char * path, char * real);
|
|
||||||
+
|
|
||||||
+typedef int (*stat_t)(const char*, struct stat*);
|
|
||||||
+static int nfssafe(stat_t func, const char *path, struct stat *buf);
|
|
||||||
+
|
|
||||||
|
|
||||||
static void usage (const char *errormsg)
|
|
||||||
{
|
|
||||||
@@ -92,7 +102,7 @@ static void usage (const char *errormsg)
|
|
||||||
" fuser -V\n"
|
|
||||||
"Show which processes use the named files, sockets, or filesystems.\n\n"
|
|
||||||
" -a display unused files too\n"
|
|
||||||
- " -c Same as \-m (for POSIX compatibility)\n"
|
|
||||||
+ " -c Same as -m (for POSIX compatibility)\n"
|
|
||||||
" -f silently ignored (for POSIX compatibility)\n"
|
|
||||||
" -i ask before killing (ignored without -k)\n"
|
|
||||||
" -k kill processes accessing the named file\n"
|
|
||||||
@@ -127,7 +137,14 @@ void print_version()
|
|
||||||
"For more information about these matters, see the files named COPYING.\n"));
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void scan_procs(struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head, struct unixsocket_list *sockets, dev_t netdev)
|
|
||||||
+static int islocatedon(const char * path, const char * loc)
|
|
||||||
+{
|
|
||||||
+ if (!path || *path == '\0')
|
|
||||||
+ return 0;
|
|
||||||
+ return (strstr(path, loc) == path);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void scan_procs(const opt_type opts, struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head, struct unixsocket_list *sockets, dev_t netdev)
|
|
||||||
{
|
|
||||||
DIR *topproc_dir;
|
|
||||||
struct dirent *topproc_dent;
|
|
||||||
@@ -137,6 +154,9 @@ static void scan_procs(struct names *nam
|
|
||||||
pid_t pid, my_pid;
|
|
||||||
uid_t uid;
|
|
||||||
struct stat *cwd_stat, *exe_stat, *root_stat;
|
|
||||||
+ char root_real[PATH_MAX+1];
|
|
||||||
+ char cwd_real[PATH_MAX+1];
|
|
||||||
+ char exe_real[PATH_MAX+1];
|
|
||||||
|
|
||||||
if ( (fd_dirpath = malloc(MAX_PATHNAME)) == NULL)
|
|
||||||
return;
|
|
||||||
@@ -157,9 +177,10 @@ static void scan_procs(struct names *nam
|
|
||||||
continue;
|
|
||||||
uid = getpiduid(pid);
|
|
||||||
|
|
||||||
- root_stat = get_pidstat(pid, "root");
|
|
||||||
- cwd_stat = get_pidstat(pid, "cwd");
|
|
||||||
- exe_stat = get_pidstat(pid, "exe");
|
|
||||||
+ root_real[0] = cwd_real[0] = exe_real[0] = '\0';
|
|
||||||
+ root_stat = get_pidstat(opts, pid, "root", root_real);
|
|
||||||
+ cwd_stat = get_pidstat(opts, pid, "cwd", cwd_real);
|
|
||||||
+ exe_stat = get_pidstat(opts, pid, "exe", exe_real);
|
|
||||||
/* Scan the devices */
|
|
||||||
for (dev_tmp = dev_head ; dev_tmp != NULL ; dev_tmp = dev_tmp->next) {
|
|
||||||
if (exe_stat != NULL && exe_stat->st_dev == dev_tmp->device)
|
|
||||||
@@ -168,6 +189,14 @@ static void scan_procs(struct names *nam
|
|
||||||
add_matched_proc(dev_tmp->name, pid, uid, ACCESS_ROOT);
|
|
||||||
if (cwd_stat != NULL && cwd_stat->st_dev == dev_tmp->device)
|
|
||||||
add_matched_proc(dev_tmp->name, pid, uid, ACCESS_CWD);
|
|
||||||
+ if ((dev_tmp->name->name_space & NAMESPACE_NFS) == 0)
|
|
||||||
+ continue;
|
|
||||||
+ if (islocatedon(&exe_real[0], dev_tmp->name->filename))
|
|
||||||
+ add_matched_proc(dev_tmp->name, pid, uid, ACCESS_EXE);
|
|
||||||
+ if (islocatedon(&root_real[0], dev_tmp->name->filename))
|
|
||||||
+ add_matched_proc(dev_tmp->name, pid, uid, ACCESS_ROOT);
|
|
||||||
+ if (islocatedon(&cwd_real[0], dev_tmp->name->filename))
|
|
||||||
+ add_matched_proc(dev_tmp->name, pid, uid, ACCESS_CWD);
|
|
||||||
}
|
|
||||||
for (ino_tmp = ino_head ; ino_tmp != NULL ; ino_tmp = ino_tmp->next) {
|
|
||||||
if (exe_stat != NULL) {
|
|
||||||
@@ -186,9 +215,19 @@ static void scan_procs(struct names *nam
|
|
||||||
add_matched_proc(ino_tmp->name, pid, uid, ACCESS_CWD);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+ if ((ino_tmp->name->name_space & NAMESPACE_NFS) == 0)
|
|
||||||
+ continue;
|
|
||||||
+ if (islocatedon(&exe_real[0], ino_tmp->name->filename))
|
|
||||||
+ add_matched_proc(ino_tmp->name, pid, uid, ACCESS_EXE);
|
|
||||||
+ if (islocatedon(&root_real[0], ino_tmp->name->filename))
|
|
||||||
+ add_matched_proc(ino_tmp->name, pid, uid, ACCESS_ROOT);
|
|
||||||
+ if (islocatedon(&cwd_real[0], ino_tmp->name->filename))
|
|
||||||
+ add_matched_proc(ino_tmp->name, pid, uid, ACCESS_CWD);
|
|
||||||
}
|
|
||||||
+#ifndef __linux__
|
|
||||||
check_dir(pid, "lib", dev_head, ino_head, uid, ACCESS_MMAP, sockets, netdev);
|
|
||||||
check_dir(pid, "mmap", dev_head, ino_head, uid, ACCESS_MMAP, sockets, netdev);
|
|
||||||
+#endif
|
|
||||||
check_dir(pid, "fd", dev_head, ino_head, uid, ACCESS_FILE, sockets, netdev);
|
|
||||||
check_map(pid, "maps", dev_head, ino_head, uid, ACCESS_MMAP);
|
|
||||||
|
|
||||||
@@ -325,10 +364,26 @@ int parse_mount(struct names *this_name,
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
-int parse_file(struct names *this_name, struct inode_list **ino_list)
|
|
||||||
+int parse_file(struct names *this_name, struct inode_list **ino_list, const opt_type opts)
|
|
||||||
{
|
|
||||||
+ char real[PATH_MAX+1] = "";
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
+ real[0] = '\0';
|
|
||||||
+ if (check4nfs(this_name->filename, real)) {
|
|
||||||
+ if ((opts & (OPT_MOUNTPOINT|OPT_MOUNTS)) == 0) {
|
|
||||||
+ free(this_name->filename);
|
|
||||||
+ this_name->filename = strdup(real);
|
|
||||||
+ this_name->name_space |= NAMESPACE_NFS;
|
|
||||||
+ add_inode(ino_list, this_name, (dev_t)-1, (ino_t)-1);
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ if (real[0] != '\0') {
|
|
||||||
+ free(this_name->filename);
|
|
||||||
+ this_name->filename = strdup(real);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (stat(this_name->filename, &st) != 0) {
|
|
||||||
fprintf(stderr,_("Cannot stat %s: %s\n"), this_name->filename,
|
|
||||||
strerror(errno));
|
|
||||||
@@ -342,34 +397,44 @@ int parse_file(struct names *this_name,
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
-int parse_unixsockets(struct names *this_name, struct inode_list **ino_list, struct unixsocket_list *sun_head)
|
|
||||||
+int parse_unixsockets(struct names *this_name, struct inode_list **ino_list, struct unixsocket_list *sun_head, dev_t net_dev, const opt_type opts)
|
|
||||||
{
|
|
||||||
struct unixsocket_list *sun_tmp;
|
|
||||||
struct stat st;
|
|
||||||
- dev_t net_dev;
|
|
||||||
-
|
|
||||||
+
|
|
||||||
+ if (check4nfs(this_name->filename, NULL)) {
|
|
||||||
+ this_name->name_space |= NAMESPACE_NFS;
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (stat(this_name->filename, &st) != 0) {
|
|
||||||
fprintf(stderr,_("Cannot stat %s: %s\n"), this_name->filename,
|
|
||||||
strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
- net_dev = find_net_dev();
|
|
||||||
|
|
||||||
for (sun_tmp = sun_head; sun_tmp != NULL ; sun_tmp = sun_tmp->next)
|
|
||||||
{
|
|
||||||
- if (sun_tmp->dev == st.st_dev && sun_tmp->inode == st.st_ino) {
|
|
||||||
+ if (sun_tmp->dev == st.st_dev && sun_tmp->inode == st.st_ino) {
|
|
||||||
add_inode(ino_list, this_name, net_dev, sun_tmp->net_inode);
|
|
||||||
- return 0;
|
|
||||||
+ return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
-int parse_mounts(struct names *this_name, struct mountdev_list *mounts, struct device_list **dev_list, const char opts)
|
|
||||||
+int parse_mounts(struct names *this_name, struct mountdev_list *mounts, struct device_list **dev_list, const opt_type opts)
|
|
||||||
{
|
|
||||||
struct stat st;
|
|
||||||
struct mountdev_list *mountptr;
|
|
||||||
dev_t match_device;
|
|
||||||
+ char real[PATH_MAX+1] = "";
|
|
||||||
+
|
|
||||||
+ real[0] = '\0';
|
|
||||||
+ if (check4nfs(this_name->filename, real)) {
|
|
||||||
+ this_name->name_space |= NAMESPACE_NFS;
|
|
||||||
+ goto skip;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
if (stat(this_name->filename, &st) != 0) {
|
|
||||||
fprintf(stderr,_("Cannot stat %s: %s\n"), this_name->filename,
|
|
||||||
@@ -388,6 +453,16 @@ int parse_mounts(struct names *this_name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
+skip:
|
|
||||||
+ match_device = -1;
|
|
||||||
+ for (mountptr = mounts ; mountptr != NULL ; mountptr = mountptr->next) {
|
|
||||||
+ if (strcmp(mountptr->dir, real) == 0) {
|
|
||||||
+ /*printf("Debug: adding parse_mounts() adding %s\n",
|
|
||||||
+ this_name->filename);*/
|
|
||||||
+ add_device(dev_list, this_name, match_device);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef WITH_IPV6
|
|
||||||
@@ -652,6 +727,150 @@ void find_net6_sockets(struct inode_list
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+/*
|
|
||||||
+ * Remove struct nfs_points and its sahdows from memory
|
|
||||||
+ */
|
|
||||||
+static void clear_shadow(struct shadow_list *restrict shadow)
|
|
||||||
+{
|
|
||||||
+ struct shadow_list *s, *n, *l;
|
|
||||||
+
|
|
||||||
+ n = shadow;
|
|
||||||
+ l = (struct shadow_list*)0;
|
|
||||||
+ for (s = shadow; n; s = n) {
|
|
||||||
+ l = s->prev;
|
|
||||||
+ n = s->next;
|
|
||||||
+ if (s == shadow) {
|
|
||||||
+ if (n) n->prev = (struct shadow_list*)0;
|
|
||||||
+ shadow = n;
|
|
||||||
+ } else if (l) {
|
|
||||||
+ if (n) n->prev = l;
|
|
||||||
+ l->next = n;
|
|
||||||
+ }
|
|
||||||
+ free(s);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void clear_mnt(void)
|
|
||||||
+{
|
|
||||||
+ struct nfs_points *p, *n, *l;
|
|
||||||
+
|
|
||||||
+ n = mnts;
|
|
||||||
+ l = (struct nfs_points*)0;
|
|
||||||
+ for (p = mnts; n; p = n) {
|
|
||||||
+ l = p->prev;
|
|
||||||
+ n = p->next;
|
|
||||||
+ if (p == mnts) {
|
|
||||||
+ if (n) n->prev = (struct nfs_points*)0;
|
|
||||||
+ mnts = n;
|
|
||||||
+ } else if (l) {
|
|
||||||
+ if (n) n->prev = l;
|
|
||||||
+ l->next = n;
|
|
||||||
+ }
|
|
||||||
+ if (p->shadow)
|
|
||||||
+ clear_shadow(p->shadow);
|
|
||||||
+ free(p);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * Check if path is ia shadow off a NFS partition.
|
|
||||||
+ */
|
|
||||||
+static int shadow(struct shadow_list *restrict this, const char *restrict name, const size_t nlen)
|
|
||||||
+{
|
|
||||||
+ struct shadow_list *s;
|
|
||||||
+
|
|
||||||
+ if (!this)
|
|
||||||
+ goto out;
|
|
||||||
+ for (s = this; s; s = s->next) {
|
|
||||||
+ if (nlen < s->nlen)
|
|
||||||
+ continue;
|
|
||||||
+ if (name[s->nlen] != '\0' && name[s->nlen] != '/')
|
|
||||||
+ continue;
|
|
||||||
+ if (strncmp(name, s->name, s->nlen) == 0)
|
|
||||||
+ return 1;
|
|
||||||
+ }
|
|
||||||
+out:
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * Check path is located on a NFS partition.
|
|
||||||
+ */
|
|
||||||
+static int check4nfs(const char * path, char * real)
|
|
||||||
+{
|
|
||||||
+ char buf[PATH_MAX+1];
|
|
||||||
+ const char *curr;
|
|
||||||
+ int deep = MAXSYMLINKS;
|
|
||||||
+
|
|
||||||
+ if (!mnts) return 0;
|
|
||||||
+
|
|
||||||
+ curr = path;
|
|
||||||
+ do {
|
|
||||||
+ const char *prev;
|
|
||||||
+ int len;
|
|
||||||
+
|
|
||||||
+ if ((prev = strdupa(curr)) == NULL)
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ errno = 0;
|
|
||||||
+ if ((len = readlink(curr, buf, PATH_MAX)) < 0)
|
|
||||||
+ break;
|
|
||||||
+ buf[len] = '\0'; /* Don't be fooled by readlink(2) */
|
|
||||||
+
|
|
||||||
+ if (strncmp(prev, "/proc/", 6) == 0) {
|
|
||||||
+ curr = &buf[0];
|
|
||||||
+ break; /* /proc/ provides the real path! */
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (len > 10) {
|
|
||||||
+ char *const ptr = &buf[len - 10];
|
|
||||||
+ if (strcmp(ptr, " (deleted)") == 0) {
|
|
||||||
+ *ptr = '\0';
|
|
||||||
+ curr = &buf[0];
|
|
||||||
+ break; /* Path is deleted from VFS cache */
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (buf[0] != '/') {
|
|
||||||
+ const char *slash;
|
|
||||||
+
|
|
||||||
+ if ((slash = strrchr(prev, '/'))) {
|
|
||||||
+ size_t off = slash - prev + 1;
|
|
||||||
+
|
|
||||||
+ if (off + len > PATH_MAX)
|
|
||||||
+ len = PATH_MAX - off;
|
|
||||||
+
|
|
||||||
+ memmove(&buf[off], &buf[0], len + 1);
|
|
||||||
+ memcpy(&buf[0], prev, off);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ curr = &buf[0];
|
|
||||||
+
|
|
||||||
+ if (deep-- <= 0) return 0;
|
|
||||||
+
|
|
||||||
+ } while (1);
|
|
||||||
+
|
|
||||||
+ if (real) strcpy(real, curr);
|
|
||||||
+
|
|
||||||
+ if (errno == EINVAL) {
|
|
||||||
+ const size_t nlen = strlen(curr);
|
|
||||||
+ struct nfs_points *p;
|
|
||||||
+ for (p = mnts; p; p = p->next) {
|
|
||||||
+ if (nlen < p->nlen)
|
|
||||||
+ continue;
|
|
||||||
+ if (curr[p->nlen] != '\0' && curr[p->nlen] != '/')
|
|
||||||
+ continue;
|
|
||||||
+ if (!strncmp(curr, p->name, p->nlen)) {
|
|
||||||
+ if (shadow(p->shadow, curr, nlen))
|
|
||||||
+ continue;
|
|
||||||
+ return 1;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
opt_type opts;
|
|
||||||
@@ -676,6 +895,7 @@ int main(int argc, char *argv[])
|
|
||||||
int optc;
|
|
||||||
char *option;
|
|
||||||
char *nsptr;
|
|
||||||
+ size_t len;
|
|
||||||
|
|
||||||
#ifdef WITH_IPV6
|
|
||||||
ipv4_only = ipv6_only = 0;
|
|
||||||
@@ -692,7 +912,6 @@ int main(int argc, char *argv[])
|
|
||||||
#endif
|
|
||||||
|
|
||||||
netdev = find_net_dev();
|
|
||||||
- scan_mount_devices(opts, &mount_devices);
|
|
||||||
fill_unix_cache(&unixsockets);
|
|
||||||
|
|
||||||
/* getopt doesnt like things like -SIGBLAH */
|
|
||||||
@@ -782,6 +1001,10 @@ int main(int argc, char *argv[])
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ if (!mount_devices)
|
|
||||||
+ scan_mount_devices(opts, &mount_devices);
|
|
||||||
+
|
|
||||||
/* File specifications */
|
|
||||||
if ( (this_name = malloc(sizeof(struct names))) == NULL)
|
|
||||||
continue;
|
|
||||||
@@ -828,10 +1051,24 @@ int main(int argc, char *argv[])
|
|
||||||
break;
|
|
||||||
default: /* FILE */
|
|
||||||
this_name->filename = strdup(argv[optc]);
|
|
||||||
- parse_file(this_name, &match_inodes);
|
|
||||||
- parse_unixsockets(this_name, &match_inodes, unixsockets);
|
|
||||||
- if (opts & OPT_MOUNTPOINT || opts & OPT_MOUNTS)
|
|
||||||
+ len = strlen(this_name->filename);
|
|
||||||
+ if (len > 1 && this_name->filename[len-1] == '/')
|
|
||||||
+ this_name->filename[len-1] = '\0';
|
|
||||||
+ if (len > 1 && this_name->filename[0] != '/') {
|
|
||||||
+ char pwd[MAX_PATHNAME];
|
|
||||||
+ if (getcwd(pwd, MAX_PATHNAME-1)) {
|
|
||||||
+ char *new, *old = this_name->filename;
|
|
||||||
+ if (asprintf(&new, "%s/%s", (strlen(pwd) > 1 ? pwd : ""), old) > 0) {
|
|
||||||
+ this_name->filename = new;
|
|
||||||
+ free(old);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ parse_file(this_name, &match_inodes, opts);
|
|
||||||
+ parse_unixsockets(this_name, &match_inodes, unixsockets, netdev, opts);
|
|
||||||
+ if (opts & (OPT_MOUNTPOINT | OPT_MOUNTS)) {
|
|
||||||
parse_mounts(this_name, mount_devices, &match_devices, opts);
|
|
||||||
+ }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -872,10 +1109,11 @@ int main(int argc, char *argv[])
|
|
||||||
#ifdef DEBUG
|
|
||||||
debug_match_lists(names_head, match_inodes, match_devices);
|
|
||||||
#endif
|
|
||||||
- scan_procs(names_head, match_inodes, match_devices, unixsockets, netdev);
|
|
||||||
+ scan_procs(opts, names_head, match_inodes, match_devices, unixsockets, netdev);
|
|
||||||
#ifdef NFS_CHECKS
|
|
||||||
scan_knfsd(names_head, match_devices);
|
|
||||||
#endif /* NFS_CHECKS */
|
|
||||||
+ clear_mnt();
|
|
||||||
return print_matches(names_head,opts, sig_number);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -978,7 +1216,7 @@ static int print_matches(struct names *n
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
-static struct stat *get_pidstat(const pid_t pid, const char *filename)
|
|
||||||
+static struct stat *get_pidstat(const opt_type opts, const pid_t pid, const char *filename, char *real)
|
|
||||||
{
|
|
||||||
char pathname[256];
|
|
||||||
struct stat *st;
|
|
||||||
@@ -986,6 +1224,10 @@ static struct stat *get_pidstat(const pi
|
|
||||||
if ( (st = malloc(sizeof(struct stat))) == NULL)
|
|
||||||
return NULL;
|
|
||||||
snprintf(pathname, 256, "/proc/%d/%s", pid, filename);
|
|
||||||
+ if (check4nfs(pathname, real)) {
|
|
||||||
+ if ((opts & (OPT_MOUNTPOINT|OPT_MOUNTS)) == 0)
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
if (stat(pathname, st) != 0)
|
|
||||||
return NULL;
|
|
||||||
else
|
|
||||||
@@ -1030,6 +1272,16 @@ static void check_dir(const pid_t pid, c
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (dev_tmp = dev_head ; dev_tmp != NULL ; dev_tmp = dev_tmp->next) {
|
|
||||||
+ if (dev_tmp->name->name_space & NAMESPACE_NFS) {
|
|
||||||
+ char buf[PATH_MAX+1];
|
|
||||||
+ ssize_t len;
|
|
||||||
+ if ((len = readlink(filepath, buf, PATH_MAX)) < 0)
|
|
||||||
+ continue;
|
|
||||||
+ buf[len] = '\0'; /* Don't be fooled by readlink(2) */
|
|
||||||
+ if (islocatedon(buf, dev_tmp->name->filename))
|
|
||||||
+ add_matched_proc(dev_tmp->name, pid,uid, access);
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
if (st.st_dev == dev_tmp->device) {
|
|
||||||
if (access == ACCESS_FILE && (lstat(filepath, &lst)==0) && (lst.st_mode & S_IWUSR)) {
|
|
||||||
add_matched_proc(dev_tmp->name, pid,uid, ACCESS_FILEWR|access);
|
|
||||||
@@ -1039,6 +1291,16 @@ static void check_dir(const pid_t pid, c
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (ino_tmp = ino_head ; ino_tmp != NULL ; ino_tmp = ino_tmp->next) {
|
|
||||||
+ if (ino_tmp->name->name_space & NAMESPACE_NFS) {
|
|
||||||
+ char buf[PATH_MAX+1];
|
|
||||||
+ ssize_t len;
|
|
||||||
+ if ((len = readlink(filepath, buf, PATH_MAX)) < 0)
|
|
||||||
+ continue;
|
|
||||||
+ buf[len] = '\0'; /* Don't be fooled by readlink(2) */
|
|
||||||
+ if (islocatedon(buf, ino_tmp->name->filename))
|
|
||||||
+ add_matched_proc(ino_tmp->name, pid,uid, access);
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
if (st.st_dev == ino_tmp->device && st.st_ino == ino_tmp->inode) {
|
|
||||||
if (access == ACCESS_FILE && (lstat(filepath, &lst)==0) && (lst.st_mode & S_IWUSR)) {
|
|
||||||
add_matched_proc(ino_tmp->name, pid,uid, ACCESS_FILEWR|access);
|
|
||||||
@@ -1050,6 +1312,8 @@ static void check_dir(const pid_t pid, c
|
|
||||||
}
|
|
||||||
} /* while fd_dent */
|
|
||||||
closedir(dirp);
|
|
||||||
+ free(dirpath);
|
|
||||||
+ free(filepath);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void check_map(const pid_t pid, const char *filename, struct device_list *dev_head, struct inode_list *ino_head, const uid_t uid, const char access)
|
|
||||||
@@ -1069,13 +1333,36 @@ static void check_map(const pid_t pid, c
|
|
||||||
while (fgets(line,BUFSIZ, fp)) {
|
|
||||||
if (sscanf(line, "%*s %*s %*s %x:%x %lld",
|
|
||||||
&tmp_maj, &tmp_min, &tmp_inode) == 3) {
|
|
||||||
+ const char * filepath = strchr(line, '/');
|
|
||||||
tmp_device = tmp_maj * 256 + tmp_min;
|
|
||||||
- for(dev_tmp = dev_head ; dev_tmp != NULL ; dev_tmp = dev_tmp->next)
|
|
||||||
+ for(dev_tmp = dev_head ; dev_tmp != NULL ; dev_tmp = dev_tmp->next) {
|
|
||||||
+ if (dev_tmp->name->name_space & NAMESPACE_NFS) {
|
|
||||||
+ char *nl;
|
|
||||||
+ if (!filepath)
|
|
||||||
+ continue;
|
|
||||||
+ if ((nl = strchr(filepath, '\n')))
|
|
||||||
+ nl = '\0';
|
|
||||||
+ if (islocatedon(filepath, dev_tmp->name->filename))
|
|
||||||
+ add_matched_proc(dev_tmp->name, pid,uid, access);
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
if (dev_tmp->device == tmp_device)
|
|
||||||
add_matched_proc(dev_tmp->name, pid, uid, access);
|
|
||||||
- for(ino_tmp = ino_head ; ino_tmp != NULL ; ino_tmp = ino_tmp->next)
|
|
||||||
+ }
|
|
||||||
+ for(ino_tmp = ino_head ; ino_tmp != NULL ; ino_tmp = ino_tmp->next) {
|
|
||||||
+ if (ino_tmp->name->name_space & NAMESPACE_NFS) {
|
|
||||||
+ char *nl;
|
|
||||||
+ if (!filepath)
|
|
||||||
+ continue;
|
|
||||||
+ if ((nl = strchr(filepath, '\n')))
|
|
||||||
+ nl = '\0';
|
|
||||||
+ if (islocatedon(filepath, ino_tmp->name->filename))
|
|
||||||
+ add_matched_proc(ino_tmp->name, pid,uid, access);
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
if (ino_tmp->device == tmp_device && ino_tmp->inode == tmp_inode)
|
|
||||||
add_matched_proc(ino_tmp->name, pid, uid, access);
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
@@ -1146,6 +1433,16 @@ void fill_unix_cache(struct unixsocket_l
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
+static inline int isnetfs(const char * type)
|
|
||||||
+{
|
|
||||||
+ static const char* netfs[] = {"nfs", "nfs4", "smbfs", "cifs", "afs", "ncpfs", (char*)0};
|
|
||||||
+ int n;
|
|
||||||
+ for (n = 0; netfs[n]; n++)
|
|
||||||
+ if (!strcasecmp(netfs[n], type))
|
|
||||||
+ return 1;
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* scan_mount_devices : Create a list of mount points and devices
|
|
||||||
* This list is used later for matching purposes
|
|
||||||
@@ -1155,17 +1452,94 @@ void scan_mount_devices(const opt_type o
|
|
||||||
FILE *mntfp;
|
|
||||||
struct mntent *mnt_ptr;
|
|
||||||
struct stat st;
|
|
||||||
-
|
|
||||||
- if ( (mntfp = setmntent("/etc/mtab","r")) == NULL) {
|
|
||||||
+ const char * mtab;
|
|
||||||
+
|
|
||||||
+ if (stat("/proc/version", &st) < 0)
|
|
||||||
+ mtab = "/etc/mtab";
|
|
||||||
+ else
|
|
||||||
+ mtab = "/proc/mounts";
|
|
||||||
+
|
|
||||||
+ if ( (mntfp = setmntent(mtab,"r")) == NULL) {
|
|
||||||
fprintf(stderr, _("Cannot open /etc/mtab: %s\n"),
|
|
||||||
strerror(errno));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
while ( (mnt_ptr = getmntent(mntfp)) != NULL) {
|
|
||||||
+ if (isnetfs(mnt_ptr->mnt_type)) {
|
|
||||||
+ /*
|
|
||||||
+ * Remember all NFS typed partitions, required to make check4nfs() work.
|
|
||||||
+ */
|
|
||||||
+ size_t nlen = strlen(mnt_ptr->mnt_dir);
|
|
||||||
+ struct nfs_points *restrict p;
|
|
||||||
+ if (posix_memalign((void*)&p, sizeof(void*), alignof(struct nfs_points)+(nlen+1)) != 0)
|
|
||||||
+ goto out;
|
|
||||||
+ p->name = ((char*)p)+alignof(struct nfs_points);
|
|
||||||
+ p->nlen = nlen;
|
|
||||||
+ p->shadow = (struct shadow_list*)0;
|
|
||||||
+
|
|
||||||
+ strcpy(p->name, mnt_ptr->mnt_dir);
|
|
||||||
+ if (mnts)
|
|
||||||
+ mnts->prev = p;
|
|
||||||
+ p->next = mnts;
|
|
||||||
+ p->prev = (struct nfs_points*)0;
|
|
||||||
+ mnts = p;
|
|
||||||
+ if ((opts & (OPT_MOUNTPOINT|OPT_MOUNTS)) == 0) {
|
|
||||||
+ add_mount_device(mount_devices, mnt_ptr->mnt_fsname, mnt_ptr->mnt_dir, (dev_t)-1);
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+ if (nfssafe(stat, mnt_ptr->mnt_dir, &st) == 0) {
|
|
||||||
+ add_mount_device(mount_devices, mnt_ptr->mnt_fsname, mnt_ptr->mnt_dir, st.st_dev);
|
|
||||||
+ } else {
|
|
||||||
+ fprintf(stderr, _("Cannot stat file %s: %s\n"), mnt_ptr->mnt_dir, strerror(errno));
|
|
||||||
+ }
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+ if ((opts & (OPT_MOUNTPOINT|OPT_MOUNTS)) == 0)
|
|
||||||
+ continue;
|
|
||||||
if (stat(mnt_ptr->mnt_dir, &st) == 0) {
|
|
||||||
add_mount_device(mount_devices, mnt_ptr->mnt_fsname, mnt_ptr->mnt_dir, st.st_dev);
|
|
||||||
+ } else {
|
|
||||||
+ fprintf(stderr, _("Cannot stat file %s: %s\n"), mnt_ptr->mnt_dir, strerror(errno));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+ endmntent(mntfp);
|
|
||||||
+
|
|
||||||
+ if (!mnts)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ if ((mntfp = setmntent("/proc/mounts", "r")) == NULL) {
|
|
||||||
+ fprintf(stderr, _("Cannot open /etc/mtab: %s\n"), strerror(errno));
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ while ((mnt_ptr = getmntent(mntfp)) != NULL) {
|
|
||||||
+ struct nfs_points *p;
|
|
||||||
+
|
|
||||||
+ for (p = mnts; p; p = p->next) {
|
|
||||||
+ struct shadow_list *s;
|
|
||||||
+ size_t nlen;
|
|
||||||
+
|
|
||||||
+ if (strcmp(mnt_ptr->mnt_dir, p->name) == 0)
|
|
||||||
+ continue;
|
|
||||||
+ if (strncmp(mnt_ptr->mnt_dir, p->name, p->nlen) != 0)
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ nlen = strlen(mnt_ptr->mnt_dir);
|
|
||||||
+ if (posix_memalign((void*)&s, sizeof(void*), alignof(struct shadow_list)+(nlen+1)) != 0)
|
|
||||||
+ goto out;
|
|
||||||
+ s->name = ((char*)s)+alignof(struct shadow_list);
|
|
||||||
+ s->nlen = nlen;
|
|
||||||
+
|
|
||||||
+ strcpy(s->name, mnt_ptr->mnt_dir);
|
|
||||||
+ if (p->shadow)
|
|
||||||
+ p->shadow->prev = s;
|
|
||||||
+ s->next = p->shadow;
|
|
||||||
+ s->prev = (struct shadow_list*)0;
|
|
||||||
+ p->shadow = s;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+out:
|
|
||||||
+ endmntent(mntfp);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
@@ -1291,3 +1665,56 @@ static void scan_knfsd(struct names *nam
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* NFSCHECKS */
|
|
||||||
+
|
|
||||||
+static sigjmp_buf jenv;
|
|
||||||
+static int timeout = 5;
|
|
||||||
+static void sigalarm(int sig)
|
|
||||||
+{
|
|
||||||
+ if (sig == SIGALRM)
|
|
||||||
+ siglongjmp(jenv, 1);
|
|
||||||
+}
|
|
||||||
+static int nfssafe(stat_t func, const char *path, struct stat *buf)
|
|
||||||
+{
|
|
||||||
+ pid_t pid = 0;
|
|
||||||
+ int ret = 0, pipes[4];
|
|
||||||
+
|
|
||||||
+ if (pipe(&pipes[0]) < 0)
|
|
||||||
+ goto err;
|
|
||||||
+ switch ((pid = fork ())) {
|
|
||||||
+ case -1:
|
|
||||||
+ close(pipes[0]);
|
|
||||||
+ close(pipes[1]);
|
|
||||||
+ goto err;
|
|
||||||
+ case 0:
|
|
||||||
+ (void) signal(SIGALRM, SIG_DFL);
|
|
||||||
+ close(pipes[0]);
|
|
||||||
+ if ((ret = func(path, buf)) == 0)
|
|
||||||
+ write(pipes[1], buf, sizeof(struct stat));
|
|
||||||
+ close(pipes[1]);
|
|
||||||
+ exit(ret);
|
|
||||||
+ default:
|
|
||||||
+ close(pipes[1]);
|
|
||||||
+ if (sigsetjmp(jenv, 1)) {
|
|
||||||
+ (void) alarm(0);
|
|
||||||
+ (void) signal(SIGALRM, SIG_DFL);
|
|
||||||
+ if (waitpid(0, (int*)0, WNOHANG) == 0)
|
|
||||||
+ kill(pid, SIGKILL);
|
|
||||||
+ errno = ETIMEDOUT;
|
|
||||||
+ timeout = 1;
|
|
||||||
+ goto err;
|
|
||||||
+ }
|
|
||||||
+ (void) signal(SIGALRM, sigalarm);
|
|
||||||
+ (void) alarm(timeout);
|
|
||||||
+ if (read(pipes[0], buf, sizeof(struct stat)) == 0) {
|
|
||||||
+ errno = EFAULT;
|
|
||||||
+ ret = -1;
|
|
||||||
+ }
|
|
||||||
+ (void) alarm(0);
|
|
||||||
+ (void) signal(SIGALRM, SIG_DFL);
|
|
||||||
+ close(pipes[0]);
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ return ret;
|
|
||||||
+err:
|
|
||||||
+ return -1;
|
|
||||||
+}
|
|
||||||
--- src/fuser.h
|
|
||||||
+++ src/fuser.h 2009-03-27 13:23:36.000000000 +0100
|
|
||||||
@@ -80,9 +80,33 @@ struct unixsocket_list {
|
|
||||||
struct unixsocket_list *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
+struct shadow_list
|
|
||||||
+{
|
|
||||||
+ struct shadow_list *next;
|
|
||||||
+ struct shadow_list *prev;
|
|
||||||
+ size_t nlen;
|
|
||||||
+ char * name;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+struct nfs_points {
|
|
||||||
+ struct nfs_points *next, *prev;
|
|
||||||
+ struct shadow_list *shadow;
|
|
||||||
+ size_t nlen;
|
|
||||||
+ char * name;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
|
|
||||||
+# ifndef restrict
|
|
||||||
+# define restrict __restrict__
|
|
||||||
+# endif
|
|
||||||
+#endif
|
|
||||||
+#define alignof(type) ((sizeof(type)+(sizeof(void*)-1)) & ~(sizeof(void*)-1))
|
|
||||||
+
|
|
||||||
+
|
|
||||||
#define NAMESPACE_FILE 0
|
|
||||||
#define NAMESPACE_TCP 1
|
|
||||||
#define NAMESPACE_UDP 2
|
|
||||||
+#define NAMESPACE_NFS 4
|
|
||||||
|
|
||||||
#define MAX_PATHNAME 200
|
|
||||||
#define MAX_CMDNAME 16
|
|
@ -1,69 +0,0 @@
|
|||||||
--- src/pstree.c
|
|
||||||
+++ src/pstree.c 2009-05-11 13:32:34.749902293 +0200
|
|
||||||
@@ -60,6 +60,7 @@ extern const char *__progname;
|
|
||||||
#define UTF_HD "\342\224\254" /* U+252C, Horizontal and down */
|
|
||||||
|
|
||||||
#define VT_BEG "\033(0\017" /* use graphic chars */
|
|
||||||
+#define VT_LEN 4
|
|
||||||
#define VT_END "\033(B" /* back to normal char set */
|
|
||||||
#define VT_V "x" /* see UTF definitions above */
|
|
||||||
#define VT_VR "t"
|
|
||||||
@@ -220,6 +221,27 @@ out_string (const char *str)
|
|
||||||
out_char (*str++);
|
|
||||||
}
|
|
||||||
|
|
||||||
+/*
|
|
||||||
+ * Only affects vt100 line drawing mode: Do not count the strlen of
|
|
||||||
+ * VT_BEG to prevent doing end-of-line way too early:
|
|
||||||
+ */
|
|
||||||
+static void
|
|
||||||
+out_sym (const char *str)
|
|
||||||
+{
|
|
||||||
+ int seq = 0;
|
|
||||||
+ if (sym == &sym_vt100 && *str == '\033') {
|
|
||||||
+ seq = 1;
|
|
||||||
+ if (cur_x <= output_width || !trunc)
|
|
||||||
+ cur_x -= VT_LEN;
|
|
||||||
+ }
|
|
||||||
+ out_string(str);
|
|
||||||
+ if (seq) {
|
|
||||||
+ str = VT_END;
|
|
||||||
+ while (*str)
|
|
||||||
+ putchar (*str++);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
|
|
||||||
static int
|
|
||||||
out_int (int x) /* non-negative integers only */
|
|
||||||
@@ -431,7 +453,11 @@ dump_tree (PROC * current, int level, in
|
|
||||||
{
|
|
||||||
for (i = width[lvl] + 1; i; i--)
|
|
||||||
out_char (' ');
|
|
||||||
- out_string (lvl == level - 1 ? last ? sym->last_2 : sym->branch_2 :
|
|
||||||
+ /*
|
|
||||||
+ * Replace all three symbol-drawing calls with calls to out_sym()
|
|
||||||
+ * to handle VT100 line drawing sequences if VT100 mode is active:
|
|
||||||
+ */
|
|
||||||
+ out_sym (lvl == level - 1 ? last ? sym->last_2 : sym->branch_2 :
|
|
||||||
more[lvl + 1] ? sym->vert_2 : sym->empty_2);
|
|
||||||
}
|
|
||||||
if (rep < 2)
|
|
||||||
@@ -543,7 +569,7 @@ dump_tree (PROC * current, int level, in
|
|
||||||
width[level] = comm_len + cur_x - offset + add;
|
|
||||||
if (cur_x >= output_width && trunc)
|
|
||||||
{
|
|
||||||
- out_string (sym->first_3);
|
|
||||||
+ out_sym (sym->first_3);
|
|
||||||
out_string ("+");
|
|
||||||
out_newline ();
|
|
||||||
}
|
|
||||||
@@ -570,7 +596,7 @@ dump_tree (PROC * current, int level, in
|
|
||||||
}
|
|
||||||
if (first)
|
|
||||||
{
|
|
||||||
- out_string (next ? sym->first_3 : sym->single_3);
|
|
||||||
+ out_sym (next ? sym->first_3 : sym->single_3);
|
|
||||||
first = 0;
|
|
||||||
}
|
|
||||||
dump_tree (walk->child, level + 1, count + 1,
|
|
@ -1,11 +0,0 @@
|
|||||||
--- src/pstree.c
|
|
||||||
+++ src/pstree.c
|
|
||||||
@@ -70,7 +70,7 @@
|
|
||||||
|
|
||||||
typedef struct _proc
|
|
||||||
{
|
|
||||||
- char comm[COMM_LEN + 1];
|
|
||||||
+ char comm[COMM_LEN + 2 + 1]; /* add another 2 for thread brackets */
|
|
||||||
char **argv; /* only used : argv[0] is 1st arg; undef if argc < 1 */
|
|
||||||
int argc; /* with -a : number of arguments, -1 if swapped */
|
|
||||||
pid_t pid;
|
|
@ -1,148 +0,0 @@
|
|||||||
--- doc/fuser.1
|
|
||||||
+++ doc/fuser.1 2009-05-11 13:49:21.894401999 +0200
|
|
||||||
@@ -11,6 +11,7 @@ fuser \- identify processes using files
|
|
||||||
.IR space\ ]
|
|
||||||
.RB [ \-k
|
|
||||||
.RB [ \-i ]
|
|
||||||
+.RB [ \-w ]
|
|
||||||
.RB [ \- \fISIGNAL
|
|
||||||
] ]
|
|
||||||
.IR name " ..."
|
|
||||||
@@ -74,6 +75,9 @@ other \fBfuser\fP processes. The effecti
|
|
||||||
.IP \fB\-i\fP
|
|
||||||
Ask the user for confirmation before killing a process. This option is
|
|
||||||
silently ignored if \fB\-k\fP is not present too.
|
|
||||||
+.IP \fB\-w\fP
|
|
||||||
+Kill only processes which have write access. This option is
|
|
||||||
+silently ignored if \fB\-k\fP is not present too.
|
|
||||||
.IP \fB\-l\fP
|
|
||||||
List all known signal names.
|
|
||||||
.IP \fB\-m\fP
|
|
||||||
--- src/fuser.c
|
|
||||||
+++ src/fuser.c 2009-05-11 13:50:26.796428307 +0200
|
|
||||||
@@ -69,7 +69,7 @@ static void check_map(const pid_t pid, c
|
|
||||||
static struct stat *get_pidstat(const opt_type opts, const pid_t pid, const char *filename, char *real);
|
|
||||||
static uid_t getpiduid(const pid_t pid);
|
|
||||||
static int print_matches(struct names *names_head, const opt_type opts, const int sig_number);
|
|
||||||
-static void kill_matched_proc(struct procs *pptr, const opt_type opts, const int sig_number);
|
|
||||||
+static int kill_matched_proc(struct procs *pptr, const opt_type opts, const int sig_number);
|
|
||||||
|
|
||||||
int parse_mount(struct names *this_name, struct device_list **dev_list);
|
|
||||||
static void add_device(struct device_list **dev_list, struct names *this_name, dev_t device);
|
|
||||||
@@ -97,7 +97,7 @@ static void usage (const char *errormsg)
|
|
||||||
fprintf(stderr, "%s\n", errormsg);
|
|
||||||
|
|
||||||
fprintf (stderr, _(
|
|
||||||
- "Usage: fuser [ -fuv ] [ -a | -s ] [ -4 | -6 ] [ -c | -m | -n SPACE ] [ -k [ -i ] [ -SIGNAL ]] NAME...\n"
|
|
||||||
+ "Usage: fuser [ -fuv ] [ -a | -s ] [ -4 | -6 ] [ -c | -m | -n SPACE ] [ -k [ -i ] [ -w ] [ -SIGNAL ]] NAME...\n"
|
|
||||||
" fuser -l\n"
|
|
||||||
" fuser -V\n"
|
|
||||||
"Show which processes use the named files, sockets, or filesystems.\n\n"
|
|
||||||
@@ -113,6 +113,7 @@ static void usage (const char *errormsg)
|
|
||||||
" -SIGNAL send this signal instead of SIGKILL\n"
|
|
||||||
" -u display user IDs\n"
|
|
||||||
" -v verbose output\n"
|
|
||||||
+ " -w kill only processes with write access\n"
|
|
||||||
" -V display version information\n"));
|
|
||||||
#ifdef WITH_IPV6
|
|
||||||
fprintf (stderr, _(
|
|
||||||
@@ -982,6 +983,9 @@ int main(int argc, char *argv[])
|
|
||||||
case 'v':
|
|
||||||
opts |= OPT_VERBOSE;
|
|
||||||
break;
|
|
||||||
+ case 'w':
|
|
||||||
+ opts |= OPT_WRITE;
|
|
||||||
+ break;
|
|
||||||
case 'V':
|
|
||||||
print_version();
|
|
||||||
return 0;
|
|
||||||
@@ -1119,6 +1123,7 @@ static int print_matches(struct names *n
|
|
||||||
int len = 0;
|
|
||||||
struct passwd *pwent = NULL;
|
|
||||||
int have_match = 0;
|
|
||||||
+ int have_kill = 0;
|
|
||||||
|
|
||||||
for (nptr = names_head; nptr != NULL ; nptr = nptr->next) {
|
|
||||||
if (opts & OPT_SILENT) {
|
|
||||||
@@ -1189,21 +1194,23 @@ static int print_matches(struct names *n
|
|
||||||
len = 0;
|
|
||||||
first = 0;
|
|
||||||
}
|
|
||||||
- if (opts & OPT_VERBOSE) {
|
|
||||||
- /* put a newline if showing all files and no procs*/
|
|
||||||
- if (nptr->matched_procs == NULL && (opts & OPT_ALLFILES))
|
|
||||||
- putc('\n', stderr);
|
|
||||||
- } else {
|
|
||||||
- if (nptr->matched_procs != NULL || (opts & OPT_ALLFILES))
|
|
||||||
- putc('\n', stderr);
|
|
||||||
- }
|
|
||||||
+ if (opts & OPT_VERBOSE) {
|
|
||||||
+ /* put a newline if showing all files and no procs*/
|
|
||||||
+ if (nptr->matched_procs == NULL && (opts & OPT_ALLFILES))
|
|
||||||
+ putc('\n', stderr);
|
|
||||||
+ } else {
|
|
||||||
+ if (nptr->matched_procs != NULL || (opts & OPT_ALLFILES))
|
|
||||||
+ putc('\n', stderr);
|
|
||||||
+ }
|
|
||||||
} /* be silent */
|
|
||||||
if (opts & OPT_KILL)
|
|
||||||
- kill_matched_proc(nptr->matched_procs, opts, sig_number);
|
|
||||||
+ have_kill = kill_matched_proc(nptr->matched_procs, opts, sig_number);
|
|
||||||
|
|
||||||
} /* next name */
|
|
||||||
- return (have_match==1?0:1);
|
|
||||||
-
|
|
||||||
+ if (opts & OPT_KILL)
|
|
||||||
+ return (have_kill==1?0:1);
|
|
||||||
+ else
|
|
||||||
+ return (have_match==1?0:1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct stat *get_pidstat(const opt_type opts, const pid_t pid, const char *filename, char *real)
|
|
||||||
@@ -1562,21 +1569,26 @@ static int ask(const pid_t pid)
|
|
||||||
} /* while */
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void kill_matched_proc(struct procs *proc_head, const opt_type opts, const int sig_number)
|
|
||||||
+static int kill_matched_proc(struct procs *proc_head, const opt_type opts, const int sig_number)
|
|
||||||
{
|
|
||||||
struct procs *pptr;
|
|
||||||
+ int ret = 0;
|
|
||||||
|
|
||||||
for (pptr = proc_head ; pptr != NULL ; pptr = pptr->next ) {
|
|
||||||
if ( (opts & OPT_INTERACTIVE) && (ask(pptr->pid) == 0))
|
|
||||||
continue;
|
|
||||||
+ if ((opts & OPT_WRITE) && ((pptr->access & ACCESS_FILEWR) == 0))
|
|
||||||
+ continue;
|
|
||||||
if ( kill (pptr->pid, sig_number) < 0) {
|
|
||||||
fprintf(stderr, _("Could not kill process %d: %s\n"),
|
|
||||||
pptr->pid,
|
|
||||||
strerror(errno)
|
|
||||||
);
|
|
||||||
+ continue;
|
|
||||||
}
|
|
||||||
-
|
|
||||||
+ ret = 1;
|
|
||||||
}
|
|
||||||
+ return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static dev_t find_net_dev(void)
|
|
||||||
--- src/fuser.h
|
|
||||||
+++ src/fuser.h 2008-08-07 14:26:48.000000000 +0200
|
|
||||||
@@ -1,6 +1,6 @@
|
|
||||||
|
|
||||||
/* Option Flags */
|
|
||||||
-typedef unsigned char opt_type;
|
|
||||||
+typedef unsigned short opt_type;
|
|
||||||
|
|
||||||
#define OPT_VERBOSE 1
|
|
||||||
#define OPT_ALLFILES 2
|
|
||||||
@@ -10,6 +10,7 @@ typedef unsigned char opt_type;
|
|
||||||
#define OPT_SILENT 32
|
|
||||||
#define OPT_USER 64
|
|
||||||
#define OPT_MOUNTPOINT 128
|
|
||||||
+#define OPT_WRITE 256
|
|
||||||
|
|
||||||
|
|
||||||
struct procs {
|
|
@ -1,56 +0,0 @@
|
|||||||
--- configure.ac
|
|
||||||
+++ configure.ac 2009-05-11 13:59:05.145901759 +0200
|
|
||||||
@@ -1,10 +1,10 @@
|
|
||||||
dnl Process this file with autoconf to produce a configure script.
|
|
||||||
-AC_PREREQ(2.61)
|
|
||||||
+AC_PREREQ(2.60)
|
|
||||||
AC_INIT([psmisc],[22.7])
|
|
||||||
AC_CONFIG_SRCDIR([src/comm.h])
|
|
||||||
AC_CONFIG_HEADER([config.h])
|
|
||||||
AC_CONFIG_AUX_DIR([config])
|
|
||||||
-AM_INIT_AUTOMAKE([1.10])
|
|
||||||
+AM_INIT_AUTOMAKE([1.9.6])
|
|
||||||
|
|
||||||
dnl Checks for programs.
|
|
||||||
AC_PROG_CXX
|
|
||||||
@@ -67,7 +67,8 @@ AC_CHECK_MEMBERS([struct user_regs_struc
|
|
||||||
struct user_regs_struct.rax,
|
|
||||||
struct user_regs_struct.rdi,
|
|
||||||
struct user_regs_struct.rsi,
|
|
||||||
- struct user_regs_struct.rdx], [],[], [#include <sys/user.h>])
|
|
||||||
+ struct user_regs_struct.rdx], [],[], [#include <sys/types.h>
|
|
||||||
+ #include <sys/user.h>])
|
|
||||||
AC_CHECK_MEMBERS([struct pt_regs.orig_gpr3,
|
|
||||||
struct pt_regs.gpr], [],[], [#include <linux/ptrace.h>])
|
|
||||||
AM_CONDITIONAL(WANT_PEEKFD_I386,
|
|
||||||
@@ -88,7 +89,7 @@ AM_CONDITIONAL(WANT_PEEKFD_PPC,
|
|
||||||
|
|
||||||
dnl Check for language stuff
|
|
||||||
AM_GNU_GETTEXT([external])
|
|
||||||
-AM_GNU_GETTEXT_VERSION([0.16.1])
|
|
||||||
+AM_GNU_GETTEXT_VERSION([0.15])
|
|
||||||
|
|
||||||
dnl Checks for library functions.
|
|
||||||
AC_FUNC_CLOSEDIR_VOID
|
|
||||||
--- src/fuser.c
|
|
||||||
+++ src/fuser.c 2008-10-01 18:02:08.000000000 +0200
|
|
||||||
@@ -149,7 +149,6 @@ static void scan_procs(const opt_type op
|
|
||||||
{
|
|
||||||
DIR *topproc_dir;
|
|
||||||
struct dirent *topproc_dent;
|
|
||||||
- char *fd_dirpath, *fd_pathname;
|
|
||||||
struct inode_list *ino_tmp;
|
|
||||||
struct device_list *dev_tmp;
|
|
||||||
pid_t pid, my_pid;
|
|
||||||
@@ -159,11 +158,6 @@ static void scan_procs(const opt_type op
|
|
||||||
char cwd_real[PATH_MAX+1];
|
|
||||||
char exe_real[PATH_MAX+1];
|
|
||||||
|
|
||||||
- if ( (fd_dirpath = malloc(MAX_PATHNAME)) == NULL)
|
|
||||||
- return;
|
|
||||||
- if ( (fd_pathname = malloc(MAX_PATHNAME)) == NULL)
|
|
||||||
- return;
|
|
||||||
-
|
|
||||||
if ( (topproc_dir = opendir("/proc")) == NULL) {
|
|
||||||
fprintf(stderr, _("Cannot open /proc directory: %s\n"), strerror(errno));
|
|
||||||
exit(1);
|
|
@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:2b9581bb21ec92d70653240069d4c1dd088c6a7f381dfc6d6590175d8988e823
|
|
||||||
size 249141
|
|
@ -1,12 +0,0 @@
|
|||||||
--- src/pstree.c.orig 2008-12-16 11:13:35.000000000 +0100
|
|
||||||
+++ src/pstree.c 2009-10-08 19:37:59.000000000 +0200
|
|
||||||
@@ -749,6 +749,9 @@
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
(void) close (fd);
|
|
||||||
+ /* If we have read the maximum screen length of args, bring it back by one to stop overflow */
|
|
||||||
+ if (size >= buffer_size)
|
|
||||||
+ size--;
|
|
||||||
if (size)
|
|
||||||
buffer[size++] = 0;
|
|
||||||
#ifdef WITH_SELINUX
|
|
@ -1,3 +1,39 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Tue Jul 13 18:47:35 CEST 2010 - werner@suse.de
|
||||||
|
|
||||||
|
- Update to psmisc-22.12
|
||||||
|
* In fuser, switched the ipv6 and ipv4 checks around Debian #581604
|
||||||
|
* peekfd configure patch for x86_64 SF#2986027
|
||||||
|
* peekfd works with ARM and MIPS thanks to patch by Arnaud Patard
|
||||||
|
* peekfd off-by-one patch applied SF#1948351
|
||||||
|
* pstree -a doesn't segfault on grsec kernels Debian #588152
|
||||||
|
* Another attempted at killall -SIGNAME Debian #573924
|
||||||
|
* fuser -k -m ... won't kill itself Debian #562767
|
||||||
|
* fuser -NAME fixed SF #2924691, Debian #563388, Gentoo #297423
|
||||||
|
* Added locale.h include for killall on non NLS SF #2922163
|
||||||
|
* Reversed normal file fuser -k check Debian #563387
|
||||||
|
* short option l returned in fuser Debian #539087
|
||||||
|
* long options terminated with 0s Debian #551833
|
||||||
|
* fuser only kills normal processes, patch thanks to Erik Li SF# 2892724
|
||||||
|
* New fuser -M if you REALLY want mount points, patch thanks to
|
||||||
|
Jeremie LE HEN SF#2899709
|
||||||
|
* Fixed killall options for VTALRM and ILL Debian #559011
|
||||||
|
* pstree -a does not compact threads Debian #525632
|
||||||
|
* new program prtstat which prints contents of /proc/<pid>/stat
|
||||||
|
Debian #281706
|
||||||
|
* killall restricts by date. Thanks to George Danchev Debian #544657
|
||||||
|
* long options terminated in pstree too to stop segfault
|
||||||
|
* Re-worked fuser getopt again so -KILL options work Gentoo #297423
|
||||||
|
* Fix off-by-one overflow in pstree SF# 2832375
|
||||||
|
* Applied patch from Kari Hautio for lazy umount'ed filesystems SF#2545632
|
||||||
|
* Applied patch from Anonymous SF submitter to fix killall -l
|
||||||
|
Fixes SF#2002570
|
||||||
|
* fuser will print mounts,nfs exports and swaps with -v Debian #356655
|
||||||
|
and SF#533958
|
||||||
|
* pstree and fuser have long options Debian #517412
|
||||||
|
* Fixed pstree -a off-by-one error in buffer, Debian #536243
|
||||||
|
* Changed configure.ac to not use CXX SF# 2789801
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Tue Jul 6 06:30:24 UTC 2010 - bg@novell.com
|
Tue Jul 6 06:30:24 UTC 2010 - bg@novell.com
|
||||||
|
|
||||||
|
43
psmisc.spec
43
psmisc.spec
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# spec file for package psmisc (Version 22.7)
|
# spec file for package psmisc (Version 22.12)
|
||||||
#
|
#
|
||||||
# Copyright (c) 2010 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
# Copyright (c) 2010 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
||||||
#
|
#
|
||||||
@ -26,23 +26,21 @@ License: GPLv2+
|
|||||||
Group: System/Monitoring
|
Group: System/Monitoring
|
||||||
PreReq: %fillup_prereq %insserv_prereq
|
PreReq: %fillup_prereq %insserv_prereq
|
||||||
AutoReqProv: on
|
AutoReqProv: on
|
||||||
Version: 22.7
|
Version: 22.12
|
||||||
Release: 9
|
Release: 9
|
||||||
Provides: ps:/usr/bin/killall
|
Provides: ps:/usr/bin/killall
|
||||||
Summary: Utilities for managing processes on your system
|
Summary: Utilities for managing processes on your system
|
||||||
Source: http://switch.dl.sourceforge.net/sourceforge/psmisc/psmisc-%{version}.tar.bz2
|
Source: http://switch.dl.sourceforge.net/sourceforge/psmisc/psmisc-%{version}.tar.bz2
|
||||||
Patch0: %name-22.7.dif
|
Patch0: %name-22.12.dif
|
||||||
Patch1: %name-22.7-pstree.patch
|
Patch1: %name-22.12-tigetstr.patch
|
||||||
Patch2: %name-22.7-nfs4fuser.patch
|
Patch2: %name-22.12-pstree_overflow.patch
|
||||||
Patch3: %name-22.6-netunix.patch
|
Patch3: %name-22.12-pstree.patch
|
||||||
Patch4: %name-22.7-writeonly.patch
|
Patch4: %name-22.12-leaks.patch
|
||||||
Patch5: %name-22.6-fdleak.patch
|
Patch5: %name-22.12-nfs4fuser.patch
|
||||||
Patch6: %name-22.6-tigetstr.patch
|
Patch6: %name-22.12-writeonly.patch
|
||||||
Patch7: %name-22.7-memleaks.patch
|
|
||||||
Patch8: %name-22.8-to-22.7-backport.patch
|
|
||||||
Patch9: psmisc-22.7-pstree_overflow.patch
|
|
||||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||||
%define nopeek s390 s390x ia64 %arm %sparc hppa
|
%define nopeek s390 s390x ia64 %sparc hppa
|
||||||
|
|
||||||
%description
|
%description
|
||||||
The psmisc package contains utilities for managing processes on your
|
The psmisc package contains utilities for managing processes on your
|
||||||
@ -60,20 +58,17 @@ Authors:
|
|||||||
|
|
||||||
%prep
|
%prep
|
||||||
%setup -q
|
%setup -q
|
||||||
%patch1 -p0 -b .pstree
|
%patch1 -p0 -b .tigetstr
|
||||||
%patch2 -p0 -b .nfs4fuser
|
%patch2 -p0 -b .pstreeovfl
|
||||||
%patch3 -p0 -b .netunix
|
%patch3 -p0 -b .pstree
|
||||||
%patch4 -p0 -b .wrtonly
|
%patch4 -p0 -b .leaks
|
||||||
%patch5 -p0 -b .fdleak
|
%patch5 -p0 -b .nfs4fuser
|
||||||
%patch6 -p0 -b .tigetstr
|
%patch6 -p0 -b .wrtonly
|
||||||
%patch7 -p0 -b .memleaks
|
|
||||||
%patch0 -p0
|
%patch0 -p0
|
||||||
%patch8 -p0
|
|
||||||
%patch9 -p0
|
|
||||||
|
|
||||||
%build
|
%build
|
||||||
autoreconf -fi
|
autoreconf -fi
|
||||||
CFLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 ${RPM_OPT_FLAGS} -pipe"
|
CFLAGS="-D_GNU_SOURCE ${RPM_OPT_FLAGS} -pipe"
|
||||||
CXXFLAGS="$CFLAGS"
|
CXXFLAGS="$CFLAGS"
|
||||||
CC=gcc
|
CC=gcc
|
||||||
CXX=g++
|
CXX=g++
|
||||||
@ -100,6 +95,7 @@ rm -rf $RPM_BUILD_ROOT
|
|||||||
%ifnarch %nopeek
|
%ifnarch %nopeek
|
||||||
%{_bindir}/peekfd
|
%{_bindir}/peekfd
|
||||||
%endif
|
%endif
|
||||||
|
%{_bindir}/prtstat
|
||||||
%{_bindir}/pstree
|
%{_bindir}/pstree
|
||||||
%{_bindir}/pstree.x11
|
%{_bindir}/pstree.x11
|
||||||
%{_mandir}/man1/fuser.1*
|
%{_mandir}/man1/fuser.1*
|
||||||
@ -107,6 +103,7 @@ rm -rf $RPM_BUILD_ROOT
|
|||||||
%ifnarch %nopeek
|
%ifnarch %nopeek
|
||||||
%{_mandir}/man1/peekfd.1*
|
%{_mandir}/man1/peekfd.1*
|
||||||
%endif
|
%endif
|
||||||
|
%{_mandir}/man1/prtstat.1*
|
||||||
%{_mandir}/man1/pstree.1*
|
%{_mandir}/man1/pstree.1*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
Loading…
Reference in New Issue
Block a user