File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / rsync / syscall.c
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Fri Feb 17 15:09:30 2012 UTC (12 years, 5 months ago) by misho
CVS tags: MAIN, HEAD
Initial revision

    1: /*
    2:  * Syscall wrappers to ensure that nothing gets done in dry_run mode
    3:  * and to handle system peculiarities.
    4:  *
    5:  * Copyright (C) 1998 Andrew Tridgell
    6:  * Copyright (C) 2002 Martin Pool
    7:  * Copyright (C) 2003-2009 Wayne Davison
    8:  *
    9:  * This program is free software; you can redistribute it and/or modify
   10:  * it under the terms of the GNU General Public License as published by
   11:  * the Free Software Foundation; either version 3 of the License, or
   12:  * (at your option) any later version.
   13:  *
   14:  * This program is distributed in the hope that it will be useful,
   15:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   16:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17:  * GNU General Public License for more details.
   18:  *
   19:  * You should have received a copy of the GNU General Public License along
   20:  * with this program; if not, visit the http://fsf.org website.
   21:  */
   22: 
   23: #include "rsync.h"
   24: 
   25: #if !defined MKNOD_CREATES_SOCKETS && defined HAVE_SYS_UN_H
   26: #include <sys/un.h>
   27: #endif
   28: #ifdef HAVE_SYS_ATTR_H
   29: #include <sys/attr.h>
   30: #endif
   31: 
   32: extern int dry_run;
   33: extern int am_root;
   34: extern int read_only;
   35: extern int list_only;
   36: extern int preserve_perms;
   37: extern int preserve_executability;
   38: 
   39: #define RETURN_ERROR_IF(x,e) \
   40: 	do { \
   41: 		if (x) { \
   42: 			errno = (e); \
   43: 			return -1; \
   44: 		} \
   45: 	} while (0)
   46: 
   47: #define RETURN_ERROR_IF_RO_OR_LO RETURN_ERROR_IF(read_only || list_only, EROFS)
   48: 
   49: int do_unlink(const char *fname)
   50: {
   51: 	if (dry_run) return 0;
   52: 	RETURN_ERROR_IF_RO_OR_LO;
   53: 	return unlink(fname);
   54: }
   55: 
   56: int do_symlink(const char *fname1, const char *fname2)
   57: {
   58: 	if (dry_run) return 0;
   59: 	RETURN_ERROR_IF_RO_OR_LO;
   60: 	return symlink(fname1, fname2);
   61: }
   62: 
   63: #ifdef HAVE_LINK
   64: int do_link(const char *fname1, const char *fname2)
   65: {
   66: 	if (dry_run) return 0;
   67: 	RETURN_ERROR_IF_RO_OR_LO;
   68: 	return link(fname1, fname2);
   69: }
   70: #endif
   71: 
   72: int do_lchown(const char *path, uid_t owner, gid_t group)
   73: {
   74: 	if (dry_run) return 0;
   75: 	RETURN_ERROR_IF_RO_OR_LO;
   76: #ifndef HAVE_LCHOWN
   77: #define lchown chown
   78: #endif
   79: 	return lchown(path, owner, group);
   80: }
   81: 
   82: int do_mknod(const char *pathname, mode_t mode, dev_t dev)
   83: {
   84: 	if (dry_run) return 0;
   85: 	RETURN_ERROR_IF_RO_OR_LO;
   86: 
   87: 	/* For --fake-super, we create a normal file with mode 0600. */
   88: 	if (am_root < 0) {
   89: 		int fd = open(pathname, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR|S_IRUSR);
   90: 		if (fd < 0 || close(fd) < 0)
   91: 			return -1;
   92: 		return 0;
   93: 	}
   94: 
   95: #if !defined MKNOD_CREATES_FIFOS && defined HAVE_MKFIFO
   96: 	if (S_ISFIFO(mode))
   97: 		return mkfifo(pathname, mode);
   98: #endif
   99: #if !defined MKNOD_CREATES_SOCKETS && defined HAVE_SYS_UN_H
  100: 	if (S_ISSOCK(mode)) {
  101: 		int sock;
  102: 		struct sockaddr_un saddr;
  103: #ifdef HAVE_SOCKADDR_UN_LEN
  104: 		unsigned int len =
  105: #endif
  106: 		    strlcpy(saddr.sun_path, pathname, sizeof saddr.sun_path);
  107: #ifdef HAVE_SOCKADDR_UN_LEN
  108: 		saddr.sun_len = len >= sizeof saddr.sun_path
  109: 			      ? sizeof saddr.sun_path : len + 1;
  110: #endif
  111: 		saddr.sun_family = AF_UNIX;
  112: 
  113: 		if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0
  114: 		    || (unlink(pathname) < 0 && errno != ENOENT)
  115: 		    || (bind(sock, (struct sockaddr*)&saddr, sizeof saddr)) < 0)
  116: 			return -1;
  117: 		close(sock);
  118: #ifdef HAVE_CHMOD
  119: 		return do_chmod(pathname, mode);
  120: #else
  121: 		return 0;
  122: #endif
  123: 	}
  124: #endif
  125: #ifdef HAVE_MKNOD
  126: 	return mknod(pathname, mode, dev);
  127: #else
  128: 	return -1;
  129: #endif
  130: }
  131: 
  132: int do_rmdir(const char *pathname)
  133: {
  134: 	if (dry_run) return 0;
  135: 	RETURN_ERROR_IF_RO_OR_LO;
  136: 	return rmdir(pathname);
  137: }
  138: 
  139: int do_open(const char *pathname, int flags, mode_t mode)
  140: {
  141: 	if (flags != O_RDONLY) {
  142: 		RETURN_ERROR_IF(dry_run, 0);
  143: 		RETURN_ERROR_IF_RO_OR_LO;
  144: 	}
  145: 
  146: 	return open(pathname, flags | O_BINARY, mode);
  147: }
  148: 
  149: #ifdef HAVE_CHMOD
  150: int do_chmod(const char *path, mode_t mode)
  151: {
  152: 	int code;
  153: 	if (dry_run) return 0;
  154: 	RETURN_ERROR_IF_RO_OR_LO;
  155: #ifdef HAVE_LCHMOD
  156: 	code = lchmod(path, mode & CHMOD_BITS);
  157: #else
  158: 	if (S_ISLNK(mode)) {
  159: # if defined HAVE_SETATTRLIST
  160: 		struct attrlist attrList;
  161: 		uint32_t m = mode & CHMOD_BITS; /* manpage is wrong: not mode_t! */
  162: 
  163: 		memset(&attrList, 0, sizeof attrList);
  164: 		attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
  165: 		attrList.commonattr = ATTR_CMN_ACCESSMASK;
  166: 		code = setattrlist(path, &attrList, &m, sizeof m, FSOPT_NOFOLLOW);
  167: # else
  168: 		code = 1;
  169: # endif
  170: 	} else
  171: 		code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
  172: #endif /* !HAVE_LCHMOD */
  173: 	if (code != 0 && (preserve_perms || preserve_executability))
  174: 		return code;
  175: 	return 0;
  176: }
  177: #endif
  178: 
  179: int do_rename(const char *fname1, const char *fname2)
  180: {
  181: 	if (dry_run) return 0;
  182: 	RETURN_ERROR_IF_RO_OR_LO;
  183: 	return rename(fname1, fname2);
  184: }
  185: 
  186: #ifdef HAVE_FTRUNCATE
  187: int do_ftruncate(int fd, OFF_T size)
  188: {
  189: 	int ret;
  190: 
  191: 	if (dry_run) return 0;
  192: 	RETURN_ERROR_IF_RO_OR_LO;
  193: 
  194: 	do {
  195: 		ret = ftruncate(fd, size);
  196: 	} while (ret < 0 && errno == EINTR);
  197: 
  198: 	return ret;
  199: }
  200: #endif
  201: 
  202: void trim_trailing_slashes(char *name)
  203: {
  204: 	int l;
  205: 	/* Some BSD systems cannot make a directory if the name
  206: 	 * contains a trailing slash.
  207: 	 * <http://www.opensource.apple.com/bugs/X/BSD%20Kernel/2734739.html> */
  208: 
  209: 	/* Don't change empty string; and also we can't improve on
  210: 	 * "/" */
  211: 
  212: 	l = strlen(name);
  213: 	while (l > 1) {
  214: 		if (name[--l] != '/')
  215: 			break;
  216: 		name[l] = '\0';
  217: 	}
  218: }
  219: 
  220: int do_mkdir(char *fname, mode_t mode)
  221: {
  222: 	if (dry_run) return 0;
  223: 	RETURN_ERROR_IF_RO_OR_LO;
  224: 	trim_trailing_slashes(fname);
  225: 	return mkdir(fname, mode);
  226: }
  227: 
  228: /* like mkstemp but forces permissions */
  229: int do_mkstemp(char *template, mode_t perms)
  230: {
  231: 	RETURN_ERROR_IF(dry_run, 0);
  232: 	RETURN_ERROR_IF(read_only, EROFS);
  233: 	perms |= S_IWUSR;
  234: 
  235: #if defined HAVE_SECURE_MKSTEMP && defined HAVE_FCHMOD && (!defined HAVE_OPEN64 || defined HAVE_MKSTEMP64)
  236: 	{
  237: 		int fd = mkstemp(template);
  238: 		if (fd == -1)
  239: 			return -1;
  240: 		if (fchmod(fd, perms) != 0 && preserve_perms) {
  241: 			int errno_save = errno;
  242: 			close(fd);
  243: 			unlink(template);
  244: 			errno = errno_save;
  245: 			return -1;
  246: 		}
  247: #if defined HAVE_SETMODE && O_BINARY
  248: 		setmode(fd, O_BINARY);
  249: #endif
  250: 		return fd;
  251: 	}
  252: #else
  253: 	if (!mktemp(template))
  254: 		return -1;
  255: 	return do_open(template, O_RDWR|O_EXCL|O_CREAT, perms);
  256: #endif
  257: }
  258: 
  259: int do_stat(const char *fname, STRUCT_STAT *st)
  260: {
  261: #ifdef USE_STAT64_FUNCS
  262: 	return stat64(fname, st);
  263: #else
  264: 	return stat(fname, st);
  265: #endif
  266: }
  267: 
  268: int do_lstat(const char *fname, STRUCT_STAT *st)
  269: {
  270: #ifdef SUPPORT_LINKS
  271: # ifdef USE_STAT64_FUNCS
  272: 	return lstat64(fname, st);
  273: # else
  274: 	return lstat(fname, st);
  275: # endif
  276: #else
  277: 	return do_stat(fname, st);
  278: #endif
  279: }
  280: 
  281: int do_fstat(int fd, STRUCT_STAT *st)
  282: {
  283: #ifdef USE_STAT64_FUNCS
  284: 	return fstat64(fd, st);
  285: #else
  286: 	return fstat(fd, st);
  287: #endif
  288: }
  289: 
  290: OFF_T do_lseek(int fd, OFF_T offset, int whence)
  291: {
  292: #ifdef HAVE_LSEEK64
  293: #if !SIZEOF_OFF64_T
  294: 	OFF_T lseek64();
  295: #else
  296: 	off64_t lseek64();
  297: #endif
  298: 	return lseek64(fd, offset, whence);
  299: #else
  300: 	return lseek(fd, offset, whence);
  301: #endif
  302: }
  303: 
  304: #ifdef HAVE_UTIMENSAT
  305: int do_utimensat(const char *fname, time_t modtime, uint32 mod_nsec)
  306: {
  307: 	struct timespec t[2];
  308: 
  309: 	if (dry_run) return 0;
  310: 	RETURN_ERROR_IF_RO_OR_LO;
  311: 
  312: 	t[0].tv_sec = 0;
  313: 	t[0].tv_nsec = UTIME_NOW;
  314: 	t[1].tv_sec = modtime;
  315: 	t[1].tv_nsec = mod_nsec;
  316: 	return utimensat(AT_FDCWD, fname, t, AT_SYMLINK_NOFOLLOW);
  317: }
  318: #endif
  319: 
  320: #ifdef HAVE_LUTIMES
  321: int do_lutimes(const char *fname, time_t modtime, uint32 mod_nsec)
  322: {
  323: 	struct timeval t[2];
  324: 
  325: 	if (dry_run) return 0;
  326: 	RETURN_ERROR_IF_RO_OR_LO;
  327: 
  328: 	t[0].tv_sec = time(NULL);
  329: 	t[0].tv_usec = 0;
  330: 	t[1].tv_sec = modtime;
  331: 	t[1].tv_usec = mod_nsec / 1000;
  332: 	return lutimes(fname, t);
  333: }
  334: #endif
  335: 
  336: #ifdef HAVE_UTIMES
  337: int do_utimes(const char *fname, time_t modtime, uint32 mod_nsec)
  338: {
  339: 	struct timeval t[2];
  340: 
  341: 	if (dry_run) return 0;
  342: 	RETURN_ERROR_IF_RO_OR_LO;
  343: 
  344: 	t[0].tv_sec = time(NULL);
  345: 	t[0].tv_usec = 0;
  346: 	t[1].tv_sec = modtime;
  347: 	t[1].tv_usec = mod_nsec / 1000;
  348: 	return utimes(fname, t);
  349: }
  350: 
  351: #elif defined HAVE_UTIME
  352: int do_utime(const char *fname, time_t modtime, UNUSED(uint32 mod_nsec))
  353: {
  354: #ifdef HAVE_STRUCT_UTIMBUF
  355: 	struct utimbuf tbuf;
  356: #else
  357: 	time_t t[2];
  358: #endif
  359: 
  360: 	if (dry_run) return 0;
  361: 	RETURN_ERROR_IF_RO_OR_LO;
  362: 
  363: # ifdef HAVE_STRUCT_UTIMBUF
  364: 	tbuf.actime = time(NULL);
  365: 	tbuf.modtime = modtime;
  366: 	return utime(fname, &tbuf);
  367: # else
  368: 	t[0] = time(NULL);
  369: 	t[1] = modtime;
  370: 	return utime(fname, t);
  371: # endif
  372: }
  373: 
  374: #else
  375: #error Need utimes or utime function.
  376: #endif

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