File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sudo / common / fileops.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 16:12:54 2014 UTC (10 years ago) by misho
Branches: sudo, MAIN
CVS tags: v1_8_10p3_0, v1_8_10p3, HEAD
sudo v 1.8.10p3

    1: /*
    2:  * Copyright (c) 1999-2005, 2007, 2009-2013
    3:  *	Todd C. Miller <Todd.Miller@courtesan.com>
    4:  *
    5:  * Permission to use, copy, modify, and distribute this software for any
    6:  * purpose with or without fee is hereby granted, provided that the above
    7:  * copyright notice and this permission notice appear in all copies.
    8:  *
    9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   16:  *
   17:  * Sponsored in part by the Defense Advanced Research Projects
   18:  * Agency (DARPA) and Air Force Research Laboratory, Air Force
   19:  * Materiel Command, USAF, under agreement number F39502-99-1-0512.
   20:  */
   21: 
   22: #include <config.h>
   23: 
   24: #include <sys/types.h>
   25: #include <sys/time.h>
   26: #ifdef HAVE_FLOCK
   27: # include <sys/file.h>
   28: #endif /* HAVE_FLOCK */
   29: #ifdef STDC_HEADERS
   30: # include <stdlib.h>
   31: # include <stddef.h>
   32: #else
   33: # ifdef HAVE_STDLIB_H
   34: #  include <stdlib.h>
   35: # endif
   36: #endif /* STDC_HEADERS */
   37: #ifdef HAVE_STRING_H
   38: # if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
   39: #  include <memory.h>
   40: # endif
   41: # include <string.h>
   42: #endif /* HAVE_STRING_H */
   43: #ifdef HAVE_STRINGS_H
   44: # include <strings.h>
   45: #endif /* HAVE_STRING_H */
   46: #if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
   47: # include <malloc.h>
   48: #endif /* HAVE_MALLOC_H && !STDC_HEADERS */
   49: #include <ctype.h>
   50: #ifdef HAVE_UNISTD_H
   51: # include <unistd.h>
   52: #endif /* HAVE_UNISTD_H */
   53: #include <fcntl.h>
   54: #ifdef HAVE_STDBOOL_H
   55: # include <stdbool.h>
   56: #else
   57: # include "compat/stdbool.h"
   58: #endif
   59: #ifdef TIME_WITH_SYS_TIME
   60: # include <time.h>
   61: #endif
   62: #ifndef HAVE_STRUCT_TIMESPEC
   63: # include "compat/timespec.h"
   64: #endif
   65: 
   66: #include "missing.h"
   67: #include "fileops.h"
   68: #include "sudo_debug.h"
   69: 
   70: /*
   71:  * Update the access and modify times on an fd or file.
   72:  */
   73: int
   74: touch(int fd, char *path, struct timeval *tvp)
   75: {
   76:     struct timeval times[2];
   77:     int rval = -1;
   78:     debug_decl(touch, SUDO_DEBUG_UTIL)
   79: 
   80:     if (tvp != NULL) {
   81: 	times[0].tv_sec = times[1].tv_sec = tvp->tv_sec;
   82: 	times[0].tv_usec = times[1].tv_usec = tvp->tv_usec;
   83:     }
   84: 
   85: #if defined(HAVE_FUTIME) || defined(HAVE_FUTIMES)
   86:     if (fd != -1)
   87: 	rval = futimes(fd, tvp ? times : NULL);
   88:     else
   89: #endif
   90:     if (path != NULL)
   91: 	rval = utimes(path, tvp ? times : NULL);
   92:     debug_return_int(rval);
   93: }
   94: 
   95: /*
   96:  * Lock/unlock a file.
   97:  */
   98: #ifdef HAVE_LOCKF
   99: bool
  100: lock_file(int fd, int lockit)
  101: {
  102:     int op = 0;
  103:     debug_decl(lock_file, SUDO_DEBUG_UTIL)
  104: 
  105:     switch (lockit) {
  106: 	case SUDO_LOCK:
  107: 	    op = F_LOCK;
  108: 	    break;
  109: 	case SUDO_TLOCK:
  110: 	    op = F_TLOCK;
  111: 	    break;
  112: 	case SUDO_UNLOCK:
  113: 	    op = F_ULOCK;
  114: 	    break;
  115:     }
  116:     debug_return_bool(lockf(fd, op, 0) == 0);
  117: }
  118: #elif defined(HAVE_FLOCK)
  119: bool
  120: lock_file(int fd, int lockit)
  121: {
  122:     int op = 0;
  123:     debug_decl(lock_file, SUDO_DEBUG_UTIL)
  124: 
  125:     switch (lockit) {
  126: 	case SUDO_LOCK:
  127: 	    op = LOCK_EX;
  128: 	    break;
  129: 	case SUDO_TLOCK:
  130: 	    op = LOCK_EX | LOCK_NB;
  131: 	    break;
  132: 	case SUDO_UNLOCK:
  133: 	    op = LOCK_UN;
  134: 	    break;
  135:     }
  136:     debug_return_bool(flock(fd, op) == 0);
  137: }
  138: #else
  139: bool
  140: lock_file(int fd, int lockit)
  141: {
  142: #ifdef F_SETLK
  143:     int func;
  144:     struct flock lock;
  145:     debug_decl(lock_file, SUDO_DEBUG_UTIL)
  146: 
  147:     lock.l_start = 0;
  148:     lock.l_len = 0;
  149:     lock.l_pid = getpid();
  150:     lock.l_type = (lockit == SUDO_UNLOCK) ? F_UNLCK : F_WRLCK;
  151:     lock.l_whence = SEEK_SET;
  152:     func = (lockit == SUDO_LOCK) ? F_SETLKW : F_SETLK;
  153: 
  154:     debug_return_bool(fcntl(fd, func, &lock) == 0);
  155: #else
  156:     return true;
  157: #endif
  158: }
  159: #endif
  160: 
  161: /*
  162:  * Read a line of input, honoring line continuation chars.
  163:  * Remove comments and strips off leading and trailing spaces.
  164:  * Returns the line length and updates the buf and bufsize pointers.
  165:  * XXX - just use a struct w/ state, including getline buffer?
  166:  *       could also make comment char and line continuation configurable
  167:  */
  168: ssize_t
  169: sudo_parseln(char **bufp, size_t *bufsizep, unsigned int *lineno, FILE *fp)
  170: {
  171:     size_t linesize = 0, total = 0;
  172:     ssize_t len;
  173:     char *cp, *line = NULL;
  174:     bool continued;
  175:     debug_decl(sudo_parseln, SUDO_DEBUG_UTIL)
  176: 
  177:     do {
  178: 	continued = false;
  179: 	len = getline(&line, &linesize, fp);
  180: 	if (len == -1)
  181: 	    break;
  182: 	if (lineno != NULL)
  183: 	    (*lineno)++;
  184: 
  185: 	/* Remove trailing newline(s) if present. */
  186: 	while (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r'))
  187: 	    line[--len] = '\0';
  188: 
  189: 	/* Remove comments or check for line continuation (but not both) */
  190: 	if ((cp = strchr(line, '#')) != NULL) {
  191: 	    *cp = '\0';
  192: 	    len = (size_t)(cp - line);
  193: 	} else if (len > 0 && line[len - 1] == '\\' && (len == 1 || line[len - 2] != '\\')) {
  194: 	    line[--len] = '\0';
  195: 	    continued = true;
  196: 	}
  197: 
  198: 	/* Trim leading and trailing whitespace */
  199: 	if (!continued) {
  200: 	    while (len > 0 && isblank((unsigned char)line[len - 1]))
  201: 		line[--len] = '\0';
  202: 	}
  203: 	for (cp = line; isblank((unsigned char)*cp); cp++)
  204: 	    len--;
  205: 
  206: 	if (*bufp == NULL || total + len >= *bufsizep) {
  207: 	    void *tmp;
  208: 	    size_t size = total + len + 1;
  209: 
  210: 	    if (size < 64) {
  211: 		size = 64;
  212: 	    } else if (size <= 0x80000000) {
  213: 		/* Round up to next highest power of two. */
  214: 		size--;
  215: 		size |= size >> 1;
  216: 		size |= size >> 2;
  217: 		size |= size >> 4;
  218: 		size |= size >> 8;
  219: 		size |= size >> 16;
  220: 		size++;
  221: 	    }
  222: 	    if ((tmp = realloc(*bufp, size)) == NULL)
  223: 		break;
  224: 	    *bufp = tmp;
  225: 	    *bufsizep = size;
  226: 	}
  227: 	memcpy(*bufp + total, cp, len + 1);
  228: 	total += len;
  229:     } while (continued);
  230:     free(line);
  231:     if (len == -1 && total == 0)
  232: 	debug_return_size_t((size_t)-1);
  233:     debug_return_size_t(total);
  234: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>