We now warn about clock skews
rc-update -u will force a regen of the dep tree rc_newer_than and rc_olderthan now take another two parameters for newest/oldest file and mtime
This commit is contained in:
parent
2243c01390
commit
3d37005a3d
@ -1,11 +1,18 @@
|
||||
#!@PREFIX@/sbin/runscript
|
||||
# Copyright 2007-2008 Roy Marples <roy@marples.name>
|
||||
# Copyright 2007-2009 Roy Marples <roy@marples.name>
|
||||
# All rights reserved. Released under the 2-clause BSD license.
|
||||
|
||||
description="Saves the caches OpenRC uses to non volatile storage"
|
||||
|
||||
start()
|
||||
{
|
||||
if [ -e "${RC_SVCDIR}"/clock-skewed ]; then
|
||||
ewarn "WARNING: clock skew detected!"
|
||||
if ! yesno "savecache_skewed"; then
|
||||
eerror "Not saving deptree cache"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
ebegin "Saving dependency cache"
|
||||
if [ ! -d "${RC_LIBDIR}"/cache ]; then
|
||||
rm -rf "${RC_LIBDIR}"/cache
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" Copyright 2007-2008 Roy Marples
|
||||
.\" Copyright 2007-2009 Roy Marples
|
||||
.\" All rights reserved
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
@ -22,7 +22,7 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd Jan 15, 2008
|
||||
.Dd Jan 10, 2009
|
||||
.Dt RC-UPDATE 8 SMM
|
||||
.Os OpenRC
|
||||
.Sh NAME
|
||||
@ -38,6 +38,7 @@
|
||||
.Ar service
|
||||
.Op Ar runlevel ...
|
||||
.Nm
|
||||
.Op Fl u , -update
|
||||
.Op Fl v , -verbose
|
||||
.Ar show
|
||||
.Op Ar runlevel ...
|
||||
@ -53,7 +54,7 @@ or
|
||||
directories. They must also conform to the OpenRC runscript standard.
|
||||
.Pp
|
||||
.Bl -tag -width "Fl a , -delete service"
|
||||
.It Fl a , -add Ar service
|
||||
.It Ar add Ar service
|
||||
Add the
|
||||
.Ar service
|
||||
to the
|
||||
@ -72,6 +73,10 @@ Show all enabled services and the runlevels they belong to. If you specify
|
||||
runlevels to show, then only those will be included in the output.
|
||||
.It Fl v , -verbose
|
||||
Show all services.
|
||||
.It Fl u , -update
|
||||
Forces an update of the dependency tree cache.
|
||||
This may be needed in the even of clock skew (a file in /etc is newer than the
|
||||
system clock).
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr rc 8 ,
|
||||
|
@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2007-2008 Roy Marples <roy@marples.name>
|
||||
* Copyright 2007-2009 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -544,7 +544,8 @@ rc_deptree_order(const RC_DEPTREE *deptree, const char *runlevel, int options)
|
||||
librc_hidden_def(rc_deptree_order)
|
||||
|
||||
static bool
|
||||
mtime_check(const char *source, const char *target, bool newer)
|
||||
mtime_check(const char *source, const char *target, bool newer,
|
||||
char *file, time_t *rel)
|
||||
{
|
||||
struct stat buf;
|
||||
time_t mtime;
|
||||
@ -565,16 +566,32 @@ mtime_check(const char *source, const char *target, bool newer)
|
||||
|
||||
if (newer) {
|
||||
if (mtime < buf.st_mtime)
|
||||
return false;
|
||||
retval = false;
|
||||
if (rel != NULL) {
|
||||
if (*rel < buf.st_mtime) {
|
||||
if (file)
|
||||
strlcpy(file, target, PATH_MAX);
|
||||
*rel = buf.st_mtime;
|
||||
}
|
||||
} else
|
||||
return retval;
|
||||
} else {
|
||||
if (mtime > buf.st_mtime)
|
||||
return false;
|
||||
retval = false;
|
||||
if (rel != NULL) {
|
||||
if (*rel > buf.st_mtime) {
|
||||
if (file)
|
||||
strlcpy(file, target, PATH_MAX);
|
||||
*rel = buf.st_mtime;
|
||||
}
|
||||
} else
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* If not a dir then reset errno */
|
||||
if (!(dp = opendir(target))) {
|
||||
errno = serrno;
|
||||
return true;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Check all the entries in the dir */
|
||||
@ -582,26 +599,30 @@ mtime_check(const char *source, const char *target, bool newer)
|
||||
if (d->d_name[0] == '.')
|
||||
continue;
|
||||
snprintf(path, sizeof(path), "%s/%s", target, d->d_name);
|
||||
retval = mtime_check(source, path, newer);
|
||||
if (!retval)
|
||||
if (!mtime_check(source, path, newer, file, rel)) {
|
||||
retval = false;
|
||||
if (rel == NULL)
|
||||
break;
|
||||
}
|
||||
}
|
||||
closedir(dp);
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool
|
||||
rc_newer_than(const char *source, const char *target)
|
||||
rc_newer_than(const char *source, const char *target,
|
||||
char *file, time_t *newest)
|
||||
{
|
||||
|
||||
return mtime_check(source, target, true);
|
||||
return mtime_check(source, target, true, file, newest);
|
||||
}
|
||||
librc_hidden_def(rc_newer_than)
|
||||
|
||||
bool
|
||||
rc_older_than(const char *source, const char *target)
|
||||
rc_older_than(const char *source, const char *target,
|
||||
char *file, time_t *oldest)
|
||||
{
|
||||
return mtime_check(source, target, false);
|
||||
return mtime_check(source, target, false, file, oldest);
|
||||
}
|
||||
librc_hidden_def(rc_older_than)
|
||||
|
||||
@ -638,7 +659,7 @@ static const char *const depdirs[] =
|
||||
};
|
||||
|
||||
bool
|
||||
rc_deptree_update_needed(void)
|
||||
rc_deptree_update_needed(char *file, time_t *newest)
|
||||
{
|
||||
bool newer = false;
|
||||
RC_STRINGLIST *config;
|
||||
@ -652,30 +673,38 @@ rc_deptree_update_needed(void)
|
||||
|
||||
/* Quick test to see if anything we use has changed and we have
|
||||
* data in our deptree */
|
||||
if (!existss(RC_DEPTREE_CACHE) ||
|
||||
!rc_newer_than(RC_DEPTREE_CACHE, RC_INITDIR) ||
|
||||
!rc_newer_than(RC_DEPTREE_CACHE, RC_CONFDIR) ||
|
||||
if (!existss(RC_DEPTREE_CACHE))
|
||||
return true;
|
||||
if (!rc_newer_than(RC_DEPTREE_CACHE, RC_INITDIR, file, newest))
|
||||
newer = true;
|
||||
if (!rc_newer_than(RC_DEPTREE_CACHE, RC_CONFDIR, file, newest))
|
||||
newer = true;
|
||||
#ifdef RC_PKG_INITDIR
|
||||
!rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_INITDIR) ||
|
||||
if (!rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_INITDIR, file, newest))
|
||||
newer = true;
|
||||
#endif
|
||||
#ifdef RC_PKG_CONFDIR
|
||||
!rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_CONFDIR) ||
|
||||
if (!rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_CONFDIR, file, newest))
|
||||
newer = true;
|
||||
#endif
|
||||
#ifdef RC_LOCAL_INITDIR
|
||||
!rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_INITDIR) ||
|
||||
if (!rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_INITDIR, file, newest))
|
||||
newer = true;
|
||||
#endif
|
||||
#ifdef RC_LOCAL_CONFDIR
|
||||
!rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_CONFDIR) ||
|
||||
if (!rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_CONFDIR, file, newest))
|
||||
newer = true;
|
||||
#endif
|
||||
!rc_newer_than(RC_DEPTREE_CACHE, "/etc/rc.conf"))
|
||||
return true;
|
||||
if (!rc_newer_than(RC_DEPTREE_CACHE, "/etc/rc.conf", file, newest))
|
||||
newer = true;
|
||||
|
||||
/* Some init scripts dependencies change depending on config files
|
||||
* outside of baselayout, like syslog-ng, so we check those too. */
|
||||
config = rc_config_list(RC_DEPCONFIG);
|
||||
TAILQ_FOREACH(s, config, entries) {
|
||||
if (!rc_newer_than(RC_DEPTREE_CACHE, s->value)) {
|
||||
if (!rc_newer_than(RC_DEPTREE_CACHE, s->value, file, newest)) {
|
||||
newer = true;
|
||||
if (newest == NULL)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2007-2008 Roy Marples <roy@marples.name>
|
||||
* Copyright 2007-2009 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -304,25 +304,31 @@ typedef void *RC_DEPTREE;
|
||||
|
||||
/*! Check to see if source is newer than target.
|
||||
* If target is a directory then we traverse it and it's children.
|
||||
* time_t returns the time of the newest file found if newer.
|
||||
* @return true if source is newer than target, otherwise false */
|
||||
bool rc_newer_than(const char *, const char *);
|
||||
bool rc_newer_than(const char *, const char *, char *, time_t *);
|
||||
|
||||
/*! Check to see if source is newer than target.
|
||||
/*! Check to see if source is older than target.
|
||||
* If target is a directory then we traverse it and it's children.
|
||||
* @return true if source is newer than target, otherwise false */
|
||||
bool rc_older_than(const char *, const char *);
|
||||
* time_t returns the time of the oldest file found if older.
|
||||
* @return true if source is older than target, otherwise false */
|
||||
bool rc_older_than(const char *, const char *, char *, time_t *);
|
||||
|
||||
/*! Update the cached dependency tree if it's older than any init script,
|
||||
* its configuration file or an external configuration file the init script
|
||||
* has specified.
|
||||
* time_t returns the time of the newest file that the dependency tree
|
||||
* will be checked against.
|
||||
* @return true if successful, otherwise false */
|
||||
bool rc_deptree_update(void);
|
||||
|
||||
/*! Check if the cached dependency tree is older than any init script,
|
||||
* its configuration file or an external configuration file the init script
|
||||
* has specified.
|
||||
* @param buffer of PATH_MAX to store newest file
|
||||
* @param mtime of newest file
|
||||
* @return true if it needs updating, otherwise false */
|
||||
bool rc_deptree_update_needed(void);
|
||||
bool rc_deptree_update_needed(char *, time_t *);
|
||||
|
||||
/*! Load the cached dependency tree and return a pointer to it.
|
||||
* This pointer should be freed with rc_deptree_free when done.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2007-2008 Roy Marples <roy@marples.name>
|
||||
* Copyright 2007-2009 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -39,7 +39,7 @@ int start_stop_daemon(int, char **);
|
||||
void run_applets(int, char **);
|
||||
|
||||
/* Handy function so we can wrap einfo around our deptree */
|
||||
RC_DEPTREE *_rc_deptree_load (int *);
|
||||
RC_DEPTREE *_rc_deptree_load (int, int *);
|
||||
|
||||
/* Test to see if we can see pid 1 or not */
|
||||
bool _rc_can_find_pids(void);
|
||||
|
@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2007-2008 Roy Marples <roy@marples.name>
|
||||
* Copyright 2007-2009 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -451,7 +451,7 @@ void run_applets(int argc, char **argv)
|
||||
if (argc < 3)
|
||||
exit (EXIT_FAILURE);
|
||||
while (i < argc) {
|
||||
if (!rc_newer_than(argv[1], argv[i++]))
|
||||
if (!rc_newer_than(argv[1], argv[i++], NULL, NULL))
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
exit(EXIT_FAILURE);
|
||||
@ -461,7 +461,7 @@ void run_applets(int argc, char **argv)
|
||||
if (argc < 3)
|
||||
exit (EXIT_FAILURE);
|
||||
while (i < argc) {
|
||||
if (!rc_newer_than(argv[1], argv[i++]))
|
||||
if (!rc_newer_than(argv[1], argv[i++], NULL, NULL))
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
exit(EXIT_SUCCESS);
|
||||
|
@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2007-2008 Roy Marples <roy@marples.name>
|
||||
* Copyright 2007-2009 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -29,17 +29,21 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <utime.h>
|
||||
|
||||
#include "builtins.h"
|
||||
#include "einfo.h"
|
||||
@ -49,13 +53,19 @@
|
||||
extern const char *applet;
|
||||
|
||||
RC_DEPTREE *
|
||||
_rc_deptree_load(int *regen) {
|
||||
_rc_deptree_load(int force, int *regen) {
|
||||
int fd;
|
||||
int retval;
|
||||
int serrno = errno;
|
||||
int merrno;
|
||||
time_t t;
|
||||
char file[PATH_MAX];
|
||||
struct stat st;
|
||||
struct utimbuf ut;
|
||||
FILE *fp;
|
||||
|
||||
if (rc_deptree_update_needed()) {
|
||||
t = 0;
|
||||
if (rc_deptree_update_needed(file, &t) || force != 0) {
|
||||
/* Test if we have permission to update the deptree */
|
||||
fd = open(RC_DEPTREE_CACHE, O_WRONLY);
|
||||
merrno = errno;
|
||||
@ -67,8 +77,30 @@ _rc_deptree_load(int *regen) {
|
||||
if (regen)
|
||||
*regen = 1;
|
||||
ebegin("Caching service dependencies");
|
||||
retval = rc_deptree_update();
|
||||
eend (retval ? 0 : -1, "Failed to update the dependency tree");
|
||||
retval = rc_deptree_update() ? 0 : -1;
|
||||
eend (retval, "Failed to update the dependency tree");
|
||||
|
||||
if (retval == 0) {
|
||||
stat(RC_DEPTREE_CACHE, &st);
|
||||
if (st.st_mtime < t) {
|
||||
eerror("Clock skew detected with `%s'", file);
|
||||
eerrorn("Adjusting mtime of `" RC_DEPTREE_CACHE
|
||||
"' to %s", ctime(&t));
|
||||
fp = fopen(RC_DEPTREE_SKEWED, "w");
|
||||
if (fp != NULL) {
|
||||
fprintf(fp, RC_DEPTREE_SKEWED "\n");
|
||||
fclose(fp);
|
||||
}
|
||||
ut.actime = t;
|
||||
ut.modtime = t;
|
||||
utime(RC_DEPTREE_CACHE, &ut);
|
||||
} else {
|
||||
if (exists(RC_DEPTREE_SKEWED))
|
||||
unlink(RC_DEPTREE_SKEWED);
|
||||
}
|
||||
}
|
||||
if (force == -1 && regen != NULL)
|
||||
*regen = retval;
|
||||
}
|
||||
return rc_deptree_load();
|
||||
}
|
||||
@ -104,9 +136,8 @@ rc_depend(int argc, char **argv)
|
||||
RC_STRINGLIST *depends;
|
||||
RC_STRING *s;
|
||||
RC_DEPTREE *deptree = NULL;
|
||||
int options = RC_DEP_TRACE;
|
||||
int options = RC_DEP_TRACE, update = 0;
|
||||
bool first = true;
|
||||
bool update = false;
|
||||
char *runlevel = xstrdup(getenv("RC_RUNLEVEL"));
|
||||
int opt;
|
||||
char *token;
|
||||
@ -130,7 +161,7 @@ rc_depend(int argc, char **argv)
|
||||
rc_stringlist_add(types, token);
|
||||
break;
|
||||
case 'u':
|
||||
update = true;
|
||||
update = 1;
|
||||
break;
|
||||
case 'T':
|
||||
options &= RC_DEP_TRACE;
|
||||
@ -140,15 +171,7 @@ rc_depend(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (update) {
|
||||
ebegin("Caching service dependencies");
|
||||
update = rc_deptree_update();
|
||||
eend(update ? 0 : -1, "%s: %s", applet, strerror(errno));
|
||||
if (!update)
|
||||
eerrorx("Failed to update the dependency tree");
|
||||
}
|
||||
|
||||
if (!(deptree = _rc_deptree_load(NULL)))
|
||||
if (!(deptree = _rc_deptree_load(update, NULL)))
|
||||
eerrorx("failed to load deptree");
|
||||
|
||||
if (!runlevel)
|
||||
|
@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2007-2008 Roy Marples <roy@marples.name>
|
||||
* Copyright 2007-2009 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -140,7 +140,7 @@ print_services(const char *runlevel, RC_STRINGLIST *svcs)
|
||||
if (!svcs)
|
||||
return;
|
||||
if (!deptree)
|
||||
deptree = _rc_deptree_load(NULL);
|
||||
deptree = _rc_deptree_load(0, NULL);
|
||||
if (!deptree) {
|
||||
TAILQ_FOREACH(s, svcs, entries)
|
||||
if (!runlevel ||
|
||||
@ -260,7 +260,7 @@ rc_status(int argc, char **argv)
|
||||
}
|
||||
|
||||
/* Output the services in the order in which they would start */
|
||||
deptree = _rc_deptree_load(NULL);
|
||||
deptree = _rc_deptree_load(0, NULL);
|
||||
|
||||
TAILQ_FOREACH(l, levels, entries) {
|
||||
print_level(l->value);
|
||||
|
@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2007-2008 Roy Marples <roy@marples.name>
|
||||
* Copyright 2007-2009 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -138,11 +138,13 @@ show(RC_STRINGLIST *runlevels, bool verbose)
|
||||
"Usage: rc-update [options] add service <runlevel>\n" \
|
||||
" rc-update [options] del service <runlevel>\n" \
|
||||
" rc-update [options] show"
|
||||
#define getoptstring getoptstring_COMMON
|
||||
#define getoptstring "u" getoptstring_COMMON
|
||||
static const struct option longopts[] = {
|
||||
{ "update", 0, NULL, 'u' },
|
||||
longopts_COMMON
|
||||
};
|
||||
static const char * const longopts_help[] = {
|
||||
"Force an update of the dependency tree",
|
||||
longopts_help_COMMON
|
||||
};
|
||||
#include "_usage.c"
|
||||
@ -167,8 +169,11 @@ rc_update(int argc, char **argv)
|
||||
int ret;
|
||||
|
||||
while ((opt = getopt_long(argc, argv, getoptstring,
|
||||
longopts, (int *) 0)) != -1)
|
||||
longopts, (int *)0)) != -1)
|
||||
switch (opt) {
|
||||
case 'u':
|
||||
_rc_deptree_load(-1, &ret);
|
||||
return ret;
|
||||
case_RC_COMMON_GETOPT
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2007-2008 Roy Marples <roy@marples.name>
|
||||
* Copyright 2007-2009 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -944,8 +944,10 @@ main(int argc, char **argv)
|
||||
}
|
||||
|
||||
/* Load our deptree */
|
||||
if ((deptree = _rc_deptree_load(®en)) == NULL)
|
||||
if ((deptree = _rc_deptree_load(0, ®en)) == NULL)
|
||||
eerrorx("failed to load deptree");
|
||||
if (exists(RC_DEPTREE_SKEWED))
|
||||
ewarn("WARNING: clock skew detected!");
|
||||
|
||||
/* Clean the failed services state dir */
|
||||
clean_failed();
|
||||
|
@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2007-2008 Roy Marples <roy@marples.name>
|
||||
* Copyright 2007-2009 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -748,7 +748,7 @@ svc_start(bool deps)
|
||||
depoptions |= RC_DEP_STRICT;
|
||||
|
||||
if (deps) {
|
||||
if (!deptree && ((deptree = _rc_deptree_load(NULL)) == NULL))
|
||||
if (!deptree && ((deptree = _rc_deptree_load(0, NULL)) == NULL))
|
||||
eerrorx("failed to load deptree");
|
||||
if (!types_b)
|
||||
setup_types();
|
||||
@ -977,7 +977,7 @@ svc_stop(bool deps)
|
||||
if (rc_conf_yesno("rc_depend_strict") || errno == ENOENT)
|
||||
depoptions |= RC_DEP_STRICT;
|
||||
|
||||
if (!deptree && ((deptree = _rc_deptree_load(NULL)) == NULL))
|
||||
if (!deptree && ((deptree = _rc_deptree_load(0, NULL)) == NULL))
|
||||
eerrorx("failed to load deptree");
|
||||
|
||||
if (!types_m)
|
||||
@ -1368,7 +1368,7 @@ runscript(int argc, char **argv)
|
||||
depoptions |= RC_DEP_STRICT;
|
||||
|
||||
if (!deptree &&
|
||||
((deptree = _rc_deptree_load(NULL)) == NULL))
|
||||
((deptree = _rc_deptree_load(0, NULL)) == NULL))
|
||||
eerrorx("failed to load deptree");
|
||||
|
||||
tmplist = rc_stringlist_new();
|
||||
|
Loading…
Reference in New Issue
Block a user