--- embedaddon/sudo/common/fileops.c 2012/02/21 16:23:02 1.1 +++ embedaddon/sudo/common/fileops.c 2013/07/22 10:46:11 1.1.1.3 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005, 2007, 2009-2011 + * Copyright (c) 1999-2005, 2007, 2009-2013 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -22,38 +22,51 @@ #include #include -#include #include #ifdef HAVE_FLOCK # include #endif /* HAVE_FLOCK */ -#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ #ifdef HAVE_STRING_H +# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS) +# include +# endif # include #endif /* HAVE_STRING_H */ #ifdef HAVE_STRINGS_H # include -#endif /* HAVE_STRINGS_H */ +#endif /* HAVE_STRING_H */ +#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS) +# include +#endif /* HAVE_MALLOC_H && !STDC_HEADERS */ #include -#include #ifdef HAVE_UNISTD_H # include #endif /* HAVE_UNISTD_H */ #include +#ifdef HAVE_STDBOOL_H +# include +#else +# include "compat/stdbool.h" +#endif #if TIME_WITH_SYS_TIME # include #endif -#ifndef HAVE_TIMESPEC +#ifndef HAVE_STRUCT_TIMESPEC # include "compat/timespec.h" #endif #include "missing.h" #include "fileops.h" +#include "sudo_debug.h" -#ifndef LINE_MAX -# define LINE_MAX 2048 -#endif - /* * Update the access and modify times on an fd or file. */ @@ -61,6 +74,8 @@ int touch(int fd, char *path, struct timeval *tvp) { struct timeval times[2]; + int rval = -1; + debug_decl(touch, SUDO_DEBUG_UTIL) if (tvp != NULL) { times[0].tv_sec = times[1].tv_sec = tvp->tv_sec; @@ -69,23 +84,23 @@ touch(int fd, char *path, struct timeval *tvp) #if defined(HAVE_FUTIME) || defined(HAVE_FUTIMES) if (fd != -1) - return futimes(fd, tvp ? times : NULL); + rval = futimes(fd, tvp ? times : NULL); else #endif if (path != NULL) - return utimes(path, tvp ? times : NULL); - else - return -1; + rval = utimes(path, tvp ? times : NULL); + debug_return_int(rval); } /* * Lock/unlock a file. */ #ifdef HAVE_LOCKF -int +bool lock_file(int fd, int lockit) { int op = 0; + debug_decl(lock_file, SUDO_DEBUG_UTIL) switch (lockit) { case SUDO_LOCK: @@ -98,13 +113,14 @@ lock_file(int fd, int lockit) op = F_ULOCK; break; } - return lockf(fd, op, 0) == 0; + debug_return_bool(lockf(fd, op, 0) == 0); } #elif HAVE_FLOCK -int +bool lock_file(int fd, int lockit) { int op = 0; + debug_decl(lock_file, SUDO_DEBUG_UTIL) switch (lockit) { case SUDO_LOCK: @@ -117,15 +133,16 @@ lock_file(int fd, int lockit) op = LOCK_UN; break; } - return flock(fd, op) == 0; + debug_return_bool(flock(fd, op) == 0); } #else -int +bool lock_file(int fd, int lockit) { #ifdef F_SETLK int func; struct flock lock; + debug_decl(lock_file, SUDO_DEBUG_UTIL) lock.l_start = 0; lock.l_len = 0; @@ -134,35 +151,83 @@ lock_file(int fd, int lockit) lock.l_whence = SEEK_SET; func = (lockit == SUDO_LOCK) ? F_SETLKW : F_SETLK; - return fcntl(fd, func, &lock) == 0; + debug_return_bool(fcntl(fd, func, &lock) == 0); #else - return TRUE; + return true; #endif } #endif /* - * Read a line of input, remove comments and strip off leading - * and trailing spaces. Returns static storage that is reused. + * Read a line of input, honoring line continuation chars. + * Remove comments and strips off leading and trailing spaces. + * Returns the line length and updates the buf and bufsize pointers. + * XXX - just use a struct w/ state, including getline buffer? + * could also make comment char and line continuation configurable */ -char * -sudo_parseln(FILE *fp) +ssize_t +sudo_parseln(char **bufp, size_t *bufsizep, unsigned int *lineno, FILE *fp) { - size_t len; - char *cp = NULL; - static char buf[LINE_MAX]; + size_t len, linesize = 0, total = 0; + char *cp, *line = NULL; + bool continued; + debug_decl(sudo_parseln, SUDO_DEBUG_UTIL) - if (fgets(buf, sizeof(buf), fp) != NULL) { - /* Remove comments */ - if ((cp = strchr(buf, '#')) != NULL) + do { + continued = false; + len = getline(&line, &linesize, fp); + if (len == -1) + break; + if (lineno != NULL) + (*lineno)++; + + /* Remove trailing newline(s) if present. */ + while (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r')) + line[--len] = '\0'; + + /* Remove comments or check for line continuation (but not both) */ + if ((cp = strchr(line, '#')) != NULL) { *cp = '\0'; + len = (size_t)(cp - line); + } else if (len > 0 && line[len - 1] == '\\' && (len == 1 || line[len - 2] != '\\')) { + line[--len] = '\0'; + continued = true; + } - /* Trim leading and trailing whitespace/newline */ - len = strlen(buf); - while (len > 0 && isspace((unsigned char)buf[len - 1])) - buf[--len] = '\0'; - for (cp = buf; isblank((unsigned char)*cp); cp++) - continue; - } - return cp; + /* Trim leading and trailing whitespace */ + if (!continued) { + while (len > 0 && isblank((unsigned char)line[len - 1])) + line[--len] = '\0'; + } + for (cp = line; isblank((unsigned char)*cp); cp++) + len--; + + if (*bufp == NULL || total + len >= *bufsizep) { + void *tmp; + size_t size = total + len + 1; + + if (size < 64) { + size = 64; + } else if (size <= 0x80000000) { + /* Round up to next highest power of two. */ + size--; + size |= size >> 1; + size |= size >> 2; + size |= size >> 4; + size |= size >> 8; + size |= size >> 16; + size++; + } + if ((tmp = realloc(*bufp, size)) == NULL) + break; + *bufp = tmp; + *bufsizep = size; + } + memcpy(*bufp + total, cp, len + 1); + total += len; + } while (continued); + free(line); + if (len == -1 && total == 0) + debug_return_size_t((size_t)-1); + debug_return_size_t(total); }