Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Evergreen:11.4
insserv
insserv-1.14.0.dif
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File insserv-1.14.0.dif of Package insserv
--- insserv.c +++ insserv.c 2011-02-25 16:37:28.887927611 +0000 @@ -26,6 +26,7 @@ #define MINIMAL_MAKE 1 /* Remove disabled scripts from .depend.boot, * .depend.start, .depend.halt, and .depend.stop */ #define MINIMAL_RULES 1 /* ditto */ +#define MINIMAL_DEPEND 1 /* Remove redundant dependencies */ #include <pwd.h> #include <string.h> @@ -389,8 +390,8 @@ static void reversereq(service_t *restri /* * Check required services for name */ -static boolean chkrequired(service_t *restrict serv) attribute((nonnull(1))); -static boolean chkrequired(service_t *restrict serv) +static boolean chkrequired(service_t *restrict serv, const boolean recursive) attribute((nonnull(1))); +static boolean chkrequired(service_t *restrict serv, const boolean recursive) { boolean ret = true; list_t * pos; @@ -409,12 +410,23 @@ static boolean chkrequired(service_t *re must = getorig(must); if ((must->attr.flags & (SERV_CMDLINE|SERV_ENABLED)) == 0) { - warn("Service %s has to be enabled to start service %s\n", - req->serv->name, serv->name); + if (recursive) { + must->attr.flags |= SERV_ENFORCE; + continue; /* Enabled this later even if not on command line */ + } + if ((must->attr.flags & SERV_WARNED) == 0) { + warn("FATAL: service %s has to be enabled to use service %s\n", + req->serv->name, serv->name); + must->attr.flags |= SERV_WARNED; + } ret = false; } } #if 0 + /* + * Once we may use REQ_MUST for X-Start-Before and/or + * X-Stop-After we may enable this, see reversereq() + */ if (serv->attr.flags & (SERV_CMDLINE|SERV_ENABLED)) goto out; np_list_for_each(pos, &serv->sort.rev) { @@ -425,9 +437,8 @@ static boolean chkrequired(service_t *re continue; must = rev->serv; must = getorig(must); - if (must->attr.flags & (SERV_CMDLINE|SERV_ENABLED)) { - warn("Service %s has to be enabled to stop service %s\n", + warn("FATAL: service %s has to be enabled to use service %s\n", serv->name, rev->serv->name); ret = false; } @@ -476,7 +487,7 @@ static boolean chkdependencies(service_t if ((cur->attr.flags & SERV_CMDLINE) && (flags & SERV_CMDLINE)) continue; - warn("Service %s has to be enabled to start service %s\n", + warn("FATAL: service %s has to be enabled to use service %s\n", name, cur->name); ret = false; } @@ -738,7 +749,7 @@ static inline void makedep(void) FILE *halt; #endif /* USE_KILL_IN_BOOT */ const char *target; - service_t *serv; + const service_t *serv; if (dryrun) { #ifdef USE_KILL_IN_BOOT @@ -818,6 +829,10 @@ static inline void makedep(void) target = (char*)0; while ((serv = listscripts(&target, 'S', LVL_BOOT|LVL_ALL))) { +#if defined(MINIMAL_DEPEND) && (MINIMAL_DEPEND != 0) + const service_t * lserv[100] = {0}; + unsigned long lcnt = 0; +#endif /* not MINIMAL_DEPEND */ boolean mark; list_t * pos; @@ -841,6 +856,10 @@ static inline void makedep(void) np_list_for_each(pos, &serv->sort.req) { req_t * req = getreq(pos); service_t * dep = req->serv; +#if defined(MINIMAL_DEPEND) && (MINIMAL_DEPEND != 0) + boolean shadow = false; + unsigned long n; +#endif /* not MINIMAL_DEPEND */ const char * name; if (!dep) @@ -870,7 +889,36 @@ static inline void makedep(void) fprintf(out, "%s:", target); mark = true; } +#if defined(MINIMAL_DEPEND) && (MINIMAL_DEPEND != 0) + for (n = 0; n < lcnt && lserv[n] ; n++) { + list_t * red; + if (lserv[n]->attr.sorder <= dep->attr.sorder) + break; + np_list_for_each(red, &(lserv[n])->sort.req) { + req_t * other = getreq(red); + if (other->serv->attr.flags & SERV_DUPLET) + continue; + if (other->serv->attr.ref <= 0) + continue; + if ((serv->start->lvl & other->serv->start->lvl) == 0) + continue; + if (!other->serv->attr.script) + continue; + if (other->serv != dep) + continue; + shadow = true; + } + } + if (shadow) + continue; +#endif /* not MINIMAL_DEPEND */ fprintf(out, " %s", name); + +#if defined(MINIMAL_DEPEND) && (MINIMAL_DEPEND != 0) + if (lcnt >= sizeof(lserv)/sizeof(lserv[0])) + continue; + lserv[lcnt++] = dep; +#endif /* not MINIMAL_DEPEND */ } if (mark) fputc('\n', out); @@ -927,6 +975,10 @@ static inline void makedep(void) target = (char*)0; while ((serv = listscripts(&target, 'K', (LVL_NORM|LVL_BOOT)))) { +#if defined(MINIMAL_DEPEND) && (MINIMAL_DEPEND != 0) + const service_t * lserv[100] = {0}; + unsigned long lcnt = 0; +#endif /* not MINIMAL_DEPEND */ boolean mark; list_t * pos; @@ -953,6 +1005,10 @@ static inline void makedep(void) np_list_for_each(pos, &serv->sort.rev) { req_t * rev = getreq(pos); service_t * dep = rev->serv; +#if defined(MINIMAL_DEPEND) && (MINIMAL_DEPEND != 0) + boolean shadow = false; + unsigned long n; +#endif /* not MINIMAL_DEPEND */ const char * name; if (!dep) @@ -976,7 +1032,36 @@ static inline void makedep(void) fprintf(out, "%s:", target); mark = true; } +#if defined(MINIMAL_DEPEND) && (MINIMAL_DEPEND != 0) + for (n = 0; n < lcnt && lserv[n]; n++) { + list_t * red; + if (lserv[n]->attr.korder <= dep->attr.korder) + break; + np_list_for_each(red, &(lserv[n])->sort.rev) { + req_t * other = getreq(red); + if (other->serv->attr.flags & SERV_DUPLET) + continue; + if (other->serv->attr.ref <= 0) + continue; + if ((serv->start->lvl & other->serv->start->lvl) == 0) + continue; + if (!other->serv->attr.script) + continue; + if (other->serv != dep) + continue; + shadow = true; + } + } + if (shadow) + continue; +#endif /* not MINIMAL_DEPEND */ fprintf(out, " %s", name); + +#if defined(MINIMAL_DEPEND) && (MINIMAL_DEPEND != 0) + if (lcnt >= sizeof(lserv)/sizeof(lserv[0])) + continue; + lserv[lcnt++] = dep; +#endif /* not MINIMAL_DEPEND */ } if (mark) fputc('\n', out); } @@ -1378,10 +1463,10 @@ static uchar scan_lsb_headers(const int description = empty; } - if (!interactive && regexecutor(®.interact, COMMON_ARGS) == true) { - if (val->rm_so < val->rm_eo) { - *(pbuf+val->rm_eo) = '\0'; - interactive = xstrdup(pbuf+val->rm_so); + if (!interactive && regexecutor(®.interact, COMMON_SHD_ARGS) == true) { + if (shl->rm_so < shl->rm_eo) { + *(pbuf+shl->rm_eo) = '\0'; + interactive = xstrdup(pbuf+shl->rm_so); } else interactive = empty; } @@ -1416,7 +1501,7 @@ static uchar scan_lsb_headers(const int char *name = basename(path); if (*name == 'S' || *name == 'K') name += 3; - warn("Script %s is broken: missing end of LSB comment.\n", name); + warn("%sscript %s is broken: missing end of LSB comment.\n", ignore ? "" : "FATAL: ", name); if (!ignore) error("exiting now!\n"); } @@ -1432,7 +1517,7 @@ static uchar scan_lsb_headers(const int char *name = basename(path); if (*name == 'S' || *name == 'K') name += 3; - warn("Script %s is broken: incomplete LSB comment.\n", name); + warn("script %s is broken: incomplete LSB comment.\n", name); if (!provides) warn("missing `Provides:' entry: please add.\n"); if (provides == empty) @@ -2338,17 +2423,18 @@ out: static struct option long_options[] = { - {"verbose", 0, (int*)0, 'v'}, - {"config", 1, (int*)0, 'c'}, - {"dryrun", 0, (int*)0, 'n'}, - {"default", 0, (int*)0, 'd'}, - {"remove", 0, (int*)0, 'r'}, - {"force", 0, (int*)0, 'f'}, - {"path", 1, (int*)0, 'p'}, - {"override",1, (int*)0, 'o'}, - {"upstart-job",1, (int*)0, 'u'}, - {"help", 0, (int*)0, 'h'}, - { 0, 0, (int*)0, 0 }, + {"verbose", 0, (int*)0, 'v'}, + {"config", 1, (int*)0, 'c'}, + {"dryrun", 0, (int*)0, 'n'}, + {"default", 0, (int*)0, 'd'}, + {"remove", 0, (int*)0, 'r'}, + {"force", 0, (int*)0, 'f'}, + {"path", 1, (int*)0, 'p'}, + {"override", 1, (int*)0, 'o'}, + {"upstart-job", 1, (int*)0, 'u'}, + {"recursive", 0, (int*)0, 'e'}, + {"help", 0, (int*)0, 'h'}, + { 0, 0, (int*)0, 0 }, }; static void help(const char *restrict const name) attribute((nonnull(1))); @@ -2364,6 +2450,8 @@ static void help(const char *restrict co printf(" -o <path>, --override <path> Path to replace " OVERRIDEDIR ".\n"); printf(" -c <config>, --config <config> Path to config file.\n"); printf(" -n, --dryrun Do not change the system, only talk about it.\n"); + printf(" -u <path>, --upstart-job <path> Path to replace existing upstart job path.\n"); + printf(" -e, --recursive Expand and enable all required services.\n"); printf(" -d, --default Use default runlevels a defined in the scripts\n"); } @@ -2386,6 +2474,8 @@ int main (int argc, char *argv[]) boolean defaults = false; boolean ignore = false; boolean loadarg = false; + boolean recursive = false; + boolean waserr = false; myname = basename(*argv); @@ -2400,7 +2490,7 @@ int main (int argc, char *argv[]) for (c = 0; c < argc; c++) argr[c] = (char*)0; - while ((c = getopt_long(argc, argv, "c:dfrhvno:p:u:", long_options, (int *)0)) != -1) { + while ((c = getopt_long(argc, argv, "c:dfrhvno:p:u:e", long_options, (int *)0)) != -1) { size_t l; switch (c) { case 'c': @@ -2445,6 +2535,9 @@ int main (int argc, char *argv[]) goto err; upstartjob_path = optarg; break; + case 'e': + recursive = true; + break; case '?': err: error("For help use: %s -h\n", myname); @@ -2612,7 +2705,7 @@ int main (int argc, char *argv[]) * Scan scripts found in the command line to be able to resolve * all dependcies given within those scripts. */ - if (argc > 1) for (c = 0; c < argc; c++) { + for (c = 0; c < argc; c++) { const char *const name = argv[c]; service_t * first = (service_t*)0; char * provides, * begin, * token; @@ -3000,8 +3093,10 @@ int main (int argc, char *argv[]) if (!del || (del && !isarg)) warn("script %s: service %s already provided!\n", d->d_name, token); - if (!del && !ignore && isarg) - error("exiting now!\n"); + if (!del && !ignore && isarg) { + waserr = true; + continue; + } if (!del || (del && !ignore && !isarg)) continue; @@ -3064,9 +3159,9 @@ int main (int argc, char *argv[]) if (del) ok = chkdependencies(service); else - ok = chkrequired(service); + ok = chkrequired(service, recursive); if (!ok && !ignore) - error("exiting now!\n"); + waserr = true; } if (script_inf.default_start && script_inf.default_start != empty) { @@ -3357,6 +3452,123 @@ int main (int argc, char *argv[]) active_script(); /* + * Check if runlevels of required scripts are a real subset + * of the services handled here. + */ + if (!del && !ignore) { + list_t * ptr; + list_for_each(ptr, s_start) { + service_t * cur = getservice(ptr); + ushort clvl = cur->start->lvl & ~LVL_SINGLE; + list_t * pos; + + cur = getorig(cur); + if (list_empty(&cur->sort.req)) + continue; + + np_list_for_each(pos, &cur->sort.req) { + req_t *req = getreq(pos); + service_t * must; + + if ((req->flags & REQ_MUST) == 0) + continue; + must = req->serv; + must = getorig(must); + + /* + * Check for recursive mode the existence of the required services + */ + if (cur->attr.flags & SERV_CMDLINE) { + + if (must->attr.flags & SERV_ENABLED) { + ushort mlvl = must->start->lvl & ~LVL_SINGLE; + + if ((mlvl & LVL_BOOT) && (clvl & LVL_BOOT) == 0) + continue; + + if ((mlvl & clvl) == clvl) + continue; + if (recursive) { + must->start->lvl |= clvl; + must->stopp->lvl |= clvl; + continue; + } + clvl &= ~mlvl; + if ((must->attr.flags & SERV_WARNED) == 0) +#ifdef OSCBUILD + warn("Service %s is missed in the runlevels %s to use service %s\n", + must->name, lvl2str(clvl), cur->name); +#else + warn("FATAL: service %s is missed in the runlevels %s to use service %s\n", + must->name, lvl2str(clvl), cur->name); + waserr = true; +#endif + must->attr.flags |= SERV_WARNED; + continue; + } + if ((must->attr.flags & (SERV_ENFORCE|SERV_KNOWN)) == SERV_ENFORCE) { + if ((must->attr.flags & SERV_WARNED) == 0) +#ifdef OSCBUILD + warn("Service %s has to exists for service %s\n", + must->name, cur->name); +#else + warn("FATAL: service %s has to exists for service %s\n", + must->name, cur->name); + waserr = true; +#endif + must->attr.flags |= SERV_WARNED; + continue; + } + if (recursive) { + must->start->lvl |= clvl; + must->stopp->lvl |= clvl; + continue; + } + continue; + } + if ((cur->attr.flags & SERV_ENABLED) == 0) + continue; + if ((must->attr.flags & (SERV_CMDLINE|SERV_KNOWN)) == 0) { + if ((must->attr.flags & SERV_WARNED) == 0) +#ifdef OSCBUILD + warn("Service %s has to exists for service %s\n", + must->name, cur->name); +#else + warn("FATAL: service %s has to exists for service %s\n", + must->name, cur->name); + waserr = true; +#endif + must->attr.flags |= SERV_WARNED; + continue; + } + if (must->attr.flags & SERV_ENABLED) { + ushort mlvl = must->start->lvl & ~LVL_SINGLE; + + if ((mlvl & LVL_BOOT) && (clvl & LVL_BOOT) == 0) + continue; + + if ((mlvl & clvl) == clvl) + continue; + clvl &= ~mlvl; + if ((must->attr.flags & SERV_WARNED) == 0) +#ifdef OSCBUILD + warn("Service %s is missed in the runlevels %s to use service %s\n", + must->name, lvl2str(clvl), cur->name); +#else + warn("FATAL: service %s is missed in the runlevels %s to use service %s\n", + must->name, lvl2str(clvl), cur->name); + waserr = true; +#endif + must->attr.flags |= SERV_WARNED; + } + } + } + } + + if (waserr) + error("exiting now!\n"); + + /* * Sorry but we support only [KS][0-9][0-9]<name> */ if (maxstart > MAX_DEEP || maxstop > MAX_DEEP) @@ -3435,13 +3647,16 @@ int main (int argc, char *argv[]) script = (char*)0; while ((serv = listscripts(&script, 'X', lvl))) { - const boolean this = chkfor(script, argv, argc); + boolean this = chkfor(script, argv, argc); boolean found, slink; char * clink; if (*script == '$') /* Do not link in virtual dependencies */ continue; + if ((serv->attr.flags & (SERV_ENFORCE|SERV_ENABLED)) == SERV_ENFORCE) + this = true; + slink = false; if ((serv->start->lvl & lvl) == 0) goto stop; @@ -3616,7 +3831,7 @@ int main (int argc, char *argv[]) script = (char*)0; while ((serv = listscripts(&script, 'X', seek))) { - const boolean this = chkfor(script, argv, argc); + boolean this = chkfor(script, argv, argc); boolean found; char * clink; char mode; @@ -3624,6 +3839,9 @@ int main (int argc, char *argv[]) if (*script == '$') /* Do not link in virtual dependencies */ continue; + if ((serv->attr.flags & (SERV_ENFORCE|SERV_ENABLED)) == SERV_ENFORCE) + this = true; + sprintf(olink, "../init.d/%s", script); if (serv->stopp->lvl & lvl) { # ifndef USE_KILL_IN_BOOT --- listing.c +++ listing.c 2010-11-26 14:16:31.675926125 +0000 @@ -534,19 +534,16 @@ out: * Sort linked list of provides into start or stop order * during this set new start or stop order of the serives. */ -#undef SORT_REQUESTS +#define getdep(req) ((dir_t*)(req)->serv->dir) void lsort(const char type) { list_t sort = { &sort, &sort }; -#ifdef SORT_REQUESTS - list_t * this; -#endif /* SORT_REQUESTS */ + list_t * ptr, * safe, * this; int order; switch (type) { case 'K': for (order = 0; order <= maxstop; order++) { - list_t * ptr, * safe; list_for_each_safe(ptr, safe, d_start) { dir_t * dir = getdir(ptr); if (dir->stopp.deep == order) @@ -554,28 +551,54 @@ void lsort(const char type) } } join(&sort, d_start); -#ifdef SORT_REQUESTS list_for_each(this, s_start) { service_t * serv = getservice(this); if (serv->attr.flags & SERV_DUPLET) continue; initial(&sort); - for (order = 0; order <= maxstop; order++) { - list_t * ptr, * safe; + for (order = maxstop; order >= 0; order--) { list_for_each_safe(ptr, safe, &serv->sort.rev) { req_t * rev = getreq(ptr); - dir_t * dir = (dir_t*)rev->serv->dir; - if (dir->stopp.deep == order) - move_tail(ptr, &sort); + dir_t * dir = getdep(rev); + if (dir->stopp.deep == order) { + service_t *const orig = getorig(rev->serv); + list_t * chk; + boolean found = false; + + list_for_each_prev(chk, &sort) { /* check if service was already resorted */ + req_t * this = getreq(chk); + if (getdep(this)->stopp.deep != order) + break; /* added on tail always with same order */ + if (getdep(this) == orig->dir) { + found = true; + } + } + + if (!found) { + if (rev->serv != orig) { /* replace alias with its original */ + req_t *restrict this; + if (posix_memalign((void*)&this, sizeof(void*), alignof(req_t)) != 0) + error("%s", strerror(errno)); + memset(this, 0, alignof(req_t)); + this->flags = rev->flags; + this->serv = orig; + replace(ptr, &this->list); + ptr = &this->list; + free(rev); + } + move_tail(ptr, &sort); + } else { /* already included */ + delete(ptr); + free(rev); + } + } } } join(&sort, &serv->sort.rev); } -#endif /* SORT_REQUESTS */ break; default: for (order = 0; order <= maxstart; order++) { - list_t * ptr, * safe; list_for_each_safe(ptr, safe, d_start) { dir_t * dir = getdir(ptr); if (dir->start.deep == order) @@ -583,28 +606,54 @@ void lsort(const char type) } } join(&sort, d_start); -#ifdef SORT_REQUESTS list_for_each(this, s_start) { service_t * serv = getservice(this); if (serv->attr.flags & SERV_DUPLET) continue; initial(&sort); - for (order = 0; order <= maxstart; order++) { - list_t * ptr, * safe; + for (order = maxstart; order >= 0; order--) { list_for_each_safe(ptr, safe, &serv->sort.req) { req_t * req = getreq(ptr); - dir_t * dir = (dir_t*)req->serv->dir; - if (dir->start.deep == order) - move_tail(ptr, &sort); + dir_t * dir = getdep(req); + if (dir->start.deep == order) { + service_t * orig = getorig(req->serv); + list_t * chk; + boolean found = false; + + list_for_each_prev(chk, &sort) { /* check if service was already resorted */ + req_t * this = getreq(chk); + if (getdep(this)->start.deep != order) + break; /* added on tail always with same order */ + if (getdep(this) == orig->dir) { + found = true; + break; + } + } + + if (!found) { + if (req->serv != orig) { /* replace alias with its original */ + req_t *restrict this; + if (posix_memalign((void*)&this, sizeof(void*), alignof(req_t)) != 0) + error("%s", strerror(errno)); + memset(this, 0, alignof(req_t)); + this->flags = req->flags; + this->serv = orig; + replace(ptr, &this->list); + ptr = &this->list; + free(req); + } + move_tail(ptr, &sort); + } else { /* already included */ + delete(ptr); + free(req); + } + } } } join(&sort, &serv->sort.req); } -#endif /* SORT_REQUESTS */ break; } - - } /* --- listing.h +++ listing.h 2011-02-07 12:23:03.970855430 +0000 @@ -64,8 +64,7 @@ typedef unsigned int uint; * * 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) +extern inline void attribute((used,__gnu_inline__,always_inline,__artificial__)) prefetch(const void *restrict x) { #if defined(__x86_64__) asm volatile ("prefetcht0 %0" :: "m" (*(unsigned long *)x)) @@ -91,6 +90,8 @@ static inline void prefetch(const void * " \n664:\n" ".previous" :: "i" ((0*32+25)), "r" (x)) +#else + __builtin_prefetch ((x), 0, 1); #endif ; } @@ -158,6 +159,18 @@ static inline void delete(list_t *restri 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) { @@ -175,12 +188,30 @@ static inline void join(list_t *restrict } } -static inline boolean list_empty(list_t *restrict head) attribute((always_inline,nonnull(1))); -static inline boolean list_empty(list_t *restrict head) +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 enty 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) { @@ -379,6 +410,8 @@ static inline char * xstrdup(const char #define SERV_NOSTOP 0x0100 #define SERV_CMDLINE 0x0200 #define SERV_FIRST 0x0400 +#define SERV_ENFORCE 0x0800 +#define SERV_WARNED 0x1000 /* * Bits of the runlevels
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor