sysvinit/killproc-2.17.dif

376 lines
8.5 KiB
Plaintext

--- libinit.c
+++ libinit.c 2011-01-27 12:58:48.944425833 +0000
@@ -218,6 +218,26 @@ static struct _sys_signals {
{ 0, "EXIT" }
};
+/*
+ * Calculate the depth of a directory, root has zero depth.
+ */
+static size_t dirdepth(const char *const path)
+{
+ const char *ptr = path;
+ size_t cnt = 0;
+
+ do {
+ const size_t off = strcspn(ptr, "/");
+ ptr += off;
+ if (*ptr++ != '/')
+ break;
+ if (*ptr)
+ cnt++;
+ } while (*ptr);
+
+ return cnt;
+}
+
typedef struct _mntinfo_
{
struct _mntinfo_ *next;
@@ -226,6 +246,7 @@ typedef struct _mntinfo_
int id, parid;
dev_t dev;
size_t nlen;
+ size_t deep;
char * point;
} MNTINFO;
@@ -253,6 +274,7 @@ static void init_mounts(void)
p->point = ((char*)p)+alignof(MNTINFO);
strcpy(p->point, point);
p->nlen = nlen;
+ p->deep = dirdepth(point);
p->parid = parid;
p->dev = makedev(maj, min);
p->id = mid;
@@ -262,20 +284,20 @@ static void init_mounts(void)
p->prev = (MNTINFO*)0;
p->parent = p;
mounts = p;
- if (mid > max)
- max = mid;
+ if (p->id > max)
+ max = p->id;
}
fclose(mnt);
- /* Sort mount points accordingly to the reverse mount order */
+ /* Sort mount points accordingly to their reverse directory depth */
save = (MNTINFO*)0;
- for (mid = 1; mid <= max; mid++) {
+ for (mid = 0; mounts; mid++) {
MNTINFO *m, *n, *l;
n = mounts;
l = (MNTINFO*)0;
for (m = mounts; n; m = n) {
n = m->next;
- if (m->id != mid)
+ if (m->deep != mid)
continue;
l = m->prev;
if (m == mounts) {
@@ -290,7 +312,6 @@ static void init_mounts(void)
m->next = save;
m->prev = (MNTINFO*)0;
save = m;
- break;
}
}
mounts = save;
@@ -307,15 +328,14 @@ static void init_mounts(void)
}
}
-static MNTINFO *find_mount(const char * path)
+static int find_mount(const char * path, MNTINFO *s)
{
MNTINFO *m;
for (m = mounts; m; m = m->next) {
- if (strncmp(path, m->point, m->nlen))
- continue;
- break;
+ if (s == m)
+ return 1;
}
- return m;
+ return 0;
}
extern inline char * handl_buf(char *restrict buf)
@@ -627,6 +647,7 @@ int pidof (const char * inname, const ch
pid_t pid;
char *swapname = NULL;
char *fullname = (char *)inname;
+ char *realname = NULL;
MNTINFO *prefix = NULL;
PROC *p, *n;
@@ -659,12 +680,17 @@ int pidof (const char * inname, const ch
warn("cannot stat %s: %s\n", fullname, strerror(errno));
return -1;
}
- init_mounts();
- for (m = mounts; m; m = m->next) {
- if (m->dev != full_st.st_dev)
- continue;
- prefix = m;
- break;
+ realname = expandpath(fullname);
+ if (realname) {
+ init_mounts();
+ for (m = mounts; m; m = m->next) {
+ if (m->dev != full_st.st_dev)
+ continue;
+ if (strncmp(realname, m->point, m->nlen) != 0)
+ continue;
+ prefix = m;
+ break;
+ }
}
}
@@ -727,20 +753,21 @@ int pidof (const char * inname, const ch
*/
if (!(flags & (KTHREAD|KSHORT)) && !isscrpt) {
char entry[PATH_MAX+1];
- char *realname = NULL;
- const char *name;
+ const char *name = NULL;
boolean found;
- if ((rll = readlinkat(dfd, here(d->d_name, "exe"), entry, PATH_MAX)) < 0) {
- if (errno != EPERM && errno != EACCES)
- goto risky;
- continue;
- }
- entry[rll] = '\0';
- name = handl_buf(entry);
+ if (prefix) {
+ if ((rll = readlinkat(dfd, here(d->d_name, "exe"), entry, PATH_MAX)) < 0) {
+ if (errno != EPERM && errno != EACCES)
+ goto risky;
+ continue;
+ }
+ entry[rll] = '\0';
+ name = handl_buf(entry);
- if (prefix && find_mount(name) != prefix)
- continue;
+ if (!find_mount(name, prefix))
+ continue;
+ }
if (fstatat(dfd, here(d->d_name, "exe"), &pid_st, 0) < 0) {
if (errno != EPERM && errno != EACCES)
@@ -765,18 +792,24 @@ int pidof (const char * inname, const ch
if (strlen(fullname) > PATH_MAX)
continue;
+ if (!name) {
+ if ((rll = readlinkat(dfd, here(d->d_name, "exe"), entry, PATH_MAX)) < 0) {
+ if (errno != EPERM && errno != EACCES)
+ goto risky;
+ continue;
+ }
+ entry[rll] = '\0';
+ name = handl_buf(entry);
+ }
+
if (strncmp(fullname, name, PATH_MAX) == 0) {
found = true;
break;
}
- if ((realname = realpath(name, NULL)) == (char*)0)
- continue;
-
- if (strncmp(realname, name, PATH_MAX) == 0)
+ if (realname && strncmp(realname, name, PATH_MAX) == 0)
found = true;
- free(realname);
break;
}
@@ -896,6 +929,7 @@ int verify_pidfile (const char * pid_fil
pid_t pid;
char *swapname = NULL, *bufp;
char *fullname = (char *)inname;
+ char *realname = NULL;
struct stat pid_st, full_st;
char buf[BUFSIZ];
@@ -958,6 +992,7 @@ int verify_pidfile (const char * pid_fil
warn("cannot stat %s: %s\n", fullname, strerror(errno));
return -1;
}
+ realname = expandpath(fullname);
}
if (flags & (KTHREAD|KSHORT)) {
@@ -997,7 +1032,6 @@ int verify_pidfile (const char * pid_fil
char entry[PATH_MAX+1];
const char *name;
- char *realname;
boolean found;
ssize_t rll;
@@ -1028,14 +1062,9 @@ int verify_pidfile (const char * pid_fil
break;
}
- if ((realname = realpath(fullname, NULL)) == (char*)0)
- goto out;
-
- if (strncmp(realname, name, PATH_MAX) == 0)
+ if (realname && strncmp(realname, name, PATH_MAX) == 0)
found = true;
- free(realname);
-
break;
}
@@ -1115,6 +1144,7 @@ int check_pids (const char * inname, con
boolean isscrpt = false;
char *swapname = (char*)0;
char *fullname = (char *)inname;
+ char *realname = (char*)0;
const char *pid;
struct stat pid_st, full_st;
PROC *p, *n, *l;
@@ -1132,6 +1162,7 @@ int check_pids (const char * inname, con
warn("cannot stat %s: %s\n", fullname, strerror(errno));
return -1;
}
+ realname = expandpath(fullname);
}
if (flags & (KTHREAD|KSHORT)) {
@@ -1191,7 +1222,6 @@ int check_pids (const char * inname, con
char entry[PATH_MAX+1];
const char *name;
- char *realname;
ssize_t rll;
if (pid_st.st_dev != full_st.st_dev)
@@ -1218,14 +1248,8 @@ int check_pids (const char * inname, con
if (strncmp(fullname, name, PATH_MAX) == 0)
continue; /* Found */
- if ((realname = realpath(fullname, NULL)) == (char*)0)
- goto ignore; /* Bogus */
-
- if (strncmp(realname, name, PATH_MAX) == 0) {
- free(realname);
+ if (realname && strncmp(realname, name, PATH_MAX) == 0)
continue; /* Found */
- }
- free(realname);
break;
}
@@ -1807,4 +1831,100 @@ void clear_nfs(void)
}
}
+/*
+ * Somehow the realpath(3) glibc function call, nevertheless
+ * it avoids lstat(2) system calls.
+ */
+static char real[PATH_MAX+1];
+char* expandpath(const char * path)
+{
+ char tmpbuf[PATH_MAX+1];
+ const char *start, *end;
+ char *curr, *dest;
+ int deep = MAXSYMLINKS;
+
+ if (!path || *path == '\0')
+ return (char*)0;
+
+ curr = &real[0];
+
+ if (*path != '/') {
+ if (!getcwd(curr, PATH_MAX))
+ return (char*)0;
+ dest = rawmemchr(curr, '\0');
+ } else {
+ *curr = '/';
+ dest = curr + 1;
+ }
+
+ for (start = end = path; *start; start = end) {
+
+ while (*start == '/')
+ ++start;
+
+ for (end = start; *end && *end != '/'; ++end)
+ ;
+
+ if (end - start == 0)
+ break;
+ else if (end - start == 1 && start[0] == '.') {
+ ;
+ } else if (end - start == 2 && start[0] == '.' && start[1] == '.') {
+ if (dest > curr + 1)
+ while ((--dest)[-1] != '/')
+ ;
+ } else {
+ char lnkbuf[PATH_MAX+1];
+ size_t len;
+ ssize_t n;
+
+ if (dest[-1] != '/')
+ *dest++ = '/';
+
+ if (dest + (end - start) > curr + PATH_MAX) {
+ errno = ENAMETOOLONG;
+ return (char*)0;
+ }
+
+ dest = mempcpy(dest, start, end - start);
+ *dest = '\0';
+
+ if (deep-- < 0) {
+ errno = ELOOP;
+ return (char*)0;
+ }
+
+ errno = 0;
+ if ((n = readlink(curr, lnkbuf, PATH_MAX)) < 0) {
+ deep = MAXSYMLINKS;
+ if (errno == EINVAL)
+ continue; /* Not a symlink */
+ return (char*)0;
+ }
+ lnkbuf[n] = '\0'; /* Don't be fooled by readlink(2) */
+
+ len = strlen(end);
+ if ((n + len) > PATH_MAX) {
+ errno = ENAMETOOLONG;
+ return (char*)0;
+ }
+
+ memmove(&tmpbuf[n], end, len + 1);
+ path = end = memcpy(tmpbuf, lnkbuf, n);
+
+ if (lnkbuf[0] == '/')
+ dest = curr + 1;
+ else if (dest > curr + 1)
+ while ((--dest)[-1] != '/');
+
+ }
+ }
+
+ if (dest > curr + 1 && dest[-1] == '/')
+ --dest;
+ *dest = '\0';
+
+ return curr;
+}
+
/* libinit.c ends here */