summaryrefslogtreecommitdiffstats
path: root/cpukit/libmisc/shell
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2010-02-01 00:03:02 +0000
committerChris Johns <chrisj@rtems.org>2010-02-01 00:03:02 +0000
commit42c4de823f3c6069240c5fa97e57a274372d4e61 (patch)
tree9531359f1bf8bf08d993cb45c9ea7ce60021e829 /cpukit/libmisc/shell
parentFixed invalid chain extract (diff)
downloadrtems-42c4de823f3c6069240c5fa97e57a274372d4e61.tar.bz2
2010-02-01 Chris Johns <chrisj@rtems.org>
* libmisc/shell/fts.c: Updated to the latest NetBSD version to resolve heap allocation bugs. * libmisc/shell/main_ls.c, libmisc/shell/print-ls.c: Fix printing size bugs. * libnetworking/rtems/mkrootfs.c: Fix byte order bug when creating the loopback interface address.
Diffstat (limited to 'cpukit/libmisc/shell')
-rw-r--r--cpukit/libmisc/shell/fts.c270
-rw-r--r--cpukit/libmisc/shell/main_ls.c13
-rw-r--r--cpukit/libmisc/shell/print-ls.c10
3 files changed, 167 insertions, 126 deletions
diff --git a/cpukit/libmisc/shell/fts.c b/cpukit/libmisc/shell/fts.c
index f7a805fc34..83e4bb6f6f 100644
--- a/cpukit/libmisc/shell/fts.c
+++ b/cpukit/libmisc/shell/fts.c
@@ -1,4 +1,4 @@
-/* $NetBSD: fts.c,v 1.26 2005/10/22 20:55:13 christos Exp $ */
+/* $NetBSD: fts.c,v 1.40 2009/11/02 17:17:34 stacktic Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
@@ -29,10 +29,6 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
@@ -42,10 +38,13 @@
#if 0
static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94";
#else
-__RCSID("$NetBSD: fts.c,v 1.26 2005/10/22 20:55:13 christos Exp $");
+__RCSID("$NetBSD: fts.c,v 1.40 2009/11/02 17:17:34 stacktic Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
+#ifndef __rtems__
+#include "namespace.h"
+#endif
#include <sys/param.h>
#include <sys/stat.h>
@@ -63,21 +62,28 @@ __RCSID("$NetBSD: fts.c,v 1.26 2005/10/22 20:55:13 christos Exp $");
#define dirfd(dp) __dirfd(dp)
#if ! HAVE_NBTOOL_CONFIG_H
-#define HAVE_STRUCT_DIRENT_D_NAMLEN 1
+#define HAVE_STRUCT_DIRENT_D_NAMLEN
#endif
-static FTSENT *fts_alloc __P((FTS *, const char *, size_t));
-static FTSENT *fts_build __P((FTS *, int));
-static void fts_lfree __P((FTSENT *));
-static void fts_load __P((FTS *, FTSENT *));
-static size_t fts_maxarglen __P((char * const *));
-static size_t fts_pow2 __P((size_t));
-static int fts_palloc __P((FTS *, size_t));
-static void fts_padjust __P((FTS *, FTSENT *));
-static FTSENT *fts_sort __P((FTS *, FTSENT *, size_t));
-static u_short fts_stat __P((FTS *, FTSENT *, int));
-static int fts_safe_changedir __P((const FTS *, const FTSENT *, int,
- const char *));
+static FTSENT *fts_alloc(FTS *, const char *, size_t);
+static FTSENT *fts_build(FTS *, int);
+static void fts_free(FTSENT *);
+static void fts_lfree(FTSENT *);
+static void fts_load(FTS *, FTSENT *);
+static size_t fts_maxarglen(char * const *);
+static size_t fts_pow2(size_t);
+static int fts_palloc(FTS *, size_t);
+static void fts_padjust(FTS *, FTSENT *);
+static FTSENT *fts_sort(FTS *, FTSENT *, size_t);
+static unsigned short fts_stat(FTS *, FTSENT *, int);
+static int fts_safe_changedir(const FTS *, const FTSENT *, int,
+ const char *);
+
+#if defined(ALIGNBYTES) && defined(ALIGN)
+#define FTS_ALLOC_ALIGNED 1
+#else
+#undef FTS_ALLOC_ALIGNED
+#endif
#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
@@ -98,10 +104,8 @@ static int fts_safe_changedir __P((const FTS *, const FTSENT *, int,
#endif
FTS *
-fts_open(
- char * const *argv,
- int options,
- int (*compar) (const FTSENT **, const FTSENT **) )
+fts_open(char * const *argv, int options,
+ int (*compar)(const FTSENT **, const FTSENT **))
{
FTS *sp;
FTSENT *p, *root;
@@ -118,7 +122,7 @@ fts_open(
}
/* Allocate/initialize the stream */
- if ((sp = malloc((u_int)sizeof(FTS))) == NULL)
+ if ((sp = malloc((unsigned int)sizeof(FTS))) == NULL)
return (NULL);
memset(sp, 0, sizeof(FTS));
sp->fts_compar = compar;
@@ -204,20 +208,21 @@ fts_open(
SET(FTS_NOCHDIR);
}
}
- free(parent);
+
+ if (nitems == 0)
+ fts_free(parent);
+
return (sp);
mem3: fts_lfree(root);
- free(parent);
+ fts_free(parent);
mem2: free(sp->fts_path);
mem1: free(sp);
return (NULL);
}
static void
-fts_load(
- FTS *sp,
- FTSENT *p)
+fts_load(FTS *sp, FTSENT *p)
{
size_t len;
char *cp;
@@ -244,8 +249,7 @@ fts_load(
}
int
-fts_close(
- FTS *sp)
+fts_close(FTS *sp)
{
FTSENT *freep, *p;
int saved_errno = 0;
@@ -258,14 +262,14 @@ fts_close(
* list which has a valid parent pointer.
*/
if (sp->fts_cur) {
- if (ISSET(FTS_SYMFOLLOW))
+ if (sp->fts_cur->fts_flags & FTS_SYMFOLLOW)
(void)close(sp->fts_cur->fts_symfd);
for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
freep = p;
p = p->fts_link ? p->fts_link : p->fts_parent;
- free(freep);
+ fts_free(freep);
}
- free(p);
+ fts_free(p);
}
/* Free up child linked list, sort array, path buffer. */
@@ -277,23 +281,23 @@ fts_close(
/* Return to original directory, save errno if necessary. */
if (!ISSET(FTS_NOCHDIR)) {
- if (fchdir(sp->fts_rfd))
+ if (fchdir(sp->fts_rfd) == -1)
saved_errno = errno;
(void)close(sp->fts_rfd);
}
/* Free up the stream pointer. */
free(sp);
- /* ISSET() is illegal after this, since the macro touches sp */
-
- /* Set errno and return. */
if (saved_errno) {
errno = saved_errno;
- return (-1);
+ return -1;
}
- return (0);
+
+ return 0;
}
+#if !defined(__FTS_COMPAT_TAILINGSLASH)
+
/*
* Special case of "/" at the end of the path so that slashes aren't
* appended which would cause paths to be written as "....//foo".
@@ -302,9 +306,23 @@ fts_close(
(p->fts_path[p->fts_pathlen - 1] == '/' \
? p->fts_pathlen - 1 : p->fts_pathlen)
+#else /* !defined(__FTS_COMPAT_TAILINGSLASH) */
+
+/*
+ * compatibility with the old behaviour.
+ *
+ * Special case a root of "/" so that slashes aren't appended which would
+ * cause paths to be written as "//foo".
+ */
+
+#define NAPPEND(p) \
+ (p->fts_level == FTS_ROOTLEVEL && p->fts_pathlen == 1 && \
+ p->fts_path[0] == '/' ? 0 : p->fts_pathlen)
+
+#endif /* !defined(__FTS_COMPAT_TAILINGSLASH) */
+
FTSENT *
-fts_read(
- FTS *sp )
+fts_read(FTS *sp)
{
FTSENT *p, *tmp;
int instr;
@@ -408,7 +426,7 @@ fts_read(
/* Move to the next node on this level. */
next: tmp = p;
if ((p = p->fts_link) != NULL) {
- free(tmp);
+ fts_free(tmp);
/*
* If reached the top, return to the original directory, and
@@ -455,14 +473,14 @@ name: t = sp->fts_path + NAPPEND(p->fts_parent);
/* Move up to the parent node. */
p = tmp->fts_parent;
- free(tmp);
+ fts_free(tmp);
if (p->fts_level == FTS_ROOTPARENTLEVEL) {
/*
* Done; free everything up and set errno to 0 so the user
* can distinguish between error and EOF.
*/
- free(p);
+ fts_free(p);
errno = 0;
return (sp->fts_cur = NULL);
}
@@ -506,10 +524,7 @@ name: t = sp->fts_path + NAPPEND(p->fts_parent);
*/
/* ARGSUSED */
int
-fts_set(
- FTS *sp __attribute__((unused)),
- FTSENT *p,
- int instr)
+fts_set(FTS *sp, FTSENT *p, int instr)
{
_DIAGASSERT(sp != NULL);
@@ -525,9 +540,7 @@ fts_set(
}
FTSENT *
-fts_children(
- FTS *sp,
- int instr )
+fts_children(FTS *sp, int instr)
{
FTSENT *p;
int fd;
@@ -611,17 +624,17 @@ fts_children(
* been found, cutting the stat calls by about 2/3.
*/
static FTSENT *
-fts_build(
- FTS *sp,
- int type)
+fts_build(FTS *sp, int type)
{
struct dirent *dp;
FTSENT *p, *head;
size_t nitems;
FTSENT *cur, *tail;
DIR *dirp;
- int adjust, cderrno, descend, len, level, nlinks, saved_errno, nostat;
- size_t maxlen;
+ void *oldaddr;
+ size_t dnamlen;
+ int cderrno, descend, level, nlinks, saved_errno, nostat, doadjust;
+ size_t len, maxlen;
#ifdef FTS_WHITEOUT
int oflag;
#endif
@@ -642,7 +655,7 @@ fts_build(
else
oflag = DTF_HIDEW|DTF_NODUP|DTF_REWIND;
#else
-#define __opendir2(path, flag) opendir(path)
+#define __opendir2(path, flag) opendir(path)
#endif
if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) {
if (type == BREAD) {
@@ -719,25 +732,35 @@ fts_build(
len++;
maxlen = sp->fts_pathlen - len;
+#if defined(__FTS_COMPAT_LEVEL)
+ if (cur->fts_level == SHRT_MAX) {
+ (void)closedir(dirp);
+ cur->fts_info = FTS_ERR;
+ SET(FTS_STOP);
+ errno = ENAMETOOLONG;
+ return (NULL);
+ }
+#endif
+
level = cur->fts_level + 1;
/* Read the directory, attaching each entry to the `link' pointer. */
- adjust = 0;
+ doadjust = 0;
for (head = tail = NULL, nitems = 0; (dp = readdir(dirp)) != NULL;) {
- size_t dlen;
if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
continue;
-#if HAVE_STRUCT_DIRENT_D_NAMLEN
- dlen = dp->d_namlen;
+#if defined(HAVE_STRUCT_DIRENT_D_NAMLEN)
+ dnamlen = dp->d_namlen;
#else
- dlen = strlen(dp->d_name);
+ dnamlen = strlen(dp->d_name);
#endif
- if ((p = fts_alloc(sp, dp->d_name, dlen)) == NULL)
+ if ((p = fts_alloc(sp, dp->d_name, dnamlen)) == NULL)
goto mem1;
- if (dlen >= maxlen) { /* include space for NUL */
- if (fts_palloc(sp, len + dlen + 1)) {
+ if (dnamlen >= maxlen) { /* include space for NUL */
+ oldaddr = sp->fts_path;
+ if (fts_palloc(sp, dnamlen + len + 1)) {
/*
* No more memory for path or structures. Save
* errno, free up the current structure and the
@@ -745,7 +768,7 @@ fts_build(
*/
mem1: saved_errno = errno;
if (p)
- free(p);
+ fts_free(p);
fts_lfree(head);
(void)closedir(dirp);
errno = saved_errno;
@@ -753,15 +776,36 @@ mem1: saved_errno = errno;
SET(FTS_STOP);
return (NULL);
}
- adjust = 1;
- if (ISSET(FTS_NOCHDIR))
- cp = sp->fts_path + len;
+ /* Did realloc() change the pointer? */
+ if (oldaddr != sp->fts_path) {
+ doadjust = 1;
+ if (ISSET(FTS_NOCHDIR))
+ cp = sp->fts_path + len;
+ }
maxlen = sp->fts_pathlen - len;
}
- p->fts_pathlen = len + dlen;
- p->fts_parent = sp->fts_cur;
+#if defined(__FTS_COMPAT_LENGTH)
+ if (len + dnamlen >= USHRT_MAX) {
+ /*
+ * In an FTSENT, fts_pathlen is an unsigned short
+ * so it is possible to wraparound here.
+ * If we do, free up the current structure and the
+ * structures already allocated, then error out
+ * with ENAMETOOLONG.
+ */
+ fts_free(p);
+ fts_lfree(head);
+ (void)closedir(dirp);
+ cur->fts_info = FTS_ERR;
+ SET(FTS_STOP);
+ errno = ENAMETOOLONG;
+ return (NULL);
+ }
+#endif
p->fts_level = level;
+ p->fts_pathlen = len + dnamlen;
+ p->fts_parent = sp->fts_cur;
#ifdef FTS_WHITEOUT
if (dp->d_type == DT_WHT)
@@ -774,8 +818,8 @@ mem1: saved_errno = errno;
p->fts_errno = cderrno;
} /* else
p->fts_info = FTS_NSOK;
- */
- /* Coverity Scan Id 1 says above is dead code */
+ */
+ /* Coverity Scan Id 1 says above is dead code */
p->fts_accpath = cur->fts_accpath;
} else if (nlinks == 0
#ifdef DT_DIR
@@ -819,7 +863,7 @@ mem1: saved_errno = errno;
* If had to realloc the path, adjust the addresses for the rest
* of the tree.
*/
- if (adjust)
+ if (doadjust)
fts_padjust(sp, head);
/*
@@ -827,7 +871,7 @@ mem1: saved_errno = errno;
* state.
*/
if (ISSET(FTS_NOCHDIR)) {
- if (cp - 1 > sp->fts_path)
+ if (len == sp->fts_pathlen || nitems == 0)
--cp;
*cp = '\0';
}
@@ -861,11 +905,8 @@ mem1: saved_errno = errno;
return (head);
}
-static u_short
-fts_stat(
- FTS *sp,
- FTSENT *p,
- int follow )
+static unsigned short
+fts_stat(FTS *sp, FTSENT *p, int follow)
{
FTSENT *t;
dev_t dev;
@@ -948,10 +989,7 @@ err: memset(sbp, 0, sizeof(*sbp));
}
static FTSENT *
-fts_sort(
- FTS *sp,
- FTSENT *head,
- size_t nitems )
+fts_sort(FTS *sp, FTSENT *head, size_t nitems)
{
FTSENT **ap, *p;
@@ -977,7 +1015,7 @@ fts_sort(
for (ap = sp->fts_array, p = head; p; p = p->fts_link)
*ap++ = p;
qsort((void *)sp->fts_array, nitems, sizeof(FTSENT *),
- (int (*) __P((const void *, const void *)))sp->fts_compar);
+ (int (*)(const void *, const void *))sp->fts_compar);
for (head = *(ap = sp->fts_array); --nitems; ++ap)
ap[0]->fts_link = ap[1];
ap[0]->fts_link = NULL;
@@ -985,18 +1023,17 @@ fts_sort(
}
static FTSENT *
-fts_alloc(
- FTS *sp,
- const char *name,
- size_t namelen )
+fts_alloc(FTS *sp, const char *name, size_t namelen)
{
FTSENT *p;
+#if defined(FTS_ALLOC_ALIGNED)
size_t len;
+#endif
_DIAGASSERT(sp != NULL);
_DIAGASSERT(name != NULL);
-#if defined(ALIGNBYTES) && defined(ALIGN)
+#if defined(FTS_ALLOC_ALIGNED)
/*
* The file name is a variable length array and no stat structure is
* necessary if the user has set the nostat bit. Allocate the FTSENT
@@ -1012,8 +1049,8 @@ fts_alloc(
return (NULL);
if (!ISSET(FTS_NOSTAT))
- p->fts_statp =
- (__fts_stat_t *)ALIGN((u_long)(p->fts_name + namelen + 2));
+ p->fts_statp = (__fts_stat_t *)ALIGN(
+ (unsigned long)(p->fts_name + namelen + 2));
#else
if ((p = malloc(sizeof(FTSENT) + namelen)) == NULL)
return (NULL);
@@ -1025,6 +1062,9 @@ fts_alloc(
}
#endif
+ if (ISSET(FTS_NOSTAT))
+ p->fts_statp = NULL;
+
/* Copy the name plus the trailing NULL. */
memmove(p->fts_name, name, namelen + 1);
@@ -1039,8 +1079,17 @@ fts_alloc(
}
static void
-fts_lfree(
- FTSENT *head )
+fts_free(FTSENT *p)
+{
+#if !defined(FTS_ALLOC_ALIGNED)
+ if (p->fts_statp)
+ free(p->fts_statp);
+#endif
+ free(p);
+}
+
+static void
+fts_lfree(FTSENT *head)
{
FTSENT *p;
@@ -1049,18 +1098,12 @@ fts_lfree(
/* Free a linked list of structures. */
while ((p = head) != NULL) {
head = head->fts_link;
-
-#if !defined(ALIGNBYTES) || !defined(ALIGN)
- if (p->fts_statp)
- free(p->fts_statp);
-#endif
- free(p);
+ fts_free(p);
}
}
static size_t
-fts_pow2(
- size_t x )
+fts_pow2(size_t x)
{
x--;
@@ -1086,18 +1129,16 @@ fts_pow2(
* so we don't realloc the path 2 bytes at a time.
*/
static int
-fts_palloc(
- FTS *sp,
- size_t size )
+fts_palloc(FTS *sp, size_t size)
{
char *new;
_DIAGASSERT(sp != NULL);
-#if 1
+#ifdef __FTS_COMPAT_LENGTH
/* Protect against fts_pathlen overflow. */
if (size > USHRT_MAX + 1) {
- errno = ENOMEM;
+ errno = ENAMETOOLONG;
return (1);
}
#endif
@@ -1115,9 +1156,7 @@ fts_palloc(
* already returned.
*/
static void
-fts_padjust(
- FTS *sp,
- FTSENT *head )
+fts_padjust(FTS *sp, FTSENT *head)
{
FTSENT *p;
char *addr;
@@ -1145,8 +1184,7 @@ fts_padjust(
}
static size_t
-fts_maxarglen(
- char * const *argv )
+fts_maxarglen(char * const *argv)
{
size_t len, max;
@@ -1164,11 +1202,7 @@ fts_maxarglen(
* Assumes p->fts_dev and p->fts_ino are filled in.
*/
static int
-fts_safe_changedir(
- const FTS *sp,
- const FTSENT *p,
- int fd,
- const char *path)
+fts_safe_changedir(const FTS *sp, const FTSENT *p, int fd, const char *path)
{
int oldfd = fd, ret = -1;
__fts_stat_t sb;
diff --git a/cpukit/libmisc/shell/main_ls.c b/cpukit/libmisc/shell/main_ls.c
index f1cbbcfc91..b60477ff79 100644
--- a/cpukit/libmisc/shell/main_ls.c
+++ b/cpukit/libmisc/shell/main_ls.c
@@ -360,7 +360,8 @@ main_ls(rtems_shell_ls_globals* globals, int argc, char *argv[])
if (!kflag)
(void)getbsize(NULL, &blocksize);
#else
- blocksize = 1024;
+ /* Make equal to 1 so ls -l shows the actual blcok count */
+ blocksize = 512;
#endif
blocksize /= 512;
}
@@ -542,6 +543,7 @@ display(rtems_shell_ls_globals* globals, FTSENT *p, FTSENT *list)
btotal = stotal = maxblock = maxsize = 0;
maxmajor = maxminor = 0;
for (cur = list, entries = 0; cur; cur = cur->fts_link) {
+ uint64_t size;
if (cur->fts_info == FTS_ERR || cur->fts_info == FTS_NS) {
warnx("%s: %s",
cur->fts_name, strerror(cur->fts_errno));
@@ -571,14 +573,17 @@ display(rtems_shell_ls_globals* globals, FTSENT *p, FTSENT *list)
maxlen = cur->fts_namelen;
if (needstats) {
sp = cur->fts_statp;
+ size = ((uint64_t) sp->st_blocks) * sp->st_blksize;
+ if (size < 0x100000000ULL)
+ size = sp->st_size;
if (sp->st_blocks > maxblock)
maxblock = sp->st_blocks;
if (sp->st_ino > maxinode)
maxinode = sp->st_ino;
if (sp->st_nlink > maxnlink)
maxnlink = sp->st_nlink;
- if (sp->st_size > maxsize)
- maxsize = sp->st_size;
+ if (size > maxsize)
+ maxsize = size;
if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) {
bcfile = 1;
if (major(sp->st_rdev) > maxmajor)
@@ -588,7 +593,7 @@ display(rtems_shell_ls_globals* globals, FTSENT *p, FTSENT *list)
}
btotal += sp->st_blocks;
- stotal += sp->st_size;
+ stotal += size;
if (f_longform) {
if (f_numericonly ||
(user = user_from_uid(sp->st_uid, 0)) ==
diff --git a/cpukit/libmisc/shell/print-ls.c b/cpukit/libmisc/shell/print-ls.c
index dc449f558f..192d8f11b8 100644
--- a/cpukit/libmisc/shell/print-ls.c
+++ b/cpukit/libmisc/shell/print-ls.c
@@ -161,11 +161,13 @@ printlong(rtems_shell_ls_globals* globals, DISPLAY *dp)
(void)printf("%*s ", dp->s_size, szbuf);
} else {
#endif
- (void)printf("%*llu ", dp->s_size,
- (long long)sp->st_size);
-#if RTEMS_REMOVED
+ {
+ unsigned long long size = sp->st_blocks;
+ size *= sp->st_blksize;
+ if (size < 0x100000000ULL)
+ size = sp->st_size;
+ (void)printf("%*llu ", dp->s_size, size);
}
-#endif
if (f_accesstime)
printtime(globals, sp->st_atime);
else if (f_statustime)