From 27d2e910a5c45234d5f8b097f323efc71ccec599 Mon Sep 17 00:00:00 2001 From: "Dr. Werner Fink" Date: Tue, 13 Jul 2010 16:50:33 +0000 Subject: [PATCH] . OBS-URL: https://build.opensuse.org/package/show/Base:System/psmisc?expand=0&rev=21 --- psmisc-22.12-leaks.patch | 269 +++++++++ psmisc-22.12-nfs4fuser.patch | 903 +++++++++++++++++++++++++++++ psmisc-22.12-pstree.patch | 74 +++ psmisc-22.12-pstree_overflow.patch | 11 + psmisc-22.12-tigetstr.patch | 11 + psmisc-22.12-writeonly.patch | 129 +++++ psmisc-22.12.dif | 49 ++ psmisc-22.12.tar.bz2 | 3 + psmisc-22.6-fdleak.patch | 18 - psmisc-22.6-netunix.patch | 36 -- psmisc-22.6-tigetstr.patch | 11 - psmisc-22.7-memleaks.patch | 241 -------- psmisc-22.7-nfs4fuser.patch | 796 ------------------------- psmisc-22.7-pstree.patch | 69 --- psmisc-22.7-pstree_overflow.patch | 11 - psmisc-22.7-writeonly.patch | 148 ----- psmisc-22.7.dif | 56 -- psmisc-22.7.tar.bz2 | 3 - psmisc-22.8-to-22.7-backport.patch | 12 - psmisc.changes | 36 ++ psmisc.spec | 43 +- 21 files changed, 1505 insertions(+), 1424 deletions(-) create mode 100644 psmisc-22.12-leaks.patch create mode 100644 psmisc-22.12-nfs4fuser.patch create mode 100644 psmisc-22.12-pstree.patch create mode 100644 psmisc-22.12-pstree_overflow.patch create mode 100644 psmisc-22.12-tigetstr.patch create mode 100644 psmisc-22.12-writeonly.patch create mode 100644 psmisc-22.12.dif create mode 100644 psmisc-22.12.tar.bz2 delete mode 100644 psmisc-22.6-fdleak.patch delete mode 100644 psmisc-22.6-netunix.patch delete mode 100644 psmisc-22.6-tigetstr.patch delete mode 100644 psmisc-22.7-memleaks.patch delete mode 100644 psmisc-22.7-nfs4fuser.patch delete mode 100644 psmisc-22.7-pstree.patch delete mode 100644 psmisc-22.7-pstree_overflow.patch delete mode 100644 psmisc-22.7-writeonly.patch delete mode 100644 psmisc-22.7.dif delete mode 100644 psmisc-22.7.tar.bz2 delete mode 100644 psmisc-22.8-to-22.7-backport.patch diff --git a/psmisc-22.12-leaks.patch b/psmisc-22.12-leaks.patch new file mode 100644 index 0000000..04676a2 --- /dev/null +++ b/psmisc-22.12-leaks.patch @@ -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); + } diff --git a/psmisc-22.12-nfs4fuser.patch b/psmisc-22.12-nfs4fuser.patch new file mode 100644 index 0000000..6278b3f --- /dev/null +++ b/psmisc-22.12-nfs4fuser.patch @@ -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 + #include + #include ++#include + #include + #include + #include ++#include + #include + #include + #include +@@ -45,6 +47,7 @@ + #include + #include + #include ++#include + + #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 diff --git a/psmisc-22.12-pstree.patch b/psmisc-22.12-pstree.patch new file mode 100644 index 0000000..19861bb --- /dev/null +++ b/psmisc-22.12-pstree.patch @@ -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, diff --git a/psmisc-22.12-pstree_overflow.patch b/psmisc-22.12-pstree_overflow.patch new file mode 100644 index 0000000..bfff1c9 --- /dev/null +++ b/psmisc-22.12-pstree_overflow.patch @@ -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; diff --git a/psmisc-22.12-tigetstr.patch b/psmisc-22.12-tigetstr.patch new file mode 100644 index 0000000..e5d79eb --- /dev/null +++ b/psmisc-22.12-tigetstr.patch @@ -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. diff --git a/psmisc-22.12-writeonly.patch b/psmisc-22.12-writeonly.patch new file mode 100644 index 0000000..8023003 --- /dev/null +++ b/psmisc-22.12-writeonly.patch @@ -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; diff --git a/psmisc-22.12.dif b/psmisc-22.12.dif new file mode 100644 index 0000000..693d524 --- /dev/null +++ b/psmisc-22.12.dif @@ -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 ]) ++ [#include ++ #include ]) + AC_CHECK_MEMBERS([struct pt_regs.orig_gpr3, + struct pt_regs.gpr], [],[], [#include ]) + AC_CHECK_MEMBERS([struct pt_regs.uregs],[],[], [#include ]) +--- 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) { diff --git a/psmisc-22.12.tar.bz2 b/psmisc-22.12.tar.bz2 new file mode 100644 index 0000000..0a7007f --- /dev/null +++ b/psmisc-22.12.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a496b4e684dc5cd5ed28ae296b071701d39845e0a799396dbc005f2736340b1d +size 298393 diff --git a/psmisc-22.6-fdleak.patch b/psmisc-22.6-fdleak.patch deleted file mode 100644 index a4c70d3..0000000 --- a/psmisc-22.6-fdleak.patch +++ /dev/null @@ -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 */ - diff --git a/psmisc-22.6-netunix.patch b/psmisc-22.6-netunix.patch deleted file mode 100644 index c4b066b..0000000 --- a/psmisc-22.6-netunix.patch +++ /dev/null @@ -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 */ diff --git a/psmisc-22.6-tigetstr.patch b/psmisc-22.6-tigetstr.patch deleted file mode 100644 index 578f330..0000000 --- a/psmisc-22.6-tigetstr.patch +++ /dev/null @@ -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. diff --git a/psmisc-22.7-memleaks.patch b/psmisc-22.7-memleaks.patch deleted file mode 100644 index 8808ee9..0000000 --- a/psmisc-22.7-memleaks.patch +++ /dev/null @@ -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); diff --git a/psmisc-22.7-nfs4fuser.patch b/psmisc-22.7-nfs4fuser.patch deleted file mode 100644 index a3c2a90..0000000 --- a/psmisc-22.7-nfs4fuser.patch +++ /dev/null @@ -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 - #include - #include -+#include - #include - #include - #include -+#include - #include - #include - #include -@@ -45,6 +47,7 @@ - #include - #include - #include -+#include - - #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 diff --git a/psmisc-22.7-pstree.patch b/psmisc-22.7-pstree.patch deleted file mode 100644 index 0160a05..0000000 --- a/psmisc-22.7-pstree.patch +++ /dev/null @@ -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, diff --git a/psmisc-22.7-pstree_overflow.patch b/psmisc-22.7-pstree_overflow.patch deleted file mode 100644 index 6c38d50..0000000 --- a/psmisc-22.7-pstree_overflow.patch +++ /dev/null @@ -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; diff --git a/psmisc-22.7-writeonly.patch b/psmisc-22.7-writeonly.patch deleted file mode 100644 index 6fcbe2c..0000000 --- a/psmisc-22.7-writeonly.patch +++ /dev/null @@ -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 { diff --git a/psmisc-22.7.dif b/psmisc-22.7.dif deleted file mode 100644 index 36dfca1..0000000 --- a/psmisc-22.7.dif +++ /dev/null @@ -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 ]) -+ struct user_regs_struct.rdx], [],[], [#include -+ #include ]) - AC_CHECK_MEMBERS([struct pt_regs.orig_gpr3, - struct pt_regs.gpr], [],[], [#include ]) - 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); diff --git a/psmisc-22.7.tar.bz2 b/psmisc-22.7.tar.bz2 deleted file mode 100644 index 303b2b3..0000000 --- a/psmisc-22.7.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2b9581bb21ec92d70653240069d4c1dd088c6a7f381dfc6d6590175d8988e823 -size 249141 diff --git a/psmisc-22.8-to-22.7-backport.patch b/psmisc-22.8-to-22.7-backport.patch deleted file mode 100644 index b5a4a1e..0000000 --- a/psmisc-22.8-to-22.7-backport.patch +++ /dev/null @@ -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 diff --git a/psmisc.changes b/psmisc.changes index 30582ed..821b2cc 100644 --- a/psmisc.changes +++ b/psmisc.changes @@ -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//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 diff --git a/psmisc.spec b/psmisc.spec index 8b0193d..a11d1c8 100644 --- a/psmisc.spec +++ b/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. # @@ -26,23 +26,21 @@ License: GPLv2+ Group: System/Monitoring PreReq: %fillup_prereq %insserv_prereq AutoReqProv: on -Version: 22.7 +Version: 22.12 Release: 9 Provides: ps:/usr/bin/killall Summary: Utilities for managing processes on your system Source: http://switch.dl.sourceforge.net/sourceforge/psmisc/psmisc-%{version}.tar.bz2 -Patch0: %name-22.7.dif -Patch1: %name-22.7-pstree.patch -Patch2: %name-22.7-nfs4fuser.patch -Patch3: %name-22.6-netunix.patch -Patch4: %name-22.7-writeonly.patch -Patch5: %name-22.6-fdleak.patch -Patch6: %name-22.6-tigetstr.patch -Patch7: %name-22.7-memleaks.patch -Patch8: %name-22.8-to-22.7-backport.patch -Patch9: psmisc-22.7-pstree_overflow.patch +Patch0: %name-22.12.dif +Patch1: %name-22.12-tigetstr.patch +Patch2: %name-22.12-pstree_overflow.patch +Patch3: %name-22.12-pstree.patch +Patch4: %name-22.12-leaks.patch +Patch5: %name-22.12-nfs4fuser.patch +Patch6: %name-22.12-writeonly.patch + BuildRoot: %{_tmppath}/%{name}-%{version}-build -%define nopeek s390 s390x ia64 %arm %sparc hppa +%define nopeek s390 s390x ia64 %sparc hppa %description The psmisc package contains utilities for managing processes on your @@ -60,20 +58,17 @@ Authors: %prep %setup -q -%patch1 -p0 -b .pstree -%patch2 -p0 -b .nfs4fuser -%patch3 -p0 -b .netunix -%patch4 -p0 -b .wrtonly -%patch5 -p0 -b .fdleak -%patch6 -p0 -b .tigetstr -%patch7 -p0 -b .memleaks +%patch1 -p0 -b .tigetstr +%patch2 -p0 -b .pstreeovfl +%patch3 -p0 -b .pstree +%patch4 -p0 -b .leaks +%patch5 -p0 -b .nfs4fuser +%patch6 -p0 -b .wrtonly %patch0 -p0 -%patch8 -p0 -%patch9 -p0 %build 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" CC=gcc CXX=g++ @@ -100,6 +95,7 @@ rm -rf $RPM_BUILD_ROOT %ifnarch %nopeek %{_bindir}/peekfd %endif +%{_bindir}/prtstat %{_bindir}/pstree %{_bindir}/pstree.x11 %{_mandir}/man1/fuser.1* @@ -107,6 +103,7 @@ rm -rf $RPM_BUILD_ROOT %ifnarch %nopeek %{_mandir}/man1/peekfd.1* %endif +%{_mandir}/man1/prtstat.1* %{_mandir}/man1/pstree.1* %changelog