sysvinit/killproc-2.17.dif

2212 lines
55 KiB
Plaintext

--- 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-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.
+ */
+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;
- struct _mntinfo_ *prev;
- struct _mntinfo_ *parent;
+ list_t this;
int id, parid;
- dev_t dev;
- size_t nlen;
- char * point;
+ dev_t dev;
+ size_t nlen;
+ char *point;
} MNTINFO;
-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->parid = parid;
p->dev = makedev(maj, min);
p->id = mid;
- 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)
+ max = p->id;
}
fclose(mnt);
- /* Sort mount points accordingly to the reverse mount order */
- 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)
+ 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) {
- 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);
}
}
+ 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) {
- if (strncmp(path, m->point, m->nlen))
- continue;
- break;
- }
- return m;
+ return (strncmp(path, s->point, s->nlen) == 0);
}
extern inline char * handl_buf(char *restrict buf)
@@ -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;
+ list_t *m, *n;
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;
}
- 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) {
+ list_t *ptr;
+ init_mounts();
+ 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)
+ continue;
+ prefix = m;
+ break;
+ }
}
}
@@ -727,20 +734,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 +773,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,17 +910,17 @@ 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];
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;
}
+ realname = expandpath(fullname);
}
if (flags & (KTHREAD|KSHORT)) {
@@ -997,7 +1012,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 +1042,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,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;
+ 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;
}
+ realname = expandpath(fullname);
}
if (flags & (KTHREAD|KSHORT)) {
@@ -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;
- char *realname;
ssize_t rll;
if (pid_st.st_dev != full_st.st_dev)
@@ -1218,14 +1225,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;
}
@@ -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);
}
}
+/*
+ * 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 */
--- 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 <libblogger.h>
#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 <linux/list.h> and <linux/prefetch.h>.
+ *
+ * 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 <werner@suse.de>, 2011
+ */
+
+#ifndef _LISTS_H
+#define _LISTS_H
+
+#include <stddef.h>
+#include <sys/types.h>
+
+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 <asm-i386/processor.h>\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 <sys/stat.h>
#include <unistd.h>
#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 <werner@suse.de>
--- 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 <werner@suse.de>, 2011
+ */
+
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+#include <errno.h>
+#include <limits.h>
+#include <mntent.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#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);