diff --git a/killproc-2.17.dif b/killproc-2.17.dif index 24d208c..e9efb71 100644 --- a/killproc-2.17.dif +++ b/killproc-2.17.dif @@ -1,13 +1,207 @@ +--- Makefile ++++ Makefile 2011-02-04 14:36:46.959926571 +0000 +@@ -12,7 +12,7 @@ INITDIR = /etc/init.d + PREFIX = /usr + DEBUG = + DESTDIR = +-VERSION = 2.17 ++VERSION = 2.18 + DATE = $(shell date +'%d%b%y' | tr '[:lower:]' '[:upper:]') + + ifneq ($(INC),) +@@ -55,6 +55,7 @@ UBINPRG = + ifeq ($(DISTRO),SuSE) + UBINPRG += usleep + UBINPRG += fsync ++ SBINPRG += rvmtab + SBINPRG += vhangup + SBINPRG += mkill + endif +@@ -101,6 +102,9 @@ vhangup: vhangup.c + mkill: mkill.c libinit.o + $(CC) $(CFLAGS) -o $@ $^ $(LIBS) + ++rvmtab: rvmtab.c libinit.o ++ $(CC) $(CFLAGS) -o $@ $^ $(LIBS) ++ + clean: + $(RM) *.o *~ $(SBINPRG) $(UBINPRG) + +@@ -143,6 +147,7 @@ FILES = README \ + checkproc.8 \ + libinit.c \ + libinit.h \ ++ lists.h \ + usleep.c \ + usleep.1 \ + fsync.c \ +@@ -151,6 +156,8 @@ FILES = README \ + vhangup.8 \ + mkill.c \ + mkill.8 \ ++ rvmtab.c \ ++ rvmtab.8 \ + killproc-$(VERSION).lsm + + dest: +--- checkproc.c ++++ checkproc.c 2011-02-04 14:01:49.604190644 +0000 +@@ -31,10 +31,11 @@ int main(int argc, char **argv) + int blog = 0; + #endif + struct stat st; +- PROC * list; ++ list_t *list; + char *fullname = NULL, * basename = NULL; + char *pid_file = NULL, *ignore_file = NULL; +- char *root = NULL, *iargv[argc]; ++ char *root = NULL; ++ extension char *iargv[argc]; + char *posixa, *posixb; /* Don't fool me with posix correct */ + int quiet = 1, iargc = 0; + unsigned short flags = (DAEMON|PIDOF|NZOMBIE); +@@ -166,7 +167,7 @@ int main(int argc, char **argv) + if (remember_pids(pid_file,fullname,root,flags) < 0) + exit(LSB_STATUS_PROOFX); + +- if (!remember) ++ if (list_empty(&remember)) + exit(LSB_STATUS_NOPROC); /* New LSB: no pid file is no job */ + } + free(pid_file); +@@ -210,7 +211,7 @@ int main(int argc, char **argv) + if (verify_pidfile(pid_file,fullname,root,flags,false) < 0) + exit(LSB_STATUS_PROOFX); + } +- if (!remember) { /* No process found with pid file */ ++ if (list_empty(&remember)) { /* No process found with pid file */ + if (pid_forced) + exit(LSB_STATUS_PROOFX); + if (pidof(fullname,root,flags) < 0) +@@ -228,16 +229,17 @@ int main(int argc, char **argv) + clear_pids(); /* Remove all pids which should be ignored */ + + num = 0; /* If quiet we could test 'remember' and exit appropiate */ +- for(list = remember; list; list = list->next) { ++ list_for_each(list, &remember) { ++ PROC *proc = list_entry(list, PROC); + if (!quiet) { + if (num) putchar(' '); +- printf("%d", (int)list->pid); ++ printf("%ld", (long int)proc->pid); + } + #ifdef USE_BLOGD + if (bootlog(B_NOTICE, "%s: %s ", we_are, fullname) == 0) { + blog++; + if (num) bootlog(-1, " "); +- bootlog(-1, "%d", (int)list->pid); ++ bootlog(-1, "%ld", (long int)proc->pid); + } + #endif + num++; +--- killproc.c ++++ killproc.c 2011-02-04 14:00:52.143926916 +0000 +@@ -40,10 +40,11 @@ int main(int argc, char **argv) + { + int c, snum; + struct stat st; +- PROC * list; ++ list_t *list; + char *fullname = NULL, *basename = NULL; + char *pid_file = NULL, *ignore_file = NULL; +- char *root = NULL, *iargv[argc]; ++ char *root = NULL; ++ extension char *iargv[argc]; + char *posixa, *posixb; /* Don't fool me with posix correct */ + int process_group = 0, group_leader = 0, wait = 5, iargc = 0; + unsigned short flags = (KILL|PIDOF|KSTOP); +@@ -216,7 +217,7 @@ int main(int argc, char **argv) + if (remember_pids(pid_file,fullname,root,flags) < 0) + exit(LSB_PROOFX); + +- if (!remember) ++ if (list_empty(&remember)) + exit(LSB_NOPROC); /* New LSB: no pid file is no job */ + } + free(pid_file); +@@ -266,7 +267,7 @@ int main(int argc, char **argv) + clear_pids(); /* Remove all pids which should be ignored */ + + /* Do main work */ +- if (!remember) { ++ if (list_empty(&remember)) { + /* killing a none existing process is already success. + * Nevertheless LSB says that we should note that if + * a signal is explicit given. +@@ -275,8 +276,10 @@ int main(int argc, char **argv) + } + + num = 0; +- for(list = remember; list; list = list->next) +- do_kill(basename, list->pid, snum, group_leader, process_group); ++ list_for_each(list, &remember) { ++ PROC *proc = list_entry(list, PROC); ++ do_kill(basename, proc->pid, snum, group_leader, process_group); ++ } + + if (snum == SIGTERM || snum == SIGKILL) { + int partsec = 5*wait; /* We look 5 times within a second */ +@@ -290,7 +293,7 @@ again: + if (check_pids(fullname,root,flags) < 0) + exit(LSB_PROOFX); + +- if (!remember) /* success */ ++ if (list_empty(&remember)) /* success */ + goto success; + + fflush(stdout); +@@ -309,8 +312,10 @@ again: + if (check_pids(fullname,root,flags) < 0) + exit(LSB_PROOFX); + +- for(list = remember; list; list = list->next) +- do_kill(basename, list->pid, SIGKILL, group_leader, process_group); ++ list_for_each(list, &remember) { ++ PROC *proc = list_entry(list, PROC); ++ do_kill(basename, proc->pid, SIGKILL, group_leader, process_group); ++ } + + /* Do we have killed them? */ + +@@ -318,7 +323,7 @@ again: + if (check_pids(fullname,root,flags) < 0) + exit(LSB_PROOFX); + +- if (remember) ++ if (!list_empty(&remember)) + goto badterm; + + success: --- libinit.c -+++ libinit.c 2011-01-27 12:58:48.944425833 +0000 -@@ -218,6 +218,26 @@ static struct _sys_signals { ++++ libinit.c 2011-02-04 13:59:58.869397977 +0000 +@@ -41,8 +41,14 @@ extern void vsyslog (int, const char *, + + char * newenvp[MAXENV]; + unsigned newenvc = 0; ++ ++#if 1 ++list_t remember = {&remember, &remember}; ++list_t doignore = {&doignore, &doignore}; ++#else + PROC * remember = (PROC*)0; + PROC * doignore = (PROC*)0; ++#endif + + char * we_are; + unsigned short stopped = 0; +@@ -218,29 +224,50 @@ static struct _sys_signals { { 0, "EXIT" } }; +/* + * Calculate the depth of a directory, root has zero depth. + */ -+static size_t dirdepth(const char *const path) ++size_t dirdepth(const char *const path) +{ + const char *ptr = path; + size_t cnt = 0; @@ -26,27 +220,59 @@ + typedef struct _mntinfo_ { - struct _mntinfo_ *next; -@@ -226,6 +246,7 @@ typedef struct _mntinfo_ +- struct _mntinfo_ *next; +- struct _mntinfo_ *prev; +- struct _mntinfo_ *parent; ++ list_t this; int id, parid; - dev_t dev; - size_t nlen; -+ size_t deep; - char * point; +- dev_t dev; +- size_t nlen; +- char * point; ++ dev_t dev; ++ size_t nlen; ++ char *point; } MNTINFO; -@@ -253,6 +274,7 @@ static void init_mounts(void) +-static MNTINFO *mounts; ++static list_t mounts = {&mounts, &mounts}; ++static list_t save = {&save, &save}; + + static void init_mounts(void) + { + char point[PATH_MAX+1]; ++ struct stat st; + int mid, parid, max = 0; + uint maj, min; +- MNTINFO *save; + FILE * mnt; +- +- if (mounts) +- return; ++ ++ /* Stat /proc/version to see if /proc is mounted. */ ++ if (stat("/proc/version", &st) < 0) ++ getproc(); ++ + if ((mnt = fopen("/proc/self/mountinfo", "r")) == (FILE*)0) + return; + while (fscanf(mnt, "%i %i %u:%u %*s %s %*[^\n]", &mid, &parid, &maj, &min, &point[0]) == 5) { +@@ -250,72 +277,46 @@ static void init_mounts(void) + if (stopped) kill(-1, SIGCONT); + error(100, "malloc(): %s\n", strerror(errno)); + } ++ append(p, mounts); 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 (mounts) +- mounts->prev = p; +- p->next = mounts; +- p->prev = (MNTINFO*)0; +- p->parent = p; +- mounts = p; - if (mid > max) - max = mid; + if (p->id > max) @@ -55,57 +281,126 @@ 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; +- save = (MNTINFO*)0; ++ /* Sort mount points accordingly to their reverse mount order */ ++ initial(&save); + for (mid = 1; mid <= max; 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) ++ list_t *this, *cpy; ++ list_for_each_safe(this, cpy, &mounts) { ++ MNTINFO *m = list_entry(this, MNTINFO); ++ if (mid != m->id) 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; +- l = m->prev; +- if (m == mounts) { +- if (n) n->prev = (MNTINFO*)0; +- mounts = n; +- } else if (l) { +- if (n) n->prev = l; +- l->next = n; +- } +- if (save) +- save->prev = m; +- m->next = save; +- m->prev = (MNTINFO*)0; +- save = m; ++ move_head(this, &save); + break; + } +- } +- mounts = save; +- +- /* Now determine the parent of each mount point */ +- for (save = mounts; save; save = save->next) { +- MNTINFO *p; +- for (p = mounts; p; p = p->next) { +- if (save->parid != p->id) ++ list_for_each_safe(this, cpy, &mounts) { ++ MNTINFO *m = list_entry(this, MNTINFO); ++ if (mid != m->parid) + continue; +- save->parent = p; - break; ++ move_head(this, &save); } } - mounts = save; -@@ -307,15 +328,14 @@ static void init_mounts(void) - } ++ if (!list_empty(&mounts)) { ++ if (stopped) kill(-1, SIGCONT); ++ error(100, "sort(): %s\n", strerror(EBADE)); ++ } ++ join(&save, &mounts); } -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) { +- 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; ++ return (strncmp(path, s->point, s->nlen) == 0); } extern inline char * handl_buf(char *restrict buf) -@@ -627,6 +647,7 @@ int pidof (const char * inname, const ch +@@ -333,7 +334,7 @@ extern inline char * handl_buf(char *res + /* write to syslog file if not open terminal */ + static void nsyslog(int pri, const char *fmt, va_list args) + { +- char newfmt[strlen(we_are)+2+strlen(fmt)+1]; ++ extension char newfmt[strlen(we_are)+2+strlen(fmt)+1]; + + strcat(strcat(strcpy(newfmt, we_are), ": "), fmt); + +@@ -365,7 +366,7 @@ void warn(const char *fmt, ...) + + static void dsyslog(int pri, const char *fmt, va_list args) + { +- char newfmt[strlen(we_are)+2+strlen(fmt)+1]; ++ extension char newfmt[strlen(we_are)+2+strlen(fmt)+1]; + + strcat(strcat(strcpy(newfmt, we_are), ": "), fmt); + vsyslog(pri, newfmt, args); +@@ -627,8 +628,9 @@ 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; +- PROC *p, *n; ++ list_t *m, *n; -@@ -659,12 +680,17 @@ int pidof (const char * inname, const ch + p_pid = getpid(); + p_ppid = getppid(); +@@ -641,30 +643,35 @@ int pidof (const char * inname, const ch + return -1; + } + +- n = remember; +- for (p = remember; n; p = n) { +- n = p->next; ++ list_for_each_safe(m, n, &remember) { ++ PROC *p = list_entry(m, PROC); ++ delete(m); + free(p); + } +- remember = (PROC*)0; + + /* killproc, daemon/startproc, pidof/pidofproc: stat fullname if a + * real program is handled, skip this if we handle a kernel thread */ + + if (!(flags & (KTHREAD|KSHORT))) { +- MNTINFO *m; + errno = 0; + if (rlstat(&fullname, &full_st, flags) < 0) { + /* stat() follows soft links -> security */ warn("cannot stat %s: %s\n", fullname, strerror(errno)); return -1; } @@ -117,8 +412,10 @@ - break; + realname = expandpath(fullname); + if (realname) { ++ list_t *ptr; + init_mounts(); -+ for (m = mounts; m; m = m->next) { ++ list_for_each(ptr, &mounts) { ++ MNTINFO *m = list_entry(ptr, MNTINFO); + if (m->dev != full_st.st_dev) + continue; + if (strncmp(realname, m->point, m->nlen) != 0) @@ -129,7 +426,7 @@ } } -@@ -727,20 +753,21 @@ int pidof (const char * inname, const ch +@@ -727,20 +734,21 @@ int pidof (const char * inname, const ch */ if (!(flags & (KTHREAD|KSHORT)) && !isscrpt) { char entry[PATH_MAX+1]; @@ -162,7 +459,7 @@ 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 +@@ -765,18 +773,24 @@ int pidof (const char * inname, const ch if (strlen(fullname) > PATH_MAX) continue; @@ -192,7 +489,7 @@ break; } -@@ -896,6 +929,7 @@ int verify_pidfile (const char * pid_fil +@@ -896,17 +910,17 @@ int verify_pidfile (const char * pid_fil pid_t pid; char *swapname = NULL, *bufp; char *fullname = (char *)inname; @@ -200,7 +497,22 @@ struct stat pid_st, full_st; char buf[BUFSIZ]; -@@ -958,6 +992,7 @@ int verify_pidfile (const char * pid_fil + if (!ignore) { +- PROC *p, *n; +- n = remember; +- for (p = remember; n; p = n) { +- n = p->next; ++ list_t *m, *n; ++ list_for_each_safe(m, n, &remember) { ++ PROC *p = list_entry(m, PROC); ++ delete(m); + free(p); + } +- remember = (PROC*)0; + } + + errno = 0; +@@ -958,6 +972,7 @@ int verify_pidfile (const char * pid_fil warn("cannot stat %s: %s\n", fullname, strerror(errno)); return -1; } @@ -208,7 +520,7 @@ } if (flags & (KTHREAD|KSHORT)) { -@@ -997,7 +1032,6 @@ int verify_pidfile (const char * pid_fil +@@ -997,7 +1012,6 @@ int verify_pidfile (const char * pid_fil char entry[PATH_MAX+1]; const char *name; @@ -216,7 +528,7 @@ boolean found; ssize_t rll; -@@ -1028,14 +1062,9 @@ int verify_pidfile (const char * pid_fil +@@ -1028,14 +1042,9 @@ int verify_pidfile (const char * pid_fil break; } @@ -232,15 +544,19 @@ break; } -@@ -1115,6 +1144,7 @@ int check_pids (const char * inname, con +@@ -1115,9 +1124,10 @@ 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 +- PROC *p, *n, *l; ++ list_t *m, *n; + int fp; + + if (!fullname) { +@@ -1132,6 +1142,7 @@ int check_pids (const char * inname, con warn("cannot stat %s: %s\n", fullname, strerror(errno)); return -1; } @@ -248,7 +564,22 @@ } if (flags & (KTHREAD|KSHORT)) { -@@ -1191,7 +1222,6 @@ int check_pids (const char * inname, con +@@ -1144,12 +1155,9 @@ int check_pids (const char * inname, con + swapname = swap_name(base_name(fullname)); + } + +- n = remember; +- l = (PROC*)0; +- for(p = remember; n; p = n) { ++ list_for_each_safe(m, n, &remember) { ++ PROC *p = list_entry(m, PROC); + boolean skip = false; +- l = p->prev; +- n = p->next; + + errno = 0; + if ((kill(p->pid, 0) < 0) && (errno == ESRCH)) +@@ -1191,7 +1199,6 @@ int check_pids (const char * inname, con char entry[PATH_MAX+1]; const char *name; @@ -256,7 +587,7 @@ ssize_t rll; if (pid_st.st_dev != full_st.st_dev) -@@ -1218,14 +1248,8 @@ int check_pids (const char * inname, con +@@ -1218,14 +1225,8 @@ int check_pids (const char * inname, con if (strncmp(fullname, name, PATH_MAX) == 0) continue; /* Found */ @@ -272,7 +603,331 @@ break; } -@@ -1807,4 +1831,100 @@ void clear_nfs(void) +@@ -1277,20 +1278,8 @@ int check_pids (const char * inname, con + ignore: + + /* Remove this entry in remember */ +- if (p == remember) { +- if (n) n->prev = (PROC*)0; +- remember = n; +- free(p); +- } else if (l) { +- if (n) n->prev = l; +- l->next = n; +- free(p); +- } else { +- warn("error in linked list handling\n"); +- free(swapname); +- return -1; +- } +- ++ delete(m); ++ free(p); + } + + free(swapname); +@@ -1302,27 +1291,17 @@ int check_pids (const char * inname, con + */ + void clear_pids (void) + { +- PROC *p, *n, *l; ++ list_t *n, *l; + +- n = remember; +- l = (PROC*)0; +- for(p = remember; n; p = n) { +- l = p->prev; +- n = p->next; ++ list_for_each_safe(n, l, &remember) { ++ PROC *p = list_entry(n, PROC); + + if (!check_ignore(p->pid) && !check_ignore(p->sid)) + continue; + + /* Remove this entry in remember */ +- if (p == remember) { +- if (n) n->prev = (PROC*)0; +- remember = n; +- free(p); +- } else if (l) { +- if (n) n->prev = l; +- l->next = n; +- free(p); +- } ++ delete(n); ++ free(p); + } + } + +@@ -1590,22 +1569,22 @@ out: + + typedef struct _shadow_ + { +- struct _shadow_ *next; +- struct _shadow_ *prev; ++ list_t this; + size_t nlen; + char * name; + } SHADOW; + + typedef struct _nfs_ + { +- struct _nfs_ *next; /* Pointer to next struct. */ +- struct _nfs_ *prev; /* Pointer to previous st. */ +- SHADOW *shadow; /* Pointer to shadows */ ++ list_t this; ++ SHADOW shadow; /* Pointer to shadows */ ++ int order; ++ int parent; + size_t nlen; + char * name; + } NFS; + +-NFS * nfs = (NFS*)0; ++static list_t nfs = {&nfs, &nfs}; + + static inline int isnetfs(const char * type) + { +@@ -1619,35 +1598,86 @@ static inline int isnetfs(const char * t + + void init_nfs(void) + { ++ char buffer[LINE_MAX]; + struct stat st; +- struct mntent * ent; ++ struct mntent ent; + FILE * mnt; + + /* Stat /proc/version to see if /proc is mounted. */ + if (stat("/proc/version", &st) < 0) + getproc(); + ++ /* Use /proc/self/mountinfo if available */ ++ if ((mnt = fopen("/proc/self/mountinfo", "r"))) { ++ char fstype[126]; ++ int mid, parid, max = 1; ++ ++ while (fscanf(mnt, "%i %i %*u:%*u %*s %s - %*s %s %*[^\n]", &mid, &parid, &buffer[0], &fstype[0]) == 3) { ++ NFS *restrict ptr; ++ size_t nlen; ++ ++ if (!isnetfs(fstype)) ++ continue; ++ nlen = strlen(buffer); ++ ++ if (posix_memalign((void*)&ptr, sizeof(void*), alignof(NFS)+(nlen+1)) != 0) ++ error(100, "malloc(): %s\n", strerror(errno)); ++ append(ptr, nfs); ++ ptr->order = mid; ++ ptr->parent = parid; ++ ptr->name = ((char*)ptr)+alignof(NFS); ++ strcpy(ptr->name, buffer); ++ ptr->nlen = nlen; ++ initial(&ptr->shadow.this); /* not required as we sort below */ ++ if (mid > max) ++ max = mid; ++ } ++ fclose(mnt); ++ ++ /* ++ * Now sort into reverse mount order, with this we do not ++ * need any shadow mounts anymore. ++ */ ++ initial(&save); ++ for (mid = 1; mid <= max; mid++) { ++ list_t *this, *cpy; ++ list_for_each_safe(this, cpy, &nfs) { ++ NFS * m = list_entry(this, NFS); ++ if (mid != m->order) ++ continue; ++ move_head(this, &save); ++ break; ++ } ++ list_for_each_safe(this, cpy, &nfs) { ++ NFS * m = list_entry(this, NFS); ++ if (mid != m->parent) ++ continue; ++ move_head(this, &save); ++ } ++ } ++ if (!list_empty(&nfs)) ++ error(100, "init_mnt(): %s\n", strerror(EBADE)); ++ join(&save, &nfs); ++ return; ++ } ++ + if ((mnt = setmntent("/proc/mounts", "r")) == (FILE*)0) + return; + +- while ((ent = getmntent(mnt))) { +- if (isnetfs(ent->mnt_type)) { +- const size_t nlen = strlen(ent->mnt_dir); ++ while (getmntent_r(mnt, &ent, buffer, sizeof(buffer))) { ++ if (isnetfs(ent.mnt_type)) { ++ const size_t nlen = strlen(ent.mnt_dir); + NFS *restrict p; + + if (posix_memalign((void*)&p, sizeof(void*), alignof(NFS)+(nlen+1)) != 0) { + if (stopped) kill(-1, SIGCONT); + error(100, "malloc(): %s\n", strerror(errno)); + } ++ append(p, nfs); + p->name = ((char*)p)+alignof(NFS); +- strcpy(p->name, ent->mnt_dir); ++ strcpy(p->name, ent.mnt_dir); + p->nlen = nlen; +- p->shadow = (SHADOW*)0; +- if (nfs) +- nfs->prev = p; +- p->next = nfs; +- p->prev = (NFS*)0; +- nfs = p; ++ initial(&p->shadow.this); + } + } + endmntent(mnt); +@@ -1655,43 +1685,41 @@ void init_nfs(void) + if ((mnt = setmntent("/proc/mounts", "r")) == (FILE*)0) + return; + +- while ((ent = getmntent(mnt))) { +- NFS *p; ++ while (getmntent_r(mnt, &ent, buffer, sizeof(buffer))) { ++ list_t *ptr; + +- for (p = nfs; p; p = p->next) { ++ list_for_each(ptr, &nfs) { ++ NFS *p = list_entry(ptr, NFS); + SHADOW * restrict s; + size_t nlen; + +- if (strcmp(ent->mnt_dir, p->name) == 0) ++ if (strcmp(ent.mnt_dir, p->name) == 0) + continue; +- if (strncmp(ent->mnt_dir, p->name, p->nlen) != 0) ++ if (strncmp(ent.mnt_dir, p->name, p->nlen) != 0) + continue; + +- nlen = strlen(ent->mnt_dir); ++ nlen = strlen(ent.mnt_dir); + if (posix_memalign((void*)&s, sizeof(void*), alignof(SHADOW)+(nlen+1))) { + if (stopped) kill(-1, SIGCONT); + error(100, "malloc(): %s\n", strerror(errno)); + } ++ append(s, p->shadow.this); + s->name = ((char*)s)+alignof(SHADOW); +- strcpy(s->name, ent->mnt_dir); ++ strcpy(s->name, ent.mnt_dir); + s->nlen = nlen; +- if (p->shadow) +- p->shadow->prev = s; +- s->next = p->shadow; +- s->prev = (SHADOW*)0; +- p->shadow = s; + } + } + endmntent(mnt); + } + +-static inline boolean shadow(SHADOW *restrict this, const char *restrict name, const size_t nlen) ++static inline boolean shadow(list_t *restrict shadow, const char *restrict name, const size_t nlen) + { +- SHADOW *s; ++ list_t *ptr; + +- if (!this) ++ if (!shadow || list_empty(shadow)) + goto out; +- for (s = this; s; s = s->next) { ++ list_for_each(ptr, shadow) { ++ SHADOW *s =list_entry(ptr, SHADOW); + if (nlen < s->nlen) + continue; + if (name[s->nlen] != '\0' && name[s->nlen] != '/') +@@ -1709,7 +1737,8 @@ boolean check4nfs(const char * path) + const char *curr; + int deep = MAXSYMLINKS; + +- if (!nfs) goto out; ++ if (list_empty(&nfs)) ++ goto out; + + curr = path; + do { +@@ -1747,15 +1776,16 @@ boolean check4nfs(const char * path) + } while (true); + + if (errno == EINVAL) { ++ list_t *ptr; + const size_t nlen = strlen(curr); +- NFS *p; +- for (p = nfs; p; p = p->next) { ++ list_for_each(ptr, &nfs) { ++ NFS *p = list_entry(ptr, NFS); + 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)) ++ if (shadow(&p->shadow.this, curr, nlen)) + continue; + return true; + } +@@ -1765,46 +1795,123 @@ out: + return false; + } + +-static inline void clear_shadow(SHADOW *restrict shadow) ++static void clear_shadow(list_t *restrict shadow) + { +- SHADOW *s, *n, *l; +- +- n = shadow; +- l = (SHADOW*)0; +- for (s = shadow; n; s = n) { +- l = s->prev; +- n = s->next; +- if (s == shadow) { +- if (n) n->prev = (SHADOW*)0; +- shadow = n; +- } else if (l) { +- if (n) n->prev = l; +- l->next = n; +- } ++ list_t *this, *ptr; ++ list_for_each_safe(this, ptr, shadow) { ++ SHADOW *s = list_entry(this, SHADOW); ++ delete(this); + free(s); + } + } + + void clear_nfs(void) + { +- NFS *p, *n, *l; ++ list_t *this, *ptr; + +- n = nfs; +- l = (NFS*)0; +- for (p = nfs; n; p = n) { +- l = p->prev; +- n = p->next; +- if (p == nfs) { +- if (n) n->prev = (NFS*)0; +- nfs = n; +- } else if (l) { +- if (n) n->prev = l; +- l->next = n; +- } +- if (p->shadow) +- clear_shadow(p->shadow); ++ list_for_each_safe(this, ptr, &nfs) { ++ NFS *p = list_entry(this, NFS); ++ delete(this); ++ if (!list_empty(&p->shadow.this)) ++ clear_shadow(&p->shadow.this); + free(p); } } @@ -373,3 +1028,1184 @@ +} + /* libinit.c ends here */ +--- libinit.h ++++ libinit.h 2011-02-04 14:11:37.615926560 +0000 +@@ -19,6 +19,8 @@ + * 2000/11/10 Werner Fink: LSB specs, logging + */ + ++#ifndef _LIBINIT_H ++#define _LIBINIT_H + #ifndef _GNU_SOURCE + # define _GNU_SOURCE + #endif +@@ -44,13 +46,7 @@ + #ifdef USE_BLOGD + # include + #endif +- +-#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)) ++#include "lists.h" + + /* + * LSB specs: +@@ -118,8 +114,6 @@ + #define DEFPIDEXT ".pid" + #define DEFPIDLEN 14 /* The string length of /var/run/.pid + 1 */ + +-typedef enum _boolean {false, true} boolean; +- + extern char **environ; + extern char * newenvp[]; + extern unsigned newenvc; +@@ -139,10 +133,12 @@ extern void clear_pids (void); + extern void error(int stat, const char *fmt, ...); + extern void warn(const char *fmt, ...); + extern int rlstat(char ** file, struct stat *st, const unsigned short flag); ++extern char* expandpath(const char * path); + extern void init_nfs(void); + extern void clear_nfs(void); + extern void getproc(void); + extern boolean check4nfs(const char * path); ++extern size_t dirdepth(const char *const path); + + /* Feature */ + extern int signame_to_signum (const char *sig); +@@ -171,14 +167,13 @@ static inline void list_signames(void) + + typedef struct _proc_ + { +- struct _proc_ *next; /* Pointer to next struct. */ +- struct _proc_ *prev; /* Pointer to previous st. */ +- pid_t pid; /* Process ID. */ +- pid_t sid; /* Session ID. */ ++ list_t this; ++ pid_t pid; /* Process ID. */ ++ pid_t sid; /* Session ID. */ + } PROC; + +-extern PROC * remember; +-extern PROC * doignore; ++extern list_t remember; ++extern list_t doignore; + + /* Inlined functions: just like macros */ + +@@ -301,31 +296,21 @@ static inline void do_list(const pid_t p + p->pid = pid; + p->sid = sid; + if (ignore) { +- if (doignore) +- doignore->prev = p; +- p->next = doignore; +- p->prev = (PROC*)0; +- doignore = p; ++ append(p, doignore); + } else { +- if (remember) +- remember->prev = p; +- p->next = remember; +- p->prev = (PROC*)0; +- remember = p; ++ append(p, remember); + } +- +- return; + } + + static inline boolean check_ignore(const pid_t pid) + { +- PROC * q, * m = doignore; ++ list_t *m; + + if (pid <= 1) + goto out; + +- for (q = doignore; m; q = m) { +- m = q->next; ++ list_for_each(m, &doignore) { ++ PROC *q = list_entry(m, PROC); + if (pid == q->pid) + return true; + } +@@ -335,28 +320,20 @@ out: + + static inline void clear_ignore(void) + { +- PROC * p, *l, * n = remember; ++ list_t *n, *l; + +- if (!doignore) ++ if (list_empty(&doignore)) + return; + +- for (p = remember; n; p = n) { +- l = p->prev; +- n = p->next; ++ list_for_each_safe(n, l, &remember) { ++ PROC *p = list_entry(n, PROC); + + if (!check_ignore(p->pid)) + continue; + + /* Remove this entry in remember because we ignore it */ +- if (p == remember) { +- if (n) n->prev = (PROC*)0; +- remember = n; +- free(p); +- } else if (l) { +- if (n) n->prev = l; +- l->next = n; +- free(p); +- } ++ delete(n); ++ free(p); + } + } +-/* libinit.h ends here */ ++#endif /* _LIBINIT_H */ +--- lists.h ++++ lists.h 2011-02-03 09:46:06.375927048 +0000 +@@ -0,0 +1,248 @@ ++/* ++ * lists.h Simple doubly linked list implementation, ++ * based on and . ++ * ++ * Version: 0.1 01-Feb-2011 Fink ++ * ++ * Copyright 2011 Werner Fink, 2005 SUSE LINUX Products GmbH, Germany. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * Author: Werner Fink , 2011 ++ */ ++ ++#ifndef _LISTS_H ++#define _LISTS_H ++ ++#include ++#include ++ ++typedef enum _boolean {false, true} boolean; ++typedef unsigned char uchar; ++#ifndef __USE_MISC ++typedef unsigned short ushort; ++typedef unsigned int uint; ++#endif ++ ++#ifndef __OPTIMIZE__ ++# warning This will not compile without -O at least ++#endif ++#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ++# ifndef inline ++# define inline __inline__ ++# endif ++# ifndef restrict ++# define restrict __restrict__ ++# endif ++# ifndef volatile ++# define volatile __volatile__ ++# endif ++# ifndef asm ++# define asm __asm__ ++# endif ++# ifndef extension ++# define extension __extension__ ++# endif ++#endif ++#ifndef attribute ++# define attribute(attr) __attribute__(attr) ++#endif ++ ++/* ++ * This is lent from the kernel by e.g. using ++ * ++ * echo '#include \nint main () { prefetch(); return 0; }' | \ ++ * gcc -I/usr/src/linux/include -D__KERNEL__ -x c -E -P - | \ ++ * sed -rn '/void[[:blank:]]+prefetch[[:blank:]]*\(/,/^}/p' ++ * ++ * on the appropiate architecture (here on i686 for i586). ++ */ ++static inline void prefetch(const void *restrict x) attribute((used,always_inline)); ++static inline void prefetch(const void *restrict x) ++{ ++#if defined(__x86_64__) ++ asm volatile ("prefetcht0 %0" :: "m" (*(unsigned long *)x)) ++#elif defined(__ia64__) ++ asm volatile ("lfetch [%0]" :: "r" (x)) ++#elif defined(__powerpc64__) ++ asm volatile ("dcbt 0,%0" :: "r" (x)) ++#elif 1 && defined(__i386__) ++ asm volatile ("661:\n\t" ++ ".byte 0x8d,0x74,0x26,0x00\n" ++ "\n662:\n" ++ ".section .altinstructions,\"a\"\n" ++ " .align 4\n" ++ " .long 661b\n" ++ " .long 663f\n" ++ " .byte %c0\n" ++ " .byte 662b-661b\n" ++ " .byte 664f-663f\n" ++ ".previous\n" ++ ".section .altinstr_replacement,\"ax\"\n" ++ " 663:\n\t" ++ " prefetchnta (%1)" ++ " \n664:\n" ++ ".previous" ++ :: "i" ((0*32+25)), "r" (x)) ++#endif ++ ; ++} ++ ++#if defined(DEBUG) && (DEBUG > 0) ++# define __align attribute((packed)) ++#else ++# define __align attribute((aligned(sizeof(struct list_struct*)))) ++#endif ++#define __packed attribute((packed)) ++ ++#define alignof(type) ((sizeof(type)+(sizeof(void*)-1)) & ~(sizeof(void*)-1)) ++#define strsize(string) ((strlen(string)+1)*sizeof(char)) ++ ++typedef struct list_struct { ++ struct list_struct * next, * prev; ++} __align list_t; ++ ++/* ++ * Linked list handling ++ * ==================== ++ * The structures which will be linked into such lists have to be of the ++ * same type. The structures may have alway a list identifier of the type ++ * `list_t' as very first element. With this the macro list_entry() can ++ * be used to cast the memory address of a list member to the corresponding ++ * allocated structure. ++ */ ++ ++/* ++ * Insert new entry as next member. ++ */ ++static inline void _insert(list_t *restrict new, list_t *restrict here) attribute((always_inline,nonnull(1,2))); ++static inline void _insert(list_t *restrict new, list_t *restrict here) ++{ ++ list_t * prev = here; ++ list_t * next = here->next; ++ ++ next->prev = new; ++ new->next = next; ++ new->prev = prev; ++ prev->next = new; ++} ++ ++#define insert(new, list) _insert(&((new)->this), (&(list))); ++#define append(new, list) _insert(&((new)->this), (&(list))->prev); ++ ++/* ++ * Set head ++ */ ++static inline void initial(list_t *restrict head) attribute((always_inline,nonnull(1))); ++static inline void initial(list_t *restrict head) ++{ ++ head->prev = head->next = head; ++} ++ ++/* ++ * Remove entries, note that the pointer its self remains. ++ */ ++static inline void delete(list_t *restrict entry) attribute((always_inline,nonnull(1))); ++static inline void delete(list_t *restrict entry) ++{ ++ list_t * prev = entry->prev; ++ list_t * next = entry->next; ++ ++ next->prev = prev; ++ prev->next = next; ++ ++ initial(entry); ++} ++ ++/* ++ * Replace an entry by a new one. ++ */ ++static inline void replace(list_t *restrict old, list_t *restrict new) attribute((always_inline,nonnull(1,2))); ++static inline void replace(list_t *restrict old, list_t *restrict new) ++{ ++ new->next = old->next; ++ new->next->prev = new; ++ new->prev = old->prev; ++ new->prev->next = new; ++} ++ ++static inline void join(list_t *restrict list, list_t *restrict head) attribute((always_inline,nonnull(1,2))); ++static inline void join(list_t *restrict list, list_t *restrict head) ++{ ++ list_t * first = list->next; ++ ++ if (first != list) { ++ list_t * last = list->prev; ++ list_t * at = head->next; ++ ++ first->prev = head; ++ head->next = first; ++ ++ last->next = at; ++ at->prev = last; ++ } ++} ++ ++static inline boolean list_empty(const list_t *restrict const head) attribute((always_inline,nonnull(1))); ++static inline boolean list_empty(const list_t *restrict const head) ++{ ++ return head->next == head; ++} ++ ++static inline void move_head(list_t *restrict entry, list_t *restrict head) attribute((always_inline,nonnull(1,2))); ++static inline void move_head(list_t *restrict entry, list_t *restrict head) ++{ ++ list_t * prev = entry->prev; ++ list_t * next = entry->next; ++ ++ next->prev = prev; /* remove entry from old list */ ++ prev->next = next; ++ ++ prev = head; ++ next = head->next; ++ ++ next->prev = entry; /* and add it at head of new list */ ++ entry->next = next; ++ entry->prev = prev; ++ prev->next = entry; ++} ++ ++static inline void move_tail(list_t *restrict entry, list_t *restrict head) attribute((always_inline,nonnull(1,2))); ++static inline void move_tail(list_t *restrict entry, list_t *restrict head) ++{ ++ list_t * prev = entry->prev; ++ list_t * next = entry->next; ++ ++ next->prev = prev; /* remove entry from old list */ ++ prev->next = next; ++ ++ prev = head->prev; ++ next = head; ++ ++ next->prev = entry; /* and add it at tail of new list */ ++ entry->next = next; ++ entry->prev = prev; ++ prev->next = entry; ++} ++ ++/* ++ * The handle of the list is named `this' ++ */ ++#define list_entry(ptr, type) (__extension__ ({ \ ++ const typeof( ((type *)0)->this ) *__mptr = (ptr); \ ++ ((type *)( (char *)(__mptr) - offsetof(type,this) )); })) ++#define list_for_each(pos, head) \ ++ for (pos = (head)->next; prefetch(pos->next), pos != (head); pos = pos->next) ++#define np_list_for_each(pos, head) \ ++ for (pos = (head)->next; pos != (head); pos = pos->next) ++#define list_for_each_safe(pos, safe, head) \ ++ for (pos = (head)->next, safe = pos->next; pos != (head); pos = safe, safe = pos->next) ++#define list_for_each_prev(pos, head) \ ++ for (pos = (head)->prev; prefetch(pos->prev), pos != (head); pos = pos->prev) ++#define np_list_for_each_prev(pos, head) \ ++ for (pos = (head)->prev; pos != (head); pos = pos->prev) ++ ++#endif /* _LISTS_H */ +--- mkill.c ++++ mkill.c 2011-02-04 12:55:08.072990008 +0000 +@@ -29,6 +29,7 @@ + #include + #include + #include "libinit.h" ++#include "lists.h" + + #ifndef MNT_FORCE + # define MNT_FORCE 0x00000001 +@@ -62,33 +63,33 @@ extern inline DIR * opendirat(int dirfd, + + typedef struct _s_shadow + { +- struct _s_shadow *next; +- struct _s_shadow *prev; ++ list_t this; + size_t nlen; + char * name; + } shadow_t; + + typedef struct _s_mnt + { +- struct _s_mnt *next; /* Pointer to next struct. */ +- struct _s_mnt *prev; /* Pointer to previous st. */ +- shadow_t *shadow; /* Pointer to shadows */ +- size_t nlen; +- char * name; +- int order; /* Order of the mount point*/ ++ list_t this; ++ int order; /* Order of the mount point*/ ++ int parent; /* Order of the parent mount point*/ ++ shadow_t shadow; /* Pointer to shadows */ ++ size_t nlen; ++ char * name; + } mntent_t; + + typedef struct _s_proc_ + { +- struct _s_proc_ *next; /* Pointer to next struct. */ +- struct _s_proc_ *prev; /* Pointer to previous st. */ +- pid_t pid; /* Process ID. */ +- int order; /* Order of the mount point*/ ++ list_t this; ++ pid_t pid; /* Process ID. */ ++ int order; /* Order of the mount point*/ + } proc_t; + + static int maxorder = 1; /* This has to be initial 1 */ +-static mntent_t * mntent; +-static proc_t * procs; ++ ++static list_t mntent = {&mntent, &mntent}; ++static list_t procs = {&procs, &procs}; ++static list_t sort = {&sort, &sort}; + + static void init_mnt(int argc, char* argv[]); + static void clear_mnt(const boolean lazy); +@@ -101,7 +102,7 @@ int main(int argc, char* argv[]) + const pid_t pid = getpid(); + const pid_t sid = getsid(0); + const pid_t ppid = getppid(); +- proc_t * this, *ptr, * last; ++ list_t * this, *ptr; + struct dirent * dent; + int dfd, num, nsig = SIGTERM; + boolean lazy = false; +@@ -306,22 +307,12 @@ int main(int argc, char* argv[]) + + if (found) { + if (isfuse) { +- this = procs; +- last = (proc_t*)0; +- +- for (ptr = procs; this; ptr = this) { +- last = ptr->prev; +- this = ptr->next; +- if (ptr->pid != curr) ++ list_for_each_safe(this, ptr, &procs) { ++ proc_t *p = list_entry(this, proc_t); ++ if (p->pid != curr) + continue; +- if (ptr == procs) { +- if (this) this->prev = (proc_t*)0; +- procs = this; +- } else if (last) { +- if (this) this->prev = last; +- last->next = this; +- } +- free(ptr); ++ delete(this); ++ free(p); + } + break; + } +@@ -343,16 +334,17 @@ int main(int argc, char* argv[]) + + num = 0; + found = false; +- for (ptr = procs; ptr; ptr = ptr->next) { ++ list_for_each(ptr, &procs) { ++ proc_t *p = list_entry(ptr, proc_t); + if (nsig) { + if (stop) +- kill(ptr->pid, SIGSTOP); +- kill(ptr->pid, nsig); ++ kill(p->pid, SIGSTOP); ++ kill(p->pid, nsig); + found = true; + } else { + if (num++ > 0) + putc(' ', stdout); +- printf("%d", ptr->pid); ++ printf("%d", p->pid); + } + } + if (stop) +@@ -376,25 +368,14 @@ int main(int argc, char* argv[]) + usleep(10000); + num -= 10000; + +- this = procs; +- last = (proc_t*)0; + found = false; +- for (ptr = procs; this; ptr = this) { +- last = ptr->prev; +- this = ptr->next; +- +- if (kill (ptr->pid, 0) < 0) { +- if (ptr == procs) { +- if (this) this->prev = (proc_t*)0; +- procs = this; +- } else if (last) { +- if (this) this->prev = last; +- last->next = this; +- } ++ list_for_each_safe(this, ptr, &procs) { ++ proc_t *p = list_entry(this, proc_t); ++ if (kill (p->pid, 0) < 0) { ++ delete(this); + free(ptr); + continue; + } +- + found = true; + } + } +@@ -402,9 +383,10 @@ int main(int argc, char* argv[]) + if (!found) + goto out; + +- for (ptr = procs; ptr; ptr = ptr->next) { +- kill(ptr->pid, SIGSTOP); +- kill(ptr->pid, SIGKILL); ++ list_for_each(ptr, &procs) { ++ proc_t *p = list_entry(ptr, proc_t); ++ kill(p->pid, SIGSTOP); ++ kill(p->pid, SIGKILL); + } + kill(-1, SIGCONT); + +@@ -414,48 +396,109 @@ out: + + static void init_mnt(int argc, char* argv[]) + { ++ char buffer[LINE_MAX]; + struct stat st; +- struct mntent * ent; ++ struct mntent ent; + FILE * mnt; +- int order; ++ int order = maxorder; + + /* Stat /proc/version to see if /proc is mounted. */ + if (stat("/proc/version", &st) < 0) + getproc(); + ++ /* Use /proc/self/mountinfo if available */ ++ if ((mnt = fopen("/proc/self/mountinfo", "r"))) { ++ int mid, parid; ++ ++ while (fscanf(mnt, "%i %i %*u:%*u %*s %s %*[^\n]", &mid, &parid, &buffer[0]) == 3) { ++ mntent_t *restrict ptr; ++ boolean found = false; ++ size_t nlen; ++ int num; ++ ++ for (num = 0; num < argc; num++) { ++ if (*(argv[num]) == '\0') ++ continue; ++ if ((found = (strcmp(argv[num], buffer) == 0))) ++ break; ++ } ++ ++ if (!found) ++ continue; ++ nlen = strlen(buffer); ++ ++ if (posix_memalign((void*)&ptr, sizeof(void*), alignof(mntent_t)+(nlen+1)) != 0) ++ error(100, "malloc(): %s\n", strerror(errno)); ++ append(ptr, mntent); ++ ptr->order = mid; ++ ptr->parent = parid; ++ ptr->name = ((char*)ptr)+alignof(mntent_t); ++ strcpy(ptr->name, buffer); ++ ptr->nlen = nlen; ++ initial(&ptr->shadow.this); /* not required as we sort below */ ++ if (mid > order) ++ order = mid; ++ } ++ fclose(mnt); ++ maxorder = order; ++ ++ /* ++ * Now sort into reverse mount order, with this we do not ++ * need any shadow mounts anymore. ++ */ ++ initial(&sort); ++ for (mid = 1; mid <= maxorder; mid++) { ++ list_t *this, *cpy; ++ list_for_each_safe(this, cpy, &mntent) { ++ mntent_t * m = list_entry(this, mntent_t); ++ if (mid != m->order) ++ continue; ++ move_head(this, &sort); ++ break; ++ } ++ list_for_each_safe(this, cpy, &mntent) { ++ mntent_t * m = list_entry(this, mntent_t); ++ if (mid != m->parent) ++ continue; ++ move_head(this, &sort); ++ } ++ } ++ if (!list_empty(&mntent)) ++ error(100, "init_mnt(): %s\n", strerror(EBADE)); ++ join(&sort, &mntent); ++ return; ++ } ++ ++ + if ((mnt = setmntent("/proc/mounts", "r")) == (FILE*)0) + error(100, "cannot open /proc/mounts: %s\n", strerror(errno)); + +- order = maxorder; +- while ((ent = getmntent(mnt))) { +- const size_t nlen = strlen(ent->mnt_dir); ++ while (getmntent_r(mnt, &ent, buffer, sizeof(buffer))) { + mntent_t *restrict ptr; + boolean found = false; ++ size_t nlen; + int num; + + for (num = 0; num < argc; num++) { + if (*(argv[num]) == '\0') + continue; +- if ((found = (strcmp(argv[num], ent->mnt_dir) == 0))) ++ if ((found = (strcmp(argv[num], ent.mnt_dir) == 0))) + break; + } + + if (!found) + continue; ++ nlen = strlen(ent.mnt_dir); + + if (posix_memalign((void*)&ptr, sizeof(void*), alignof(mntent_t)+(nlen+1)) != 0) + error(100, "malloc(): %s\n", strerror(errno)); ++ append(ptr, mntent); + ptr->order = order++; ++ ptr->parent = -1; + ptr->name = ((char*)ptr)+alignof(mntent_t); +- ptr->shadow = (shadow_t*)0; +- +- strcpy(ptr->name, ent->mnt_dir); ++ strcpy(ptr->name, ent.mnt_dir); + ptr->nlen = nlen; +- if (mntent) +- mntent->prev = ptr; +- ptr->next = mntent; +- ptr->prev = (mntent_t*)0; +- mntent = ptr; ++ initial(&ptr->shadow.this); + } + endmntent(mnt); + maxorder = order; +@@ -463,134 +506,99 @@ static void init_mnt(int argc, char* arg + if ((mnt = setmntent("/proc/mounts", "r")) == (FILE*)0) + error(100, "cannot open /proc/mounts: %s\n", strerror(errno)); + +- while ((ent = getmntent(mnt))) { +- mntent_t *p; ++ while (getmntent_r(mnt, &ent, buffer, sizeof(buffer))) { ++ list_t *ptr; + +- for (p = mntent; p; p = p->next) { ++ list_for_each(ptr, &mntent) { ++ mntent_t *p = list_entry(ptr, mntent_t); + shadow_t *restrict s; + size_t nlen; + +- if (strcmp(ent->mnt_dir, p->name) == 0) ++ if (strcmp(ent.mnt_dir, p->name) == 0) + continue; +- if (strncmp(ent->mnt_dir, p->name, p->nlen) != 0) ++ if (strncmp(ent.mnt_dir, p->name, p->nlen) != 0) + continue; + +- nlen = strlen(ent->mnt_dir); ++ nlen = strlen(ent.mnt_dir); + if (posix_memalign((void*)&s, sizeof(void*), alignof(shadow_t)+(nlen+1)) != 0) + error(100, "malloc(): %s\n", strerror(errno)); ++ append(s, p->shadow.this); + s->name = ((char*)s)+alignof(shadow_t); +- +- strcpy(s->name, ent->mnt_dir); ++ strcpy(s->name, ent.mnt_dir); + s->nlen = nlen; +- if (p->shadow) +- p->shadow->prev = s; +- s->next = p->shadow; +- s->prev = (shadow_t*)0; +- p->shadow = s; + } + } + endmntent(mnt); + } + +-static void clear_shadow(shadow_t *restrict shadow) ++static void clear_shadow(list_t *restrict shadow, const boolean lazy) + { +- shadow_t *s, *n, *l; +- +- n = shadow; +- l = (shadow_t*)0; +- for (s = shadow; n; s = n) { +- l = s->prev; +- n = s->next; +- if (s == shadow) { +- if (n) n->prev = (shadow_t*)0; +- shadow = n; +- } else if (l) { +- if (n) n->prev = l; +- l->next = n; +- } ++ list_t *this, *ptr; ++ list_for_each_safe(this, ptr, shadow) { ++ shadow_t *s = list_entry(this, shadow_t); ++ delete(this); ++ if (lazy) ++ umount2(s->name, MNT_DETACH); + free(s); + } + } + + static void clear_mnt(const boolean lazy) + { +- mntent_t *p, *n, *l; ++ list_t *this, *ptr; + +- n = mntent; +- l = (mntent_t*)0; +- for (p = mntent; n; p = n) { +- l = p->prev; +- n = p->next; ++ list_for_each_safe(this, ptr, &mntent) { ++ mntent_t *p = list_entry(this, mntent_t); ++ delete(this); ++ if (!list_empty(&p->shadow.this)) { ++ clear_shadow(&p->shadow.this, lazy); ++ } + if (lazy) + umount2(p->name, MNT_DETACH); +- if (p == mntent) { +- if (n) n->prev = (mntent_t*)0; +- mntent = n; +- } else if (l) { +- if (n) n->prev = l; +- l->next = n; +- } +- if (p->shadow) +- clear_shadow(p->shadow); + free(p); + } + } + + static void add_proc(pid_t pid, int order) + { +- proc_t * ptr = (proc_t*)xmalloc(sizeof(proc_t)); ++ proc_t *restrict ptr; ++ ++ if (posix_memalign((void*)&ptr, sizeof(void*), alignof(proc_t)) != 0) ++ error(100, "malloc(): %s\n", strerror(errno)); ++ append(ptr, procs); + ptr->pid = pid; + ptr->order = order; +- if (procs) +- procs->prev = ptr; +- ptr->next = procs; +- ptr->prev = (proc_t*)0; +- procs = ptr; + } + + static void sort_proc(void) + { +- proc_t * sort = (proc_t*)0; + int order; + ++ initial(&sort); + for (order = maxorder; order > 0; order--) { +- proc_t * this = procs; +- proc_t * last = (proc_t*)0; +- proc_t * ptr; +- +- for (ptr = procs; this; ptr = this) { +- last = ptr->prev; +- this = ptr->next; ++ list_t *this, *ptr; + +- if (ptr->order != order) +- continue; ++ list_for_each_safe(this, ptr, &procs) { ++ proc_t *p = list_entry(this, proc_t); + +- if (ptr == procs) { +- if (this) this->prev = (proc_t*)0; +- procs = this; +- } else if (last) { +- if (this) this->prev = last; +- last->next = this; +- } ++ if (p->order != order) ++ continue; + +- if (sort) +- sort->prev = ptr; +- ptr->next = sort; +- ptr->prev = (proc_t*)0; +- sort = ptr; ++ move_tail(this, &sort); + } + } +- +- procs = sort; ++ join(&sort, &procs); + } + +-static boolean shadow(shadow_t *restrict this, const char *restrict name, const size_t nlen) ++static boolean shadow(list_t *restrict shadow, const char *restrict name, const size_t nlen) + { +- shadow_t *s; ++ list_t *ptr; + +- if (!this) ++ if (!shadow || list_empty(shadow)) + goto out; +- for (s = this; s; s = s->next) { ++ ++ list_for_each(ptr, shadow) { ++ shadow_t *s = list_entry(ptr, shadow_t); + if (nlen < s->nlen) + continue; + if (name[s->nlen] != '\0' && name[s->nlen] != '/') +@@ -605,15 +613,16 @@ out: + static int check(const char *restrict name) + { + const size_t nlen = strlen(name); +- mntent_t *p; ++ list_t *ptr; + +- for (p = mntent; p; p = p->next) { ++ list_for_each(ptr, &mntent) { ++ mntent_t *p = list_entry(ptr, mntent_t); + if (nlen < p->nlen) + continue; + if (name[p->nlen] != '\0' && name[p->nlen] != '/') + continue; + if (strncmp(name, p->name, p->nlen) == 0) { +- if (shadow(p->shadow, name, nlen)) ++ if (shadow(&p->shadow.this, name, nlen)) + continue; + return p->order; + } +--- rvmtab.8 ++++ rvmtab.8 2011-02-03 08:22:08.192425628 +0000 +@@ -0,0 +1,62 @@ ++.\" ++.\" Copyright 2011 Werner Fink, 2008 SUSE LINUX Products GmbH, Germany. ++.\" ++.\" This program is free software; you can redistribute it and/or modify ++.\" it under the terms of the GNU General Public License as published by ++.\" the Free Software Foundation; either version 2 of the License, or ++.\" (at your option) any later version. ++.\" ++.TH RVMTAB 8 "Feb 01, 2011" "Version 0.1" "The SuSE boot concept" ++.UC 8 ++.SH RVMTAB ++Rvmtab \- Sort \fI/proc/mounts\fR in the order of \fI/proc/self/mountinfo\fR ++.\" ++.SH SYNOPSIS ++.\" ++.B rvmtab ++.\" ++.SH DESCRIPTION ++.B rvmtab ++will list out the content of ++.I /proc/mounts ++sorted first of all in the reverse order of the parent IDs found in ++.I /proc/self/mountinfo ++and then in a second sub sort in the reverse order of mount IDs ++also found in ++.IR /proc/self/mountinfo . ++.\" ++.SH OPTIONS ++Currently ++.B rvmtab ++does not know about any option. ++\." ++.SH EXAMPLES ++.nf ++.B rvmtab ++.fi ++\." ++.SH RETURN VALUE ++Beside permsissions and and alloc errors ++.B rvmtab ++always returns success. ++\." ++.SH FILES ++.TP ++.I /proc/ ++path to the proc file system ++.RB (see " proc" (5)). ++.TP ++.I /proc/mounts ++this file contains of a list of all the file systems currently mounted. ++.TP ++.I /proc/self/mountinfo ++this file contains information about mount points like the unique mount ID. ++\." ++.SH SEE ALSO ++.BR proc (5), ++\." ++.SH COPYRIGHT ++2011 Werner Fink, ++2011 SUSE LINUX Products GmbH, Germany. ++.SH AUTHOR ++Werner Fink +--- rvmtab.c ++++ rvmtab.c 2011-02-04 11:51:12.214987615 +0000 +@@ -0,0 +1,172 @@ ++/* ++ * rvmtab.c Sort /proc/mounts or /etc/mtab in the sorting order of ++ * /proc/self/mountinfo usable for sequential umount calls ++ * ++ * Version: 0.1 01-Feb-2011 Fink ++ * ++ * Copyright 2011 Werner Fink, 2005 SUSE LINUX Products GmbH, Germany. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * Author: Werner Fink , 2011 ++ */ ++ ++#ifndef _GNU_SOURCE ++# define _GNU_SOURCE ++#endif ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "libinit.h" ++#include "lists.h" ++ ++typedef struct mounts_s { ++ list_t this; ++ int freq; ++ int passno; ++ size_t nlen; ++ char *device; ++ char *mpoint; ++ char *fstype; ++ char *mntopt; ++} mounts_t; ++ ++typedef struct mntinfo_s { ++ list_t this; ++ int id, parid; ++ dev_t dev; ++ char *mpoint; ++} mntinfo_t; ++ ++static list_t mounts = {&mounts, &mounts}; ++static list_t mntinfo = {&mntinfo, &mntinfo}; ++static list_t save = {&save, &save}; ++ ++int main () ++{ ++ list_t *ptr; ++ FILE *minfo, *mtab; ++ struct mntent ent; ++ struct stat st; ++ char buffer[LINE_MAX]; ++ int mid, max, parid; ++ uint maj, min; ++ ++ /* Stat /proc/version to see if /proc is mounted. */ ++ if (stat("/proc/version", &st) < 0) ++ getproc(); ++ ++ mtab = setmntent("/proc/mounts", "r"); ++ if (!mtab) { ++ mtab = setmntent("/etc/mtab", "r"); ++ if (!mtab) ++ goto err; ++ } ++ while (getmntent_r(mtab, &ent, buffer, sizeof(buffer))) { ++ mounts_t *restrict p; ++ size_t l1, l2, l3, l4; ++ ++ l1 = strlen(ent.mnt_fsname); ++ l2 = strlen(ent.mnt_dir); ++ l3 = strlen(ent.mnt_type); ++ l4 = strlen(ent.mnt_opts); ++ ++ if (posix_memalign((void*)&p, sizeof(void*), alignof(mounts_t)+(l1+l2+l3+l4+4)) != 0) ++ goto err; ++ append(p, mounts); ++ p->freq = ent.mnt_freq; ++ p->passno = ent.mnt_passno; ++ p->nlen = l2; ++ ++ p->device = ((char*)p)+alignof(mounts_t); ++ p->mpoint = p->device+l1+1; ++ p->fstype = p->mpoint+l2+1; ++ p->mntopt = p->fstype+l3+1; ++ ++ strcpy(p->device, ent.mnt_fsname); ++ strcpy(p->mpoint, ent.mnt_dir); ++ strcpy(p->fstype, ent.mnt_type); ++ strcpy(p->mntopt, ent.mnt_opts); ++ } ++ endmntent(mtab); ++ ++ minfo = fopen("/proc/self/mountinfo", "r"); ++ if (!minfo) ++ goto err; ++ max = 1; ++ while (fscanf(minfo, "%i %i %u:%u %*s %s %*[^\n]", &mid, &parid, &maj, &min, &buffer[0]) == 5) { ++ mntinfo_t *restrict p; ++ ++ if (posix_memalign((void*)&p, sizeof(void*), alignof(mntinfo_t)+(strlen(buffer)+1)) != 0) ++ goto err; ++ append(p, mntinfo); ++ p->mpoint = ((char*)p)+alignof(mntinfo_t); ++ strcpy(p->mpoint, buffer); ++ p->parid = parid; ++ p->dev = makedev(maj, min); ++ p->id = mid; ++ if (mid > max) ++ max = mid; ++ } ++ fclose(minfo); ++ ++ initial(&save); ++ for (mid = 1; mid <= max; mid++) { ++ list_t *this, *cpy; ++ list_for_each_safe(this, cpy, &mntinfo) { ++ mntinfo_t * m = list_entry(this, mntinfo_t); ++ if (mid != m->id) ++ continue; ++ move_head(this, &save); ++ break; ++ } ++ list_for_each_safe(this, cpy, &mntinfo) { ++ mntinfo_t * m = list_entry(this, mntinfo_t); ++ if (mid != m->parid) ++ continue; ++ move_head(this, &save); ++ } ++ } ++ if (!list_empty(&mntinfo)) { ++ errno = EBADE; ++ goto err; ++ } ++ join(&save, &mntinfo); ++ ++#if 0 ++ list_for_each(ptr, &mntinfo) { ++ mntinfo_t *m = list_entry(ptr, mntinfo_t); ++ printf("%d %d 0x%3.3x %s\n", m->id, m->parid, (uint)m->dev, m->mpoint); ++ } ++ putchar('\n'); ++#endif ++ list_for_each(ptr, &mntinfo) { ++ mntinfo_t *m = list_entry(ptr, mntinfo_t); ++ list_t *tmp; ++ list_for_each(tmp, &mounts) { ++ mounts_t *p = list_entry(tmp, mounts_t); ++ if (!p->mpoint || !p->device) ++ continue; ++ if (strcmp("rootfs", p->device) == 0) ++ continue; ++ if (strcmp(m->mpoint, p->mpoint)) ++ continue; ++ printf("%s %s %s %s %d %d\n", p->device, p->mpoint, p->fstype, ++ p->mntopt, p->freq, p->passno); ++ } ++ } ++ return 0; ++err: ++ fprintf(stderr, "rvmtab: %s\n", strerror(errno)); ++ return 1; ++} +--- startproc.c ++++ startproc.c 2011-02-04 14:01:24.935925784 +0000 +@@ -51,7 +51,7 @@ static int wpopts = WNOHANG|WUNTRACED; + static char *wlist = NULL; + + static volatile sig_atomic_t signaled = 0; +-static void (*save_sigquit) = SIG_DFL; ++static sighandler_t save_sigquit = SIG_DFL; + static void sig_quit(int nsig) + { + (void)signal(nsig, save_sigquit); +@@ -71,7 +71,8 @@ int main(int argc, char **argv) + struct stat st; + char *fullname = NULL, *basename = NULL; + char *log_file = NULL, *pid_file = NULL, *ignore_file = NULL; +- char *root = NULL, *iargv[argc]; ++ char *root = NULL; ++ extension char *iargv[argc]; + int c, nicelvl = 0, env = 0, iargc = 0; + unsigned short flags = (DAEMON|PIDOF); + +@@ -345,7 +346,7 @@ int main(int argc, char **argv) + clear_pids(); /* Remove all pids which should be ignored */ + + /* Do main work */ +- if (!remember) { /* No process found with pid file */ ++ if (list_empty(&remember)) { /* No process found with pid file */ + if (force) + goto force; + if (pidof(fullname,root,flags) < 0) +@@ -353,7 +354,7 @@ int main(int argc, char **argv) + clear_pids(); /* Remove all pids which should be ignored */ + } + +- if (remember) ++ if (!list_empty(&remember)) + exit(LSB_OK); /* Accordingly to LSB we have succeed. */ + + force: +@@ -369,7 +370,7 @@ check_again: + exit(LSB_PROOFX); + clear_pids(); /* Remove all pids which should be ignored */ + +- if (!remember) ++ if (list_empty(&remember)) + exit(LSB_NOPROC); + + if (seconds > 0) { +@@ -378,8 +379,16 @@ check_again: + goto check_again; + } + +- if (!quiet) +- printf("%d\n", remember->pid); ++ if (!quiet) { ++ list_t *list; ++ int nl = 0; ++ list_for_each(list, &remember) { ++ PROC *proc = list_entry(list, PROC); ++ if (nl++) putchar(' '); ++ printf("%ld", (long int)proc->pid); ++ } ++ if (nl) putchar('\n'); ++ } + + exit(LSB_OK); + diff --git a/sysvinit.changes b/sysvinit.changes index c1655a8..d9b9de4 100644 --- a/sysvinit.changes +++ b/sysvinit.changes @@ -1,3 +1,12 @@ +------------------------------------------------------------------- +Fri Feb 4 15:02:22 CET 2011 - werner@novell.com + +- Killproc: + * Add new program rvmtab to write out the current content of + /proc/mounts in the reverse mount order determined with the + of /proc/self/mountinfo + * Use faster pointer list implementation + ------------------------------------------------------------------- Thu Jan 27 13:00:09 UTC 2011 - werner@novell.com diff --git a/sysvinit.spec b/sysvinit.spec index bad4472..b30f1df 100644 --- a/sysvinit.spec +++ b/sysvinit.spec @@ -287,6 +287,7 @@ rm -rf ${RPM_BUILD_ROOT} /sbin/detectups %endif /sbin/startpar +/sbin/rvmtab /sbin/vhangup /sbin/mkill /sbin/startproc @@ -321,6 +322,7 @@ rm -rf ${RPM_BUILD_ROOT} %doc %{_mandir}/man8/start_daemon.8.gz %doc %{_mandir}/man8/startpar.8.gz %doc %{_mandir}/man8/sulogin.8.gz +%doc %{_mandir}/man8/rvmtab.8.gz %doc %{_mandir}/man8/vhangup.8.gz %doc %{_mandir}/man8/mkill.8.gz