コード例 #1
0
rtems_task Init(
  rtems_task_argument argument
)
{
  int status = 0;
  void *alloc_ptr = (void *)0;
  char linkname_n[20] = {0};
  char linkname_p[20] = {0};
  int i;
  struct stat stat_buf;

  puts( "\n\n*** TEST IMFS 02 ***" );

  puts( "Creating directory /dir00" );
  status = mkdir( "/dir00", S_IRWXU );
  rtems_test_assert( status == 0 );

  puts( "Creating directory /dir00/dir01" );
  status = mkdir( "/dir00/dir01", S_IRWXU );
  rtems_test_assert( status == 0 );

  puts( "Changing directory to /dir00" );
  status = chdir( "/dir00" );
  rtems_test_assert( status == 0 );

  puts( "Creating link dir01-link0 for dir01" );
  status = link( "dir01", "dir01-link0" );
  rtems_test_assert( status == 0 );

  for( i = 1 ; ; ++i ) {
    sprintf( linkname_p, "dir01-link%d", i-1 );
    sprintf( linkname_n, "dir01-link%d", i );
    printf( "\nCreating link %s for %s\n", linkname_n, linkname_p );
    status = link( linkname_p, linkname_n );
    if( status != 0 ) {
      puts("Link creation failed" );
      break;
    }
  }

  puts( "Creating a regular node /node, RDONLY" );
  status = mknod( "/node", S_IFREG | S_IRUSR, 0LL );
  rtems_test_assert( status == 0 );

  puts( "Creating link /node-link for /node" );
  status = link( "/node" , "/node-link" );
  rtems_test_assert( status == 0 );

  puts( "Opening /node-link in WRONLY mode -- expect EACCES" );
  status = open( "/node-link", O_WRONLY );
  rtems_test_assert( status == -1 );
  rtems_test_assert( errno == EACCES );

  puts( "Creating a symlink /node-slink for /node" );
  status = symlink( "/node" , "/node-slink" );
  rtems_test_assert( status == 0 );

  puts( "Opening /node-slink in WRONLY mode -- expect EACCES" );  
  status = open( "/node-slink", O_WRONLY );
  rtems_test_assert( status == -1 );
  rtems_test_assert( errno == EACCES );

  puts( "Allocate most of heap" );
  alloc_ptr = malloc( malloc_free_space() - 150 );

  puts( "Attempt to mount a fs at /dir01 -- expect ENOMEM" );
  status = mount( NULL,
		  "dir01",
		  "imfs",
		  RTEMS_FILESYSTEM_READ_WRITE,
		  NULL );
  rtems_test_assert( status == -1 );
  rtems_test_assert( errno == ENOMEM );

  puts( "Freeing allocated memory" );
  free( alloc_ptr );

  puts( "Allocate most of heap" );
  alloc_ptr = malloc( malloc_free_space() - 4 );

  puts( "Changing directory to /" );
  status = chdir( "/" );
  rtems_test_assert( status == 0 );

  puts( "Attempt to create /node-link-2 for /node -- expect ENOMEM" );
  status = link( "/node", "/node-link-2" );
  rtems_test_assert( status == -1 );
  rtems_test_assert( errno == ENOMEM );

  puts( "Attempt to create /node-slink-2 for /node -- expect ENOMEM" );
  status = symlink( "/node", "node-slink-2" );
  rtems_test_assert( status == -1 );
  rtems_test_assert( errno == ENOMEM );

  puts( "Freeing allocated memory" );
  free( alloc_ptr );

  puts( "Allocate most of heap" );
  alloc_ptr = malloc( malloc_free_space() - 40 );

  puts( "Attempt to create /node-slink-2 for /node -- expect ENOMEM" );
  status = symlink( "/node", "node-slink-2" );
  rtems_test_assert( status == -1 );
  rtems_test_assert( errno == ENOMEM );

  puts( "Freeing allocated memory" );
  free( alloc_ptr );

  puts( "Attempt to stat a hardlink -- expect ENOTSUP" );
  status = lstat( "/node-link", &stat_buf );
  rtems_test_assert( status == -1 );
  rtems_test_assert( errno == ENOTSUP );

  puts( "Changing euid to 10" );
  status = seteuid( 10 );
  rtems_test_assert( status == 0 );

#if defined(RTEMS_POSIX_API)
  puts( "Attempt chmod on /node -- expect EPERM" );
  status = chmod( "/node", S_IRUSR );
  rtems_test_assert( status == -1 );
  rtems_test_assert( errno == EPERM );

  puts( "Attempt chown on /node -- expect EPERM" );
  status = chown( "/node", 10, 10 );
  rtems_test_assert( status == -1 );
  rtems_test_assert( errno == EPERM );
#else
  puts( "Attempt chmod on /node -- EPERM only when POSIX enabled" );
  puts( "Attempt chown on /node -- EPERM only when POSIX enabled" );
#endif

  puts( "Changing euid back to 0 [root]" );
  status = seteuid( 0 );
  rtems_test_assert( status == 0 );

  puts( "Creating a fifo -- OK" );
  status = mkfifo( "/fifo", S_IRWXU );
  rtems_test_assert( status == 0 );

  IMFS_dump();
  
  puts( "chown /fifo to 10 -- OK" );
  status = chown( "/fifo", 10, 10 );
  rtems_test_assert( status == 0 );

  puts( "Changing euid to 10" );
  status = seteuid( 10 );
  rtems_test_assert( status == 0 );

  puts( "chmod /fifo -- OK" );
  status = chmod( "/fifo", S_IRWXU );
  rtems_test_assert( status == 0 );

  printk( "chown /fifo to %o -- OK", 0 );
  status = chown( "/fifo", 0, 0 );
  rtems_test_assert( status == 0 );

  puts( "*** END OF TEST IMFS 02 ***" );
  rtems_test_exit(0);
}
コード例 #2
0
int
main(int argc, char **argv)
{
	struct	dialup	*dial;
	struct	dialup	dent;
	struct	stat	sb;
	FILE	*fp;
	char	*sh = 0;
	char	*cp;
	char	pass[BUFSIZ];
	int	fd;
	int	found = 0;
	int	opt;

	Prog = Basename(argv[0]);

	setlocale(LC_ALL, "");
	bindtextdomain(PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);

	openlog(Prog, LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH);

	while ((opt = getopt (argc, argv, "a:d:")) != EOF) {
		switch (opt) {
			case 'a':
				aflg++;
				sh = optarg;
				break;
			case 'd':
				dflg++;
				sh = optarg;
				break;
			default:
				usage ();
		}
	}
	if (! aflg && ! dflg)
		aflg++;

	if (! sh) {
		if (optind >= argc)
			usage ();
		else
			sh = argv[optind];
	}
	if (aflg + dflg != 1)
		usage ();

	/*
	 * Add a new shell to the password file, or update an existing
	 * entry.  Begin by getting an encrypted password for this
	 * shell.
	 */

	if (aflg) {
		int	tries = 3;

		dent.du_shell = sh;
		dent.du_passwd = "";  /* XXX warning: const */

again:
		if (! (cp = getpass(_("Shell password: "******"re-enter Shell password: "******"%s: Passwords do not match, try again.\n"),
				Prog);

			if (--tries)
				goto again;

			exit(1);
		}
		strzero(cp);
		dent.du_passwd = pw_encrypt(pass, crypt_make_salt());
		strzero(pass);
	}

	/*
	 * Create the temporary file for the updated dialup password
	 * information to be placed into.  Turn it into a (FILE *)
	 * for use by putduent().
	 */

	if ((fd = open (DTMP, O_CREAT|O_EXCL|O_RDWR, 0600)) < 0) {
		snprintf(pass, sizeof pass, _("%s: can't create %s"), Prog, DTMP);
		perror (pass);
		exit (1);
	}
	if (! (fp = fdopen (fd, "r+"))) {
		snprintf(pass, sizeof pass, _("%s: can't open %s"), Prog, DTMP);
		perror (pass);
		unlink (DTMP);
		exit (1);
	}

	/*
	 * Scan the dialup password file for the named entry,
	 * copying out other entries along the way.  Copying
	 * stops when a match is found or the file runs out.
	 */

	while ((dial = getduent ())) {
		if (strcmp (dial->du_shell, sh) == 0) {
			found = 1;
			break;
		}
		if (putduent (dial, fp))
			goto failure;
	}

	/*
	 * To delete the entry, just don't copy it.  To update
	 * the entry, output the modified version - works with
	 * new entries as well.
	 */

	if (dflg && ! found) {
		fprintf(stderr, _("%s: Shell %s not found.\n"), Prog, sh);
		goto failure;
	}
	if (aflg)
		if (putduent (&dent, fp))
			goto failure;

	/*
	 * Now copy out the remaining entries.  Flush and close the
	 * new file before doing anything nasty to the existing
	 * file.
	 */


	while ((dial = getduent ()))
		if (putduent (dial, fp))
			goto failure;

	if (fflush (fp))
		goto failure;

	fclose (fp);

	/*
	 * If the original file did not exist, we must create a new
	 * file with owner "root" and mode 400.  Otherwise we copy
	 * the modes from the existing file to the new file.
	 *
	 * After this is done the new file will replace the old file.
	 */

	pwd_init();

	if (! stat (DIALPWD, &sb)) {
		chown (DTMP, sb.st_uid, sb.st_gid);
		chmod (DTMP, sb.st_mode);
		unlink (DIALPWD);
	} else {
		chown (DTMP, 0, 0);
		chmod (DTMP, 0400);
	}
	if (! link (DTMP, DIALPWD))
		unlink (DTMP);

	if (aflg && ! found)
		SYSLOG((LOG_INFO, DIALADD, sh));
	else if (aflg && found)
		SYSLOG((LOG_INFO, DIALCHG, sh));
	else if (dflg)
		SYSLOG((LOG_INFO, DIALREM, sh));

	closelog();
	sync ();
	exit (0);

failure:
	unlink (DTMP);
	closelog();
	exit (1);
}
コード例 #3
0
ファイル: udev-node.c プロジェクト: RaghavanSanthanam/systemd
static int node_permissions_apply(struct udev_device *dev, bool apply,
                                  mode_t mode, uid_t uid, gid_t gid,
                                  struct udev_list *seclabel_list) {
        const char *devnode = udev_device_get_devnode(dev);
        dev_t devnum = udev_device_get_devnum(dev);
        struct stat stats;
        struct udev_list_entry *entry;
        int err = 0;

        if (streq(udev_device_get_subsystem(dev), "block"))
                mode |= S_IFBLK;
        else
                mode |= S_IFCHR;

        if (lstat(devnode, &stats) != 0) {
                err = -errno;
                log_debug_errno(errno, "can not stat() node '%s' (%m)", devnode);
                goto out;
        }

        if (((stats.st_mode & S_IFMT) != (mode & S_IFMT)) || (stats.st_rdev != devnum)) {
                err = -EEXIST;
                log_debug("found node '%s' with non-matching devnum %s, skip handling",
                          udev_device_get_devnode(dev), udev_device_get_id_filename(dev));
                goto out;
        }

        if (apply) {
                bool selinux = false;
                bool smack = false;

                if ((stats.st_mode & 0777) != (mode & 0777) || stats.st_uid != uid || stats.st_gid != gid) {
                        log_debug("set permissions %s, %#o, uid=%u, gid=%u", devnode, mode, uid, gid);
                        err = chmod(devnode, mode);
                        if (err < 0)
                                log_warning_errno(errno, "setting mode of %s to %#o failed: %m", devnode, mode);
                        err = chown(devnode, uid, gid);
                        if (err < 0)
                                log_warning_errno(errno, "setting owner of %s to uid=%u, gid=%u failed: %m", devnode, uid, gid);
                } else {
                        log_debug("preserve permissions %s, %#o, uid=%u, gid=%u", devnode, mode, uid, gid);
                }

                /* apply SECLABEL{$module}=$label */
                udev_list_entry_foreach(entry, udev_list_get_entry(seclabel_list)) {
                        const char *name, *label;
                        int r;

                        name = udev_list_entry_get_name(entry);
                        label = udev_list_entry_get_value(entry);

                        if (streq(name, "selinux")) {
                                selinux = true;

                                r = mac_selinux_apply(devnode, label);
                                if (r < 0)
                                        log_error_errno(r, "SECLABEL: failed to set SELinux label '%s': %m", label);
                                else
                                        log_debug("SECLABEL: set SELinux label '%s'", label);

                        } else if (streq(name, "smack")) {
                                smack = true;

                                r = mac_smack_apply(devnode, label);
                                if (r < 0)
                                        log_error_errno(r, "SECLABEL: failed to set SMACK label '%s': %m", label);
                                else
                                        log_debug("SECLABEL: set SMACK label '%s'", label);

                        } else
                                log_error("SECLABEL: unknown subsystem, ignoring '%s'='%s'", name, label);
                }

                /* set the defaults */
                if (!selinux)
                        mac_selinux_fix(devnode, true, false);
                if (!smack)
                        mac_smack_apply(devnode, NULL);
        }

        /* always update timestamp when we re-use the node, like on media change events */
        utimensat(AT_FDCWD, devnode, NULL, 0);
out:
        return err;
}
コード例 #4
0
ファイル: copy_file.c プロジェクト: emuikernel/WNR2000v4
int copy_file(const char *source, const char *dest, int flags)
{
	struct stat source_stat;
	struct stat dest_stat;
	int status = 0;
	signed char dest_exists = 0;
	signed char ovr;

#define FLAGS_DEREF (flags & FILEUTILS_DEREFERENCE)

	if ((FLAGS_DEREF ? stat : lstat)(source, &source_stat) < 0) {
		// This may be a dangling symlink.
		// Making [sym]links to dangling symlinks works, so...
		if (flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK))
			goto make_links;
		bb_perror_msg("cannot stat '%s'", source);
		return -1;
	}

	if (lstat(dest, &dest_stat) < 0) {
		if (errno != ENOENT) {
			bb_perror_msg("cannot stat '%s'", dest);
			return -1;
		}
	} else {
		if (source_stat.st_dev == dest_stat.st_dev
		 && source_stat.st_ino == dest_stat.st_ino
		) {
			bb_error_msg("'%s' and '%s' are the same file", source, dest);
			return -1;
		}
		dest_exists = 1;
	}

	if (S_ISDIR(source_stat.st_mode)) {
		DIR *dp;
		struct dirent *d;
		mode_t saved_umask = 0;

		if (!(flags & FILEUTILS_RECUR)) {
			bb_error_msg("omitting directory '%s'", source);
			return -1;
		}

		/* Create DEST.  */
		if (dest_exists) {
			if (!S_ISDIR(dest_stat.st_mode)) {
				bb_error_msg("target '%s' is not a directory", dest);
				return -1;
			}
		} else {
			mode_t mode;
			saved_umask = umask(0);

			mode = source_stat.st_mode;
			if (!(flags & FILEUTILS_PRESERVE_STATUS))
				mode = source_stat.st_mode & ~saved_umask;
			mode |= S_IRWXU;

			if (mkdir(dest, mode) < 0) {
				umask(saved_umask);
				bb_perror_msg("cannot create directory '%s'", dest);
				return -1;
			}

			umask(saved_umask);
		}

		/* Recursively copy files in SOURCE.  */
		dp = opendir(source);
		if (dp == NULL) {
			status = -1;
			goto preserve_status;
		}

		while ((d = readdir(dp)) != NULL) {
			char *new_source, *new_dest;

			new_source = concat_subpath_file(source, d->d_name);
			if (new_source == NULL)
				continue;
			new_dest = concat_path_file(dest, d->d_name);
			if (copy_file(new_source, new_dest, flags) < 0)
				status = -1;
			free(new_source);
			free(new_dest);
		}
		closedir(dp);

		if (!dest_exists
		 && chmod(dest, source_stat.st_mode & ~saved_umask) < 0
		) {
			bb_perror_msg("cannot change permissions of '%s'", dest);
			status = -1;
		}

	} else if (flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK)) {
		int (*lf)(const char *oldpath, const char *newpath);
 make_links:
		// Hmm... maybe
		// if (DEREF && MAKE_SOFTLINK) source = realpath(source) ?
		// (but realpath returns NULL on dangling symlinks...)
		lf = (flags & FILEUTILS_MAKE_SOFTLINK) ? symlink : link;
		if (lf(source, dest) < 0) {
			ovr = retry_overwrite(dest, flags);
			if (ovr <= 0)
				return ovr;
			if (lf(source, dest) < 0) {
				bb_perror_msg("cannot create link '%s'", dest);
				return -1;
			}
		}
		return 0;

	} else if (S_ISREG(source_stat.st_mode)
	// Huh? DEREF uses stat, which never returns links IIRC...
	 || (FLAGS_DEREF && S_ISLNK(source_stat.st_mode))
	) {
		int src_fd;
		int dst_fd;
		if (ENABLE_FEATURE_PRESERVE_HARDLINKS) {
			char *link_name;

			if (!FLAGS_DEREF
			 && is_in_ino_dev_hashtable(&source_stat, &link_name)
			) {
				if (link(link_name, dest) < 0) {
					ovr = retry_overwrite(dest, flags);
					if (ovr <= 0)
						return ovr;
					if (link(link_name, dest) < 0) {
						bb_perror_msg("cannot create link '%s'", dest);
						return -1;
					}
				}
				return 0;
			}
			// TODO: probably is_in_.. and add_to_...
			// can be combined: find_or_add_...
			add_to_ino_dev_hashtable(&source_stat, dest);
		}

		src_fd = open(source, O_RDONLY);
		if (src_fd == -1) {
			bb_perror_msg("cannot open '%s'", source);
			return -1;
		}

		// POSIX: if exists and -i, ask (w/o -i assume yes).
		// Then open w/o EXCL.
		// If open still fails and -f, try unlink, then try open again.
		// Result: a mess:
		// If dest is a softlink, we overwrite softlink's destination!
		// (or fail, if it points to dir/nonexistent location/etc).
		// This is strange, but POSIX-correct.
		// coreutils cp has --remove-destination to override this...
		dst_fd = open(dest, (flags & FILEUTILS_INTERACTIVE)
				? O_WRONLY|O_CREAT|O_TRUNC|O_EXCL
				: O_WRONLY|O_CREAT|O_TRUNC, source_stat.st_mode);
		if (dst_fd == -1) {
			// We would not do POSIX insanity. -i asks,
			// then _unlinks_ the offender. Presto.
			// Or else we will end up having 3 open()s!
			ovr = retry_overwrite(dest, flags);
			if (ovr <= 0) {
				close(src_fd);
				return ovr;
			}
			dst_fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, source_stat.st_mode);
			if (dst_fd == -1) {
				bb_perror_msg("cannot open '%s'", dest);
				close(src_fd);
				return -1;
			}
		}

		if (bb_copyfd_eof(src_fd, dst_fd) == -1)
			status = -1;
		if (close(dst_fd) < 0) {
			bb_perror_msg("cannot close '%s'", dest);
			status = -1;
		}
		if (close(src_fd) < 0) {
			bb_perror_msg("cannot close '%s'", source);
			status = -1;
		}

	} else if (S_ISBLK(source_stat.st_mode) || S_ISCHR(source_stat.st_mode)
	 || S_ISSOCK(source_stat.st_mode) || S_ISFIFO(source_stat.st_mode)
	 || S_ISLNK(source_stat.st_mode)
	) {
		// We are lazy here, a bit lax with races...
		if (dest_exists) {
			ovr = retry_overwrite(dest, flags);
			if (ovr <= 0)
				return ovr;
		}
		if (S_ISFIFO(source_stat.st_mode)) {
			if (mkfifo(dest, source_stat.st_mode) < 0) {
				bb_perror_msg("cannot create fifo '%s'", dest);
				return -1;
			}
		} else if (S_ISLNK(source_stat.st_mode)) {
			char *lpath;

			lpath = xreadlink(source);
			if (symlink(lpath, dest) < 0) {
				bb_perror_msg("cannot create symlink '%s'", dest);
				free(lpath);
				return -1;
			}
			free(lpath);

			if (flags & FILEUTILS_PRESERVE_STATUS)
				if (lchown(dest, source_stat.st_uid, source_stat.st_gid) < 0)
					bb_perror_msg("cannot preserve %s of '%s'", "ownership", dest);

			return 0;

		} else {
			if (mknod(dest, source_stat.st_mode, source_stat.st_rdev) < 0) {
				bb_perror_msg("cannot create '%s'", dest);
				return -1;
			}
		}
	} else {
		bb_error_msg("internal error: unrecognized file type");
		return -1;
	}

 preserve_status:

	if (flags & FILEUTILS_PRESERVE_STATUS
	/* Cannot happen: */
	/* && !(flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK)) */
	) {
		struct utimbuf times;

		times.actime = source_stat.st_atime;
		times.modtime = source_stat.st_mtime;
		if (utime(dest, &times) < 0)
			bb_perror_msg("cannot preserve %s of '%s'", "times", dest);
		if (chown(dest, source_stat.st_uid, source_stat.st_gid) < 0) {
			source_stat.st_mode &= ~(S_ISUID | S_ISGID);
			bb_perror_msg("cannot preserve %s of '%s'", "ownership", dest);
		}
		if (chmod(dest, source_stat.st_mode) < 0)
			bb_perror_msg("cannot preserve %s of '%s'", "permissions", dest);
	}

	return status;
}
コード例 #5
0
ファイル: test30.c プロジェクト: Spenser309/CS551
void test30a()
{				/* Test normal operation. */

#define BUF_SIZE 1024

  int fd1, fd2;
  char buf[BUF_SIZE];
  struct stat st, dirst;
  time_t time1, time2;
  int stat_loc, cnt;

  subtest = 1;

  System("rm -rf ../DIR_30/*");

  /* Check if processes have independent new fds */
  switch (fork()) {
      case -1:	printf("Can't fork\n");	break;
      case 0:
	alarm(20);
	if ((fd1 = creat("myfile", 0644)) != 3) e(1);
	if (close(fd1) != 0) e(2);
	exit(0);
      default:
	if ((fd1 = creat("myfile", 0644)) != 3) e(3);
	if (close(fd1) != 0) e(4);
	if (wait(&stat_loc) == -1) e(5);
	if (stat_loc != 0) e(6);
  }

  /* Save the dir status. */
  Stat(".", &dirst);
  time(&time1);
  while (time1 == time((time_t *)0))
	;

  /* Check if the file status information is updated correctly */
  cnt = 0;
  System("rm -rf myfile");
  do {
	time(&time1);
	if ((fd1 = creat("myfile", 0644)) != 3) e(7);
	Stat("myfile", &st);
	time(&time2);
  } while (time1 != time2 && cnt++ < 100);
  if (cnt >= 100) e(8);
  if (st.st_uid != geteuid()) e(9);	/* Uid should be set. */
#if defined(NGROUPS_MAX) && NGROUPS_MAX == 0
  if (st.st_gid != getegid()) e(10);
#endif /* defined(NGROUPS_MAX) && NGROUPS_MAX == 0 */
  if (!S_ISREG(st.st_mode)) e(11);
  if ((st.st_mode & 0777) != 0644) e(12);
  if (st.st_nlink != 1) e(13);
  if (st.st_ctime != time1) e(14);	/* All time fields should be updated */
  if (st.st_atime != time1) e(15);
  if (st.st_mtime != time1) e(16);
  if (st.st_size != 0) e(17);	/* File should be trunked. */

  /* Check if c and mtime for "." is updated. */
  Stat(".", &st);
  if (st.st_ctime <= dirst.st_ctime) e(18);
  if (st.st_mtime <= dirst.st_mtime) e(19);

  /* Let's see if cread fds are write only. */
  if (read(fd1, buf, 7) != -1) e(20);	/* we can't read */
  if (errno != EBADF) e(21);	/* a write only fd */
  if (write(fd1, "HELLO", 6) != 6) e(22);	/* but we can write */

  /* No O_APPEND flag should have been used. */
  if (lseek(fd1, (off_t) 1, SEEK_SET) != 1) e(23);
  if (write(fd1, "ello", 5) != 5) e(24);
  Stat("myfile", &st);
  if (st.st_size != 6) e(25);
  if (st.st_size == 11) e(26);	/* O_APPEND should make it 11. */
  if (close(fd1) != 0) e(27);

  /* A creat should set the file offset to 0. */
  if ((fd1 = creat("myfile", 0644)) != 3) e(28);
  if (lseek(fd1, (off_t) 0, SEEK_CUR) != 0) e(29);
  if (close(fd1) != 0) e(30);

  /* Test if file permission bits and the file ownership are unchanged. */
  /* So we will see if creat() is just an open() if the file exists. */
  if (superuser) {
	System("echo > bar; chmod 073 bar");	/* Make bar 073 */
	if (chown("bar", 1, 1) != 0) e(1137);
	fd1 = creat("bar", 0777);	/* knock knock */
	if (fd1 == -1) e(31);
	Stat("bar", &st);
	if (st.st_size != (size_t) 0) e(32);	/* empty file. */
	if (write(fd1, "foo", 3) != 3) e(33);	/* rewrite bar */
	if (close(fd1) != 0) e(34);
	Stat("bar", &st);
	if (st.st_uid != 1) e(35);
	if (st.st_gid != 1) e(36);
	if ((st.st_mode & 0777) != 073) e(37);	/* mode still is 077 */
	if (st.st_size != (size_t) 3) e(38);
  }

  /* Fifo's should be openable with creat(). */
  if (mkfifo("fifo", 0644) != 0) e(39);

  /* Creat() should have no effect on FIFO files. */
  switch (fork()) {
      case -1:	printf("Can't fork\n");	break;
      case 0:
	alarm(20);		/* Give child 20 seconds to live. */
	if ((fd1 = open("fifo", O_WRONLY)) != 3) e(40);
	if (write(fd1, "I did see Elvis.\n", 18) != 18) e(41);
	if ((fd2 = creat("fifo", 0644)) != 4) e(42);
	if (write(fd2, "I DID.\n", 8) != 8) e(43);
	if (close(fd2) != 0) e(44);
	if (close(fd1) != 0) e(45);
	exit(0);
      default:
	if ((fd1 = open("fifo", O_RDONLY)) != 3) e(46);
	if (read(fd1, buf, 18) != 18) e(47);
	if (strcmp(buf, "I did see Elvis.\n") != 0) e(48);
	if (strcmp(buf, "I DID.\n") == 0) e(49);
	if (read(fd1, buf, BUF_SIZE) != 8) e(50);
	if (strcmp(buf, "I DID.\n") != 0) e(51);
	if (close(fd1) != 0) e(52);
	if (wait(&stat_loc) == -1) e(53);
	if (stat_loc != 0) e(54);	/* The alarm went off? */
  }

  /* Creat() should have no effect on directroys. */
  System("mkdir dir; touch dir/f1 dir/f2 dir/f3");
  if ((fd1 = creat("dir", 0644)) != -1) e(55);
  if (errno != EISDIR) e(56);
  close(fd1);

  /* The path should contain only dirs in the prefix. */
  if ((fd1 = creat("dir/f1/nono", 0644)) != -1) e(57);
  if (errno != ENOTDIR) e(58);
  close(fd1);

  /* The path should contain only dirs in the prefix. */
  if ((fd1 = creat("", 0644)) != -1) e(59);
  if (errno != ENOENT) e(60);
  close(fd1);
  if ((fd1 = creat("dir/noso/nono", 0644)) != -1) e(61);
  if (errno != ENOENT) e(62);
  close(fd1);

}
コード例 #6
0
/* __CFWriteBytesToFileWithAtomicity is a "safe save" facility. Write the bytes using the specified mode on the file to the provided URL. If the atomic flag is true, try to do it in a fashion that will enable a safe save.
 */
static Boolean __CFWriteBytesToFileWithAtomicity(CFURLRef url, const void *bytes, int length, SInt32 mode, Boolean atomic) {
    int fd = -1;
    char auxPath[CFMaxPathSize + 16];
    char cpath[CFMaxPathSize];
    uid_t owner = getuid();
    gid_t group = getgid();
    Boolean writingFileAsRoot = ((getuid() != geteuid()) && (geteuid() == 0));
    
    if (!CFURLGetFileSystemRepresentation(url, true, (uint8_t *)cpath, CFMaxPathSize)) {
        return false;
    }
    
    if (-1 == mode || writingFileAsRoot) {
        struct stat statBuf;
        if (0 == stat(cpath, &statBuf)) {
            mode = statBuf.st_mode;
            owner = statBuf.st_uid;
            group = statBuf.st_gid;
        } else {
            mode = 0664;
            if (writingFileAsRoot && (0 == strncmp(cpath, "/Library/Preferences", 20))) {
                owner = geteuid();
                group = 80;
            }
        }
    }
    
    if (atomic) {
        CFURLRef dir = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorSystemDefault, url);
        CFURLRef tempFile = CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault, dir, CFSTR("cf#XXXXX"), false);
        CFRelease(dir);
        if (!CFURLGetFileSystemRepresentation(tempFile, true, (uint8_t *)auxPath, CFMaxPathSize)) {
            CFRelease(tempFile);
            return false;
        }
        CFRelease(tempFile);
        fd = mkstemp(auxPath);
    } else {
        fd = open(cpath, O_WRONLY|O_CREAT|O_TRUNC, mode);
    }
    
    if (fd < 0) return false;
    
    if (length && (write(fd, bytes, length) != length || fsync(fd) < 0)) {
        int saveerr = thread_errno();
        close(fd);
        if (atomic)
            unlink(auxPath);
        thread_set_errno(saveerr);
        return false;
    }
    
    close(fd);
    
    if (atomic) {
        // preserve the mode as passed in originally
        chmod(auxPath, mode);
                
        if (0 != rename(auxPath, cpath)) {
            unlink(auxPath);
            return false;
        }
        
        // If the file was renamed successfully and we wrote it as root we need to reset the owner & group as they were.
        if (writingFileAsRoot) {
            chown(cpath, owner, group);
        }
    }
    return true;
}
コード例 #7
0
void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
{
	file_header_t *file_header = archive_handle->file_header;
	int dst_fd;
	int res;

	if (archive_handle->ah_flags & ARCHIVE_CREATE_LEADING_DIRS) {
		char *slash = strrchr(file_header->name, '/');
		if (slash) {
			*slash = '\0';
			bb_make_directory(file_header->name, -1, FILEUTILS_RECUR);
			*slash = '/';
		}
	}

	if (archive_handle->ah_flags & ARCHIVE_UNLINK_OLD) {
		/* Remove the entry if it exists */
		if ((!S_ISDIR(file_header->mode))
		 && (unlink(file_header->name) == -1)
		 && (errno != ENOENT)
		) {
			bb_perror_msg_and_die("can't remove old file %s",
					file_header->name);
		}
	}
	else if (archive_handle->ah_flags & ARCHIVE_EXTRACT_NEWER) {
		/* Remove the existing entry if its older than the extracted entry */
		struct stat existing_sb;
		if (lstat(file_header->name, &existing_sb) == -1) {
			if (errno != ENOENT) {
				bb_perror_msg_and_die("can't stat old file");
			}
		}
		else if (existing_sb.st_mtime >= file_header->mtime) {
			if (!(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) {
				bb_error_msg("%s not created: newer or "
					"same age file exists", file_header->name);
			}
			data_skip(archive_handle);
			return;
		}
		else if ((unlink(file_header->name) == -1) && (errno != EISDIR)) {
			bb_perror_msg_and_die("can't remove old file %s",
					file_header->name);
		}
	}

	/* Handle hard links separately
	 * We identified hard links as regular files of size 0 with a symlink */
	if (S_ISREG(file_header->mode)
	 && file_header->link_target
	 && file_header->size == 0
	) {
		/* hard link */
		res = link(file_header->link_target, file_header->name);
		if ((res == -1) && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) {
			bb_perror_msg("can't create %slink "
					"from %s to %s", "hard",
					file_header->name,
					file_header->link_target);
		}
	} else {
		/* Create the filesystem entry */
		switch (file_header->mode & S_IFMT) {
		case S_IFREG: {
			/* Regular file */
			int flags = O_WRONLY | O_CREAT | O_EXCL;
			if (archive_handle->ah_flags & ARCHIVE_O_TRUNC)
				flags = O_WRONLY | O_CREAT | O_TRUNC;
			dst_fd = xopen3(file_header->name,
				flags,
				file_header->mode
				);
			bb_copyfd_exact_size(archive_handle->src_fd, dst_fd, file_header->size);
			close(dst_fd);
			break;
		}
		case S_IFDIR:
			res = mkdir(file_header->name, file_header->mode);
			if ((res == -1)
			 && (errno != EISDIR) /* btw, Linux doesn't return this */
			 && (errno != EEXIST)
			 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
			) {
				bb_perror_msg("can't make dir %s", file_header->name);
			}
			break;
		case S_IFLNK:
			/* Symlink */
			res = symlink(file_header->link_target, file_header->name);
			if ((res == -1)
			 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
			) {
				bb_perror_msg("can't create %slink "
					"from %s to %s", "sym",
					file_header->name,
					file_header->link_target);
			}
			break;
		case S_IFSOCK:
		case S_IFBLK:
		case S_IFCHR:
		case S_IFIFO:
			res = mknod(file_header->name, file_header->mode, file_header->device);
			if ((res == -1)
			 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
			) {
				bb_perror_msg("can't create node %s", file_header->name);
			}
			break;
		default:
			bb_error_msg_and_die("unrecognized file type");
		}
	}

	if (!(archive_handle->ah_flags & ARCHIVE_DONT_RESTORE_OWNER)) {
#if ENABLE_FEATURE_TAR_UNAME_GNAME
		if (!(archive_handle->ah_flags & ARCHIVE_NUMERIC_OWNER)) {
			uid_t uid = file_header->uid;
			gid_t gid = file_header->gid;

			if (file_header->tar__uname) {
//TODO: cache last name/id pair?
				struct passwd *pwd = getpwnam(file_header->tar__uname);
				if (pwd) uid = pwd->pw_uid;
			}
			if (file_header->tar__gname) {
				struct group *grp = getgrnam(file_header->tar__gname);
				if (grp) gid = grp->gr_gid;
			}
			/* GNU tar 1.15.1 uses chown, not lchown */
			chown(file_header->name, uid, gid);
		} else
#endif
			chown(file_header->name, file_header->uid, file_header->gid);
	}
	if (!S_ISLNK(file_header->mode)) {
		/* uclibc has no lchmod, glibc is even stranger -
		 * it has lchmod which seems to do nothing!
		 * so we use chmod... */
		if (!(archive_handle->ah_flags & ARCHIVE_DONT_RESTORE_PERM)) {
			chmod(file_header->name, file_header->mode);
		}
		/* same for utime */
		if (archive_handle->ah_flags & ARCHIVE_RESTORE_DATE) {
			struct timeval t[2];

			t[1].tv_sec = t[0].tv_sec = file_header->mtime;
			t[1].tv_usec = t[0].tv_usec = 0;
			utimes(file_header->name, t);
		}
	}
}
コード例 #8
0
ファイル: install.c プロジェクト: Edwin-Edward/elks
void copylink(char *source, char *dest, int mode, int owner, int group)
{
	struct stat sst, dst;
	int sfd, dfd, n;
	int r, same= 0, change= 0, docopy= 1;
	char buf[4096];
#	define hdr ((struct exec *) buf)
	pid_t pid;
	int status;

	/* Source must exist as a plain file, dest may exist as a plain file. */

	if (stat(source, &sst) < 0) { report(source); return; }

	if (mode == -1) {
		mode= sst.st_mode & 07777;
		if (!lflag || cflag) {
			mode|= 0444;
			if (mode & 0111) mode|= 0111;
		}
	}
	if (owner == -1) owner= sst.st_uid;
	if (group == -1) group= sst.st_gid;

	if (!S_ISREG(sst.st_mode)) {
		fprintf(stderr, "install: %s is not a regular file\n", source);
		excode= 1;
		return;
	}
	r= stat(dest, &dst);
	if (r < 0) {
		if (errno != ENOENT) { report(dest); return; }
	} else {
		if (!S_ISREG(dst.st_mode)) {
			fprintf(stderr, "install: %s is not a regular file\n",
									dest);
			excode= 1;
			return;
		}

		/* Are the files the same? */
		if (sst.st_dev == dst.st_dev && sst.st_ino == dst.st_ino) {
			if (!lflag && cflag) {
				fprintf(stderr,
				"install: %s and %s are the same, can't copy\n",
					source, dest);
				excode= 1;
				return;
			}
			same= 1;
		}
	}

	if (lflag && !same) {
		/* Try to link the files. */

		if (r >= 0 && unlink(dest) < 0) {
			report(dest); return;
		}

		if (link(source, dest) >= 0) {
			docopy= 0;
		} else {
			if (!cflag || errno != EXDEV) {
				fprintf(stderr,
					"install: can't link %s to %s: %s\n",
					source, dest, strerror(errno));
				excode= 1;
				return;
			}
		}
	}

	if (docopy && !same) {
		/* Copy the files, stripping if necessary. */
		long count= LONG_MAX;
		int first= 1;

		if ((sfd= open(source, O_RDONLY)) < 0) {
			report(source); return;
		}

		/* Open for write is less simple, its mode may be 444. */
		dfd= open(dest, O_WRONLY|O_CREAT|O_TRUNC, mode | 0600);
		if (dfd < 0 && errno == EACCES) {
			(void) chmod(dest, mode | 0600);
			dfd= open(dest, O_WRONLY|O_TRUNC);
		}
		if (dfd < 0) {
			report(dest);
			close(sfd);
			return;
		}

		pid= 0;
		while (count > 0 && (n= read(sfd, buf, sizeof(buf))) > 0) {
			if (first && n >= A_MINHDR && !BADMAG(*hdr)) {
				if (strip) {
					count= hdr->a_hdrlen
						+ hdr->a_text + hdr->a_data;
#ifdef A_NSYM
					hdr->a_flags &= ~A_NSYM;
#endif
					hdr->a_syms= 0;
				}
				if (stack != -1 && setstack(hdr)) change= 1;

				if (compress != nil) {
					/* Write first #! line. */
					(void) write(dfd, zcat, strlen(zcat));

					/* Put a compressor in between. */
					if ((pid= filter(dfd, compress)) < 0) {
						close(sfd);
						close(dfd);
						return;
					}
					change= 1;
				}
			}
			if (count < n) n= count;

			if (write(dfd, buf, n) < 0) {
				report(dest);
				close(sfd);
				close(dfd);
				if (pid != 0) (void) waitpid(pid, nil, 0);
				return;
			}
			count-= n;
			first= 0;
		}
		if (n < 0) report(source);
		close(sfd);
		close(dfd);
		if (pid != 0 && waitpid(pid, &status, 0) < 0 || status != 0) {
			excode= 1;
			return;
		}
		if (n < 0) return;
	} else {
		if (stack != -1) {
			/* The file has been linked into place.  Set the
			 * stack size.
			 */
			if ((dfd= open(dest, O_RDWR)) < 0) {
				report(dest);
				return;
			}

			if ((n= read(dfd, buf, sizeof(*hdr))) < 0) {
				report(dest); return;
			}

			if (n >= A_MINHDR && !BADMAG(*hdr) && setstack(hdr)) {
				if (lseek(dfd, (off_t) 0, SEEK_SET) == -1
					|| write(dfd, buf, n) < 0
				) {
					report(dest);
					close(dfd);
					return;
				}
				change= 1;
			}
			close(dfd);
		}
	}

	if (stat(dest, &dst) < 0) { report(dest); return; }

	if ((dst.st_mode & 07777) != mode) {
		if (chmod(dest, mode) < 0) { report(dest); return; }
	}
	if (dst.st_uid != owner || dst.st_gid != group) {
		if (chown(dest, owner, group) < 0 && errno != EPERM) {
			report(dest); return;
		}
		/* Set the mode again, chown may have wrecked it. */
		(void) chmod(dest, mode);
	}
	if (!change) {
		struct utimbuf ubuf;

		ubuf.actime= dst.st_atime;
		ubuf.modtime= sst.st_mtime;

		if (utime(dest, &ubuf) < 0 && errno != EPERM) {
			report(dest); return;
		}
	}
}
コード例 #9
0
ファイル: lpr.c プロジェクト: 2trill2spill/freebsd
int
main(int argc, char *argv[])
{
	struct passwd *pw;
	struct group *gptr;
	const char *arg, *cp, *printer;
	char *p;
	char buf[BUFSIZ];
	int c, i, f, errs;
	int	 ret, didlink;
	struct stat stb;
	struct stat statb1, statb2;
	struct printer myprinter, *pp = &myprinter;

	printer = NULL;
	euid = geteuid();
	uid = getuid();
	PRIV_END
	if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
		signal(SIGHUP, cleanup);
	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
		signal(SIGINT, cleanup);
	if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
		signal(SIGQUIT, cleanup);
	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
		signal(SIGTERM, cleanup);

	progname = argv[0];
	gethostname(local_host, sizeof(local_host));
	openlog("lpd", 0, LOG_LPR);

	errs = 0;
	while ((c = getopt(argc, argv,
			   ":#:1:2:3:4:C:J:L:P:T:U:Z:cdfghi:lnmprstvw:"))
	       != -1)
		switch (c) {
		case '#':		/* n copies */
			i = strtol(optarg, &p, 10);
			if (*p)
				errx(1, "Bad argument to -#, number expected");
			if (i > 0)
				ncopies = i;
			break;

		case '1':		/* troff fonts */
		case '2':
		case '3':
		case '4':
			fonts[optopt - '1'] = optarg;
			break;

		case 'C':		/* classification spec */
			hdr++;
			class = optarg;
			break;

		case 'J':		/* job name */
			hdr++;
			jobname = optarg;
			break;

		case 'P':		/* specifiy printer name */
			printer = optarg;
			break;

		case 'L':               /* pr's locale */
			locale = optarg;
			break;

		case 'T':		/* pr's title line */
			title = optarg;
			break;

		case 'U':		/* user name */
			hdr++;
			Uflag = optarg;
			break;

		case 'Z':
			Zflag = optarg;
			break;

		case 'c':		/* print cifplot output */
		case 'd':		/* print tex output (dvi files) */
		case 'g':		/* print graph(1G) output */
		case 'l':		/* literal output */
		case 'n':		/* print ditroff output */
		case 't':		/* print troff output (cat files) */
		case 'p':		/* print using ``pr'' */
		case 'v':		/* print vplot output */
			format = optopt;
			break;

		case 'f':		/* print fortran output */
			format = 'r';
			break;

		case 'h':		/* nulifiy header page */
			hdr = 0;
			break;

		case 'i':		/* indent output */
			iflag++;
			indent = strtol(optarg, &p, 10);
			if (*p)
				errx(1, "Bad argument to -i, number expected");
			break;

		case 'm':		/* send mail when done */
			mailflg++;
			break;

		case 'q':		/* just queue job */
			qflag++;
			break;

		case 'r':		/* remove file when done */
			rflag++;
			break;

		case 's':		/* try to link files */
			sflag++;
			break;

		case 'w':		/* versatec page width */
			width = optarg;
			break;

		case ':':		/* catch "missing argument" error */
			if (optopt == 'i') {
				iflag++; /* -i without args is valid */
				indent = 8;
			} else
				errs++;
			break;

		default:
			errs++;
		}
	argc -= optind;
	argv += optind;
	if (errs)
		usage();
	if (printer == NULL && (printer = getenv("PRINTER")) == NULL)
		printer = DEFLP;
	chkprinter(printer, pp);
	if (pp->no_copies && ncopies > 1)
		errx(1, "multiple copies are not allowed");
	if (pp->max_copies > 0 && ncopies > pp->max_copies)
		errx(1, "only %ld copies are allowed", pp->max_copies);
	/*
	 * Get the identity of the person doing the lpr using the same
	 * algorithm as lprm.  Actually, not quite -- lprm will override
	 * the login name with "root" if the user is running as root;
	 * the daemon actually checks for the string "root" in its
	 * permission checking.  Sigh.
	 */
	userid = getuid();
	if (Uflag) {
		if (userid != 0 && userid != pp->daemon_user)
			errx(1, "only privileged users may use the `-U' flag");
		lpr_username = Uflag;		/* -U person doing 'lpr' */
	} else {
		lpr_username = getlogin();	/* person doing 'lpr' */
		if (userid != pp->daemon_user || lpr_username == 0) {
			if ((pw = getpwuid(userid)) == NULL)
				errx(1, "Who are you?");
			lpr_username = pw->pw_name;
		}
	}

	/*
	 * Check for restricted group access.
	 */
	if (pp->restrict_grp != NULL && userid != pp->daemon_user) {
		if ((gptr = getgrnam(pp->restrict_grp)) == NULL)
			errx(1, "Restricted group specified incorrectly");
		if (gptr->gr_gid != getgid()) {
			while (*gptr->gr_mem != NULL) {
				if ((strcmp(lpr_username, *gptr->gr_mem)) == 0)
					break;
				gptr->gr_mem++;
			}
			if (*gptr->gr_mem == NULL)
				errx(1, "Not a member of the restricted group");
		}
	}
	/*
	 * Check to make sure queuing is enabled if userid is not root.
	 */
	lock_file_name(pp, buf, sizeof buf);
	if (userid && stat(buf, &stb) == 0 && (stb.st_mode & LFM_QUEUE_DIS))
		errx(1, "Printer queue is disabled");
	/*
	 * Initialize the control file.
	 */
	mktemps(pp);
	tfd = nfile(tfname);
	PRIV_START
	(void) fchown(tfd, pp->daemon_user, -1);
	/* owned by daemon for protection */
	PRIV_END
	card('H', local_host);
	card('P', lpr_username);
	card('C', class);
	if (hdr && !pp->no_header) {
		if (jobname == NULL) {
			if (argc == 0)
				jobname = "stdin";
			else
				jobname = ((arg = strrchr(argv[0], '/'))
					   ? arg + 1 : argv[0]);
		}
		card('J', jobname);
		card('L', lpr_username);
	}
	if (format != 'p' && Zflag != 0)
		card('Z', Zflag);
	if (iflag)
		card('I', itoa(indent));
	if (mailflg)
		card('M', lpr_username);
	if (format == 't' || format == 'n' || format == 'd')
		for (i = 0; i < 4; i++)
			if (fonts[i] != NULL)
				card('1'+i, fonts[i]);
	if (width != NULL)
		card('W', width);
	/*
	 * XXX
	 * Our use of `Z' here is incompatible with LPRng's
	 * use.  We assume that the only use of our existing
	 * `Z' card is as shown for `p' format (pr) files.
	 */
	if (format == 'p') {
		char *s;

		if (locale)
			card('Z', locale);
		else if ((s = setlocale(LC_TIME, "")) != NULL)
			card('Z', s);
	}

	/*
	 * Read the files and spool them.
	 */
	if (argc == 0)
		copy(pp, 0, " ");
	else while (argc--) {
		if (argv[0][0] == '-' && argv[0][1] == '\0') {
			/* use stdin */
			copy(pp, 0, " ");
			argv++;
			continue;
		}
		if ((f = test(arg = *argv++)) < 0)
			continue;	/* file unreasonable */

		if (sflag && (cp = linked(arg)) != NULL) {
			(void)snprintf(buf, sizeof(buf), "%ju %ju",
			    (uintmax_t)statb.st_dev, (uintmax_t)statb.st_ino);
			card('S', buf);
			if (format == 'p')
				card('T', title ? title : arg);
			for (i = 0; i < ncopies; i++)
				card(format, &dfname[inchar-2]);
			card('U', &dfname[inchar-2]);
			if (f)
				card('U', cp);
			card('N', arg);
			dfname[inchar]++;
			nact++;
			continue;
		}
		if (sflag)
			printf("%s: %s: not linked, copying instead\n",
			    progname, arg);

		if (f) {
			/*
			 * The user wants the file removed after it is copied
			 * to the spool area, so see if the file can be moved
			 * instead of copy/unlink'ed.  This is much faster and
			 * uses less spool space than copying the file.  This
			 * can be very significant when running services like
			 * samba, pcnfs, CAP, et al.
			 */
			PRIV_START
			didlink = 0;
			/*
			 * There are several things to check to avoid any
			 * security issues.  Some of these are redundant
			 * under BSD's, but are necessary when lpr is built
			 * under some other OS's (which I do do...)
			 */
			if (lstat(arg, &statb1) < 0)
				goto nohardlink;
			if (S_ISLNK(statb1.st_mode))
				goto nohardlink;
			if (link(arg, dfname) != 0)
				goto nohardlink;
			didlink = 1;
			/*
			 * Make sure the user hasn't tried to trick us via
			 * any race conditions
			 */
			if (lstat(dfname, &statb2) < 0)
				goto nohardlink;
			if (statb1.st_dev != statb2.st_dev)
				goto nohardlink;
			if (statb1.st_ino != statb2.st_ino)
				goto nohardlink;
			/*
			 * Skip if the file already had multiple hard links,
			 * because changing the owner and access-bits would
			 * change ALL versions of the file
			 */
			if (statb2.st_nlink > 2)
				goto nohardlink;
			/*
			 * If we can access and remove the original file
			 * without special setuid-ness then this method is
			 * safe.  Otherwise, abandon the move and fall back
			 * to the (usual) copy method.
			 */
			PRIV_END
			ret = access(dfname, R_OK);
			if (ret == 0)
				ret = unlink(arg);
			PRIV_START
			if (ret != 0)
				goto nohardlink;
			/*
			 * Unlink of user file was successful.  Change the
			 * owner and permissions, add entries to the control
			 * file, and skip the file copying step.
			 */
			chown(dfname, pp->daemon_user, getegid());
			chmod(dfname, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
			PRIV_END
			if (format == 'p')
				card('T', title ? title : arg);
			for (i = 0; i < ncopies; i++)
				card(format, &dfname[inchar-2]);
			card('U', &dfname[inchar-2]);
			card('N', arg);
			nact++;
			continue;
		nohardlink:
			if (didlink)
				unlink(dfname);
			PRIV_END           /* restore old uid */
		} /* end: if (f) */

		if ((i = open(arg, O_RDONLY)) < 0) {
			printf("%s: cannot open %s\n", progname, arg);
		} else {
			copy(pp, i, arg);
			(void) close(i);
			if (f && unlink(arg) < 0)
				printf("%s: %s: not removed\n", progname, arg);
		}
	}

	if (nact) {
		(void) close(tfd);
		tfname[inchar]--;
		/*
		 * Touch the control file to fix position in the queue.
		 */
		PRIV_START
		if ((tfd = open(tfname, O_RDWR)) >= 0) {
			char touch_c;

			if (read(tfd, &touch_c, 1) == 1 &&
			    lseek(tfd, (off_t)0, 0) == 0 &&
			    write(tfd, &touch_c, 1) != 1) {
				printf("%s: cannot touch %s\n", progname,
				    tfname);
				tfname[inchar]++;
				cleanup(0);
			}
			(void) close(tfd);
		}
		if (link(tfname, cfname) < 0) {
			printf("%s: cannot rename %s\n", progname, cfname);
			tfname[inchar]++;
			cleanup(0);
		}
		unlink(tfname);
		PRIV_END
		if (qflag)		/* just q things up */
			exit(0);
		if (!startdaemon(pp))
			printf("jobs queued, but cannot start daemon.\n");
		exit(0);
	}
	cleanup(0);
	return (1);
	/* NOTREACHED */
}
コード例 #10
0
ファイル: virnetsocket.c プロジェクト: foomango/libvirt
int virNetSocketNewListenUNIX(const char *path,
                              mode_t mask,
                              uid_t user,
                              gid_t grp,
                              virNetSocketPtr *retsock)
{
    virSocketAddr addr;
    mode_t oldmask;
    int fd;

    *retsock = NULL;

    memset(&addr, 0, sizeof(addr));

    addr.len = sizeof(addr.data.un);

    if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
        virReportSystemError(errno, "%s", _("Failed to create socket"));
        goto error;
    }

    addr.data.un.sun_family = AF_UNIX;
    if (virStrcpyStatic(addr.data.un.sun_path, path) == NULL) {
        virReportSystemError(ENAMETOOLONG,
                             _("Path %s too long for unix socket"), path);
        goto error;
    }
    if (addr.data.un.sun_path[0] == '@')
        addr.data.un.sun_path[0] = '\0';
    else
        unlink(addr.data.un.sun_path);

    oldmask = umask(~mask);

    if (bind(fd, &addr.data.sa, addr.len) < 0) {
        umask(oldmask);
        virReportSystemError(errno,
                             _("Failed to bind socket to '%s'"),
                             path);
        goto error;
    }
    umask(oldmask);

    /* chown() doesn't work for abstract sockets but we use them only
     * if libvirtd runs unprivileged
     */
    if (grp != 0 && chown(path, user, grp)) {
        virReportSystemError(errno,
                             _("Failed to change ownership of '%s' to %d:%d"),
                             path, (int) user, (int) grp);
        goto error;
    }

    if (!(*retsock = virNetSocketNew(&addr, NULL, false, fd, -1, 0)))
        goto error;

    return 0;

error:
    if (path[0] != '@')
        unlink(path);
    VIR_FORCE_CLOSE(fd);
    return -1;
}