Пример #1
0
/**
 * set the stat() data of a file
 **/
int setfile(const char *path, struct stat *fs)
{
	DBG_IN();

	struct utimbuf ut;
	int rval;

	rval = 0;
	fs->st_mode &= S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO;

	ut.actime  = fs->st_atime;
	ut.modtime = fs->st_mtime;
	if (utime(path, &ut)) {
		usyslog(LOG_WARNING,   "utimes: %s", path);
		rval = 1;
	}
	/*
	* Changing the ownership probably won't succeed, unless we're root
	* or POSIX_CHOWN_RESTRICTED is not set.  Set uid/gid before setting
	* the mode; current BSD behavior is to remove all setuid bits on
	* chown.  If chown fails, lose setuid/setgid bits.
	*/
	if (chown(path, fs->st_uid, fs->st_gid)) {
		if (errno != EPERM) {
			usyslog(LOG_WARNING,   "chown: %s", path);
			rval = 1;
		}
		fs->st_mode &= ~(S_ISTXT | S_ISUID | S_ISGID);
	}
	
	if (chmod(path, fs->st_mode)) {
		usyslog(LOG_WARNING,   "chown: %s", path);
		rval = 1;
	}

#ifdef HAVE_CHFLAGS
		/*
		 * XXX
		 * NFS doesn't support chflags; ignore errors unless there's reason
		 * to believe we're losing bits.  (Note, this still won't be right
		 * if the server supports flags and we were trying to *remove* flags
		 * on a file that we copied, i.e., that we didn't create.)
		 */
		errno = 0;
		if (chflags(path, fs->st_flags)) {
			if (errno != EOPNOTSUPP || fs->st_flags != 0) {
				usyslog(LOG_WARNING,   "chflags: %s", path);
				rval = 1;
			}
			return (rval);
		}
#endif
	return 0;
}
Пример #2
0
/**
 * copy a special file, actually we recreate this file and only copy
 * its stat() data
 */
int copy_special(struct cow *cow)
{
	DBG_IN();

	if (mknod(cow->to_path, cow->stat->st_mode, cow->stat->st_rdev)) {
		usyslog(LOG_WARNING,   "mknod: %s", cow->to_path);
		return (1);
	}
	return setfile(cow->to_path, cow->stat);
}
Пример #3
0
/**
 * copy a fifo, actually we recreate the fifo and only copy
 * its stat() data
 **/
int copy_fifo(struct cow *cow)
{
	DBG_IN();

	if (mkfifo(cow->to_path, cow->stat->st_mode)) {
		usyslog(LOG_WARNING,   "mkfifo: %s", cow->to_path);
		return (1);
	}
	return setfile(cow->to_path, cow->stat);
}
Пример #4
0
/**
 * copy a link, actually we recreate the link and only copy its stat() data.
 */
int copy_link(struct cow *cow)
{
	DBG_IN();

	int len;
	char link[PATHLEN_MAX];

	if ((len = readlink(cow->from_path, link, sizeof(link)-1)) == -1) {
		usyslog(LOG_WARNING,   "readlink: %s", cow->from_path);
		return (1);
	}

	link[len] = '\0';
	
	if (symlink(link, cow->to_path)) {
		usyslog(LOG_WARNING,   "symlink: %s", link);
		return (1);
	}
	
	return setlink(cow->to_path, cow->stat);
}
Пример #5
0
/**
 * set the stat() data of a link
 **/
static int setlink(const char *path, struct stat *fs)
{
	DBG_IN();

	if (lchown(path, fs->st_uid, fs->st_gid)) {
		if (errno != EPERM) {
			usyslog(LOG_WARNING,   "lchown: %s", path);
			return (1);
		}
	}
	return (0);
}
Пример #6
0
/**
 * initiate the cow-copy action
 */
int cow_cp(const char *path, int branch_ro, int branch_rw) {
	DBG_IN();

	// create the path to the file
	path_create_cutlast(path, branch_ro, branch_rw);

	char from[PATHLEN_MAX], to[PATHLEN_MAX];
	snprintf(from, PATHLEN_MAX, "%s%s", uopt.branches[branch_ro].path, path);
	snprintf(to, PATHLEN_MAX, "%s%s", uopt.branches[branch_rw].path, path);

	setlocale(LC_ALL, "");

	struct cow cow;

	cow.uid = getuid();

	// Copy the umask for explicit mode setting.
	cow.umask = umask(0);
	umask(cow.umask);

	cow.from_path = from;
	cow.to_path = to;

	struct stat buf;
	lstat(cow.from_path, &buf);
	cow.stat = &buf;

	int res;
	switch (buf.st_mode & S_IFMT) {
		case S_IFLNK:
			res = copy_link(&cow);
			break;
		case S_IFDIR:
			res = copy_directory(path, branch_ro, branch_rw);
			break;
		case S_IFBLK:
		case S_IFCHR:
			res = copy_special(&cow);
			break;
		case S_IFIFO:
			res = copy_fifo(&cow);
			break;
		case S_IFSOCK:
			usyslog(LOG_WARNING, "COW of sockets not supported: %s\n", cow.from_path);
			return 1;
		default:
			res = copy_file(&cow);
	}

	return res;
}
Пример #7
0
/**
 * Actually create the directory here.
 */
static int do_create(const char *path, int nbranch_ro, int nbranch_rw) {
	DBG_IN();

	char dirp[PATHLEN_MAX]; // dir path to create
	sprintf(dirp, "%s%s", uopt.branches[nbranch_rw].path, path);

	struct stat buf;
	int res = stat(dirp, &buf);
	if (res != -1) return 0; // already exists

	if (nbranch_ro == nbranch_rw) {
		// special case nbranch_ro = nbranch_rw, this is if we a create
		// unionfs meta directories, so not directly on cow operations
		buf.st_mode = S_IRWXU | S_IRWXG;
	} else {
		// data from the ro-branch
		char o_dirp[PATHLEN_MAX]; // the pathname we want to copy
		sprintf(o_dirp, "%s%s", uopt.branches[nbranch_ro].path, path);
		res = stat(o_dirp, &buf);
		if (res == -1) return 1; // lower level branch removed in the mean time?
	}

	res = mkdir(dirp, buf.st_mode);
	if (res == -1) {
		usyslog(LOG_DAEMON, "Creating %s failed: \n", dirp);
		return 1;
	}

	if (nbranch_ro == nbranch_rw) return 0; // the special case again

	if (setfile(dirp, &buf))  return 1; // directory already removed by another process?

	// TODO: time, but its values are modified by the next dir/file creation steps?

	return 0;
}
Пример #8
0
int lpc31_usbhost_initialize(void)
{
  pid_t pid;
  int ret;

  /* First, register all of the class drivers needed to support the drivers
   * that we care about
   */

#ifdef CONFIG_USBHOST_HUB
  /* Initialize USB hub support */

  ret = usbhost_hub_initialize();
  if (ret < 0)
    {
      syslog(LOG_ERR, "ERROR: usbhost_hub_initialize failed: %d\n", ret);
    }
#endif

#ifdef CONFIG_USBHOST_MSC
  /* Register the USB host Mass Storage Class */

  ret = usbhost_msc_initialize();
  if (ret != OK)
    {
      usyslog(LOG_ERR, "ERROR: Failed to register the mass storage class: %d\n", ret);
    }
#endif

#ifdef CONFIG_USBHOST_CDCACM
  /* Register the CDC/ACM serial class */

  ret = usbhost_cdcacm_initialize();
  if (ret != OK)
    {
      uerr("ERROR: Failed to register the CDC/ACM serial class\n");
    }
#endif

#ifdef CONFIG_USBHOST_HIDKBD
  /* Register the USB host HID keyboard class driver */

  ret = usbhost_kbdinit();
  if (ret != OK)
    {
      uerr("ERROR: Failed to register the KBD class\n");
    }
#endif

  /* Then get an instance of the USB EHCI interface. */

  g_ehciconn = lpc31_ehci_initialize(0);
  if (!g_ehciconn)
    {
      uerr("ERROR: lpc31_ehci_initialize failed\n");
      return -ENODEV;
    }

  /* Start a thread to handle device connection. */

  pid = kthread_create("EHCI Monitor", CONFIG_USBHOST_DEFPRIO,
                       CONFIG_USBHOST_STACKSIZE,
                       (main_t)ehci_waiter, (FAR char * const *)NULL);
  if (pid < 0)
    {
      uerr("ERROR: Failed to create ehci_waiter task: %d\n", ret);
      return -ENODEV;
    }

  return OK;
}
Пример #9
0
/**
 * copy an ordinary file with all of its stat() data
 **/
int copy_file(struct cow *cow)
{
	DBG_IN();

	static char buf[MAXBSIZE];
	struct stat to_stat, *fs;
	int from_fd, rcount, to_fd, wcount;
	int rval = 0;
#ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED
	char *p;
#endif

	if ((from_fd = open(cow->from_path, O_RDONLY, 0)) == -1) {
		usyslog(LOG_WARNING, "%s", cow->from_path);
		return (1);
	}

	fs = cow->stat;

	to_fd = open(cow->to_path, O_WRONLY | O_TRUNC | O_CREAT,
	             fs->st_mode & ~(S_ISTXT | S_ISUID | S_ISGID));

	if (to_fd == -1) {
		usyslog(LOG_WARNING, "%s", cow->to_path);
		(void)close(from_fd);
		return (1);
	}

	/*
	 * Mmap and write if less than 8M (the limit is so we don't totally
	 * trash memory on big files.  This is really a minor hack, but it
	 * wins some CPU back.
	 */
#ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED
	if (fs->st_size > 0 && fs->st_size <= 8 * 1048576) {
		if ((p = mmap(NULL, (size_t)fs->st_size, PROT_READ,
		    MAP_FILE|MAP_SHARED, from_fd, (off_t)0)) == MAP_FAILED) {
			usyslog(LOG_WARNING,   "mmap: %s", cow->from_path);
			rval = 1;
		} else {
			madvise(p, fs->st_size, MADV_SEQUENTIAL);
			if (write(to_fd, p, fs->st_size) != fs->st_size) {
				usyslog(LOG_WARNING,   "%s", cow->to_path);
				rval = 1;
			}
			/* Some systems don't unmap on close(2). */
			if (munmap(p, fs->st_size) < 0) {
				usyslog(LOG_WARNING,   "%s", cow->from_path);
				rval = 1;
			}
		}
	} else
#endif
	{
		while ((rcount = read(from_fd, buf, MAXBSIZE)) > 0) {
			wcount = write(to_fd, buf, rcount);
			if (rcount != wcount || wcount == -1) {
				usyslog(LOG_WARNING,   "%s", cow->to_path);
				rval = 1;
				break;
			}
		}
		if (rcount < 0) {
			usyslog(LOG_WARNING,   "copy failed: %s", cow->from_path);
			return 1;
		}
	}

	if (rval == 1) {
		(void)close(from_fd);
		(void)close(to_fd);
		return (1);
	}

	if (setfile(cow->to_path, cow->stat))
		rval = 1;
	/*
	 * If the source was setuid or setgid, lose the bits unless the
	 * copy is owned by the same user and group.
	 */
#define	RETAINBITS \
	(S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
	else if (fs->st_mode & (S_ISUID | S_ISGID) && fs->st_uid == cow->uid) {
		if (fstat(to_fd, &to_stat)) {
			usyslog(LOG_WARNING,   "%s", cow->to_path);
			rval = 1;
		} else if (fs->st_gid == to_stat.st_gid &&
		    fchmod(to_fd, fs->st_mode & RETAINBITS & ~cow->umask)) {
			usyslog(LOG_WARNING,   "%s", cow->to_path);
			rval = 1;
		}
	}
	(void)close(from_fd);
	if (close(to_fd)) {
		usyslog(LOG_WARNING,   "%s", cow->to_path);
		rval = 1;
	}
	
	return (rval);
}