Rtld on diet part 2:

Do not use stdio for libmap.conf read.  Directly map the file and
parse lines from the mappings.

Reviewed by:	kan
MFC after:	3 weeks
This commit is contained in:
Konstantin Belousov 2012-03-12 12:16:08 +00:00
parent ef5cdcbd69
commit 68f1db20b3
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=232862

View File

@ -2,11 +2,14 @@
* $FreeBSD$
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/queue.h>
#include <sys/param.h>
#include <sys/fcntl.h>
#include <sys/mman.h>
#include <sys/queue.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "debug.h"
#include "rtld.h"
@ -25,7 +28,6 @@ TAILQ_HEAD(lm_list, lm);
struct lm {
char *f;
char *t;
TAILQ_ENTRY(lm) lm_link;
};
@ -37,17 +39,15 @@ struct lmp {
TAILQ_ENTRY(lmp) lmp_link;
};
static int lm_count;
static int lm_count;
static void lmc_parse (FILE *);
static void lm_add (const char *, const char *, const char *);
static void lm_free (struct lm_list *);
static char * lml_find (struct lm_list *, const char *);
static struct lm_list * lmp_find (const char *);
static struct lm_list * lmp_init (char *);
static const char * quickbasename (const char *);
static int readstrfn (void * cookie, char *buf, int len);
static int closestrfn (void * cookie);
static void lmc_parse(char *, size_t);
static void lm_add(const char *, const char *, const char *);
static void lm_free(struct lm_list *);
static char *lml_find(struct lm_list *, const char *);
static struct lm_list *lmp_find(const char *);
static struct lm_list *lmp_init(char *);
static const char *quickbasename(const char *);
#define iseol(c) (((c) == '#') || ((c) == '\0') || \
((c) == '\n') || ((c) == '\r'))
@ -59,56 +59,88 @@ static int closestrfn (void * cookie);
#define rtld_isspace(c) ((c) == ' ' || (c) == '\t')
int
lm_init (char *libmap_override)
lm_init(char *libmap_override)
{
FILE *fp;
dbg("%s(\"%s\")", __func__, libmap_override);
struct stat st;
char *lm_map, *p;
int fd;
dbg("lm_init(\"%s\")", libmap_override);
TAILQ_INIT(&lmp_head);
fp = fopen(_PATH_LIBMAP_CONF, "r");
if (fp) {
lmc_parse(fp);
fclose(fp);
fd = open(_PATH_LIBMAP_CONF, O_RDONLY);
if (fd == -1) {
dbg("lm_init: open(\"%s\") failed, %s", _PATH_LIBMAP_CONF,
strerror(errno));
goto override;
}
if (fstat(fd, &st) == -1) {
close(fd);
dbg("lm_init: fstat(\"%s\") failed, %s", _PATH_LIBMAP_CONF,
strerror(errno));
goto override;
}
lm_map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (lm_map == (const char *)MAP_FAILED) {
close(fd);
dbg("lm_init: mmap(\"%s\") failed, %s", _PATH_LIBMAP_CONF,
strerror(errno));
goto override;
}
close(fd);
lmc_parse(lm_map, st.st_size);
munmap(lm_map, st.st_size);
override:
if (libmap_override) {
char *p;
/* do some character replacement to make $LIBMAP look like a
text file, then "open" it with funopen */
/*
* Do some character replacement to make $LIBMAP look
* like a text file, then parse it.
*/
libmap_override = xstrdup(libmap_override);
for (p = libmap_override; *p; p++) {
switch (*p) {
case '=':
*p = ' '; break;
case ',':
*p = '\n'; break;
case '=':
*p = ' ';
break;
case ',':
*p = '\n';
break;
}
}
fp = funopen(libmap_override, readstrfn, NULL, NULL, closestrfn);
if (fp) {
lmc_parse(fp);
fclose(fp);
}
lmc_parse(p, strlen(p));
free(p);
}
return (lm_count == 0);
}
static void
lmc_parse (FILE *fp)
lmc_parse(char *lm_p, size_t lm_len)
{
char *cp;
char *f, *t, *c, *p;
char prog[MAXPATHLEN];
char line[MAXPATHLEN + 2];
dbg("%s(%p)", __func__, fp);
char *cp, *f, *t, *c, *p;
char prog[MAXPATHLEN];
char line[MAXPATHLEN + 2];
size_t cnt;
int i;
cnt = 0;
p = NULL;
while ((cp = fgets(line, MAXPATHLEN + 1, fp)) != NULL) {
while (cnt < lm_len) {
i = 0;
while (lm_p[cnt] != '\n' && cnt < lm_len &&
i < sizeof(line) - 1) {
line[i] = lm_p[cnt];
cnt++;
i++;
}
line[i] = '\0';
while (lm_p[cnt] != '\n' && cnt < lm_len)
cnt++;
/* skip over nl */
cnt++;
cp = &line[0];
t = f = c = NULL;
/* Skip over leading space */
@ -344,31 +376,3 @@ quickbasename (const char *path)
}
return (p);
}
static int
readstrfn(void * cookie, char *buf, int len)
{
static char *current;
static int left;
int copied;
copied = 0;
if (!current) {
current = cookie;
left = strlen(cookie);
}
while (*current && left && len) {
*buf++ = *current++;
left--;
len--;
copied++;
}
return copied;
}
static int
closestrfn(void * cookie)
{
free(cookie);
return 0;
}