Example #1
0
int
main(int argc, char *argv[])
{
	int opt;

	while ((opt = getopt(argc, argv, "i:D:U:I:o:bBcdeKklnsStV")) != -1)
		switch (opt) {
		case 'i': 
			opt = *optarg++;
			if (opt == 'D')
				addsym(true, true, optarg);
			else if (opt == 'U')
				addsym(true, false, optarg);
			else
				usage();
			break;
		case 'D': 
			addsym(false, true, optarg);
			break;
		case 'U': 
			addsym(false, false, optarg);
			break;
		case 'I': 
			break;
		case 'b': 
		case 'l': 
			lnblank = true;
			break;
		case 'B': 
			compblank = true;
			break;
		case 'c': 
			complement = true;
			break;
		case 'd':
			debugging = true;
			break;
		case 'e': 
			iocccok = true;
			break;
		case 'K': 
			strictlogic = true;
			break;
		case 'k': 
			killconsts = true;
			break;
		case 'n': 
			lnnum = true;
			break;
		case 'o': 
			ofilename = optarg;
			break;
		case 's': 
			symlist = true;
			break;
		case 'S': 
			symlist = symdepth = true;
			break;
		case 't': 
			text = true;
			break;
		case 'V': 
			version();
		default:
			usage();
		}
	argc -= optind;
	argv += optind;
	if (compblank && lnblank)
		errx(2, "-B and -b are mutually exclusive");
	if (argc > 1) {
		errx(2, "can only do one file");
	} else if (argc == 1 && strcmp(*argv, "-") != 0) {
		filename = *argv;
		input = fopen(filename, "rb");
		if (input == NULL)
			err(2, "can't open %s", filename);
	} else {
		filename = "[stdin]";
		input = stdin;
	}
	if (ofilename == NULL) {
		ofilename = "[stdout]";
		output = stdout;
	} else {
		struct stat ist, ost;
		if (stat(ofilename, &ost) == 0 &&
		    fstat(fileno(input), &ist) == 0)
			overwriting = (ist.st_dev == ost.st_dev
				    && ist.st_ino == ost.st_ino);
		if (overwriting) {
			const char *dirsep;
			int ofd;

			dirsep = strrchr(ofilename, '/');
			if (dirsep != NULL)
				snprintf(tempname, sizeof(tempname),
				    "%.*s/" TEMPLATE,
				    (int)(dirsep - ofilename), ofilename);
			else
				snprintf(tempname, sizeof(tempname),
				    TEMPLATE);
			ofd = mkstemp(tempname);
			if (ofd != -1)
				output = fdopen(ofd, "wb+");
			if (output == NULL)
				err(2, "can't create temporary file");
			fchmod(ofd, ist.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO));
		} else {
			output = fopen(ofilename, "wb");
			if (output == NULL)
				err(2, "can't open %s", ofilename);
		}
	}
	process();
	abort(); 
}
Example #2
0
/*
 * Like fgets, but go through the list of files chaining them together.
 * Set len to the length of the line.
 */
int
mf_fgets(SPACE *sp, enum e_spflag spflag)
{
	struct stat sb;
	ssize_t len;
	char *dirbuf, *basebuf;
	static char *p = NULL;
	static size_t plen = 0;
	int c;
	static int firstfile;

	if (infile == NULL) {
		/* stdin? */
		if (files->fname == NULL) {
			if (inplace != NULL)
				errx(1, "-I or -i may not be used with stdin");
			infile = stdin;
			fname = "stdin";
			outfile = stdout;
			outfname = "stdout";
		}
		firstfile = 1;
	}

	for (;;) {
		if (infile != NULL && (c = getc(infile)) != EOF && !quit) {
			(void)ungetc(c, infile);
			break;
		}
		/* If we are here then either eof or no files are open yet */
		if (infile == stdin) {
			sp->len = 0;
			return (0);
		}
		if (infile != NULL) {
			fclose(infile);
			if (*oldfname != '\0') {
				/* if there was a backup file, remove it */
				unlink(oldfname);
				/*
				 * Backup the original.  Note that hard links
				 * are not supported on all filesystems.
				 */
				if ((link(fname, oldfname) != 0) &&
				   (rename(fname, oldfname) != 0)) {
					warn("rename()");
					if (*tmpfname)
						unlink(tmpfname);
					exit(1);
				}
				*oldfname = '\0';
			}
			if (*tmpfname != '\0') {
				if (outfile != NULL && outfile != stdout)
					if (fclose(outfile) != 0) {
						warn("fclose()");
						unlink(tmpfname);
						exit(1);
					}
				outfile = NULL;
				if (rename(tmpfname, fname) != 0) {
					/* this should not happen really! */
					warn("rename()");
					unlink(tmpfname);
					exit(1);
				}
				*tmpfname = '\0';
			}
			outfname = NULL;
		}
		if (firstfile == 0)
			files = files->next;
		else
			firstfile = 0;
		if (files == NULL) {
			sp->len = 0;
			return (0);
		}
		fname = files->fname;
		if (inplace != NULL) {
			if (lstat(fname, &sb) != 0)
				err(1, "%s", fname);
			if (!S_ISREG(sb.st_mode))
				errx(1, "%s: %s %s", fname,
				    "in-place editing only",
				    "works for regular files");
			if (*inplace != '\0') {
				strlcpy(oldfname, fname,
				    sizeof(oldfname));
				len = strlcat(oldfname, inplace,
				    sizeof(oldfname));
				if (len > (ssize_t)sizeof(oldfname))
					errx(1, "%s: name too long", fname);
			}
			if ((dirbuf = strdup(fname)) == NULL ||
			    (basebuf = strdup(fname)) == NULL)
				err(1, "strdup");
			len = snprintf(tmpfname, sizeof(tmpfname),
			    "%s/.!%ld!%s", dirname(dirbuf), (long)getpid(),
			    basename(basebuf));
			free(dirbuf);
			free(basebuf);
			if (len >= (ssize_t)sizeof(tmpfname))
				errx(1, "%s: name too long", fname);
			unlink(tmpfname);
			if (outfile != NULL && outfile != stdout)
				fclose(outfile);
			if ((outfile = fopen(tmpfname, "w")) == NULL)
				err(1, "%s", fname);
			fchown(fileno(outfile), sb.st_uid, sb.st_gid);
			fchmod(fileno(outfile), sb.st_mode & ALLPERMS);
			outfname = tmpfname;
			if (!ispan) {
				linenum = 0;
				resetstate();
			}
		} else {
			outfile = stdout;
			outfname = "stdout";
		}
		if ((infile = fopen(fname, "r")) == NULL) {
			warn("%s", fname);
			rval = 1;
			continue;
		}
	}
	/*
	 * We are here only when infile is open and we still have something
	 * to read from it.
	 *
	 * Use getline() so that we can handle essentially infinite input
	 * data.  The p and plen are static so each invocation gives
	 * getline() the same buffer which is expanded as needed.
	 */
	len = getline(&p, &plen, infile);
	if (len == -1)
		err(1, "%s", fname);
	if (len != 0 && p[len - 1] == '\n') {
		sp->append_newline = 1;
		len--;
	} else if (!lastline()) {
		sp->append_newline = 1;
	} else {
		sp->append_newline = 0;
	}
	cspace(sp, p, len, spflag);

	linenum++;

	return (1);
}
Example #3
0
void *					/* O - Profile or NULL on error */
cupsdCreateProfile(int job_id)		/* I - Job ID or 0 for none */
{
#ifdef HAVE_SANDBOX_H
  cups_file_t	*fp;			/* File pointer */
  char		profile[1024],		/* File containing the profile */
		cache[1024],		/* Quoted CacheDir */
		request[1024],		/* Quoted RequestRoot */
		root[1024],		/* Quoted ServerRoot */
		temp[1024];		/* Quoted TempDir */
  const char	*nodebug;		/* " (with no-log)" for no debug */


  if (!UseProfiles)
  {
   /*
    * Only use sandbox profiles as root...
    */

    cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d) = NULL",
                    job_id);

    return (NULL);
  }

  if ((fp = cupsTempFile2(profile, sizeof(profile))) == NULL)
  {
    cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d) = NULL",
                    job_id);
    cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create security profile: %s",
                    strerror(errno));
    return (NULL);
  }

  fchown(cupsFileNumber(fp), RunUser, Group);
  fchmod(cupsFileNumber(fp), 0640);

  cupsd_requote(cache, CacheDir, sizeof(cache));
  cupsd_requote(request, RequestRoot, sizeof(request));
  cupsd_requote(root, ServerRoot, sizeof(root));
  cupsd_requote(temp, TempDir, sizeof(temp));

  nodebug = LogLevel < CUPSD_LOG_DEBUG ? " (with no-log)" : "";

  cupsFilePuts(fp, "(version 1)\n");
  cupsFilePuts(fp, "(allow default)\n");
  cupsFilePrintf(fp,
                 "(deny file-write* file-read-data file-read-metadata\n"
                 "  (regex"
		 " #\"^%s$\""		/* RequestRoot */
		 " #\"^%s/\""		/* RequestRoot/... */
		 ")%s)\n",
		 request, request, nodebug);
  if (!RunUser)
    cupsFilePrintf(fp,
		   "(deny file-write* file-read-data file-read-metadata\n"
		   "  (regex"
		   " #\"^/Users$\""
		   " #\"^/Users/\""
		   ")%s)\n", nodebug);
  cupsFilePrintf(fp,
                 "(deny file-write*\n"
                 "  (regex"
		 " #\"^%s$\""		/* ServerRoot */
		 " #\"^%s/\""		/* ServerRoot/... */
		 " #\"^/private/etc$\""
		 " #\"^/private/etc/\""
		 " #\"^/usr/local/etc$\""
		 " #\"^/usr/local/etc/\""
		 " #\"^/Library$\""
		 " #\"^/Library/\""
		 " #\"^/System$\""
		 " #\"^/System/\""
		 ")%s)\n",
		 root, root, nodebug);
  /* Specifically allow applications to stat RequestRoot */
  cupsFilePrintf(fp,
                 "(allow file-read-metadata\n"
                 "  (regex"
		 " #\"^%s$\""		/* RequestRoot */
		 "))\n",
		 request);
  cupsFilePrintf(fp,
                 "(allow file-write* file-read-data file-read-metadata\n"
                 "  (regex"
		 " #\"^%s$\""		/* TempDir */
		 " #\"^%s/\""		/* TempDir/... */
		 " #\"^%s$\""		/* CacheDir */
		 " #\"^%s/\""		/* CacheDir/... */
		 " #\"^%s/Library$\""	/* RequestRoot/Library */
		 " #\"^%s/Library/\""	/* RequestRoot/Library/... */
		 " #\"^/Library/Application Support/\""
		 " #\"^/Library/Caches/\""
		 " #\"^/Library/Preferences/\""
		 " #\"^/Library/Printers/.*/\""
		 " #\"^/Users/Shared/\""
		 "))\n",
		 temp, temp, cache, cache, request, request);
  cupsFilePrintf(fp,
		 "(deny file-write*\n"
		 "  (regex"
		 " #\"^/Library/Printers/PPDs$\""
		 " #\"^/Library/Printers/PPDs/\""
		 " #\"^/Library/Printers/PPD Plugins$\""
		 " #\"^/Library/Printers/PPD Plugins/\""
		 ")%s)\n", nodebug);
  if (job_id)
  {
   /*
    * Allow job filters to read the spool file(s)...
    */

    cupsFilePrintf(fp,
                   "(allow file-read-data file-read-metadata\n"
                   "  (regex #\"^%s/([ac]%05d|d%05d-[0-9][0-9][0-9])$\"))\n",
		   request, job_id, job_id);
  }
  else
  {
   /*
    * Allow email notifications from notifiers...
    */

    cupsFilePuts(fp,
		 "(allow process-exec\n"
		 "  (literal \"/usr/sbin/sendmail\")\n"
		 "  (with no-sandbox)\n"
		 ")\n");
  }

  cupsFileClose(fp);

  cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d) = \"%s\"",
                  job_id, profile);
  return ((void *)strdup(profile));

#else
  cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d) = NULL",
                  job_id);

  return (NULL);
#endif /* HAVE_SANDBOX_H */
}
Example #4
0
/*
 * install --
 *	build a path name and install the file
 */
void
install(const char *from_name, const char *to_name, u_long fset, u_long fclr,
	u_int flags)
{
	struct stat from_sb, temp_sb, to_sb;
	struct utimbuf utb;
	int devnull, files_match, from_fd, serrno, target;
	int tempcopy, temp_fd, to_fd;
	u_long nfset;
	char backup[MAXPATHLEN], *p, pathbuf[MAXPATHLEN], tempfile[MAXPATHLEN];

	files_match = 0;
	from_fd = -1;

	/* If try to install NULL file to a directory, fails. */
	if (flags & DIRECTORY || strcmp(from_name, _PATH_DEVNULL)) {
		if (stat(from_name, &from_sb))
			err(EX_OSERR, "%s", from_name);
		if (!S_ISREG(from_sb.st_mode)) {
			errno = EFTYPE;
			err(EX_OSERR, "%s", from_name);
		}
		/* Build the target path. */
		if (flags & DIRECTORY) {
			snprintf(pathbuf, sizeof(pathbuf), "%s/%s",
			    to_name,
			    (p = strrchr(from_name, '/')) ? ++p : from_name);
			to_name = pathbuf;
		}
		devnull = 0;
	} else {
		devnull = 1;
	}

	target = stat(to_name, &to_sb) == 0;

	/* Only install to regular files. */
	if (target && !S_ISREG(to_sb.st_mode)) {
		errno = EFTYPE;
		warn("%s", to_name);
		return;
	}

	/* Only copy safe if the target exists. */
	tempcopy = safecopy && target;

	if (!devnull && (from_fd = open(from_name, O_RDONLY, 0)) < 0)
		err(EX_OSERR, "%s", from_name);

	/* If we don't strip, we can compare first. */
	if (docompare && !dostrip && target) {
		if ((to_fd = open(to_name, O_RDONLY, 0)) < 0)
			err(EX_OSERR, "%s", to_name);
		if (devnull)
			files_match = to_sb.st_size == 0;
		else
			files_match = !(compare(from_fd, from_name,
			    (size_t)from_sb.st_size, to_fd,
			    to_name, (size_t)to_sb.st_size));

		/* Close "to" file unless we match. */
		if (!files_match)
			close(to_fd);
	}

	if (!files_match) {
		if (tempcopy) {
			to_fd = create_tempfile(to_name, tempfile,
			    sizeof(tempfile));
			if (to_fd < 0)
				err(EX_OSERR, "%s", tempfile);
		} else {
			if ((to_fd = create_newfile(to_name, target,
			    &to_sb)) < 0)
				err(EX_OSERR, "%s", to_name);
			if (verbose)
				printf("install: %s -> %s\n",
				    from_name, to_name);
		}
		if (!devnull)
			copy(from_fd, from_name, to_fd,
			     tempcopy ? tempfile : to_name, from_sb.st_size);
	}

	if (dostrip) {
		strip(tempcopy ? tempfile : to_name);

		/*
		 * Re-open our fd on the target, in case we used a strip
		 * that does not work in-place -- like GNU binutils strip.
		 */
		close(to_fd);
		to_fd = open(tempcopy ? tempfile : to_name, O_RDONLY, 0);
		if (to_fd < 0)
			err(EX_OSERR, "stripping %s", to_name);
	}

	/*
	 * Compare the stripped temp file with the target.
	 */
	if (docompare && dostrip && target) {
		temp_fd = to_fd;

		/* Re-open to_fd using the real target name. */
		if ((to_fd = open(to_name, O_RDONLY, 0)) < 0)
			err(EX_OSERR, "%s", to_name);

		if (fstat(temp_fd, &temp_sb)) {
			serrno = errno;
			unlink(tempfile);
			errno = serrno;
			err(EX_OSERR, "%s", tempfile);
		}

		if (compare(temp_fd, tempfile, (size_t)temp_sb.st_size, to_fd,
			    to_name, (size_t)to_sb.st_size) == 0) {
			/*
			 * If target has more than one link we need to
			 * replace it in order to snap the extra links.
			 * Need to preserve target file times, though.
			 */
			if (to_sb.st_nlink != 1) {
				utb.actime = to_sb.st_atime;
				utb.modtime = to_sb.st_mtime;
				utime(tempfile, &utb);
			} else {
				files_match = 1;
				unlink(tempfile);
			}
			close(temp_fd);
		}
	}

	/*
	 * Move the new file into place if doing a safe copy
	 * and the files are different (or just not compared).
	 */
	if (tempcopy && !files_match) {
		/* Try to turn off the immutable bits. */
		if (to_sb.st_flags & NOCHANGEBITS)
			chflags(to_name, to_sb.st_flags & ~NOCHANGEBITS);
		if (dobackup) {
			if ((size_t)snprintf(backup, MAXPATHLEN, "%s%s", to_name,
			    suffix) != strlen(to_name) + strlen(suffix)) {
				unlink(tempfile);
				errx(EX_OSERR, "%s: backup filename too long",
				    to_name);
			}
			if (verbose)
				printf("install: %s -> %s\n", to_name, backup);
			if (rename(to_name, backup) < 0) {
				serrno = errno;
				unlink(tempfile);
				errno = serrno;
				err(EX_OSERR, "rename: %s to %s", to_name,
				     backup);
			}
		}
		if (verbose)
			printf("install: %s -> %s\n", from_name, to_name);
		if (rename(tempfile, to_name) < 0) {
			serrno = errno;
			unlink(tempfile);
			errno = serrno;
			err(EX_OSERR, "rename: %s to %s",
			    tempfile, to_name);
		}

		/* Re-open to_fd so we aren't hosed by the rename(2). */
		close(to_fd);
		if ((to_fd = open(to_name, O_RDONLY, 0)) < 0)
			err(EX_OSERR, "%s", to_name);
	}

	/*
	 * Preserve the timestamp of the source file if necessary.
	 */
	if (dopreserve && !files_match && !devnull) {
		utb.actime = from_sb.st_atime;
		utb.modtime = from_sb.st_mtime;
		utime(to_name, &utb);
	}

	if (fstat(to_fd, &to_sb) == -1) {
		serrno = errno;
		unlink(to_name);
		errno = serrno;
		err(EX_OSERR, "%s", to_name);
	}

	/*
	 * Set owner, group, mode for target; do the chown first,
	 * chown may lose the setuid bits.
	 */
	if ((gid != (gid_t)-1 && gid != to_sb.st_gid) ||
	    (uid != (uid_t)-1 && uid != to_sb.st_uid) ||
	    (mode != to_sb.st_mode)) {
		/* Try to turn off the immutable bits. */
		if (to_sb.st_flags & NOCHANGEBITS)
			fchflags(to_fd, to_sb.st_flags & ~NOCHANGEBITS);
	}

	if ((gid != (gid_t)-1 && gid != to_sb.st_gid) ||
	    (uid != (uid_t)-1 && uid != to_sb.st_uid))
		if (fchown(to_fd, uid, gid) == -1) {
			serrno = errno;
			unlink(to_name);
			errno = serrno;
			err(EX_OSERR,"%s: chown/chgrp", to_name);
		}

	if (mode != to_sb.st_mode)
		if (fchmod(to_fd, mode)) {
			serrno = errno;
			unlink(to_name);
			errno = serrno;
			err(EX_OSERR, "%s: chmod", to_name);
		}

	/*
	 * If provided a set of flags, set them, otherwise, preserve the
	 * flags, except for the dump and history flags.  The dump flag
	 * is left clear on the target while the history flag from when
	 * the target was created (which is inherited from the target's
	 * parent directory) is retained.
	 */
	if (flags & SETFLAGS) {
		nfset = (to_sb.st_flags | fset) & ~fclr;
	} else {
		nfset = (from_sb.st_flags & ~(UF_NODUMP | UF_NOHISTORY)) |
			(to_sb.st_flags & UF_NOHISTORY);
	}

	/*
	 * NFS does not support flags.  Ignore EOPNOTSUPP flags if we're just
	 * trying to turn off UF_NODUMP.  If we're trying to set real flags,
	 * then warn if the the fs doesn't support it, otherwise fail.
	 */
	if (!devnull && fchflags(to_fd, nfset)) {
		if (flags & SETFLAGS) {
			if (errno == EOPNOTSUPP)
				warn("%s: chflags", to_name);
			else {
				serrno = errno;
				unlink(to_name);
				errno = serrno;
				err(EX_OSERR, "%s: chflags", to_name);
			}
		}
	}

	close(to_fd);
	if (!devnull)
		close(from_fd);
}
Example #5
0
int set_attr(const char *file, struct hostfs_iattr *attrs, int fd)
{
	struct timeval times[2];
	struct timespec atime_ts, mtime_ts;
	int err, ma;

	if (attrs->ia_valid & HOSTFS_ATTR_MODE) {
		if (fd >= 0) {
			if (fchmod(fd, attrs->ia_mode) != 0)
				return (-errno);
		} else if (chmod(file, attrs->ia_mode) != 0) {
			return -errno;
		}
	}
	if (attrs->ia_valid & HOSTFS_ATTR_UID) {
		if (fd >= 0) {
			if (fchown(fd, attrs->ia_uid, -1))
				return -errno;
		} else if (chown(file, attrs->ia_uid, -1)) {
			return -errno;
		}
	}
	if (attrs->ia_valid & HOSTFS_ATTR_GID) {
		if (fd >= 0) {
			if (fchown(fd, -1, attrs->ia_gid))
				return -errno;
		} else if (chown(file, -1, attrs->ia_gid)) {
			return -errno;
		}
	}
	if (attrs->ia_valid & HOSTFS_ATTR_SIZE) {
		if (fd >= 0) {
			if (ftruncate(fd, attrs->ia_size))
				return -errno;
		} else if (truncate(file, attrs->ia_size)) {
			return -errno;
		}
	}

	/*
	 * Update accessed and/or modified time, in two parts: first set
	 * times according to the changes to perform, and then call futimes()
	 * or utimes() to apply them.
	 */
	ma = (HOSTFS_ATTR_ATIME_SET | HOSTFS_ATTR_MTIME_SET);
	if (attrs->ia_valid & ma) {
		err = stat_file(file, NULL, NULL, NULL, NULL, NULL, NULL,
				&atime_ts, &mtime_ts, NULL, NULL, NULL, fd);
		if (err != 0)
			return err;

		times[0].tv_sec = atime_ts.tv_sec;
		times[0].tv_usec = atime_ts.tv_nsec / 1000;
		times[1].tv_sec = mtime_ts.tv_sec;
		times[1].tv_usec = mtime_ts.tv_nsec / 1000;

		if (attrs->ia_valid & HOSTFS_ATTR_ATIME_SET) {
			times[0].tv_sec = attrs->ia_atime.tv_sec;
			times[0].tv_usec = attrs->ia_atime.tv_nsec / 1000;
		}
		if (attrs->ia_valid & HOSTFS_ATTR_MTIME_SET) {
			times[1].tv_sec = attrs->ia_mtime.tv_sec;
			times[1].tv_usec = attrs->ia_mtime.tv_nsec / 1000;
		}

		if (fd >= 0) {
			if (futimes(fd, times) != 0)
				return -errno;
		} else if (utimes(file, times) != 0) {
			return -errno;
		}
	}

	/* Note: ctime is not handled */
	if (attrs->ia_valid & (HOSTFS_ATTR_ATIME | HOSTFS_ATTR_MTIME)) {
		err = stat_file(file, NULL, NULL, NULL, NULL, NULL, NULL,
				&attrs->ia_atime, &attrs->ia_mtime, NULL,
				NULL, NULL, fd);
		if (err != 0)
			return err;
	}
	return 0;
}
Example #6
0
int
main(int ac, char **av)
{
	struct stat stat_buf;	/* stat(2) struct contents */
	int lc;			/* loop counter */
	char *msg;		/* message returned from parse_opts */
	int ind;		/* counter variable for chmod(2) tests */
	int mode;		/* file mode permission */

	TST_TOTAL = sizeof(Modes) / sizeof(int);

	/* Parse standard options given to run the test. */
	msg = parse_opts(ac, av, (option_t *) NULL, NULL);
	if (msg != (char *) NULL) {
		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
		tst_exit();
	}

	/* Perform global setup for test */
	setup();

	/* Check looping state if -i option given */
	for (lc = 0; TEST_LOOPING(lc); lc++) {
		/* Reset Tst_count in case we are looping. */
		Tst_count = 0;

		for (ind = 0; ind < TST_TOTAL; ind++) {
			mode = Modes[ind];

			/* 
			 * Call fchmod(2) with different mode permission
			 * bits to set it for "testfile".
		 	 */
			TEST(fchmod(fd, mode));

			/* check return code of fchmod(2) */
			if (TEST_RETURN == -1) {
				tst_resm(TFAIL, "fchmod(%d, %#o) Failed, "
					 "errno=%d : %s", fd, mode, TEST_ERRNO,
					 strerror(TEST_ERRNO));
				continue;
			}
			/*
			 * Perform functional verification if test
			 * executed without (-f) option.
			 */
			if (STD_FUNCTIONAL_TEST) {
				/*
			 	 * Get the testfile information using
				 * fstat(2).
				 */
				if (fstat(fd, &stat_buf) < 0) {
					tst_brkm(TFAIL, cleanup, "fstat(2) of "							 "%s failed, errno:%d",
						 TESTFILE, TEST_ERRNO);
				}
				stat_buf.st_mode &= ~S_IFREG;

				/*
				 * Check for expected mode permissions
				 * on testfile.
				 */
				if (stat_buf.st_mode == mode) {
					tst_resm(TPASS, "Functionality of "							 "fchmod(%d, %#o) successful",
						 fd, mode);
				} else {
					tst_resm(TFAIL, "%s: Incorrect modes "
						 "0%03o, Expected 0%03o",
						 TESTFILE, stat_buf.st_mode,
						 mode);
				}
			} else {
				tst_resm(TPASS, "call succeeded");
			}
		}
	}	/* End for TEST_LOOPING */

	/* Call cleanup() to undo setup done for the test. */
	cleanup();

	/*NOTREACHED*/
	return(0);
}	/* End main */
Example #7
0
/* write all status data to file */
int xsddefault_save_status_data(void)
{
	char *tmp_log = NULL;
	customvariablesmember *temp_customvariablesmember = NULL;
	host *temp_host = NULL;
	service *temp_service = NULL;
	contact *temp_contact = NULL;
	comment *temp_comment = NULL;
	scheduled_downtime *temp_downtime = NULL;
	time_t current_time;
	int fd = 0;
	FILE *fp = NULL;
	int result = OK;

	log_debug_info(DEBUGL_FUNCTIONS, 0, "save_status_data()\n");

	/* users may not want us to write status data */
	if (!status_file || !strcmp(status_file, "/dev/null"))
		return OK;

	asprintf(&tmp_log, "%sXXXXXX", temp_file);
	if (tmp_log == NULL)
		return ERROR;

	log_debug_info(DEBUGL_STATUSDATA, 2, "Writing status data to temp file '%s'\n", tmp_log);

	if ((fd = mkstemp(tmp_log)) == -1) {

		/* log an error */
		logit(NSLOG_RUNTIME_ERROR,
		      "Error: Unable to create temp file '%s' for writing status data: %s\n", tmp_log, strerror(errno));

		/* free memory */
		my_free(tmp_log);

		return ERROR;
	}
	fp = (FILE *)fdopen(fd, "w");
	if (fp == NULL) {

		close(fd);
		unlink(tmp_log);

		/* log an error */
		logit(NSLOG_RUNTIME_ERROR,
		      "Error: Unable to open temp file '%s' for writing status data: %s\n", tmp_log, strerror(errno));

		/* free memory */
		my_free(tmp_log);

		return ERROR;
	}

	/* generate check statistics */
	generate_check_stats();

	/* write version info to status file */
	fprintf(fp, "########################################\n");
	fprintf(fp, "#          NAGIOS STATUS FILE\n");
	fprintf(fp, "#\n");
	fprintf(fp, "# THIS FILE IS AUTOMATICALLY GENERATED\n");
	fprintf(fp, "# BY NAGIOS.  DO NOT MODIFY THIS FILE!\n");
	fprintf(fp, "########################################\n\n");

	time(&current_time);

	/* write file info */
	fprintf(fp, "info {\n");
	fprintf(fp, "\tcreated=%lu\n", current_time);
	fprintf(fp, "\tversion=%s\n", PROGRAM_VERSION);
	fprintf(fp, "\t}\n\n");

	/* save program status data */
	fprintf(fp, "programstatus {\n");
	fprintf(fp, "\tmodified_host_attributes=%lu\n", modified_host_process_attributes);
	fprintf(fp, "\tmodified_service_attributes=%lu\n", modified_service_process_attributes);
	fprintf(fp, "\tnagios_pid=%d\n", nagios_pid);
	fprintf(fp, "\tdaemon_mode=%d\n", daemon_mode);
	fprintf(fp, "\tprogram_start=%lu\n", program_start);
	fprintf(fp, "\tlast_log_rotation=%lu\n", last_log_rotation);
	fprintf(fp, "\tenable_notifications=%d\n", enable_notifications);
	fprintf(fp, "\tactive_service_checks_enabled=%d\n", execute_service_checks);
	fprintf(fp, "\tpassive_service_checks_enabled=%d\n", accept_passive_service_checks);
	fprintf(fp, "\tactive_host_checks_enabled=%d\n", execute_host_checks);
	fprintf(fp, "\tpassive_host_checks_enabled=%d\n", accept_passive_host_checks);
	fprintf(fp, "\tenable_event_handlers=%d\n", enable_event_handlers);
	fprintf(fp, "\tobsess_over_services=%d\n", obsess_over_services);
	fprintf(fp, "\tobsess_over_hosts=%d\n", obsess_over_hosts);
	fprintf(fp, "\tcheck_service_freshness=%d\n", check_service_freshness);
	fprintf(fp, "\tcheck_host_freshness=%d\n", check_host_freshness);
	fprintf(fp, "\tenable_flap_detection=%d\n", enable_flap_detection);
	fprintf(fp, "\tprocess_performance_data=%d\n", process_performance_data);
	fprintf(fp, "\tglobal_host_event_handler=%s\n", (global_host_event_handler == NULL) ? "" : global_host_event_handler);
	fprintf(fp, "\tglobal_service_event_handler=%s\n", (global_service_event_handler == NULL) ? "" : global_service_event_handler);
	fprintf(fp, "\tnext_comment_id=%lu\n", next_comment_id);
	fprintf(fp, "\tnext_downtime_id=%lu\n", next_downtime_id);
	fprintf(fp, "\tnext_event_id=%lu\n", next_event_id);
	fprintf(fp, "\tnext_problem_id=%lu\n", next_problem_id);
	fprintf(fp, "\tnext_notification_id=%lu\n", next_notification_id);
	fprintf(fp, "\tactive_scheduled_host_check_stats=%d,%d,%d\n", check_statistics[ACTIVE_SCHEDULED_HOST_CHECK_STATS].minute_stats[0], check_statistics[ACTIVE_SCHEDULED_HOST_CHECK_STATS].minute_stats[1], check_statistics[ACTIVE_SCHEDULED_HOST_CHECK_STATS].minute_stats[2]);
	fprintf(fp, "\tactive_ondemand_host_check_stats=%d,%d,%d\n", check_statistics[ACTIVE_ONDEMAND_HOST_CHECK_STATS].minute_stats[0], check_statistics[ACTIVE_ONDEMAND_HOST_CHECK_STATS].minute_stats[1], check_statistics[ACTIVE_ONDEMAND_HOST_CHECK_STATS].minute_stats[2]);
	fprintf(fp, "\tpassive_host_check_stats=%d,%d,%d\n", check_statistics[PASSIVE_HOST_CHECK_STATS].minute_stats[0], check_statistics[PASSIVE_HOST_CHECK_STATS].minute_stats[1], check_statistics[PASSIVE_HOST_CHECK_STATS].minute_stats[2]);
	fprintf(fp, "\tactive_scheduled_service_check_stats=%d,%d,%d\n", check_statistics[ACTIVE_SCHEDULED_SERVICE_CHECK_STATS].minute_stats[0], check_statistics[ACTIVE_SCHEDULED_SERVICE_CHECK_STATS].minute_stats[1], check_statistics[ACTIVE_SCHEDULED_SERVICE_CHECK_STATS].minute_stats[2]);
	fprintf(fp, "\tactive_ondemand_service_check_stats=%d,%d,%d\n", check_statistics[ACTIVE_ONDEMAND_SERVICE_CHECK_STATS].minute_stats[0], check_statistics[ACTIVE_ONDEMAND_SERVICE_CHECK_STATS].minute_stats[1], check_statistics[ACTIVE_ONDEMAND_SERVICE_CHECK_STATS].minute_stats[2]);
	fprintf(fp, "\tpassive_service_check_stats=%d,%d,%d\n", check_statistics[PASSIVE_SERVICE_CHECK_STATS].minute_stats[0], check_statistics[PASSIVE_SERVICE_CHECK_STATS].minute_stats[1], check_statistics[PASSIVE_SERVICE_CHECK_STATS].minute_stats[2]);
	fprintf(fp, "\tcached_host_check_stats=%d,%d,%d\n", check_statistics[ACTIVE_CACHED_HOST_CHECK_STATS].minute_stats[0], check_statistics[ACTIVE_CACHED_HOST_CHECK_STATS].minute_stats[1], check_statistics[ACTIVE_CACHED_HOST_CHECK_STATS].minute_stats[2]);
	fprintf(fp, "\tcached_service_check_stats=%d,%d,%d\n", check_statistics[ACTIVE_CACHED_SERVICE_CHECK_STATS].minute_stats[0], check_statistics[ACTIVE_CACHED_SERVICE_CHECK_STATS].minute_stats[1], check_statistics[ACTIVE_CACHED_SERVICE_CHECK_STATS].minute_stats[2]);
	fprintf(fp, "\texternal_command_stats=%d,%d,%d\n", check_statistics[EXTERNAL_COMMAND_STATS].minute_stats[0], check_statistics[EXTERNAL_COMMAND_STATS].minute_stats[1], check_statistics[EXTERNAL_COMMAND_STATS].minute_stats[2]);

	fprintf(fp, "\tparallel_host_check_stats=%d,%d,%d\n", check_statistics[PARALLEL_HOST_CHECK_STATS].minute_stats[0], check_statistics[PARALLEL_HOST_CHECK_STATS].minute_stats[1], check_statistics[PARALLEL_HOST_CHECK_STATS].minute_stats[2]);
	fprintf(fp, "\tserial_host_check_stats=%d,%d,%d\n", check_statistics[SERIAL_HOST_CHECK_STATS].minute_stats[0], check_statistics[SERIAL_HOST_CHECK_STATS].minute_stats[1], check_statistics[SERIAL_HOST_CHECK_STATS].minute_stats[2]);
	fprintf(fp, "\t}\n\n");


	/* save host status data */
	for (temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {

		fprintf(fp, "hoststatus {\n");
		fprintf(fp, "\thost_name=%s\n", temp_host->name);

		fprintf(fp, "\tmodified_attributes=%lu\n", temp_host->modified_attributes);
		fprintf(fp, "\tcheck_command=%s\n", (temp_host->check_command == NULL) ? "" : temp_host->check_command);
		fprintf(fp, "\tcheck_period=%s\n", (temp_host->check_period == NULL) ? "" : temp_host->check_period);
		fprintf(fp, "\tnotification_period=%s\n", (temp_host->notification_period == NULL) ? "" : temp_host->notification_period);
		fprintf(fp, "\tcheck_interval=%f\n", temp_host->check_interval);
		fprintf(fp, "\tretry_interval=%f\n", temp_host->retry_interval);
		fprintf(fp, "\tevent_handler=%s\n", (temp_host->event_handler == NULL) ? "" : temp_host->event_handler);

		fprintf(fp, "\thas_been_checked=%d\n", temp_host->has_been_checked);
		fprintf(fp, "\tshould_be_scheduled=%d\n", temp_host->should_be_scheduled);
		fprintf(fp, "\tcheck_execution_time=%.3f\n", temp_host->execution_time);
		fprintf(fp, "\tcheck_latency=%.3f\n", temp_host->latency);
		fprintf(fp, "\tcheck_type=%d\n", temp_host->check_type);
		fprintf(fp, "\tcurrent_state=%d\n", temp_host->current_state);
		fprintf(fp, "\tlast_hard_state=%d\n", temp_host->last_hard_state);
		fprintf(fp, "\tlast_event_id=%lu\n", temp_host->last_event_id);
		fprintf(fp, "\tcurrent_event_id=%lu\n", temp_host->current_event_id);
		fprintf(fp, "\tcurrent_problem_id=%lu\n", temp_host->current_problem_id);
		fprintf(fp, "\tlast_problem_id=%lu\n", temp_host->last_problem_id);
		fprintf(fp, "\tplugin_output=%s\n", (temp_host->plugin_output == NULL) ? "" : temp_host->plugin_output);
		fprintf(fp, "\tlong_plugin_output=%s\n", (temp_host->long_plugin_output == NULL) ? "" : temp_host->long_plugin_output);
		fprintf(fp, "\tperformance_data=%s\n", (temp_host->perf_data == NULL) ? "" : temp_host->perf_data);
		fprintf(fp, "\tlast_check=%lu\n", temp_host->last_check);
		fprintf(fp, "\tnext_check=%lu\n", temp_host->next_check);
		fprintf(fp, "\tcheck_options=%d\n", temp_host->check_options);
		fprintf(fp, "\tcurrent_attempt=%d\n", temp_host->current_attempt);
		fprintf(fp, "\tmax_attempts=%d\n", temp_host->max_attempts);
		fprintf(fp, "\tstate_type=%d\n", temp_host->state_type);
		fprintf(fp, "\tlast_state_change=%lu\n", temp_host->last_state_change);
		fprintf(fp, "\tlast_hard_state_change=%lu\n", temp_host->last_hard_state_change);
		fprintf(fp, "\tlast_time_up=%lu\n", temp_host->last_time_up);
		fprintf(fp, "\tlast_time_down=%lu\n", temp_host->last_time_down);
		fprintf(fp, "\tlast_time_unreachable=%lu\n", temp_host->last_time_unreachable);
		fprintf(fp, "\tlast_notification=%lu\n", temp_host->last_notification);
		fprintf(fp, "\tnext_notification=%lu\n", temp_host->next_notification);
		fprintf(fp, "\tno_more_notifications=%d\n", temp_host->no_more_notifications);
		fprintf(fp, "\tcurrent_notification_number=%d\n", temp_host->current_notification_number);
		fprintf(fp, "\tcurrent_notification_id=%lu\n", temp_host->current_notification_id);
		fprintf(fp, "\tnotifications_enabled=%d\n", temp_host->notifications_enabled);
		fprintf(fp, "\tproblem_has_been_acknowledged=%d\n", temp_host->problem_has_been_acknowledged);
		fprintf(fp, "\tacknowledgement_type=%d\n", temp_host->acknowledgement_type);
		fprintf(fp, "\tactive_checks_enabled=%d\n", temp_host->checks_enabled);
		fprintf(fp, "\tpassive_checks_enabled=%d\n", temp_host->accept_passive_checks);
		fprintf(fp, "\tevent_handler_enabled=%d\n", temp_host->event_handler_enabled);
		fprintf(fp, "\tflap_detection_enabled=%d\n", temp_host->flap_detection_enabled);
		fprintf(fp, "\tprocess_performance_data=%d\n", temp_host->process_performance_data);
		fprintf(fp, "\tobsess=%d\n", temp_host->obsess);
		fprintf(fp, "\tlast_update=%lu\n", current_time);
		fprintf(fp, "\tis_flapping=%d\n", temp_host->is_flapping);
		fprintf(fp, "\tpercent_state_change=%.2f\n", temp_host->percent_state_change);
		fprintf(fp, "\tscheduled_downtime_depth=%d\n", temp_host->scheduled_downtime_depth);
		/* custom variables */
		for (temp_customvariablesmember = temp_host->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) {
			if (temp_customvariablesmember->variable_name)
				fprintf(fp, "\t_%s=%d;%s\n", temp_customvariablesmember->variable_name, temp_customvariablesmember->has_been_modified, (temp_customvariablesmember->variable_value == NULL) ? "" : temp_customvariablesmember->variable_value);
		}
		fprintf(fp, "\t}\n\n");
	}

	/* save service status data */
	for (temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {

		fprintf(fp, "servicestatus {\n");
		fprintf(fp, "\thost_name=%s\n", temp_service->host_name);

		fprintf(fp, "\tservice_description=%s\n", temp_service->description);
		fprintf(fp, "\tmodified_attributes=%lu\n", temp_service->modified_attributes);
		fprintf(fp, "\tcheck_command=%s\n", (temp_service->check_command == NULL) ? "" : temp_service->check_command);
		fprintf(fp, "\tcheck_period=%s\n", (temp_service->check_period == NULL) ? "" : temp_service->check_period);
		fprintf(fp, "\tnotification_period=%s\n", (temp_service->notification_period == NULL) ? "" : temp_service->notification_period);
		fprintf(fp, "\tcheck_interval=%f\n", temp_service->check_interval);
		fprintf(fp, "\tretry_interval=%f\n", temp_service->retry_interval);
		fprintf(fp, "\tevent_handler=%s\n", (temp_service->event_handler == NULL) ? "" : temp_service->event_handler);

		fprintf(fp, "\thas_been_checked=%d\n", temp_service->has_been_checked);
		fprintf(fp, "\tshould_be_scheduled=%d\n", temp_service->should_be_scheduled);
		fprintf(fp, "\tcheck_execution_time=%.3f\n", temp_service->execution_time);
		fprintf(fp, "\tcheck_latency=%.3f\n", temp_service->latency);
		fprintf(fp, "\tcheck_type=%d\n", temp_service->check_type);
		fprintf(fp, "\tcurrent_state=%d\n", temp_service->current_state);
		fprintf(fp, "\tlast_hard_state=%d\n", temp_service->last_hard_state);
		fprintf(fp, "\tlast_event_id=%lu\n", temp_service->last_event_id);
		fprintf(fp, "\tcurrent_event_id=%lu\n", temp_service->current_event_id);
		fprintf(fp, "\tcurrent_problem_id=%lu\n", temp_service->current_problem_id);
		fprintf(fp, "\tlast_problem_id=%lu\n", temp_service->last_problem_id);
		fprintf(fp, "\tcurrent_attempt=%d\n", temp_service->current_attempt);
		fprintf(fp, "\tmax_attempts=%d\n", temp_service->max_attempts);
		fprintf(fp, "\tstate_type=%d\n", temp_service->state_type);
		fprintf(fp, "\tlast_state_change=%lu\n", temp_service->last_state_change);
		fprintf(fp, "\tlast_hard_state_change=%lu\n", temp_service->last_hard_state_change);
		fprintf(fp, "\tlast_time_ok=%lu\n", temp_service->last_time_ok);
		fprintf(fp, "\tlast_time_warning=%lu\n", temp_service->last_time_warning);
		fprintf(fp, "\tlast_time_unknown=%lu\n", temp_service->last_time_unknown);
		fprintf(fp, "\tlast_time_critical=%lu\n", temp_service->last_time_critical);
		fprintf(fp, "\tplugin_output=%s\n", (temp_service->plugin_output == NULL) ? "" : temp_service->plugin_output);
		fprintf(fp, "\tlong_plugin_output=%s\n", (temp_service->long_plugin_output == NULL) ? "" : temp_service->long_plugin_output);
		fprintf(fp, "\tperformance_data=%s\n", (temp_service->perf_data == NULL) ? "" : temp_service->perf_data);
		fprintf(fp, "\tlast_check=%lu\n", temp_service->last_check);
		fprintf(fp, "\tnext_check=%lu\n", temp_service->next_check);
		fprintf(fp, "\tcheck_options=%d\n", temp_service->check_options);
		fprintf(fp, "\tcurrent_notification_number=%d\n", temp_service->current_notification_number);
		fprintf(fp, "\tcurrent_notification_id=%lu\n", temp_service->current_notification_id);
		fprintf(fp, "\tlast_notification=%lu\n", temp_service->last_notification);
		fprintf(fp, "\tnext_notification=%lu\n", temp_service->next_notification);
		fprintf(fp, "\tno_more_notifications=%d\n", temp_service->no_more_notifications);
		fprintf(fp, "\tnotifications_enabled=%d\n", temp_service->notifications_enabled);
		fprintf(fp, "\tactive_checks_enabled=%d\n", temp_service->checks_enabled);
		fprintf(fp, "\tpassive_checks_enabled=%d\n", temp_service->accept_passive_checks);
		fprintf(fp, "\tevent_handler_enabled=%d\n", temp_service->event_handler_enabled);
		fprintf(fp, "\tproblem_has_been_acknowledged=%d\n", temp_service->problem_has_been_acknowledged);
		fprintf(fp, "\tacknowledgement_type=%d\n", temp_service->acknowledgement_type);
		fprintf(fp, "\tflap_detection_enabled=%d\n", temp_service->flap_detection_enabled);
		fprintf(fp, "\tprocess_performance_data=%d\n", temp_service->process_performance_data);
		fprintf(fp, "\tobsess=%d\n", temp_service->obsess);
		fprintf(fp, "\tlast_update=%lu\n", current_time);
		fprintf(fp, "\tis_flapping=%d\n", temp_service->is_flapping);
		fprintf(fp, "\tpercent_state_change=%.2f\n", temp_service->percent_state_change);
		fprintf(fp, "\tscheduled_downtime_depth=%d\n", temp_service->scheduled_downtime_depth);
		/* custom variables */
		for (temp_customvariablesmember = temp_service->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) {
			if (temp_customvariablesmember->variable_name)
				fprintf(fp, "\t_%s=%d;%s\n", temp_customvariablesmember->variable_name, temp_customvariablesmember->has_been_modified, (temp_customvariablesmember->variable_value == NULL) ? "" : temp_customvariablesmember->variable_value);
		}
		fprintf(fp, "\t}\n\n");
	}

	/* save contact status data */
	for (temp_contact = contact_list; temp_contact != NULL; temp_contact = temp_contact->next) {

		fprintf(fp, "contactstatus {\n");
		fprintf(fp, "\tcontact_name=%s\n", temp_contact->name);

		fprintf(fp, "\tmodified_attributes=%lu\n", temp_contact->modified_attributes);
		fprintf(fp, "\tmodified_host_attributes=%lu\n", temp_contact->modified_host_attributes);
		fprintf(fp, "\tmodified_service_attributes=%lu\n", temp_contact->modified_service_attributes);
		fprintf(fp, "\thost_notification_period=%s\n", (temp_contact->host_notification_period == NULL) ? "" : temp_contact->host_notification_period);
		fprintf(fp, "\tservice_notification_period=%s\n", (temp_contact->service_notification_period == NULL) ? "" : temp_contact->service_notification_period);

		fprintf(fp, "\tlast_host_notification=%lu\n", temp_contact->last_host_notification);
		fprintf(fp, "\tlast_service_notification=%lu\n", temp_contact->last_service_notification);
		fprintf(fp, "\thost_notifications_enabled=%d\n", temp_contact->host_notifications_enabled);
		fprintf(fp, "\tservice_notifications_enabled=%d\n", temp_contact->service_notifications_enabled);
		/* custom variables */
		for (temp_customvariablesmember = temp_contact->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) {
			if (temp_customvariablesmember->variable_name)
				fprintf(fp, "\t_%s=%d;%s\n", temp_customvariablesmember->variable_name, temp_customvariablesmember->has_been_modified, (temp_customvariablesmember->variable_value == NULL) ? "" : temp_customvariablesmember->variable_value);
		}
		fprintf(fp, "\t}\n\n");
	}

	/* save all comments */
	for (temp_comment = comment_list; temp_comment != NULL; temp_comment = temp_comment->next) {

		if (temp_comment->comment_type == HOST_COMMENT)
			fprintf(fp, "hostcomment {\n");
		else
			fprintf(fp, "servicecomment {\n");
		fprintf(fp, "\thost_name=%s\n", temp_comment->host_name);
		if (temp_comment->comment_type == SERVICE_COMMENT)
			fprintf(fp, "\tservice_description=%s\n", temp_comment->service_description);
		fprintf(fp, "\tentry_type=%d\n", temp_comment->entry_type);
		fprintf(fp, "\tcomment_id=%lu\n", temp_comment->comment_id);
		fprintf(fp, "\tsource=%d\n", temp_comment->source);
		fprintf(fp, "\tpersistent=%d\n", temp_comment->persistent);
		fprintf(fp, "\tentry_time=%lu\n", temp_comment->entry_time);
		fprintf(fp, "\texpires=%d\n", temp_comment->expires);
		fprintf(fp, "\texpire_time=%lu\n", temp_comment->expire_time);
		fprintf(fp, "\tauthor=%s\n", temp_comment->author);
		fprintf(fp, "\tcomment_data=%s\n", temp_comment->comment_data);
		fprintf(fp, "\t}\n\n");
	}

	/* save all downtime */
	for (temp_downtime = scheduled_downtime_list; temp_downtime != NULL; temp_downtime = temp_downtime->next) {

		if (temp_downtime->type == HOST_DOWNTIME)
			fprintf(fp, "hostdowntime {\n");
		else
			fprintf(fp, "servicedowntime {\n");
		fprintf(fp, "\thost_name=%s\n", temp_downtime->host_name);
		if (temp_downtime->type == SERVICE_DOWNTIME)
			fprintf(fp, "\tservice_description=%s\n", temp_downtime->service_description);
		fprintf(fp, "\tdowntime_id=%lu\n", temp_downtime->downtime_id);
		fprintf(fp, "\tcomment_id=%lu\n", temp_downtime->comment_id);
		fprintf(fp, "\tentry_time=%lu\n", temp_downtime->entry_time);
		fprintf(fp, "\tstart_time=%lu\n", temp_downtime->start_time);
		fprintf(fp, "\tflex_downtime_start=%lu\n", temp_downtime->flex_downtime_start);
		fprintf(fp, "\tend_time=%lu\n", temp_downtime->end_time);
		fprintf(fp, "\ttriggered_by=%lu\n", temp_downtime->triggered_by);
		fprintf(fp, "\tfixed=%d\n", temp_downtime->fixed);
		fprintf(fp, "\tduration=%lu\n", temp_downtime->duration);
		fprintf(fp, "\tis_in_effect=%d\n", temp_downtime->is_in_effect);
		fprintf(fp, "\tstart_notification_sent=%d\n", temp_downtime->start_notification_sent);
		fprintf(fp, "\tauthor=%s\n", temp_downtime->author);
		fprintf(fp, "\tcomment=%s\n", temp_downtime->comment);
		fprintf(fp, "\t}\n\n");
	}


	/* reset file permissions */
	fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);

	/* flush the file to disk */
	fflush(fp);

	/* fsync the file so that it is completely written out before moving it */
	fsync(fd);

	/* close the temp file */
	result = fclose(fp);

	/* save/close was successful */
	if (result == 0) {

		result = OK;

		/* move the temp file to the status log (overwrite the old status log) */
		if (my_rename(tmp_log, status_file)) {
			unlink(tmp_log);
			logit(NSLOG_RUNTIME_ERROR,
			      "Error: Unable to update status data file '%s': %s", status_file, strerror(errno));
			result = ERROR;
		}
	}

	/* a problem occurred saving the file */
	else {

		result = ERROR;

		/* remove temp file and log an error */
		unlink(tmp_log);
		logit(NSLOG_RUNTIME_ERROR,
		      "Error: Unable to save status file: %s", strerror(errno));
	}

	/* free memory */
	my_free(tmp_log);

	return result;
}
Example #8
0
LIBSTDCL_API CONTEXT* 
clcontext_create( 
	const char* platform_name, 
	int devtyp, 
	size_t ndevmax,
	cl_context_properties* ctxprop_ext, 
	int lock_key
)
{

	int n;
	int err = 0;
	int i;
	size_t devlist_sz;
	CONTEXT* cp = 0;
	cl_platform_id* platforms = 0;
	cl_uint nplatforms;
	char info[1024];
	cl_platform_id platformid;
	int nctxprop = 0;
	cl_context_properties* ctxprop;
	size_t sz;
	cl_uint ndev = 0;
	cl_command_queue_properties prop = 0;

	DEBUG(__FILE__,__LINE__,"clcontext_create() called");


//	if (ndevmax) 
//		WARN(__FILE__,__LINE__,"__clcontext_create(): ndevmax argument ignored");


	/***
	 *** allocate CONTEXT struct
	 ***/

	DEBUG(__FILE__,__LINE__,
		"clcontext_create: sizeof CONTEXT %d",sizeof(CONTEXT));

//	cp = (CONTEXT*)malloc(sizeof(CONTEXT));
	assert(sizeof(CONTEXT)<getpagesize());
#ifdef _WIN64
	cp = (CONTEXT*)_aligned_malloc(sizeof(CONTEXT),getpagesize());
	if (!cp) {
		WARN(__FILE__,__LINE__,"memalign failed");
	}
#else
	if (posix_memalign((void**)&cp,getpagesize(),sizeof(CONTEXT))) {
		WARN(__FILE__,__LINE__,"posix_memalign failed");
	}
#endif

	DEBUG(__FILE__,__LINE__,"clcontext_create: context_ptr=%p",cp);
	
	if ((intptr_t)cp & (getpagesize()-1)) {
		ERROR(__FILE__,__LINE__,
			"clcontext_create: fatal error: unaligned context_ptr");
		exit(-1);
	}

	if (!cp) { errno=ENOMEM; return(0); }

	

   /***
    *** get platform id
    ***/



   clGetPlatformIDs(0,0,&nplatforms);

//	printf("XXX %d\n",nplatforms);

   if (nplatforms) {

      platforms = (cl_platform_id*)malloc(nplatforms*sizeof(cl_platform_id));
      clGetPlatformIDs(nplatforms,platforms,0);

      for(i=0;i<nplatforms;i++) { 

         char info[1024];

         DEBUG(__FILE__,__LINE__,"_libstdcl_init: available platform:");

         clGetPlatformInfo(platforms[i],CL_PLATFORM_PROFILE,1024,info,0);
         DEBUG(__FILE__,__LINE__,
            "_libstdcl_init: [%p]CL_PLATFORM_PROFILE=%s",platforms[i],info);

         clGetPlatformInfo(platforms[i],CL_PLATFORM_VERSION,1024,info,0);
         DEBUG(__FILE__,__LINE__,
            "_libstdcl_init: [%p]CL_PLATFORM_VERSION=%s",platforms[i],info);

         clGetPlatformInfo(platforms[i],CL_PLATFORM_NAME,1024,info,0);
         DEBUG(__FILE__,__LINE__,
            "_libstdcl_init: [%p]CL_PLATFORM_NAME=%s",platforms[i],info);

         clGetPlatformInfo(platforms[i],CL_PLATFORM_VENDOR,1024,info,0);
         DEBUG(__FILE__,__LINE__,
            "_libstdcl_init: [%p]CL_PLATFORM_VENDOR=%s",platforms[i],info);

         clGetPlatformInfo(platforms[i],CL_PLATFORM_EXTENSIONS,1024,info,0);
         DEBUG(__FILE__,__LINE__,
            "_libstdcl_init: [%p]CL_PLATFORM_EXTENSIONS=%s",platforms[i],info);

      }

   } else {

      WARN(__FILE__,__LINE__,
         "_libstdcl_init: no platforms found, continue and hope for the best");

   }

	platformid 
		= __get_platformid(nplatforms, platforms, platform_name);

	DEBUG(__FILE__,__LINE__,"clcontext_create: platformid=%p",platformid);

	

	/***
	 *** create context
	 ***/

	

	while (ctxprop_ext != 0 && ctxprop_ext[nctxprop] != 0) ++nctxprop;

//	cl_context_properties ctxprop[3] = {
//		(cl_context_properties)CL_CONTEXT_PLATFORM,
//		(cl_context_properties)platformid,
//		(cl_context_properties)0
//	};

	nctxprop += 3;

	ctxprop = (cl_context_properties*)malloc(nctxprop*sizeof(cl_context_properties));

	ctxprop[0] = (cl_context_properties)CL_CONTEXT_PLATFORM;
	ctxprop[1] = (cl_context_properties)platformid;

	for(i=0;i<nctxprop-3;i++) ctxprop[2+i] = ctxprop_ext[i];

	ctxprop[nctxprop-1] =  (cl_context_properties)0;

	

	clGetPlatformInfo(platformid,CL_PLATFORM_PROFILE,0,0,&sz);
	cp->platform_profile = (char*)malloc(sz);
	clGetPlatformInfo(platformid,CL_PLATFORM_PROFILE,sz,cp->platform_profile,0);

	clGetPlatformInfo(platformid,CL_PLATFORM_VERSION,0,0,&sz);
	cp->platform_version = (char*)malloc(sz);
	clGetPlatformInfo(platformid,CL_PLATFORM_VERSION,sz,cp->platform_version,0);

	clGetPlatformInfo(platformid,CL_PLATFORM_NAME,0,0,&sz);
	cp->platform_name = (char*)malloc(sz);
	clGetPlatformInfo(platformid,CL_PLATFORM_NAME,sz,cp->platform_name,0);

	clGetPlatformInfo(platformid,CL_PLATFORM_VENDOR,0,0,&sz);
	cp->platform_vendor = (char*)malloc(sz);
	clGetPlatformInfo(platformid,CL_PLATFORM_VENDOR,sz,cp->platform_vendor,0);

	clGetPlatformInfo(platformid,CL_PLATFORM_EXTENSIONS,0,0,&sz);
	cp->platform_extensions = (char*)malloc(sz);
	clGetPlatformInfo(platformid,CL_PLATFORM_EXTENSIONS,sz,
		cp->platform_extensions,0);


#ifdef _WIN64
	cp->ctx = clCreateContextFromType(ctxprop,devtyp,0,0,&err);
#else

	if (lock_key > 0) {

		if (ndevmax == 0) ndevmax = 1;

		cl_uint platform_ndev;
		err = clGetDeviceIDs(platformid,devtyp,0,0,&platform_ndev);
//		cl_uint platform_vndev = 2*platform_ndev;
		cl_uint platform_vndev = platform_ndev;

//DEBUG(__FILE__,__LINE__,"%d %d",platform_ndev,platform_vndev);
	
		cl_device_id* platform_dev 
			= (cl_device_id*)malloc(platform_ndev*sizeof(cl_device_id));

		err = clGetDeviceIDs(platformid,devtyp,platform_ndev,platform_dev,0);

		DEBUG(__FILE__,__LINE__,"clcontext_create: lock_key=%d",lock_key);

		pid_t pid = getpid();

		size_t sz_page = getpagesize();

//		system("ls /dev/shm");

		char shmobj[64];
		snprintf(shmobj,64,"/stdcl_ctx_lock%d.%d",devtyp,lock_key);

		DEBUG(__FILE__,__LINE__,
			"clcontext_create: attempt master shm_open %s from %d",shmobj,pid);

		int fd = shm_open(shmobj,O_RDWR|O_CREAT|O_EXCL,0);
		void* p0;

		struct timeval t0,t1;
		int timeout = 0;

		int noff = 0;

		if (fd < 0) {
			
			DEBUG(__FILE__,__LINE__,
				"clcontext_create: master shm_open failed from %d (%d)",pid,fd);

			DEBUG(__FILE__,__LINE__,
				"clcontext_create: attempt slave shm_open from %d",pid);

			timeout = 0;
			gettimeofday(&t0,0);
			t0.tv_sec += 10;

			do {
	
				fd = shm_open(shmobj,O_RDWR,0);
				gettimeofday(&t1,0);

				if (t1.tv_sec > t0.tv_sec && t1.tv_usec > t0.tv_usec) timeout = 1;

			} while (fd < 0 && !timeout);

			if (timeout) {

				ERROR(__FILE__,__LINE__,"clcontext_create: shm_open timeout");

			}

			ftruncate(fd,sz_page);

			p0 = mmap(0,sz_page,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);

			if (!p0) return(0);

			__ctx_lock = (struct __ctx_lock_struct*)p0;

			pthread_mutex_lock(&__ctx_lock->mtx);
//			if (__ctx_lock->refc < platform_ndev) {
			if (__ctx_lock->refc < platform_vndev) {
				noff = __ctx_lock->refc;
//				ndev = min(ndevmax,platform_ndev-noff);
				ndev = min(ndevmax,platform_vndev-noff);
				__ctx_lock->refc += ndev;
			}
			pthread_mutex_unlock(&__ctx_lock->mtx);

			close(fd);

		} else {

			DEBUG(__FILE__,__LINE__,
				"clcontext_create: master shm_open succeeded from %d",pid);

			ftruncate(fd,sz_page);

			p0 = mmap(0,sz_page,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);

			if (!p0) return(0);

			__ctx_lock = (struct __ctx_lock_struct*)p0;

			__ctx_lock->magic = 20110415;
			__ctx_lock->key = lock_key;
			pthread_mutex_init(&__ctx_lock->mtx,0);
//			ndev = min(ndevmax,platform_ndev);
			ndev = min(ndevmax,platform_vndev);
		DEBUG(__FILE__,__LINE__,"ndev=%d %d %d",ndev,ndevmax,platform_vndev);
			__ctx_lock->refc = ndev;

			fchmod(fd,S_IRUSR|S_IWUSR);

			close(fd);

		}

		DEBUG(__FILE__,__LINE__,"ndev=%d",ndev);

//		if (noff < platform_ndev) {
		if (noff < platform_vndev) {

//			cp->ctx = clCreateContext(ctxprop,ndev,platform_dev + noff,0,0,&err);
			cp->ctx = clCreateContext(ctxprop,ndev,platform_dev + noff%platform_ndev,0,0,&err);

			DEBUG(__FILE__,__LINE__,
				"clcontext_create: platform_ndev=%d ndev=%d noffset=%d",
				platform_ndev,ndev,noff);

			if (platform_dev) free(platform_dev);

		} else {

			cp->ctx = 0;

		}

	} else {

		cp->ctx = clCreateContextFromType(ctxprop,devtyp,0,0,&err);

	}
#endif

	if (cp->ctx) {

		cp->devtyp = devtyp;
		err = clGetContextInfo(cp->ctx,CL_CONTEXT_DEVICES,0,0,&devlist_sz);
		cp->ndev = devlist_sz/sizeof(cl_device_id);
		cp->dev = (cl_device_id*)malloc(10*devlist_sz);
		err=clGetContextInfo(cp->ctx,CL_CONTEXT_DEVICES,devlist_sz,cp->dev,0);

//		cp->devtyp = devtyp;
//		err = clGetDeviceIDs(platformid,devtyp,0,0,&(cp->ndev));
//		DEBUG(__FILE__,__LINE__,"xxx %d",err);
//		DEBUG(__FILE__,__LINE__,"number of devices %d",cp->ndev);
//		cp->dev = (cl_device_id*)malloc(cp->ndev * sizeof(cl_device_id) );
//		err = clGetDeviceIDs(platformid,devtyp,cp->ndev,cp->dev,&(cp->ndev));
//		DEBUG(__FILE__,__LINE__,"xxx %d",err);
//		DEBUG(__FILE__,__LINE__," %p device[0]",cp->dev[0]);

		
	} else {

		WARN(__FILE__,__LINE__,"clcontext_create: failed");

#ifndef _WIN64
		if (lock_key > 0 && ndev > 0) {
			pthread_mutex_lock(&__ctx_lock->mtx);
			__ctx_lock->refc -= ndev;
			pthread_mutex_unlock(&__ctx_lock->mtx);
		}

		free(cp);
#else
		_aligned_free(cp);
#endif

      return((CONTEXT*)0);

   }


	DEBUG(__FILE__,__LINE__,"number of devices %d",cp->ndev);

		
	/* XXX XXX TESTING ONLY!!!! */
	//_aligned_free(cp);
	//DEBUG(__FILE__,__LINE__,"MADE IT"); return (CONTEXT*)0;


	/***
	 *** create command queues
	 ***/

	cp->cmdq = (cl_command_queue*)malloc(sizeof(cl_command_queue)*cp->ndev);

	DEBUG(__FILE__,__LINE__,"will try to create cmdq");

	

// XXX something is broken in clCreateCommandQueue, using lazy creation
// XXX as a workaround -DAR
//	{
		//cl_command_queue_properties prop = 00;
		//prop |= CL_QUEUE_PROFILING_ENABLE; /* XXX this should be choice -DAR */
		for(i=0;i<cp->ndev;i++) {
			//DEBUG(__FILE__,__LINE__,"%d calling clCreateCommandQueue(%p,%p,%x,%p)",i,cp->ctx,cp->dev[i],prop,&err);
#ifdef _WIN64
			cp->cmdq[i] = 0; /* have to defer, dllmain limitations */
#else
			cp->cmdq[i] = clCreateCommandQueue(cp->ctx,cp->dev[i],prop,&err);
			//cp->cmdq[i] = clCreateCommandQueue(cp->ctx,cp->dev[i],0,&err);
			//cl_command_queue cmdq = clCreateCommandQueue(cp->ctx,cp->dev[0],0,&err);

			DEBUG(__FILE__,__LINE__,"clcontext_create: error from create cmdq %d (%p)\n",
				err,cp->cmdq[i]);
#endif
			//DEBUG(__FILE__,__LINE__,"MADE IT"); return (CONTEXT*)0;
		}
//	}
//	printf("WARNING CMDQs NOT CREATED\n");
//	for(i=0;i<cp->ndev;i++) cp->cmdq[i] = (cl_command_queue)0;



	/***
	 *** init context resources
	 ***/

	LIST_INIT(&cp->prgs_listhead);

	LIST_INIT(&cp->txt_listhead);

	LIST_INIT(&cp->memd_listhead);


//	struct _prgs_struct* prgs 
//		= (struct _prgs_struct*)malloc(sizeof(struct _prgs_struct));
//	prgs->len=-1;
//	LIST_INSERT_HEAD(&cp->prgs_listhead, prgs, prgs_list);
//
//	prgs = (struct _prgs_struct*)malloc(sizeof(struct _prgs_struct));
//	prgs->len=-2;
//	LIST_INSERT_HEAD(&cp->prgs_listhead, prgs, prgs_list);

/*
	printf("%p searching _proc_cl for prgs...\n",_proc_cl.clstrtab);
	printf("%s\n",&_proc_cl.clstrtab[1]);
	struct clprgs_entry* sp;
	for(n=0,sp=_proc_cl.clprgs;n<_proc_cl.clprgs_n;n++,sp++) {
		printf("found %s (%d bytes)\n",&_proc_cl.clstrtab[sp->e_name],sp->e_size);
		struct _prgs_struct* prgs = (struct _prgs_struct*)
			clload(cp,_proc_cl.cltexts+sp->e_offset,sp->e_size,0);
	}
*/


	/*** 
	 *** initialize event lists
	 ***/
	
//	cp->nkev = cp->kev_first = cp->kev_free = 0;
	cp->kev = (struct _event_list_struct*)
		malloc(cp->ndev*sizeof(struct _event_list_struct));

	for(i=0;i<cp->ndev;i++) {
		cp->kev[i].nev = cp->kev[i].ev_first = cp->kev[i].ev_free = 0;
	}

//	cp->nmev = cp->mev_first = cp->mev_free = 0;
	cp->mev = (struct _event_list_struct*)
		malloc(cp->ndev*sizeof(struct _event_list_struct));

	for(i=0;i<cp->ndev;i++) {
		cp->mev[i].nev = cp->mev[i].ev_first = cp->mev[i].ev_free = 0;
	}

//#ifdef ENABLE_CLEXPORT
//	cp->ndev_v = 0;
//	cp->extd = 0;
//	cp->imtd = 0;
//#endif


	if (platforms) free(platforms);

	return(cp);

}
int VolumeManager::createAsec(const char *id, unsigned int numSectors, const char *fstype,
        const char *key, const int ownerUid, bool isExternal) {
    struct asec_superblock sb;
    memset(&sb, 0, sizeof(sb));

    const bool wantFilesystem = strcmp(fstype, "none");
    bool usingExt4 = false;
    if (wantFilesystem) {
        usingExt4 = !strcmp(fstype, "ext4");
        if (usingExt4) {
            sb.c_opts |= ASEC_SB_C_OPTS_EXT4;
        } else if (strcmp(fstype, "fat")) {
            SLOGE("Invalid filesystem type %s", fstype);
            errno = EINVAL;
            return -1;
        }
    }

    sb.magic = ASEC_SB_MAGIC;
    sb.ver = ASEC_SB_VER;

    if (numSectors < ((1024*1024)/512)) {
        SLOGE("Invalid container size specified (%d sectors)", numSectors);
        errno = EINVAL;
        return -1;
    }

    if (lookupVolume(id)) {
        SLOGE("ASEC id '%s' currently exists", id);
        errno = EADDRINUSE;
        return -1;
    }

    char asecFileName[255];

    if (!findAsec(id, asecFileName, sizeof(asecFileName))) {
        SLOGE("ASEC file '%s' currently exists - destroy it first! (%s)",
                asecFileName, strerror(errno));
        errno = EADDRINUSE;
        return -1;
    }

    const char *asecDir = isExternal ? Volume::SEC_ASECDIR_EXT : Volume::SEC_ASECDIR_INT;

    int written = snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", asecDir, id);
    if ((written < 0) || (size_t(written) >= sizeof(asecFileName))) {
        errno = EINVAL;
        return -1;
    }

    if (!access(asecFileName, F_OK)) {
        SLOGE("ASEC file '%s' currently exists - destroy it first! (%s)",
                asecFileName, strerror(errno));
        errno = EADDRINUSE;
        return -1;
    }

    /*
     * Add some headroom
     */
    unsigned fatSize = (((numSectors * 4) / 512) + 1) * 2;
    unsigned numImgSectors = numSectors + fatSize + 2;

    if (numImgSectors % 63) {
        numImgSectors += (63 - (numImgSectors % 63));
    }

    // Add +1 for our superblock which is at the end
    if (Loop::createImageFile(asecFileName, numImgSectors + 1)) {
        SLOGE("ASEC image file creation failed (%s)", strerror(errno));
        return -1;
    }

    char idHash[33];
    if (!asecHash(id, idHash, sizeof(idHash))) {
        SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
        unlink(asecFileName);
        return -1;
    }

    char loopDevice[255];
    if (Loop::create(idHash, asecFileName, loopDevice, sizeof(loopDevice))) {
        SLOGE("ASEC loop device creation failed (%s)", strerror(errno));
        unlink(asecFileName);
        return -1;
    }

    char dmDevice[255];
    bool cleanupDm = false;

    if (strcmp(key, "none")) {
        // XXX: This is all we support for now
        sb.c_cipher = ASEC_SB_C_CIPHER_TWOFISH;
        if (Devmapper::create(idHash, loopDevice, key, numImgSectors, dmDevice,
                             sizeof(dmDevice))) {
            SLOGE("ASEC device mapping failed (%s)", strerror(errno));
            Loop::destroyByDevice(loopDevice);
            unlink(asecFileName);
            return -1;
        }
        cleanupDm = true;
    } else {
        sb.c_cipher = ASEC_SB_C_CIPHER_NONE;
        strcpy(dmDevice, loopDevice);
    }

    /*
     * Drop down the superblock at the end of the file
     */

    int sbfd = open(loopDevice, O_RDWR);
    if (sbfd < 0) {
        SLOGE("Failed to open new DM device for superblock write (%s)", strerror(errno));
        if (cleanupDm) {
            Devmapper::destroy(idHash);
        }
        Loop::destroyByDevice(loopDevice);
        unlink(asecFileName);
        return -1;
    }

    if (lseek(sbfd, (numImgSectors * 512), SEEK_SET) < 0) {
        close(sbfd);
        SLOGE("Failed to lseek for superblock (%s)", strerror(errno));
        if (cleanupDm) {
            Devmapper::destroy(idHash);
        }
        Loop::destroyByDevice(loopDevice);
        unlink(asecFileName);
        return -1;
    }

    if (write(sbfd, &sb, sizeof(sb)) != sizeof(sb)) {
        close(sbfd);
        SLOGE("Failed to write superblock (%s)", strerror(errno));
        if (cleanupDm) {
            Devmapper::destroy(idHash);
        }
        Loop::destroyByDevice(loopDevice);
        unlink(asecFileName);
        return -1;
    }
    close(sbfd);

    if (wantFilesystem) {
        int formatStatus;
        char mountPoint[255];

        int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
        if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
            SLOGE("ASEC fs format failed: couldn't construct mountPoint");
            if (cleanupDm) {
                Devmapper::destroy(idHash);
            }
            Loop::destroyByDevice(loopDevice);
            unlink(asecFileName);
            return -1;
        }

        if (usingExt4) {
            formatStatus = Ext4::format(dmDevice, mountPoint);
        } else {
            formatStatus = Fat::format(dmDevice, numImgSectors, 0);
        }

        if (formatStatus < 0) {
            SLOGE("ASEC fs format failed (%s)", strerror(errno));
            if (cleanupDm) {
                Devmapper::destroy(idHash);
            }
            Loop::destroyByDevice(loopDevice);
            unlink(asecFileName);
            return -1;
        }

        if (mkdir(mountPoint, 0000)) {
            if (errno != EEXIST) {
                SLOGE("Mountpoint creation failed (%s)", strerror(errno));
                if (cleanupDm) {
                    Devmapper::destroy(idHash);
                }
                Loop::destroyByDevice(loopDevice);
                unlink(asecFileName);
                return -1;
            }
        }

        int mountStatus;
        if (usingExt4) {
            mountStatus = Ext4::doMount(dmDevice, mountPoint, false, false, false, false);
        } else {
            mountStatus = Fat::doMount(dmDevice, mountPoint, false, false, false, ownerUid, 0, 0000,
                    false);
        }

        if (mountStatus) {
            SLOGE("ASEC FAT mount failed (%s)", strerror(errno));
            if (cleanupDm) {
                Devmapper::destroy(idHash);
            }
            Loop::destroyByDevice(loopDevice);
            unlink(asecFileName);
            return -1;
        }

        if (usingExt4) {
            int dirfd = open(mountPoint, O_DIRECTORY);
            if (dirfd >= 0) {
                if (fchown(dirfd, ownerUid, AID_SYSTEM)
                        || fchmod(dirfd, S_IRUSR | S_IWUSR | S_IXUSR | S_ISGID | S_IRGRP | S_IXGRP)) {
                    SLOGI("Cannot chown/chmod new ASEC mount point %s", mountPoint);
                }
                close(dirfd);
            }
        }
    } else {
        SLOGI("Created raw secure container %s (no filesystem)", id);
    }

    mActiveContainers->push_back(new ContainerData(strdup(id), ASEC));
    return 0;
}
Example #10
0
int 
main(int argc, char *argv[])
{
        int fd;

        char* mount_point;

        struct mntent *mnt;
        FILE* mtab;
        FILE* new_mtab;

        progname = argv[0];

        if (argc != 2) {
                usage();
                exit(1);
        }

        if (geteuid() != 0) {
                fprintf(stderr, "%s must be installed suid root\n", progname);
                exit(1);
        }

        mount_point = canonicalize(argv[1]);

	if (mount_point == NULL)
	{
		exit(1);
	}

        if (umount_ok(mount_point) != 0) {
                exit(1);
        }

        if (umount(mount_point) != 0) {
                fprintf(stderr, "Could not umount %s: %s\n",
                        mount_point, strerror(errno));
                exit(1);
        }

#ifndef EMBED
        if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1)
        {
                fprintf(stderr, "Can't get "MOUNTED"~ lock file");
                return 1;
        }
        close(fd);
	
        if ((mtab = setmntent(MOUNTED, "r")) == NULL) {
                fprintf(stderr, "Can't open " MOUNTED ": %s\n",
                        strerror(errno));
                return 1;
        }

#define MOUNTED_TMP MOUNTED".tmp"

        if ((new_mtab = setmntent(MOUNTED_TMP, "w")) == NULL) {
                fprintf(stderr, "Can't open " MOUNTED_TMP ": %s\n",
                        strerror(errno));
                endmntent(mtab);
                return 1;
        }

        while ((mnt = getmntent(mtab)) != NULL) {
                if (strcmp(mnt->mnt_dir, mount_point) != 0) {
                        addmntent(new_mtab, mnt);
                }
        }

        endmntent(mtab);

        if (fchmod (fileno (new_mtab), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
                fprintf(stderr, "Error changing mode of %s: %s\n",
                        MOUNTED_TMP, strerror(errno));
                exit(1);
        }

        endmntent(new_mtab);

        if (rename(MOUNTED_TMP, MOUNTED) < 0) {
                fprintf(stderr, "Cannot rename %s to %s: %s\n",
                        MOUNTED, MOUNTED_TMP, strerror(errno));
                exit(1);
        }

        if (unlink(MOUNTED"~") == -1)
        {
                fprintf(stderr, "Can't remove "MOUNTED"~");
                return 1;
        }
#endif /* EMBED */

	return 0;
}	
Example #11
0
/*
 * klog_rotate() - roate a log file if we have specified rotation
 * parameters in krb5.conf.
 */
static void
klog_rotate(struct log_entry *le)
{
	time_t t;
	int i;
	char *name_buf1;
	char *name_buf2;
	char *old_name;
	char *new_name;
	char *tmp;
	FILE *fp;
	int num_vers;

	/*
	 * By default we don't rotate.
	 */
	if (le->lfu_rotate_period == K_LOG_DEF_FILE_ROTATE_PERIOD)
		return;

	t = time(0);

	if (t >= le->lfu_last_rotated + le->lfu_rotate_period) {
		/*
		 * The N log file versions will be renamed X.N-1 X.N-2, ... X.0.
		 * So the allocate file name buffers that can the version
		 * number extensions.
		 * 32 extra bytes is plenty.
		 */
		name_buf1 = malloc(strlen(le->lfu_fname) + 32);

		if (name_buf1 == NULL)
			return;

		name_buf2 = malloc(strlen(le->lfu_fname) + 32);

		if (name_buf2 == NULL) {
			free(name_buf1);
			return;
		}

		old_name = name_buf1;
		new_name = name_buf2;

		/*
		 * If there N versions, then the first one has file extension
		 * of N-1.
		 */
		(void) sprintf(new_name, "%s.%d", le->lfu_fname,
			le->lfu_rotate_versions - 1);

		/*
		 * Rename file.N-2 to file.N-1, file.N-3 to file.N-2, ... 
		 * file.0 to file.1
		 */
		for (i = le->lfu_rotate_versions - 1; i > 0; i--) {
			(void) sprintf(old_name, "%s.%d", le->lfu_fname, i - 1);
			(void) rename(old_name, new_name);

			/*
			 * swap old name and new name. This way,
			 * on the next iteration, new_name.X
			 * becomes new_name.X-1.
			 */
			tmp = old_name;
			old_name = new_name;
			new_name = tmp;
		}
		old_name = le->lfu_fname;

		(void) rename(old_name, new_name);

		/*
		 * Even though we don't know yet if the fopen()
		 * of the log file will succeed, we mark the log
		 * as rotated. This is so we don't repeatably
		 * rotate file.N-2 to file.N-1 ... etc without
		 * waiting for the rotate period to elapse.
		 */
		le->lfu_last_rotated = t;

		fp = fopen(old_name, le->lfu_fopen_mode);

		if (fp != NULL) {

			/* Set the permissions to 644 */
			if (fchmod(fileno(fp),
			    S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) == -1) {
			fprintf(stderr,
gettext("During rotate, couldn't set permissions for log file %s: %s\n"),
				old_name, error_message(errno));
			}

			(void) fclose(le->lfu_filep);
			le->lfu_filep = fp;

			/*
			 * If the version parameter in krb5.conf was
			 * 0, then we take this to mean that rotating the
			 * log file will cause us to dispose of the
			 * old one, and created a new one. We have just
			 * renamed the old one to file.-1, so remove it.
			 */ 
			if (le->lfu_rotate_versions <= 0)
				(void) unlink(new_name);

		} else {
			fprintf(stderr,
		gettext("During rotate, couldn't open log file %s: %s\n"),
				old_name, error_message(errno));
			/*
			 * Put it back.
			 */
			(void) rename(new_name, old_name);
		}
		free(name_buf1);
		free(name_buf2);
	}
}
Example #12
0
/* callback: net_connect() finished for DCC GET */
void sig_dccget_connected(GET_DCC_REC *dcc)
{
	struct stat statbuf;
	char *fname, *tempfname, *str;
        int ret, ret_errno, temphandle, old_umask;

	if (!dcc->from_dccserver) {
		if (net_geterror(dcc->handle) != 0) {
			/* error connecting */
			signal_emit("dcc error connect", 1, dcc);
			dcc_destroy(DCC(dcc));
			return;
		}

		g_source_remove(dcc->tagconn);
		dcc->tagconn = -1;
	}

	g_free_not_null(dcc->file);
	dcc->file = dcc_get_download_path(dcc->arg);

	/* if some plugin wants to change the file name/path here.. */
	signal_emit("dcc get receive", 1, dcc);

	if (stat(dcc->file, &statbuf) == 0 &&
	    dcc->get_type == DCC_GET_RENAME) {
		/* file exists, rename.. */
		fname = dcc_get_rename_file(dcc->file);
		g_free(dcc->file);
		dcc->file = fname;
	}

	if (dcc->get_type != DCC_GET_RESUME) {
		int dcc_file_create_mode = octal2dec(settings_get_int("dcc_file_create_mode"));

		/* we want to overwrite the file, remove it here.
		   if it gets created after this, we'll fail. */
		unlink(dcc->file);

		/* just to make sure we won't run into race conditions
		   if download_path is in some global temp directory */
		tempfname = g_strconcat(dcc->file, ".XXXXXX", NULL);

                old_umask = umask(0077);
		temphandle = mkstemp(tempfname);
		umask(old_umask);

		if (temphandle == -1)
			ret = -1;
		else
			ret = fchmod(temphandle, dcc_file_create_mode);

		if (ret != -1) {
			ret = link(tempfname, dcc->file);

			if (ret == -1 &&
			    /* Linux */
			    (errno == EPERM ||
			     /* FUSE */
			     errno == ENOSYS ||
			     /* BSD */
			     errno == EOPNOTSUPP)) {
				/* hard links aren't supported - some people
				   want to download stuff to FAT/NTFS/etc
				   partitions, so fallback to rename() */
				ret = rename(tempfname, dcc->file);
			}
		}

		/* if ret = 0, we're the file owner now */
		dcc->fhandle = ret == -1 ? -1 :
			open(dcc->file, O_WRONLY | O_TRUNC);

		/* close/remove the temp file */
		ret_errno = errno;
		close(temphandle);
		unlink(tempfname);
		g_free(tempfname);

		if (dcc->fhandle == -1) {
			signal_emit("dcc error file create", 3,
				    dcc, dcc->file, g_strerror(ret_errno));
			dcc_destroy(DCC(dcc));
			return;
		}
	}

	dcc->starttime = time(NULL);
	if (dcc->size == 0) {
		dcc_close(DCC(dcc));
		return;
	}
	dcc->tagread = g_input_add(dcc->handle, G_INPUT_READ,
				   (GInputFunction) sig_dccget_receive, dcc);
	signal_emit("dcc connected", 1, dcc);

	if (dcc->from_dccserver) {
		str = g_strdup_printf("121 %s %d\n",
				      dcc->server ? dcc->server->nick : "??", 0);
		net_transmit(dcc->handle, str, strlen(str));
	}
}
Example #13
0
int
setfile(struct stat *fs, int fd)
{
	static struct timeval tv[2];
	struct stat ts;
	int rval, gotstat, islink, fdval;

	rval = 0;
	fdval = fd != -1;
	islink = !fdval && S_ISLNK(fs->st_mode);
	fs->st_mode &= S_ISUID | S_ISGID | S_ISVTX |
		       S_IRWXU | S_IRWXG | S_IRWXO;

	TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atimespec);
	TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtimespec);
	if (islink ? lutimes(to.p_path, tv) : utimes(to.p_path, tv)) {
		warn("%sutimes: %s", islink ? "l" : "", to.p_path);
		rval = 1;
	}
	if (fdval ? fstat(fd, &ts) :
	    (islink ? lstat(to.p_path, &ts) : stat(to.p_path, &ts)))
		gotstat = 0;
	else {
		gotstat = 1;
		ts.st_mode &= S_ISUID | S_ISGID | S_ISVTX |
			      S_IRWXU | S_IRWXG | S_IRWXO;
	}
	/*
	 * 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 (!gotstat || fs->st_uid != ts.st_uid || fs->st_gid != ts.st_gid)
		if (fdval ? fchown(fd, fs->st_uid, fs->st_gid) :
		    (islink ? lchown(to.p_path, fs->st_uid, fs->st_gid) :
		    chown(to.p_path, fs->st_uid, fs->st_gid))) {
			if (errno != EPERM) {
				warn("chown: %s", to.p_path);
				rval = 1;
			}
			fs->st_mode &= ~(S_ISUID | S_ISGID);
		}

	if (!gotstat || fs->st_mode != ts.st_mode)
		if (fdval ? fchmod(fd, fs->st_mode) :
		    (islink ? lchmod(to.p_path, fs->st_mode) :
		    chmod(to.p_path, fs->st_mode))) {
			warn("chmod: %s", to.p_path);
			rval = 1;
		}

	if (!gotstat || fs->st_flags != ts.st_flags)
		if (fdval ?
		    fchflags(fd, fs->st_flags) :
		    (islink ? lchflags(to.p_path, fs->st_flags) :
		    chflags(to.p_path, fs->st_flags))) {
			warn("chflags: %s", to.p_path);
			rval = 1;
		}

	return (rval);
}
Example #14
0
XP_File XP_FileOpen( const char* name, XP_FileType type,
                     const XP_FilePerm permissions )
{
    char* newName = WH_FileName(name, type);
    XP_File result;
#ifdef XP_UNIX
    XP_StatStruct st;
    XP_Bool make_private_p = FALSE;
#endif

    /* One should never open newsrc for output directly. */
    XP_ASSERT (type != xpNewsRC || type != xpSNewsRC ||
               !strchr (permissions, 'w'));

    if (newName == NULL)
        return NULL;

#ifdef XP_UNIX
    switch (type)
    {
    /* These files are always private: if the user chmods them, we
     make them -rw------ again the next time we use them, because
     it's really important.
     */
    case xpHTTPCookie:
    case xpKeyChain:
    case xpSignedAppletDB:
    case xpSARCache:
    case xpSARCacheIndex:
    case xpCertDB:
    case xpCertDBNameIDX:
    case xpKeyDB:
    case xpSecModuleDB:
    /* Always make tmp files private, because of their short lifetime. */
    case xpTemporary:
    case xpTemporaryNewsRC:
    case xpFileToPost:
    case xpPKCS12File:
        if (strchr (permissions, 'w'))     /* opening for output */
            make_private_p = TRUE;
        break;

    /* These files are created private, but if the user then goes and
     chmods them, we let their changes stick, because it's reasonable
     for a user to decide to give away read permission on these
     (though by default, it makes sense for them to be more private
     than the user's other files.)
     */
    case xpCacheFAT:
    case xpCache:
    case xpRegistry:
    case xpGlobalHistory:
    case xpHotlist:
    case xpBookmarks:
    case xpMailFolder:
        if (strchr (permissions, 'w') &&   /* opening for output */
                XP_Stat (newName, &st, type))  /* and it doesn't exist yet */
            make_private_p = TRUE;
        break;


    case xpProxyConfig:
    case xpSocksConfig:
    case xpNewsRC:
    case xpSNewsRC:
    case xpNewsgroups:
    case xpSNewsgroups:
    case xpURL:
    case xpMimeTypes:
    case xpSignature:
    case xpMailFolderSummary:
    case xpFolderCache:
    case xpJSMailFilters:
    case xpJSHTMLFilters:
    case xpMailSort:
    case xpNewsSort:
    case xpMailPopState:
    case xpMailFilterLog:
    case xpNewsFilterLog:
    case xpExtCache:
    case xpExtCacheIndex:
    case xpXoverCache:
    case xpMailSubdirectory:

    case xpVCardFile:
    case xpLDIFFile:
    case xpAddrBook:
    case xpAddrBookNew:
    case xpJSCookieFilters:
        /* These files need not be more private than any other, so we
         always create them with the default umask. */
        break;
    default:
        XP_ASSERT(0);
    }
#endif /* XP_UNIX */

#ifndef MCC_PROXY
    /* At this point, we'd better have an absolute path, because passing a
     relative path to fopen() is undefined.  (For the client, at least -
     I gather the proxy is different?) */
#endif/* !MCC_PROXY */

    result = fopen(newName, permissions);

#ifdef XP_MAC
    if (result != 0)
    {
        int err;

        err = setvbuf(	result, 		/* file to buffer */
                        NULL,			/* allocate the buffer for us */
                        _IOFBF, 		/* fully buffer */
                        8 * 1024);		/* 8k buffer */

        XP_ASSERT(err == 0);
    }
#endif

#ifdef XP_UNIX
    if (make_private_p && result)
#ifdef SCO_SV
        chmod (newName, S_IRUSR | S_IWUSR); /* rw only by owner */
#else
        fchmod (fileno (result), S_IRUSR | S_IWUSR); /* rw only by owner */
#endif
#endif /* XP_UNIX */

    XP_FREE(newName);
    return result;
}
/* dump Dalvik and native stack traces, return the trace file location (NULL if none) */
const char *dump_traces() {
    const char* result = NULL;

    char traces_path[PROPERTY_VALUE_MAX] = "";
    property_get("dalvik.vm.stack-trace-file", traces_path, "");
    if (!traces_path[0]) return NULL;

    /* move the old traces.txt (if any) out of the way temporarily */
    char anr_traces_path[PATH_MAX];
    strlcpy(anr_traces_path, traces_path, sizeof(anr_traces_path));
    strlcat(anr_traces_path, ".anr", sizeof(anr_traces_path));
    if (rename(traces_path, anr_traces_path) && errno != ENOENT) {
        fprintf(stderr, "rename(%s, %s): %s\n", traces_path, anr_traces_path, strerror(errno));
        return NULL;  // Can't rename old traces.txt -- no permission? -- leave it alone instead
    }

    /* make the directory if necessary */
    char anr_traces_dir[PATH_MAX];
    strlcpy(anr_traces_dir, traces_path, sizeof(anr_traces_dir));
    char *slash = strrchr(anr_traces_dir, '/');
    if (slash != NULL) {
        *slash = '\0';
        if (!mkdir(anr_traces_dir, 0775)) {
            chown(anr_traces_dir, AID_SYSTEM, AID_SYSTEM);
            chmod(anr_traces_dir, 0775);
        } else if (errno != EEXIST) {
            fprintf(stderr, "mkdir(%s): %s\n", anr_traces_dir, strerror(errno));
            return NULL;
        }
    }

    /* create a new, empty traces.txt file to receive stack dumps */
    int fd = open(traces_path, O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW, 0666);  /* -rw-rw-rw- */
    if (fd < 0) {
        fprintf(stderr, "%s: %s\n", traces_path, strerror(errno));
        return NULL;
    }
    int chmod_ret = fchmod(fd, 0666);
    if (chmod_ret < 0) {
        fprintf(stderr, "fchmod on %s failed: %s\n", traces_path, strerror(errno));
        close(fd);
        return NULL;
    }

    /* walk /proc and kill -QUIT all Dalvik processes */
    DIR *proc = opendir("/proc");
    if (proc == NULL) {
        fprintf(stderr, "/proc: %s\n", strerror(errno));
        goto error_close_fd;
    }

    /* use inotify to find when processes are done dumping */
    int ifd = inotify_init();
    if (ifd < 0) {
        fprintf(stderr, "inotify_init: %s\n", strerror(errno));
        goto error_close_fd;
    }

    int wfd = inotify_add_watch(ifd, traces_path, IN_CLOSE_WRITE);
    if (wfd < 0) {
        fprintf(stderr, "inotify_add_watch(%s): %s\n", traces_path, strerror(errno));
        goto error_close_ifd;
    }

    struct dirent *d;
    int dalvik_found = 0;
    while ((d = readdir(proc))) {
        int pid = atoi(d->d_name);
        if (pid <= 0) continue;

        char path[PATH_MAX];
        char data[PATH_MAX];
        snprintf(path, sizeof(path), "/proc/%d/exe", pid);
        ssize_t len = readlink(path, data, sizeof(data) - 1);
        if (len <= 0) {
            continue;
        }
        data[len] = '\0';

        if (!strcmp(data, "/system/bin/app_process")) {
            /* skip zygote -- it won't dump its stack anyway */
            snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
            int fd = open(path, O_RDONLY);
            len = read(fd, data, sizeof(data) - 1);
            close(fd);
            if (len <= 0) {
                continue;
            }
            data[len] = '\0';
            if (!strcmp(data, "zygote")) {
                continue;
            }

            ++dalvik_found;
            if (kill(pid, SIGQUIT)) {
                fprintf(stderr, "kill(%d, SIGQUIT): %s\n", pid, strerror(errno));
                continue;
            }

            /* wait for the writable-close notification from inotify */
            struct pollfd pfd = { ifd, POLLIN, 0 };
            int ret = poll(&pfd, 1, 200);  /* 200 msec timeout */
            if (ret < 0) {
                fprintf(stderr, "poll: %s\n", strerror(errno));
            } else if (ret == 0) {
                fprintf(stderr, "warning: timed out dumping pid %d\n", pid);
            } else {
                struct inotify_event ie;
                read(ifd, &ie, sizeof(ie));
            }
        } else if (should_dump_native_traces(data)) {
            /* dump native process if appropriate */
            if (lseek(fd, 0, SEEK_END) < 0) {
                fprintf(stderr, "lseek: %s\n", strerror(errno));
            } else {
                dump_backtrace_to_file(pid, fd);
            }
        }
    }

    if (dalvik_found == 0) {
        fprintf(stderr, "Warning: no Dalvik processes found to dump stacks\n");
    }

    static char dump_traces_path[PATH_MAX];
    strlcpy(dump_traces_path, traces_path, sizeof(dump_traces_path));
    strlcat(dump_traces_path, ".bugreport", sizeof(dump_traces_path));
    if (rename(traces_path, dump_traces_path)) {
        fprintf(stderr, "rename(%s, %s): %s\n", traces_path, dump_traces_path, strerror(errno));
        goto error_close_ifd;
    }
    result = dump_traces_path;

    /* replace the saved [ANR] traces.txt file */
    rename(anr_traces_path, traces_path);

error_close_ifd:
    close(ifd);
error_close_fd:
    close(fd);
    return result;
}
int VolumeManager::fixupAsecPermissions(const char *id, gid_t gid, const char* filename) {
    char asecFileName[255];
    char loopDevice[255];
    char mountPoint[255];

    if (gid < AID_APP) {
        SLOGE("Group ID is not in application range");
        return -1;
    }

    if (findAsec(id, asecFileName, sizeof(asecFileName))) {
        SLOGE("Couldn't find ASEC %s", id);
        return -1;
    }

    char idHash[33];
    if (!asecHash(id, idHash, sizeof(idHash))) {
        SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
        return -1;
    }

    if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
        SLOGE("Unable fix permissions during lookup on %s (%s)", id, strerror(errno));
        return -1;
    }

    unsigned int nr_sec = 0;
    struct asec_superblock sb;

    if (Loop::lookupInfo(loopDevice, &sb, &nr_sec)) {
        return -1;
    }

    int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
    if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
        SLOGE("Unable remount to fix permissions for %s: couldn't construct mountpoint", id);
        return -1;
    }

    int result = 0;
    if ((sb.c_opts & ASEC_SB_C_OPTS_EXT4) == 0) {
        return 0;
    }

    int ret = Ext4::doMount(loopDevice, mountPoint,
            false /* read-only */,
            true  /* remount */,
            false /* executable */,
            false /* sdcard */);
    if (ret) {
        SLOGE("Unable remount to fix permissions for %s (%s)", id, strerror(errno));
        return -1;
    }

    char *paths[] = { mountPoint, NULL };

    FTS *fts = fts_open(paths, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL);
    if (fts) {
        // Traverse the entire hierarchy and chown to system UID.
        for (FTSENT *ftsent = fts_read(fts); ftsent != NULL; ftsent = fts_read(fts)) {
            // We don't care about the lost+found directory.
            if (!strcmp(ftsent->fts_name, "lost+found")) {
                continue;
            }

            /*
             * There can only be one file marked as private right now.
             * This should be more robust, but it satisfies the requirements
             * we have for right now.
             */
            const bool privateFile = !strcmp(ftsent->fts_name, filename);

            int fd = open(ftsent->fts_accpath, O_NOFOLLOW);
            if (fd < 0) {
                SLOGE("Couldn't open file %s: %s", ftsent->fts_accpath, strerror(errno));
                result = -1;
                continue;
            }

            result |= fchown(fd, AID_SYSTEM, privateFile? gid : AID_SYSTEM);

            if (ftsent->fts_info & FTS_D) {
                result |= fchmod(fd, 0755);
            } else if (ftsent->fts_info & FTS_F) {
                result |= fchmod(fd, privateFile ? 0640 : 0644);
            }
            close(fd);
        }
        fts_close(fts);

        // Finally make the directory readable by everyone.
        int dirfd = open(mountPoint, O_DIRECTORY);
        if (dirfd < 0 || fchmod(dirfd, 0755)) {
            SLOGE("Couldn't change owner of existing directory %s: %s", mountPoint, strerror(errno));
            result |= -1;
        }
        close(dirfd);
    } else {
        result |= -1;
    }

    result |= Ext4::doMount(loopDevice, mountPoint,
            true /* read-only */,
            true /* remount */,
            true /* execute */,
            false /* sdcard */);

    if (result) {
        SLOGE("ASEC fix permissions failed (%s)", strerror(errno));
        return -1;
    }

    if (mDebug) {
        SLOGD("ASEC %s permissions fixed", id);
    }
    return 0;
}
Example #17
0
int
main(int argc, char *argv[])
{
    int i, n, fdflags;
    struct sigaction sa;
    FILE *iffile;
    char *p;
    struct passwd *pw;
    struct timeval timo;
    sigset_t mask;
    struct protent *protp;
    struct stat statbuf;
    int connect_attempts = 0;
    char numbuf[16];

    phase = PHASE_INITIALIZE;
    p = ttyname(0);
    if (p)
	strcpy(devnam, p);
    strcpy(default_devnam, devnam);

    script_env = NULL;

    /* Initialize syslog facilities */
#ifdef ULTRIX
    openlog("pppd", LOG_PID);
#else
    openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
    setlogmask(LOG_UPTO(LOG_INFO));
#endif

    if (gethostname(hostname, MAXNAMELEN) < 0 ) {
	option_error("Couldn't get hostname: %m");
	die(1);
    }
    hostname[MAXNAMELEN-1] = 0;

    uid = getuid();
    privileged = uid == 0;
    sprintf(numbuf, "%d", uid);
    script_setenv("UID", numbuf);

    /*
     * Initialize to the standard option set, then parse, in order,
     * the system options file, the user's options file,
     * the tty's options file, and the command line arguments.
     */
    for (i = 0; (protp = protocols[i]) != NULL; ++i)
        (*protp->init)(0);

    progname = *argv;

    if (!options_from_file(_PATH_SYSOPTIONS, !privileged, 0, 1)
	|| !options_from_user())
	exit(1);
    scan_args(argc-1, argv+1);	/* look for tty name on command line */
    if (!options_for_tty()
	|| !parse_args(argc-1, argv+1))
	exit(1);

    /*
     * Check that we are running as root.
     */
    if (geteuid() != 0) {
	option_error("must be root to run %s, since it is not setuid-root",
		     argv[0]);
	die(1);
    }

    if (!ppp_available()) {
	option_error(no_ppp_msg);
	exit(1);
    }

    /*
     * Check that the options given are valid and consistent.
     */
    sys_check_options();
    auth_check_options();
    for (i = 0; (protp = protocols[i]) != NULL; ++i)
	if (protp->check_options != NULL)
	    (*protp->check_options)();
    if (demand && connector == 0) {
	option_error("connect script required for demand-dialling\n");
	exit(1);
    }

    script_setenv("DEVICE", devnam);
    sprintf(numbuf, "%d", baud_rate);
    script_setenv("SPEED", numbuf);

    /*
     * If the user has specified the default device name explicitly,
     * pretend they hadn't.
     */
    if (!default_device && strcmp(devnam, default_devnam) == 0)
	default_device = 1;
    if (default_device)
	nodetach = 1;

    /*
     * Initialize system-dependent stuff and magic number package.
     */
    sys_init();
    magic_init();
    if (debug)
	setlogmask(LOG_UPTO(LOG_DEBUG));

    /*
     * Detach ourselves from the terminal, if required,
     * and identify who is running us.
     */
    if (nodetach == 0)
	detach();
    pid = getpid();
    p = getlogin();
    stime = time(NULL);
    if (p == NULL) {
	pw = getpwuid(uid);
	if (pw != NULL && pw->pw_name != NULL)
	    p = pw->pw_name;
	else
	    p = "(unknown)";
    }
    syslog(LOG_NOTICE, "pppd %s.%d%s started by %s, uid %d",
	   VERSION, PATCHLEVEL, IMPLEMENTATION, p, uid);
  
    /*
     * Compute mask of all interesting signals and install signal handlers
     * for each.  Only one signal handler may be active at a time.  Therefore,
     * all other signals should be masked when any handler is executing.
     */
    sigemptyset(&mask);
    sigaddset(&mask, SIGHUP);
    sigaddset(&mask, SIGINT);
    sigaddset(&mask, SIGTERM);
    sigaddset(&mask, SIGCHLD);

#define SIGNAL(s, handler)	{ \
	sa.sa_handler = handler; \
	if (sigaction(s, &sa, NULL) < 0) { \
	    syslog(LOG_ERR, "Couldn't establish signal handler (%d): %m", s); \
	    die(1); \
	} \
    }

    sa.sa_mask = mask;
    sa.sa_flags = 0;
    SIGNAL(SIGHUP, hup);		/* Hangup */
    SIGNAL(SIGINT, term);		/* Interrupt */
    SIGNAL(SIGTERM, term);		/* Terminate */
    SIGNAL(SIGCHLD, chld);

    SIGNAL(SIGUSR1, toggle_debug);	/* Toggle debug flag */
    SIGNAL(SIGUSR2, open_ccp);		/* Reopen CCP */

    /*
     * Install a handler for other signals which would otherwise
     * cause pppd to exit without cleaning up.
     */
    SIGNAL(SIGABRT, bad_signal);
    SIGNAL(SIGALRM, bad_signal);
    SIGNAL(SIGFPE, bad_signal);
    SIGNAL(SIGILL, bad_signal);
    SIGNAL(SIGPIPE, bad_signal);
    SIGNAL(SIGQUIT, bad_signal);
    SIGNAL(SIGSEGV, bad_signal);
#ifdef SIGBUS
    SIGNAL(SIGBUS, bad_signal);
#endif
#ifdef SIGEMT
    SIGNAL(SIGEMT, bad_signal);
#endif
#ifdef SIGPOLL
    SIGNAL(SIGPOLL, bad_signal);
#endif
#ifdef SIGPROF
    SIGNAL(SIGPROF, bad_signal);
#endif
#ifdef SIGSYS
    SIGNAL(SIGSYS, bad_signal);
#endif
#ifdef SIGTRAP
    SIGNAL(SIGTRAP, bad_signal);
#endif
#ifdef SIGVTALRM
    SIGNAL(SIGVTALRM, bad_signal);
#endif
#ifdef SIGXCPU
    SIGNAL(SIGXCPU, bad_signal);
#endif
#ifdef SIGXFSZ
    SIGNAL(SIGXFSZ, bad_signal);
#endif

    /*
     * Apparently we can get a SIGPIPE when we call syslog, if
     * syslogd has died and been restarted.  Ignoring it seems
     * be sufficient.
     */
    signal(SIGPIPE, SIG_IGN);

    /*
     * If we're doing dial-on-demand, set up the interface now.
     */
    if (demand) {
	/*
	 * Open the loopback channel and set it up to be the ppp interface.
	 */
	open_ppp_loopback();

	syslog(LOG_INFO, "Using interface ppp%d", ifunit);
	sprintf(ifname, "ppp%d", ifunit);
	script_setenv("IFNAME", ifname);

	create_pidfile();	/* write pid to file */

	/*
	 * Configure the interface and mark it up, etc.
	 */
	demand_conf();
    }

    for (;;) {

	need_holdoff = 1;

	if (demand) {
	    /*
	     * Don't do anything until we see some activity.
	     */
	    phase = PHASE_DORMANT;
	    kill_link = 0;
	    demand_unblock();
	    for (;;) {
		wait_loop_output(timeleft(&timo));
		calltimeout();
		if (kill_link) {
		    if (!persist)
			die(0);
		    kill_link = 0;
		}
		if (get_loop_output())
		    break;
		reap_kids();
	    }

	    /*
	     * Now we want to bring up the link.
	     */
	    demand_block();
	    syslog(LOG_INFO, "Starting link");
	}

	/*
	 * Lock the device if we've been asked to.
	 */
	if (lockflag && !default_device) {
	    if (lock(devnam) < 0)
		goto fail;
	    locked = 1;
	}

	/*
	 * Open the serial device and set it up to be the ppp interface.
	 * First we open it in non-blocking mode so we can set the
	 * various termios flags appropriately.  If we aren't dialling
	 * out and we want to use the modem lines, we reopen it later
	 * in order to wait for the carrier detect signal from the modem.
	 */
	while ((ttyfd = open(devnam, O_NONBLOCK | O_RDWR, 0)) < 0) {
	    if (errno != EINTR)
		syslog(LOG_ERR, "Failed to open %s: %m", devnam);
	    if (!persist || errno != EINTR)
		goto fail;
	}
	if ((fdflags = fcntl(ttyfd, F_GETFL)) == -1
	    || fcntl(ttyfd, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
	    syslog(LOG_WARNING,
		   "Couldn't reset non-blocking mode on device: %m");

	hungup = 0;
	kill_link = 0;

	/*
	 * Do the equivalent of `mesg n' to stop broadcast messages.
	 */
	if (fstat(ttyfd, &statbuf) < 0
	    || fchmod(ttyfd, statbuf.st_mode & ~(S_IWGRP | S_IWOTH)) < 0) {
	    syslog(LOG_WARNING,
		   "Couldn't restrict write permissions to %s: %m", devnam);
	} else
	    tty_mode = statbuf.st_mode;

	/* run connection script */
	if (connector && connector[0]) {
	    MAINDEBUG((LOG_INFO, "Connecting with <%s>", connector));

	    /*
	     * Set line speed, flow control, etc.
	     * On most systems we set CLOCAL for now so that we can talk
	     * to the modem before carrier comes up.  But this has the
	     * side effect that we might miss it if CD drops before we
	     * get to clear CLOCAL below.  On systems where we can talk
	     * successfully to the modem with CLOCAL clear and CD down,
	     * we can clear CLOCAL at this point.
	     */
	    set_up_tty(ttyfd, 1);

	    /* drop dtr to hang up in case modem is off hook */
	    if (!default_device && modem) {
		setdtr(ttyfd, FALSE);
		sleep(1);
		setdtr(ttyfd, TRUE);
	    }

	    if (device_script(connector, ttyfd, ttyfd) < 0) {
		syslog(LOG_ERR, "Connect script failed");
		setdtr(ttyfd, FALSE);
		connect_attempts++;
		goto fail;
	    }


	    syslog(LOG_INFO, "Serial connection established.");
	    sleep(1);		/* give it time to set up its terminal */
	}

	connect_attempts = 0;	/* we made it through ok */

	/* set line speed, flow control, etc.; clear CLOCAL if modem option */
	set_up_tty(ttyfd, 0);

	/* reopen tty if necessary to wait for carrier */
	if (connector == NULL && modem) {
	    while ((i = open(devnam, O_RDWR)) < 0) {
		if (errno != EINTR)
		    syslog(LOG_ERR, "Failed to reopen %s: %m", devnam);
		if (!persist || errno != EINTR ||
			hungup || kill_link)
		    goto fail;
	    }
	    close(i);
	}

	/* run welcome script, if any */
	if (welcomer && welcomer[0]) {
	    if (device_script(welcomer, ttyfd, ttyfd) < 0)
		syslog(LOG_WARNING, "Welcome script failed");
	}

	/* set up the serial device as a ppp interface */
	establish_ppp(ttyfd);

	if (!demand) {
	    
	    syslog(LOG_INFO, "Using interface ppp%d", ifunit);
	    sprintf(ifname, "ppp%d", ifunit);
	    
	    create_pidfile();	/* write pid to file */

	    /* write interface unit number to file */
	    for (n = strlen(devnam); n > 0 ; n--)
		    if (devnam[n] == '/') { 
			    n++;
			    break;
		    }
	    sprintf(iffilename, "%s%s.if", _PATH_VARRUN, &devnam[n]);
	    if ((iffile = fopen(iffilename, "w")) != NULL) {
		fprintf(iffile, "ppp%d\n", ifunit);
		fclose(iffile);
	    } else {
		syslog(LOG_ERR, "Failed to create if file %s: %m", iffilename);
		iffilename[0] = 0;
	    }

	    script_setenv("IFNAME", ifname);
	}

	/*
	 * Start opening the connection and wait for
	 * incoming events (reply, timeout, etc.).
	 */
	syslog(LOG_NOTICE, "Connect: %s <--> %s", ifname, devnam);
	stime = time(NULL);
	lcp_lowerup(0);
	lcp_open(0);		/* Start protocol */
	for (phase = PHASE_ESTABLISH; phase != PHASE_DEAD; ) {
	    wait_input(timeleft(&timo));
	    calltimeout();
	    get_input();
	    if (kill_link) {
		lcp_close(0, "User request");
		kill_link = 0;
	    }
	    if (open_ccp_flag) {
		if (phase == PHASE_NETWORK) {
		    ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */
		    (*ccp_protent.open)(0);
		}
		open_ccp_flag = 0;
	    }
	    reap_kids();	/* Don't leave dead kids lying around */
	}

	/*
	 * If we may want to bring the link up again, transfer
	 * the ppp unit back to the loopback.  Set the
	 * real serial device back to its normal mode of operation.
	 */
	clean_check();
	if (demand)
	    restore_loop();
	disestablish_ppp(ttyfd);

	/*
	 * Run disconnector script, if requested.
	 * XXX we may not be able to do this if the line has hung up!
	 */
	if (disconnector && !hungup) {
	    set_up_tty(ttyfd, 1);
	    if (device_script(disconnector, ttyfd, ttyfd) < 0) {
		syslog(LOG_WARNING, "disconnect script failed");
	    } else {
		syslog(LOG_INFO, "Serial link disconnected.");
	    }
	}

    fail:
	if (ttyfd >= 0)
	    close_tty();
	if (locked) {
	    unlock();
	    locked = 0;
	}

	if (!demand) {
	    if (pidfilename[0] != 0
		&& unlink(pidfilename) < 0 && errno != ENOENT) 
		syslog(LOG_WARNING, "unable to delete pid file: %m");
	    pidfilename[0] = 0;

	    if (iffile)
		    if (unlink(iffilename) < 0 && errno != ENOENT) 
			    syslog(LOG_WARNING, "unable to delete if file: %m");
	    iffilename[0] = 0;
	}

	/* limit to retries? */
	if (max_con_attempts)
	    if (connect_attempts >= max_con_attempts)
		break;

	if (!persist)
	    die(1);

	if (demand)
	    demand_discard();
	if (holdoff > 0 && need_holdoff) {
	    phase = PHASE_HOLDOFF;
	    TIMEOUT(holdoff_end, NULL, holdoff);
	    do {
		wait_time(timeleft(&timo));
		calltimeout();
		if (kill_link) {
		    if (!persist)
			die(0);
		    kill_link = 0;
		    phase = PHASE_DORMANT; /* allow signal to end holdoff */
		}
		reap_kids();
	    } while (phase == PHASE_HOLDOFF);
	}
    }

    die(0);
    return 0;
}
Example #18
0
/*
 * This is seriously ugly code following.  Written very fast!
 * [And subsequently made even worse..  Sigh!  This code was just born
 * to be hacked, I guess.. :) -jkh]
 */
static int
pkg_do(char *pkg)
{
    Package Plist;
    char pkg_fullname[FILENAME_MAX];
    char playpen[FILENAME_MAX];
    char extract_contents[FILENAME_MAX];
    char *extract;
    const char *where_to;
    FILE *cfile;
    int code;
    PackingList p;
    struct stat sb;
    int inPlace, conflictsfound, errcode;
    /* support for separate pre/post install scripts */
    int new_m = 0;
    char pre_script[FILENAME_MAX] = INSTALL_FNAME;
    char post_script[FILENAME_MAX];
    char pre_arg[FILENAME_MAX], post_arg[FILENAME_MAX];
    char *conflict[2];
    char **matched;
    int fd;

    conflictsfound = 0;
    code = 0;
    zapLogDir = 0;
    LogDir[0] = '\0';
    strcpy(playpen, FirstPen);
    inPlace = 0;

    memset(&Plist, '\0', sizeof(Plist));

    /* Are we coming in for a second pass, everything already extracted? */
    if (!pkg) {
	fgets(playpen, FILENAME_MAX, stdin);
	playpen[strlen(playpen) - 1] = '\0'; /* pesky newline! */
	if (chdir(playpen) == FAIL) {
	    warnx("pkg_add in SLAVE mode can't chdir to %s", playpen);
	    return 1;
	}
	read_plist(&Plist, stdin);
	where_to = playpen;
    }
    /* Nope - do it now */
    else {
	/* Is it an ftp://foo.bar.baz/file.t[bg]z specification? */
	if (isURL(pkg)) {
	    if (!(where_to = fileGetURL(NULL, pkg, KeepPackage))) {
		warnx("unable to fetch '%s' by URL", pkg);
		return 1;
	    }
	    strcpy(pkg_fullname, pkg);
	    cfile = fopen(CONTENTS_FNAME, "r");
	    if (!cfile) {
		warnx(
		"unable to open table of contents file '%s' - not a package?",
		CONTENTS_FNAME);
		goto bomb;
	    }
	    read_plist(&Plist, cfile);
	    fclose(cfile);
	}
	else {
	    strcpy(pkg_fullname, pkg);		/*
						 * Copy for sanity's sake,
						 * could remove pkg_fullname
						 */
	    if (strcmp(pkg, "-")) {
		if (stat(pkg_fullname, &sb) == FAIL) {
		    warnx("can't stat package file '%s'", pkg_fullname);
		    goto bomb;
		}
		sprintf(extract_contents, "--fast-read %s", CONTENTS_FNAME);
		extract = extract_contents;
	    }
	    else {
		extract = NULL;
		sb.st_size = 100000;	/* Make up a plausible average size */
	    }
	    if (!(where_to = make_playpen(playpen, sb.st_size * 4)))
		errx(1, "unable to make playpen for %lld bytes", (long long)sb.st_size * 4);
	    /* Since we can call ourselves recursively, keep notes on where we came from */
	    if (!getenv("_TOP"))
		setenv("_TOP", where_to, 1);
	    if (unpack(pkg_fullname, extract)) {
		warnx(
	"unable to extract table of contents file from '%s' - not a package?",
		pkg_fullname);
		goto bomb;
	    }
	    cfile = fopen(CONTENTS_FNAME, "r");
	    if (!cfile) {
		warnx(
	"unable to open table of contents file '%s' - not a package?",
		CONTENTS_FNAME);
		goto bomb;
	    }
	    read_plist(&Plist, cfile);
	    fclose(cfile);

	    /* Extract directly rather than moving?  Oh goodie! */
	    if (find_plist_option(&Plist, "extract-in-place")) {
		if (Verbose)
		    printf("Doing in-place extraction for %s\n", pkg_fullname);
		p = find_plist(&Plist, PLIST_CWD);
		if (p) {
		    if (!isdir(p->name) && !Fake) {
			if (Verbose)
			    printf("Desired prefix of %s does not exist, creating..\n", p->name);
			vsystem("/bin/mkdir -p %s", p->name);
			if (chdir(p->name) == -1) {
			    warn("unable to change directory to '%s'", p->name);
			    goto bomb;
			}
		    }
		    where_to = p->name;
		    inPlace = 1;
		}
		else {
		    warnx(
		"no prefix specified in '%s' - this is a bad package!",
			pkg_fullname);
		    goto bomb;
		}
	    }

	    /*
	     * Apply a crude heuristic to see how much space the package will
	     * take up once it's unpacked.  I've noticed that most packages
	     * compress an average of 75%, so multiply by 4 for good measure.
	     */

	    if (!extract && !inPlace && min_free(playpen) < sb.st_size * 4) {
		warnx("projected size of %lld exceeds available free space.\n"
"Please set your PKG_TMPDIR variable to point to a location with more\n"
		       "free space and try again", (long long)sb.st_size * 4);
		warnx("not extracting %s\ninto %s, sorry!",
			pkg_fullname, where_to);
		goto bomb;
	    }

	    /* If this is a direct extract and we didn't want it, stop now */
	    if (inPlace && Fake)
		goto success;

	    /* Finally unpack the whole mess.  If extract is null we
	       already + did so so don't bother doing it again. */
	    if (extract && unpack(pkg_fullname, NULL)) {
		warnx("unable to extract '%s'!", pkg_fullname);
		goto bomb;
	    }
	}

	/* Check for sanity and dependencies */
	if (sanity_check(pkg))
	    goto bomb;

	/* If we're running in MASTER mode, just output the plist and return */
	if (AddMode == MASTER) {
	    printf("%s\n", where_playpen());
	    write_plist(&Plist, stdout);
	    return 0;
	}
    }

    /*
     * If we have a prefix, delete the first one we see and add this
     * one in place of it.
     */
    if (Prefix) {
	delete_plist(&Plist, FALSE, PLIST_CWD, NULL);
	add_plist_top(&Plist, PLIST_CWD, Prefix);
    }

    setenv(PKG_PREFIX_VNAME, (p = find_plist(&Plist, PLIST_CWD)) ? p->name : ".", 1);
    /* Protect against old packages with bogus @name and origin fields */
    if (Plist.name == NULL)
	Plist.name = "anonymous";
    if (Plist.origin == NULL)
	Plist.origin = "anonymous/anonymous";

    /*
     * See if we're already registered either with the same name (the same
     * version) or some other version with the same origin.
     */
    if ((isinstalledpkg(Plist.name) > 0 ||
         matchbyorigin(Plist.origin, NULL) != NULL) && !Force) {
	warnx("package '%s' or its older version already installed%s",
	      Plist.name, FailOnAlreadyInstalled ? "" : " (ignored)");
	code = FailOnAlreadyInstalled != FALSE;
	goto success;	/* close enough for government work */
    }

    /* Now check the packing list for conflicts */
    if (!IgnoreDeps){
    for (p = Plist.head; p != NULL; p = p->next) {
	if (p->type == PLIST_CONFLICTS) {
	    int i;
	    conflict[0] = strdup(p->name);
	    conflict[1] = NULL;
	    matched = matchinstalled(MATCH_GLOB, conflict, &errcode);
	    free(conflict[0]);
	    if (errcode == 0 && matched != NULL)
		for (i = 0; matched[i] != NULL; i++)
		    if (isinstalledpkg(matched[i]) > 0) {
			warnx("package '%s' conflicts with %s", Plist.name,
				matched[i]);
			conflictsfound = 1;
		    }

	    continue;
	}
    }
    if(conflictsfound) {
	if(!Force) {
	    warnx("please use pkg_delete first to remove conflicting package(s) or -f to force installation");
	    code = 1;
	    goto bomb;
	} else
	    warnx("-f specified; proceeding anyway");
    }

#if ENSURE_THAT_ALL_REQUIREMENTS_ARE_MET
    /*
     * Before attempting to do the slave mode bit, ensure that we've
     * downloaded & processed everything we need.
     * It's possible that we haven't already installed all of our
     * dependencies if the dependency list was misgenerated due to
     * other dynamic dependencies or if a dependency was added to a
     * package without all REQUIRED_BY packages being regenerated.
     */
    for (p = pkg ? Plist.head : NULL; p; p = p->next) {
	const char *ext;
	char *deporigin;

	if (p->type != PLIST_PKGDEP)
	    continue;
	deporigin = (p->next->type == PLIST_DEPORIGIN) ? p->next->name : NULL;

	if (isinstalledpkg(p->name) <= 0 &&
	    !(deporigin != NULL && matchbyorigin(deporigin, NULL) != NULL)) {
	    char subpkg[FILENAME_MAX], *sep;

	    strlcpy(subpkg, pkg, sizeof subpkg);
	    if ((sep = strrchr(subpkg, '/')) != NULL) {
		*sep = '\0';
		if ((sep = strrchr(subpkg, '/')) != NULL) {
		    *sep = '\0';
		    strlcat(subpkg, "/All/", sizeof subpkg);
		    strlcat(subpkg, p->name, sizeof subpkg);
		    if ((ext = strrchr(pkg, '.')) == NULL)
			ext = ".tbz";
		    strlcat(subpkg, ext, sizeof subpkg);
		    pkg_do(subpkg);
		}
	    }
	}
    }
#endif

    /* Now check the packing list for dependencies */
    for (p = Plist.head; p ; p = p->next) {
	char *deporigin;

	if (p->type != PLIST_PKGDEP)
	    continue;
	deporigin = (p->next->type == PLIST_DEPORIGIN) ? p->next->name : NULL;
	if (Verbose) {
	    printf("Package '%s' depends on '%s'", Plist.name, p->name);
	    if (deporigin != NULL)
		printf(" with '%s' origin", deporigin);
	    printf(".\n");
	}
	if (isinstalledpkg(p->name) <= 0 &&
	    !(deporigin != NULL && matchbyorigin(deporigin, NULL) != NULL)) {
	    char path[FILENAME_MAX];
	    const char *cp = NULL;

	    if (!Fake) {
		char prefixArg[2 + MAXPATHLEN]; /* "-P" + Prefix */
		if (PrefixRecursive) {
		    strlcpy(prefixArg, "-P", sizeof(prefixArg));
		    strlcat(prefixArg, Prefix, sizeof(prefixArg));
		}
		if (!isURL(pkg) && !getenv("PKG_ADD_BASE")) {
		    const char *ext;

		    ext = strrchr(pkg_fullname, '.');
		    if (ext == NULL)
			ext = ".tbz";
		    snprintf(path, FILENAME_MAX, "%s/%s%s", getenv("_TOP"), p->name, ext);
		    if (fexists(path))
			cp = path;
		    else
			cp = fileFindByPath(pkg, p->name);
		    if (cp) {
			if (Verbose)
			    printf("Loading it from %s.\n", cp);
			if (vsystem("%s %s %s '%s'", PkgAddCmd, Verbose ? "-v " : "", PrefixRecursive ? prefixArg : "", cp)) {
			    warnx("autoload of dependency '%s' failed%s",
				cp, Force ? " (proceeding anyway)" : "!");
			    if (!Force)
				++code;
			}
		    }
		    else {
			warnx("could not find package %s %s",
			      p->name, Force ? " (proceeding anyway)" : "!");
			if (!Force)
			    ++code;
		    }
		}
		else if ((cp = fileGetURL(pkg, p->name, KeepPackage)) != NULL) {
		    if (Verbose)
			printf("Finished loading %s via a URL\n", p->name);
		    if (!fexists("+CONTENTS")) {
			warnx("autoloaded package %s has no +CONTENTS file?",
				p->name);
			if (!Force)
			    ++code;
		    }
		    else if (vsystem("(pwd; /bin/cat +CONTENTS) | %s %s %s %s -S", PkgAddCmd, Verbose ? "-v" : "", PrefixRecursive ? prefixArg : "", KeepPackage ? "-K" : "")) {
			warnx("pkg_add of dependency '%s' failed%s",
				p->name, Force ? " (proceeding anyway)" : "!");
			if (!Force)
			    ++code;
		    }
		    else if (Verbose)
			printf("\t'%s' loaded successfully.\n", p->name);
		    /* Nuke the temporary playpen */
		    leave_playpen();
		}
	    }
	    else {
		if (Verbose)
		    printf("and was not found%s.\n", Force ? " (proceeding anyway)" : "");
		else
		    printf("Package dependency %s for %s not found%s\n", p->name, pkg,
			   Force ? " (proceeding anyway)" : "!");
		if (!Force)
		    ++code;
	    }
	}
	else if (Verbose)
	    printf(" - already installed.\n");
    }
    } /* if (!IgnoreDeps) */

    if (code != 0)
	goto bomb;

    /* Look for the requirements file */
    if ((fd = open(REQUIRE_FNAME, O_RDWR)) != -1) {
	fstat(fd, &sb);
	fchmod(fd, sb.st_mode | S_IXALL);	/* be sure, chmod a+x */
	close(fd);
	if (Verbose)
	    printf("Running requirements file first for %s..\n", Plist.name);
	if (!Fake && vsystem("./%s %s INSTALL", REQUIRE_FNAME, Plist.name)) {
	    warnx("package %s fails requirements %s", pkg_fullname,
		   Force ? "installing anyway" : "- not installed");
	    if (!Force) {
		code = 1;
		goto success;	/* close enough for government work */
	    }
	}
    }

    /*
     * Test whether to use the old method of passing tokens to installation
     * scripts, and set appropriate variables..
     */

    if (fexists(POST_INSTALL_FNAME)) {
	new_m = 1;
	sprintf(post_script, "%s", POST_INSTALL_FNAME);
	pre_arg[0] = '\0';
	post_arg[0] = '\0';
    } else {
	if (fexists(INSTALL_FNAME)) {
	    sprintf(post_script, "%s", INSTALL_FNAME);
	    sprintf(pre_arg, "PRE-INSTALL");
	    sprintf(post_arg, "POST-INSTALL");
	}
    }

    /* If we're really installing, and have an installation file, run it */
    if (!NoInstall && (fd = open(pre_script, O_RDWR)) != -1) {
	fstat(fd, &sb);
	fchmod(fd, sb.st_mode | S_IXALL);	/* be sure, chmod a+x */
	close(fd);
	if (Verbose)
	    printf("Running pre-install for %s..\n", Plist.name);
	if (!Fake && vsystem("./%s %s %s", pre_script, Plist.name, pre_arg)) {
	    warnx("install script returned error status");
	    unlink(pre_script);
	    code = 1;
	    goto success;		/* nothing to uninstall yet */
	}
    }

    /* Now finally extract the entire show if we're not going direct */
    if (!inPlace && !Fake)
	extract_plist(".", &Plist);

    if (!Fake && fexists(MTREE_FNAME)) {
	if (Verbose)
	    printf("Running mtree for %s..\n", Plist.name);
	p = find_plist(&Plist, PLIST_CWD);
	if (Verbose)
	    printf("mtree -U -f %s -d -e -p %s >%s\n", MTREE_FNAME, p ? p->name : "/", _PATH_DEVNULL);
	if (!Fake) {
	    if (vsystem("/usr/sbin/mtree -U -f %s -d -e -p %s >%s", MTREE_FNAME, p ? p->name : "/", _PATH_DEVNULL))
		warnx("mtree returned a non-zero status - continuing");
	}
    }

    /* Run the installation script one last time? */
    if (!NoInstall && (fd = open(post_script, O_RDWR)) != -1) {
	fstat(fd, &sb);
	fchmod(fd, sb.st_mode | S_IXALL);	/* be sure, chmod a+x */
	close(fd);
	if (Verbose)
	    printf("Running post-install for %s..\n", Plist.name);
	if (!Fake && vsystem("./%s %s %s", post_script, Plist.name, post_arg)) {
	    warnx("install script returned error status");
	    unlink(post_script);
	    code = 1;
	    goto fail;
	}
    }

    /* Time to record the deed? */
    if (!NoRecord && !Fake) {
	char contents[FILENAME_MAX];
	char **depnames = NULL, **deporigins = NULL, ***depmatches;
	int i, dep_count = 0;
	FILE *contfile;

	if (getuid() != 0)
	    warnx("not running as root - trying to record install anyway");
	sprintf(LogDir, "%s/%s", LOG_DIR, Plist.name);
	zapLogDir = 1;
	if (Verbose)
	    printf("Attempting to record package into %s..\n", LogDir);
	if (make_hierarchy(LogDir)) {
	    warnx("can't record package into '%s', you're on your own!",
		   LogDir);
	    bzero(LogDir, FILENAME_MAX);
	    code = 1;
	    goto success;	/* close enough for government work */
	}
	/* Make sure pkg_info can read the entry */
	fd = open(LogDir, O_RDWR);
	fstat(fd, &sb);
	fchmod(fd, sb.st_mode | S_IRALL | S_IXALL);	/* be sure, chmod a+rx */
	close(fd);
	move_file(".", DESC_FNAME, LogDir);
	move_file(".", COMMENT_FNAME, LogDir);
	if (fexists(INSTALL_FNAME))
	    move_file(".", INSTALL_FNAME, LogDir);
	if (fexists(POST_INSTALL_FNAME))
	    move_file(".", POST_INSTALL_FNAME, LogDir);
	if (fexists(DEINSTALL_FNAME))
	    move_file(".", DEINSTALL_FNAME, LogDir);
	if (fexists(POST_DEINSTALL_FNAME))
	    move_file(".", POST_DEINSTALL_FNAME, LogDir);
	if (fexists(REQUIRE_FNAME))
	    move_file(".", REQUIRE_FNAME, LogDir);
	if (fexists(DISPLAY_FNAME))
	    move_file(".", DISPLAY_FNAME, LogDir);
	if (fexists(MTREE_FNAME))
	    move_file(".", MTREE_FNAME, LogDir);
	sprintf(contents, "%s/%s", LogDir, CONTENTS_FNAME);
	contfile = fopen(contents, "w");
	if (!contfile) {
	    warnx("can't open new contents file '%s'! can't register pkg",
		contents);
	    goto success; /* can't log, but still keep pkg */
	}
	write_plist(&Plist, contfile);
	fclose(contfile);
	for (p = Plist.head; p ; p = p->next) {
	    char *deporigin;

	    if (p->type != PLIST_PKGDEP)
		continue;
	    deporigin = (p->next->type == PLIST_DEPORIGIN) ? p->next->name :
							     NULL;
	    if (Verbose) {
		printf("Trying to record dependency on package '%s'", p->name);
		if (deporigin != NULL)
		    printf(" with '%s' origin", deporigin);
		printf(".\n");
	    }

	    if (deporigin) {
		/* Defer to origin lookup */
		depnames = realloc(depnames, (dep_count + 1) * sizeof(*depnames));
		depnames[dep_count] = p->name;
		deporigins = realloc(deporigins, (dep_count + 2) * sizeof(*deporigins));
		deporigins[dep_count] = deporigin;
		deporigins[dep_count + 1] = NULL;
		dep_count++;
	    } else {
	       /* No origin recorded, try to register on literal package name */
	       sprintf(contents, "%s/%s/%s", LOG_DIR, p->name,
		     REQUIRED_BY_FNAME);
	       contfile = fopen(contents, "a");
	       if (!contfile) {
		  warnx("can't open dependency file '%s'!\n"
			"dependency registration is incomplete", contents);
	       } else {
		  fprintf(contfile, "%s\n", Plist.name);
		  if (fclose(contfile) == EOF) {
		     warnx("cannot properly close file %s", contents);
		  }
	       }
	    }
	}
	if (dep_count > 0) {
	    depmatches = matchallbyorigin((const char **)deporigins, NULL);
	    free(deporigins);
	    if (!IgnoreDeps && depmatches) {
		for (i = 0; i < dep_count; i++) {
		    if (depmatches[i]) {
			int j;
			char **tmp = depmatches[i];
			for (j = 0; tmp[j] != NULL; j++) {
			    /* Origin looked up */
			    sprintf(contents, "%s/%s/%s", LOG_DIR, tmp[j],
				REQUIRED_BY_FNAME);
			    if (depnames[i] && strcmp(depnames[i], tmp[j]) != 0)
				warnx("warning: package '%s' requires '%s', but '%s' "
				    "is installed", Plist.name, depnames[i], tmp[j]);
			    contfile = fopen(contents, "a");
			    if (!contfile) {
				warnx("can't open dependency file '%s'!\n"
				    "dependency registration is incomplete", contents);
			    } else {
				fprintf(contfile, "%s\n", Plist.name);
				if (fclose(contfile) == EOF)
				    warnx("cannot properly close file %s", contents);
			    }
			}
		    } else if (depnames[i]) {
			/* No package present with this origin, try literal package name */
			sprintf(contents, "%s/%s/%s", LOG_DIR, depnames[i],
			    REQUIRED_BY_FNAME);
			contfile = fopen(contents, "a");
			if (!contfile) {
			    warnx("can't open dependency file '%s'!\n"
				"dependency registration is incomplete", contents);
			} else {
			    fprintf(contfile, "%s\n", Plist.name);
			    if (fclose(contfile) == EOF) {
				warnx("cannot properly close file %s", contents);
			    }
			}
		    }
		}
	    }
	}
	if (Verbose)
	    printf("Package %s registered in %s\n", Plist.name, LogDir);
    }

    if ((p = find_plist(&Plist, PLIST_DISPLAY)) != NULL) {
	FILE *fp;
	char buf[BUFSIZ];

	snprintf(buf, sizeof buf, "%s/%s", LogDir, p->name);
	fp = fopen(buf, "r");
	if (fp) {
	    putc('\n', stdout);
	    while (fgets(buf, sizeof(buf), fp))
		fputs(buf, stdout);
	    putc('\n', stdout);
	    (void) fclose(fp);
	} else {
    	    if (!Fake) {
		warnx("cannot open %s as display file", buf);  
	    }
	}
    }

    goto success;

 bomb:
    code = 1;
    goto success;

 fail:
    /* Nuke the whole (installed) show, XXX but don't clean directories */
    if (!Fake)
	delete_package(FALSE, FALSE, &Plist);

 success:
    /* delete the packing list contents */
    free_plist(&Plist);
    leave_playpen();
    return code;
}
Example #19
0
/*
 * Given a file descriptor, create a capability with specific rights and
 * make sure only those rights work. 
*/
static int
try_file_ops(int fd, cap_rights_t rights)
{
	struct stat sb;
	struct statfs sf;
	int fd_cap, fd_capcap;
	ssize_t ssize, ssize2;
	off_t off;
	void *p;
	char ch;
	int ret, is_nfs;
	struct pollfd pollfd;
	int success = PASSED;

	REQUIRE(fstatfs(fd, &sf));
	is_nfs = (strncmp("nfs", sf.f_fstypename, sizeof(sf.f_fstypename))
	    == 0);

	REQUIRE(fd_cap = cap_new(fd, rights));
	REQUIRE(fd_capcap = cap_new(fd_cap, rights));
	CHECK(fd_capcap != fd_cap);

	pollfd.fd = fd_cap;
	pollfd.events = POLLIN | POLLERR | POLLHUP;
	pollfd.revents = 0;

	ssize = read(fd_cap, &ch, sizeof(ch));
	CHECK_RESULT(read, CAP_READ | CAP_SEEK, ssize >= 0);

	ssize = pread(fd_cap, &ch, sizeof(ch), 0);
	ssize2 = pread(fd_cap, &ch, sizeof(ch), 0);
	CHECK_RESULT(pread, CAP_READ, ssize >= 0);
	CHECK(ssize == ssize2);

	ssize = write(fd_cap, &ch, sizeof(ch));
	CHECK_RESULT(write, CAP_WRITE | CAP_SEEK, ssize >= 0);

	ssize = pwrite(fd_cap, &ch, sizeof(ch), 0);
	CHECK_RESULT(pwrite, CAP_WRITE, ssize >= 0);

	off = lseek(fd_cap, 0, SEEK_SET);
	CHECK_RESULT(lseek, CAP_SEEK, off >= 0);

	/*
	 * Note: this is not expected to work over NFS.
	 */
	ret = fchflags(fd_cap, UF_NODUMP);
	CHECK_RESULT(fchflags, CAP_FCHFLAGS,
	    (ret == 0) || (is_nfs && (errno == EOPNOTSUPP)));

	ret = fstat(fd_cap, &sb);
	CHECK_RESULT(fstat, CAP_FSTAT, ret == 0);

	p = mmap(NULL, getpagesize(), PROT_READ, MAP_SHARED, fd_cap, 0);
	CHECK_MMAP_RESULT(CAP_MMAP | CAP_READ);

	p = mmap(NULL, getpagesize(), PROT_WRITE, MAP_SHARED, fd_cap, 0);
	CHECK_MMAP_RESULT(CAP_MMAP | CAP_WRITE);

	p = mmap(NULL, getpagesize(), PROT_EXEC, MAP_SHARED, fd_cap, 0);
	CHECK_MMAP_RESULT(CAP_MMAP | CAP_MAPEXEC);

	p = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED,
	    fd_cap, 0);
	CHECK_MMAP_RESULT(CAP_MMAP | CAP_READ | CAP_WRITE);

	p = mmap(NULL, getpagesize(), PROT_READ | PROT_EXEC, MAP_SHARED,
	    fd_cap, 0);
	CHECK_MMAP_RESULT(CAP_MMAP | CAP_READ | CAP_MAPEXEC);

	p = mmap(NULL, getpagesize(), PROT_EXEC | PROT_WRITE, MAP_SHARED,
	    fd_cap, 0);
	CHECK_MMAP_RESULT(CAP_MMAP | CAP_MAPEXEC | CAP_WRITE);

	p = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC,
	    MAP_SHARED, fd_cap, 0);
	CHECK_MMAP_RESULT(CAP_MMAP | CAP_READ | CAP_WRITE | CAP_MAPEXEC);

	ret = fsync(fd_cap);
	CHECK_RESULT(fsync, CAP_FSYNC, ret == 0);

	ret = fchown(fd_cap, -1, -1);
	CHECK_RESULT(fchown, CAP_FCHOWN, ret == 0);

	ret = fchmod(fd_cap, 0644);
	CHECK_RESULT(fchmod, CAP_FCHMOD, ret == 0);

	/* XXX flock */

	ret = ftruncate(fd_cap, 0);
	CHECK_RESULT(ftruncate, CAP_FTRUNCATE, ret == 0);

	ret = fstatfs(fd_cap, &sf);
	CHECK_RESULT(fstatfs, CAP_FSTATFS, ret == 0);

	ret = fpathconf(fd_cap, _PC_NAME_MAX);
	CHECK_RESULT(fpathconf, CAP_FPATHCONF, ret >= 0);

	ret = futimes(fd_cap, NULL);
	CHECK_RESULT(futimes, CAP_FUTIMES, ret == 0);

	ret = poll(&pollfd, 1, 0);
	if (rights & CAP_POLL_EVENT)
		CHECK((pollfd.revents & POLLNVAL) == 0);
	else
		CHECK((pollfd.revents & POLLNVAL) != 0);

	/* XXX: select, kqueue */

	close (fd_cap);
	return (success);
}
Example #20
0
int
main(int argc, char **argv)
{
	char errmsg[255], path[PATH_MAX];
	char *cp, *snapname;
	struct statfs stfsbuf;
	struct group *grp;
	struct stat stbuf;
	struct iovec *iov;
	int fd, iovlen;

	if (argc == 2)
		snapname = argv[1];
	else if (argc == 3)
		snapname = argv[2];	/* Old usage. */
	else
		usage();

	/*
	 * Check that the user running this program has permission
	 * to create and remove a snapshot file from the directory
	 * in which they have requested to have it made. If the 
	 * directory is sticky and not owned by the user, then they
	 * will not be able to remove the snapshot when they are
	 * done with it.
	 */
	if (strlen(snapname) >= PATH_MAX)
		errx(1, "pathname too long %s", snapname);
	cp = strrchr(snapname, '/');
	if (cp == NULL) {
		strlcpy(path, ".", PATH_MAX);
	} else if (cp == snapname) {
		strlcpy(path, "/", PATH_MAX);
	} else {
		strlcpy(path, snapname, cp - snapname + 1);
	}
	if (statfs(path, &stfsbuf) < 0)
		err(1, "%s", path);
	if (stat(path, &stbuf) < 0)
		err(1, "%s", path);
	if (!S_ISDIR(stbuf.st_mode))
		errx(1, "%s: Not a directory", path);
	if (access(path, W_OK) < 0)
		err(1, "Lack write permission in %s", path);
	if ((stbuf.st_mode & S_ISTXT) && stbuf.st_uid != getuid())
		errx(1, "Lack write permission in %s: Sticky bit set", path);

	/*
	 * Having verified access to the directory in which the
	 * snapshot is to be built, proceed with creating it.
	 */
	if ((grp = getgrnam("operator")) == NULL)
		errx(1, "Cannot retrieve operator gid");

	iov = NULL;
	iovlen = 0;
	build_iovec(&iov, &iovlen, "fstype", "ffs", 4);
	build_iovec(&iov, &iovlen, "from", snapname, (size_t)-1);
	build_iovec(&iov, &iovlen, "fspath", stfsbuf.f_mntonname, (size_t)-1);
	build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg));
	build_iovec(&iov, &iovlen, "update", NULL, 0);
	build_iovec(&iov, &iovlen, "snapshot", NULL, 0);

	*errmsg = '\0';
	if (nmount(iov, iovlen, stfsbuf.f_flags) < 0) {
		errmsg[sizeof(errmsg) - 1] = '\0';
		err(1, "Cannot create snapshot %s%s%s", snapname,
		    *errmsg != '\0' ? ": " : "", errmsg);
	}
	if ((fd = open(snapname, O_RDONLY)) < 0)
		err(1, "Cannot open %s", snapname);
	if (fstat(fd, &stbuf) != 0)
		err(1, "Cannot stat %s", snapname);
	if ((stbuf.st_flags & SF_SNAPSHOT) == 0)
		errx(1, "File %s is not a snapshot", snapname);
	if (fchown(fd, -1, grp->gr_gid) != 0)
		err(1, "Cannot chown %s", snapname);
	if (fchmod(fd, S_IRUSR | S_IRGRP) != 0)
		err(1, "Cannot chmod %s", snapname);

	exit(EXIT_SUCCESS);
}
Example #21
0
int patch_main(int argc UNUSED_PARAM, char **argv)
{
	int opts;
	int reverse, state = 0;
	char *oldname = NULL, *newname = NULL;
	char *opt_p, *opt_i;
	long oldlen = oldlen; /* for compiler */
	long newlen = newlen; /* for compiler */

	INIT_TT();

	opts = getopt32(argv, FLAG_STR, &opt_p, &opt_i);
	argv += optind;
	reverse = opts & FLAG_REVERSE;
	TT.prefix = (opts & FLAG_PATHLEN) ? xatoi(opt_p) : 0; // can be negative!
	TT.filein = TT.fileout = -1;
	if (opts & FLAG_INPUT) {
		xmove_fd(xopen_stdin(opt_i), STDIN_FILENO);
	} else {
		if (argv[0] && argv[1]) {
			xmove_fd(xopen_stdin(argv[1]), STDIN_FILENO);
		}
	}
	if (argv[0]) {
		oldname = xstrdup(argv[0]);
		newname = xstrdup(argv[0]);
	}

	// Loop through the lines in the patch
	for(;;) {
		char *patchline;

		patchline = xmalloc_fgetline(stdin);
		if (!patchline) break;

		// Other versions of patch accept damaged patches,
		// so we need to also.
		if (!*patchline) {
			free(patchline);
			patchline = xstrdup(" ");
		}

		// Are we assembling a hunk?
		if (state >= 2) {
			if (*patchline==' ' || *patchline=='+' || *patchline=='-') {
				dlist_add(&TT.current_hunk, patchline);

				if (*patchline != '+') oldlen--;
				if (*patchline != '-') newlen--;

				// Context line?
				if (*patchline==' ' && state==2) TT.context++;
				else state=3;

				// If we've consumed all expected hunk lines, apply the hunk.

				if (!oldlen && !newlen) state = apply_one_hunk();
				continue;
			}
			fail_hunk();
			state = 0;
			continue;
		}

		// Open a new file?
		if (!strncmp("--- ", patchline, 4) || !strncmp("+++ ", patchline, 4)) {
			char *s, **name = reverse ? &newname : &oldname;
			int i;

			if (*patchline == '+') {
				name = reverse ? &oldname : &newname;
				state = 1;
			}

			finish_oldfile();

			if (!argv[0]) {
				free(*name);
				// Trim date from end of filename (if any).  We don't care.
				for (s = patchline+4; *s && *s!='\t'; s++)
					if (*s=='\\' && s[1]) s++;
				i = atoi(s);
				if (i>1900 && i<=1970)
					*name = xstrdup("/dev/null");
				else {
					*s = 0;
					*name = xstrdup(patchline+4);
				}
			}

			// We defer actually opening the file because svn produces broken
			// patches that don't signal they want to create a new file the
			// way the patch man page says, so you have to read the first hunk
			// and _guess_.

		// Start a new hunk?  Usually @@ -oldline,oldlen +newline,newlen @@
		// but a missing ,value means the value is 1.
		} else if (state == 1 && !strncmp("@@ -", patchline, 4)) {
			int i;
			char *s = patchline+4;

			// Read oldline[,oldlen] +newline[,newlen]

			TT.oldlen = oldlen = TT.newlen = newlen = 1;
			TT.oldline = strtol(s, &s, 10);
			if (*s == ',') TT.oldlen = oldlen = strtol(s+1, &s, 10);
			TT.newline = strtol(s+2, &s, 10);
			if (*s == ',') TT.newlen = newlen = strtol(s+1, &s, 10);

			if (oldlen < 1 && newlen < 1)
				bb_error_msg_and_die("Really? %s", patchline);

			TT.context = 0;
			state = 2;

			// If this is the first hunk, open the file.
			if (TT.filein == -1) {
				int oldsum, newsum, empty = 0;
				char *name;

				oldsum = TT.oldline + oldlen;
				newsum = TT.newline + newlen;

				name = reverse ? oldname : newname;

				// We're deleting oldname if new file is /dev/null (before -p)
				// or if new hunk is empty (zero context) after patching
				if (!strcmp(name, "/dev/null") || !(reverse ? oldsum : newsum))
				{
					name = reverse ? newname : oldname;
					empty++;
				}

				// handle -p path truncation.
				for (i=0, s = name; *s;) {
					if ((option_mask32 & FLAG_PATHLEN) && TT.prefix == i) break;
					if (*(s++)=='/') {
						name = s;
						i++;
					}
				}

				if (empty) {
					// File is empty after the patches have been applied
					state = 0;
					if (option_mask32 & FLAG_RMEMPTY) {
						// If flag -E or --remove-empty-files is set
						printf("removing %s\n", name);
						xunlink(name);
					} else {
						printf("patching file %s\n", name);
						xclose(xopen(name, O_WRONLY | O_TRUNC));
					}
				// If we've got a file to open, do so.
				} else if (!(option_mask32 & FLAG_PATHLEN) || i <= TT.prefix) {
					struct stat statbuf;

					// If the old file was null, we're creating a new one.
					if (!strcmp(oldname, "/dev/null") || !oldsum) {
						printf("creating %s\n", name);
						s = strrchr(name, '/');
						if (s) {
							*s = 0;
							bb_make_directory(name, -1, FILEUTILS_RECUR);
							*s = '/';
						}
						TT.filein = xopen(name, O_CREAT|O_EXCL|O_RDWR);
					} else {
						printf("patching file %s\n", name);
						TT.filein = xopen(name, O_RDONLY);
					}

					TT.tempname = xasprintf("%sXXXXXX", name);
					TT.fileout = xmkstemp(TT.tempname);
					// Set permissions of output file
					fstat(TT.filein, &statbuf);
					fchmod(TT.fileout, statbuf.st_mode);

					TT.linenum = 0;
					TT.hunknum = 0;
				}
			}

			TT.hunknum++;

			continue;
		}

		// If we didn't continue above, discard this line.
		free(patchline);
	}

	finish_oldfile();

	if (ENABLE_FEATURE_CLEAN_UP) {
		free(oldname);
		free(newname);
	}

	return TT.exitval;
}
Example #22
0
void
update_mtab (const char *dir, struct my_mntent *instead) {
	mntFILE *mfp, *mftmp;
	const char *fnam = MOUNTED;
	struct mntentchn mtabhead;	/* dummy */
	struct mntentchn *mc, *mc0, *absent = NULL;

	if (mtab_does_not_exist() || mtab_is_a_symlink())
		return;

	lock_mtab();

	/* having locked mtab, read it again */
	mc0 = mc = &mtabhead;
	mc->nxt = mc->prev = NULL;

	mfp = my_setmntent(fnam, "r");
	if (mfp == NULL || mfp->mntent_fp == NULL) {
		int errsv = errno;
		error (_("cannot open %s (%s) - mtab not updated"),
		       fnam, strerror (errsv));
		goto leave;
	}

	read_mntentchn(mfp, fnam, mc);

	/* find last occurrence of dir */
	for (mc = mc0->prev; mc && mc != mc0; mc = mc->prev)
		if (streq(mc->m.mnt_dir, dir))
			break;
	if (mc && mc != mc0) {
		if (instead == NULL) {
			/* An umount - remove entry */
			if (mc && mc != mc0) {
				mc->prev->nxt = mc->nxt;
				mc->nxt->prev = mc->prev;
				free(mc);
			}
		} else {
			/* A remount */
			mc->m.mnt_opts = instead->mnt_opts;
		}
	} else if (instead) {
		/* not found, add a new entry */
		absent = xmalloc(sizeof(*absent));
		absent->m = *instead;
		absent->nxt = mc0;
		absent->prev = mc0->prev;
		mc0->prev = absent;
		if (mc0->nxt == NULL)
			mc0->nxt = absent;
	}

	/* write chain to mtemp */
	mftmp = my_setmntent (MOUNTED_TEMP, "w");
	if (mftmp == NULL || mftmp->mntent_fp == NULL) {
		int errsv = errno;
		error (_("cannot open %s (%s) - mtab not updated"),
		       MOUNTED_TEMP, strerror (errsv));
		goto leave;
	}

	for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) {
		if (my_addmntent(mftmp, &(mc->m)) == 1) {
			int errsv = errno;
			die (EX_FILEIO, _("error writing %s: %s"),
			     MOUNTED_TEMP, strerror (errsv));
		}
	}

	discard_mntentchn(mc0);

	if (fchmod (fileno (mftmp->mntent_fp),
		    S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
		int errsv = errno;
		fprintf(stderr, _("error changing mode of %s: %s\n"),
			MOUNTED_TEMP, strerror (errsv));
	}
	my_endmntent (mftmp);

	{ /*
	   * If mount is setuid and some non-root user mounts sth,
	   * then mtab.tmp might get the group of this user. Copy uid/gid
	   * from the present mtab before renaming.
	   */
	    struct stat sbuf;
	    if (stat (MOUNTED, &sbuf) == 0)
		chown (MOUNTED_TEMP, sbuf.st_uid, sbuf.st_gid);
	}

	/* rename mtemp to mtab */
	if (rename (MOUNTED_TEMP, MOUNTED) < 0) {
		int errsv = errno;
		fprintf(stderr, _("can't rename %s to %s: %s\n"),
			MOUNTED_TEMP, MOUNTED, strerror(errsv));
	}

 leave:
	unlock_mtab();
}
Example #23
0
int
extractfile(char *name)
{
	int flags;
	uid_t uid;
	gid_t gid;
	mode_t mode;
	int extsize;
	struct timeval mtimep[2], ctimep[2];
	struct entry *ep;
	char *buf;

	curfile.name = name;
	curfile.action = USING;
	mtimep[0].tv_sec = curfile.atime_sec;
	mtimep[0].tv_usec = curfile.atime_nsec / 1000;
	mtimep[1].tv_sec = curfile.mtime_sec;
	mtimep[1].tv_usec = curfile.mtime_nsec / 1000;
	ctimep[0].tv_sec = curfile.atime_sec;
	ctimep[0].tv_usec = curfile.atime_nsec / 1000;
	ctimep[1].tv_sec = curfile.birthtime_sec;
	ctimep[1].tv_usec = curfile.birthtime_nsec / 1000;
	extsize = curfile.extsize;
	uid = getuid();
	if (uid == 0)
		uid = curfile.uid;
	gid = curfile.gid;
	mode = curfile.mode;
	flags = curfile.file_flags;
	switch (mode & IFMT) {

	default:
		fprintf(stderr, "%s: unknown file mode 0%o\n", name, mode);
		skipfile();
		return (FAIL);

	case IFSOCK:
		vprintf(stdout, "skipped socket %s\n", name);
		skipfile();
		return (GOOD);

	case IFDIR:
		if (mflag) {
			ep = lookupname(name);
			if (ep == NULL || ep->e_flags & EXTRACT)
				panic("unextracted directory %s\n", name);
			skipfile();
			return (GOOD);
		}
		vprintf(stdout, "extract file %s\n", name);
		return (genliteraldir(name, curfile.ino));

	case IFLNK:
		lnkbuf[0] = '\0';
		pathlen = 0;
		buf = setupextattr(extsize);
		getfile(xtrlnkfile, xtrattr, xtrlnkskip);
		if (pathlen == 0) {
			vprintf(stdout,
			    "%s: zero length symbolic link (ignored)\n", name);
			return (GOOD);
		}
		if (linkit(lnkbuf, name, SYMLINK) == GOOD) {
			if (extsize > 0)
				set_extattr_link(name, buf, extsize);
			(void) lchown(name, uid, gid);
			(void) lchmod(name, mode);
			(void) lutimes(name, ctimep);
			(void) lutimes(name, mtimep);
			(void) lchflags(name, flags);
			return (GOOD);
		}
		return (FAIL);

	case IFIFO:
		vprintf(stdout, "extract fifo %s\n", name);
		if (Nflag) {
			skipfile();
			return (GOOD);
		}
		if (uflag)
			(void) unlink(name);
		if (mkfifo(name, 0600) < 0) {
			fprintf(stderr, "%s: cannot create fifo: %s\n",
			    name, strerror(errno));
			skipfile();
			return (FAIL);
		}
		if (extsize == 0) {
			skipfile();
		} else {
			buf = setupextattr(extsize);
			getfile(xtrnull, xtrattr, xtrnull);
			set_extattr_file(name, buf, extsize);
		}
		(void) chown(name, uid, gid);
		(void) chmod(name, mode);
		(void) utimes(name, ctimep);
		(void) utimes(name, mtimep);
		(void) chflags(name, flags);
		return (GOOD);

	case IFCHR:
	case IFBLK:
		vprintf(stdout, "extract special file %s\n", name);
		if (Nflag) {
			skipfile();
			return (GOOD);
		}
		if (uflag)
			(void) unlink(name);
		if (mknod(name, (mode & (IFCHR | IFBLK)) | 0600,
		    (int)curfile.rdev) < 0) {
			fprintf(stderr, "%s: cannot create special file: %s\n",
			    name, strerror(errno));
			skipfile();
			return (FAIL);
		}
		if (extsize == 0) {
			skipfile();
		} else {
			buf = setupextattr(extsize);
			getfile(xtrnull, xtrattr, xtrnull);
			set_extattr_file(name, buf, extsize);
		}
		(void) chown(name, uid, gid);
		(void) chmod(name, mode);
		(void) utimes(name, ctimep);
		(void) utimes(name, mtimep);
		(void) chflags(name, flags);
		return (GOOD);

	case IFREG:
		vprintf(stdout, "extract file %s\n", name);
		if (Nflag) {
			skipfile();
			return (GOOD);
		}
		if (uflag)
			(void) unlink(name);
		if ((ofile = open(name, O_WRONLY | O_CREAT | O_TRUNC,
		    0600)) < 0) {
			fprintf(stderr, "%s: cannot create file: %s\n",
			    name, strerror(errno));
			skipfile();
			return (FAIL);
		}
		buf = setupextattr(extsize);
		getfile(xtrfile, xtrattr, xtrskip);
		if (extsize > 0)
			set_extattr_fd(ofile, name, buf, extsize);
		(void) fchown(ofile, uid, gid);
		(void) fchmod(ofile, mode);
		(void) futimes(ofile, ctimep);
		(void) futimes(ofile, mtimep);
		(void) fchflags(ofile, flags);
		(void) close(ofile);
		return (GOOD);
	}
	/* NOTREACHED */
}
Example #24
0
int main(int ac, char **av)
{
	struct stat stat_buf;	/* stat struct */
	int lc;			/* loop counter */
	char *msg;		/* message returned from parse_opts */
	mode_t dir_mode;	/* mode permissions set on test directory */

	/* Parse standard options given to run the test. */
	msg = parse_opts(ac, av, NULL, NULL);
	if (msg != NULL) {
		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);

	}

	setup();

	for (lc = 0; TEST_LOOPING(lc); lc++) {

		Tst_count = 0;

		/*
		 * Call fchmod(2) with mode argument
		 * to set setgid bit on TESTDIR.
		 */

		TEST(fchmod(fd, PERMS));

		if (TEST_RETURN == -1) {
			tst_resm(TFAIL, "fchmod(%d, %#o) Failed, errno=%d : %s",
				 fd, PERMS, TEST_ERRNO, strerror(TEST_ERRNO));
			continue;
		}
		/*
		 * Perform functional verification if test
		 * executed without (-f) option.
		 */
		if (STD_FUNCTIONAL_TEST) {
			/*
			 * Get the directory information using
			 * fstat(2).
			 */
			if (fstat(fd, &stat_buf) < 0) {
				tst_brkm(TFAIL, cleanup,
					 "fstat(2) of %s failed, errno:%d",
					 TESTDIR, TEST_ERRNO);
			}
			dir_mode = stat_buf.st_mode;
			if ((PERMS & ~S_ISGID) != dir_mode) {
				tst_resm(TFAIL, "%s: Incorrect modes 0%03o, "
					 "Expected 0%03o",
					 TESTDIR, dir_mode, PERMS & ~S_ISGID);
			} else {
				tst_resm(TPASS, "Functionality of fchmod(%d, "
					 "%#o) successful", fd, PERMS & ~S_ISGID);
			}
		} else {
			tst_resm(TPASS, "call succeeded");
		}
	}

	cleanup();

	tst_exit();
}
Example #25
0
static int copy_reg(const char *source, const char *dest)
{
	SMB_STRUCT_STAT source_stats;
	int saved_errno;
	int ifd = -1;
	int ofd = -1;

	if (sys_lstat(source, &source_stats, false) == -1)
		return -1;

	if (!S_ISREG (source_stats.st_ex_mode))
		return -1;

	if (source_stats.st_ex_size > module_sizelimit) {
		DEBUG(5,
			("%s: size of %s larger than sizelimit (%lld > %lld), rename prohititted\n",
			MODULE, source,
			(long long)source_stats.st_ex_size,
			(long long)module_sizelimit));
		return -1;
	}

	if((ifd = open (source, O_RDONLY, 0)) < 0)
		return -1;

	if (unlink (dest) && errno != ENOENT) {
		close(ifd);
		return -1;
	}

#ifdef O_NOFOLLOW
	if((ofd = open (dest, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0600)) < 0 )
#else
	if((ofd = open (dest, O_WRONLY | O_CREAT | O_TRUNC , 0600)) < 0 )
#endif
		goto err;

	if (transfer_file(ifd, ofd, source_stats.st_ex_size) == -1)
		goto err;

	/*
	 * Try to preserve ownership.  For non-root it might fail, but that's ok.
	 * But root probably wants to know, e.g. if NFS disallows it.
	 */

#ifdef HAVE_FCHOWN
	if ((fchown(ofd, source_stats.st_ex_uid, source_stats.st_ex_gid) == -1) && (errno != EPERM))
#else
	if ((chown(dest, source_stats.st_ex_uid, source_stats.st_ex_gid) == -1) && (errno != EPERM))
#endif
		goto err;

	/*
	 * fchown turns off set[ug]id bits for non-root,
	 * so do the chmod last.
	 */

#if defined(HAVE_FCHMOD)
	if ((fchmod (ofd, source_stats.st_ex_mode & 07777) == -1) &&
			(errno != EPERM))
#else
	if ((chmod (dest, source_stats.st_ex_mode & 07777) == -1) &&
			(errno != EPERM))
#endif
		goto err;

	if (close (ifd) == -1)
		goto err;

	if (close (ofd) == -1)
		return -1;

	/* Try to copy the old file's modtime and access time.  */
#if defined(HAVE_UTIMENSAT)
	{
		struct timespec ts[2];

		ts[0] = source_stats.st_ex_atime;
		ts[1] = source_stats.st_ex_mtime;
		utimensat(AT_FDCWD, dest, ts, AT_SYMLINK_NOFOLLOW);
	}
#elif defined(HAVE_UTIMES)
	{
		struct timeval tv[2];

		tv[0] = convert_timespec_to_timeval(source_stats.st_ex_atime);
		tv[1] = convert_timespec_to_timeval(source_stats.st_ex_mtime);
#ifdef HAVE_LUTIMES
		lutimes(dest, tv);
#else
		utimes(dest, tv);
#endif
	}
#elif defined(HAVE_UTIME)
	{
		struct utimbuf tv;

		tv.actime = convert_timespec_to_time_t(source_stats.st_ex_atime);
		tv.modtime = convert_timespec_to_time_t(source_stats.st_ex_mtime);
		utime(dest, &tv);
	}
#endif

	if (unlink (source) == -1)
		return -1;

	return 0;

  err:

	saved_errno = errno;
	if (ifd != -1)
		close(ifd);
	if (ofd != -1)
		close(ofd);
	errno = saved_errno;
	return -1;
}
Example #26
0
static gboolean
write_regular_file_content (OstreeRepo            *self,
                            OstreeRepoCheckoutOptions *options,
                            GOutputStream         *output,
                            GFileInfo             *file_info,
                            GVariant              *xattrs,
                            GInputStream          *input,
                            GCancellable          *cancellable,
                            GError               **error)
{
  gboolean ret = FALSE;
  const OstreeRepoCheckoutMode mode = options->mode;
  int fd;
  int res;

  if (g_output_stream_splice (output, input, 0,
                              cancellable, error) < 0)
    goto out;

  if (!g_output_stream_flush (output, cancellable, error))
    goto out;

  fd = g_file_descriptor_based_get_fd ((GFileDescriptorBased*)output);

  if (mode != OSTREE_REPO_CHECKOUT_MODE_USER)
    {
      do
        res = fchown (fd,
                      g_file_info_get_attribute_uint32 (file_info, "unix::uid"),
                      g_file_info_get_attribute_uint32 (file_info, "unix::gid"));
      while (G_UNLIKELY (res == -1 && errno == EINTR));
      if (G_UNLIKELY (res == -1))
        {
          glnx_set_error_from_errno (error);
          goto out;
        }

      do
        res = fchmod (fd, g_file_info_get_attribute_uint32 (file_info, "unix::mode"));
      while (G_UNLIKELY (res == -1 && errno == EINTR));
      if (G_UNLIKELY (res == -1))
        {
          glnx_set_error_from_errno (error);
          goto out;
        }
              
      if (xattrs)
        {
          if (!glnx_fd_set_all_xattrs (fd, xattrs, cancellable, error))
            goto out;
        }
    }
          
  if (fsync_is_enabled (self, options))
    {
      if (fsync (fd) == -1)
        {
          glnx_set_error_from_errno (error);
          goto out;
        }
    }
          
  if (!g_output_stream_close (output, cancellable, error))
    goto out;

  ret = TRUE;
 out:
  return ret;
}
Example #27
0
int x11_write_data(Context *c) {
        _cleanup_fclose_ FILE *f = NULL;
        _cleanup_free_ char *temp_path = NULL;
        struct stat st;
        int r;

        if (isempty(c->x11_layout) &&
            isempty(c->x11_model) &&
            isempty(c->x11_variant) &&
            isempty(c->x11_options)) {

                if (unlink("/etc/X11/xorg.conf.d/00-keyboard.conf") < 0)
                        return errno == ENOENT ? 0 : -errno;

                c->vc_mtime = USEC_INFINITY;
                return 0;
        }

        mkdir_p_label("/etc/X11/xorg.conf.d", 0755);

        r = fopen_temporary("/etc/X11/xorg.conf.d/00-keyboard.conf", &f, &temp_path);
        if (r < 0)
                return r;

        (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
        (void) fchmod(fileno(f), 0644);

        fputs("# Written by systemd-localed(8), read by systemd-localed and Xorg. It's\n"
              "# probably wise not to edit this file manually. Use localectl(1) to\n"
              "# instruct systemd-localed to update it.\n"
              "Section \"InputClass\"\n"
              "        Identifier \"system-keyboard\"\n"
              "        MatchIsKeyboard \"on\"\n", f);

        if (!isempty(c->x11_layout))
                fprintf(f, "        Option \"XkbLayout\" \"%s\"\n", c->x11_layout);

        if (!isempty(c->x11_model))
                fprintf(f, "        Option \"XkbModel\" \"%s\"\n", c->x11_model);

        if (!isempty(c->x11_variant))
                fprintf(f, "        Option \"XkbVariant\" \"%s\"\n", c->x11_variant);

        if (!isempty(c->x11_options))
                fprintf(f, "        Option \"XkbOptions\" \"%s\"\n", c->x11_options);

        fputs("EndSection\n", f);

        r = fflush_sync_and_check(f);
        if (r < 0)
                goto fail;

        if (rename(temp_path, "/etc/X11/xorg.conf.d/00-keyboard.conf") < 0) {
                r = -errno;
                goto fail;
        }

        if (stat("/etc/X11/xorg.conf.d/00-keyboard.conf", &st) >= 0)
                c->x11_mtime = timespec_load(&st.st_mtim);

        return 0;

fail:
        if (temp_path)
                (void) unlink(temp_path);

        return r;
}
Example #28
0
/*
 * checkout_tree_at:
 * @self: Repo
 * @mode: Options controlling all files
 * @overwrite_mode: Whether or not to overwrite files
 * @destination_parent_fd: Place tree here
 * @destination_name: Use this name for tree
 * @source: Source tree
 * @source_info: Source info
 * @cancellable: Cancellable
 * @error: Error
 *
 * Like ostree_repo_checkout_tree(), but check out @source into the
 * relative @destination_name, located by @destination_parent_fd.
 */
static gboolean
checkout_tree_at (OstreeRepo                        *self,
                  OstreeRepoCheckoutOptions         *options,
                  int                                destination_parent_fd,
                  const char                        *destination_name,
                  OstreeRepoFile                    *source,
                  GFileInfo                         *source_info,
                  GCancellable                      *cancellable,
                  GError                           **error)
{
  gboolean ret = FALSE;
  gboolean did_exist = FALSE;
  int destination_dfd = -1;
  int res;
  g_autoptr(GVariant) xattrs = NULL;
  g_autoptr(GFileEnumerator) dir_enum = NULL;

  /* Create initially with mode 0700, then chown/chmod only when we're
   * done.  This avoids anyone else being able to operate on partially
   * constructed dirs.
   */
  do
    res = mkdirat (destination_parent_fd, destination_name, 0700);
  while (G_UNLIKELY (res == -1 && errno == EINTR));
  if (res == -1)
    {
      if (errno == EEXIST && options->overwrite_mode == OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES)
        did_exist = TRUE;
      else
        {
          glnx_set_error_from_errno (error);
          goto out;
        }
    }

  if (!glnx_opendirat (destination_parent_fd, destination_name, TRUE,
                       &destination_dfd, error))
    goto out;

  /* Set the xattrs now, so any derived labeling works */
  if (!did_exist && options->mode != OSTREE_REPO_CHECKOUT_MODE_USER)
    {
      if (!ostree_repo_file_get_xattrs (source, &xattrs, NULL, error))
        goto out;

      if (xattrs)
        {
          if (!glnx_fd_set_all_xattrs (destination_dfd, xattrs, cancellable, error))
            goto out;
        }
    }

  if (g_file_info_get_file_type (source_info) != G_FILE_TYPE_DIRECTORY)
    {
      ret = checkout_one_file_at (self, options,
                                  (GFile *) source,
                                  source_info,
                                  destination_dfd,
                                  g_file_info_get_name (source_info),
                                  cancellable, error);
      goto out;
    }
  dir_enum = g_file_enumerate_children ((GFile*)source,
                                        OSTREE_GIO_FAST_QUERYINFO, 
                                        G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                        cancellable, 
                                        error);
  if (!dir_enum)
    goto out;

  while (TRUE)
    {
      GFileInfo *file_info;
      GFile *src_child;
      const char *name;

      if (!gs_file_enumerator_iterate (dir_enum, &file_info, &src_child,
                                       cancellable, error))
        goto out;
      if (file_info == NULL)
        break;

      name = g_file_info_get_name (file_info);

      if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY)
        {
          if (!checkout_tree_at (self, options,
                                 destination_dfd, name,
                                 (OstreeRepoFile*)src_child, file_info,
                                 cancellable, error))
            goto out;
        }
      else
        {
          if (!checkout_one_file_at (self, options,
                                     src_child, file_info,
                                     destination_dfd, name,
                                     cancellable, error))
            goto out;
        }
    }

  /* We do fchmod/fchown last so that no one else could access the
   * partially created directory and change content we're laying out.
   */
  if (!did_exist)
    {
      do
        res = fchmod (destination_dfd,
                      g_file_info_get_attribute_uint32 (source_info, "unix::mode"));
      while (G_UNLIKELY (res == -1 && errno == EINTR));
      if (G_UNLIKELY (res == -1))
        {
          glnx_set_error_from_errno (error);
          goto out;
        }
    }

  if (!did_exist && options->mode != OSTREE_REPO_CHECKOUT_MODE_USER)
    {
      do
        res = fchown (destination_dfd,
                      g_file_info_get_attribute_uint32 (source_info, "unix::uid"),
                      g_file_info_get_attribute_uint32 (source_info, "unix::gid"));
      while (G_UNLIKELY (res == -1 && errno == EINTR));
      if (G_UNLIKELY (res == -1))
        {
          glnx_set_error_from_errno (error);
          goto out;
        }
    }

  /* Set directory mtime to 0, so that it is constant for all checkouts.
   * Must be done after setting permissions and creating all children.
   */
  if (!did_exist)
    {
      const struct timespec times[2] = { { 0, UTIME_OMIT }, { 0, } };
      do
        res = futimens (destination_dfd, times);
      while (G_UNLIKELY (res == -1 && errno == EINTR));
      if (G_UNLIKELY (res == -1))
        {
          glnx_set_error_from_errno (error);
          goto out;
        }
    }

  if (fsync_is_enabled (self, options))
    {
      if (fsync (destination_dfd) == -1)
        {
          glnx_set_error_from_errno (error);
          goto out;
        }
    }

  ret = TRUE;
 out:
  if (destination_dfd != -1)
    (void) close (destination_dfd);
  return ret;
}
bool hostupdate_h(connection_t *c) {
	/* FIXME: Whoah! Even more!! */
	char rawfile[MAX_STRING_SIZE];
	char rawhost[MAX_STRING_SIZE], b64host[MAX_STRING_SIZE];
	char rawdgst[MAX_STRING_SIZE], b64dgst[MAX_STRING_SIZE];
	char updname[MAX_STRING_SIZE], hosttoupd[MAX_STRING_SIZE];
	char *fname;
	FILE *fp;
	size_t slen, dlen, rlen;
	RSA *updkey;

	/* We ignore host files updates, maybe for reason */
	if (ignorenetupdates() || ignorehostsupdates()) return true;

	/* handle received host data, check sign, (over)write on disk */
	if (sscanf(c->buffer,
		"%*d " MAX_STRING " " MAX_STRING " " MAX_STRING " %zd %zd " MAX_STRING,
		updname, hosttoupd, b64host, &slen, &dlen, b64dgst) != 6) {
		logger(LOG_ERR, "Got bad %s from %s (%s)", "HOSTUPDATE", c->name, c->hostname);
		return false;
	}

	/* verify the originating node is permitted to send updates */
	if (dontverifyupdatepermission()) goto _next;
	if(!getconf_bool_node_offline(updname, "HostsFilesMaster")) {
		ifdebug(PROTOCOL) logger(LOG_WARNING,
		"Ignoring hosts update request originating from %s [which came from %s (%s)]",
		updname, c->name, c->hostname);

		return true;
	}

	/* some other sanity checks */
_next:	if (!isvalidfname(updname)) {
		logger(LOG_ERR,
		"Got bogus updater name \"%s\" from %s (%s) (from: %s)",
		updname, c->name, c->hostname, updname);

		return false;
	}

	if (!isvalidfname(hosttoupd)) {
		logger(LOG_ERR,
		"Got bogus update name \"%s\" from %s (%s) (from: %s)",
		hosttoupd, c->name, c->hostname, updname);

		return false;
	}

	if (slen >= MAX_STRING_SIZE || dlen >= MAX_STRING_SIZE) {
		logger(LOG_ERR,
		"HOSTUPDATE string sizes for %s are bigger than buffer can fit (%zd, %zd)",
		hosttoupd, slen, dlen);

		return false;
	}

	/* verify it */
	if (dontverifyupdatesignature()) goto _out;
	if (!read_rsa_public_key_offline(updname, &updkey)) {
		logger(LOG_ERR, "Could not find public key for %s", updname);
		return true;
	}
	base64_decode(b64dgst, rawdgst, sizeof(rawdgst)-1);
	snprintf(rawhost, sizeof(rawhost), "%s %s %s %zd %zd",
		updname, hosttoupd, b64host, slen, dlen);
	rlen = strlen(rawhost);
	if (!EVP_verify(updkey, rawdgst, dlen, rawhost, rlen)) {
		logger(LOG_WARNING,
		"Ignoring hosts update request with bad signature from %s for %s"
		" [which came from %s (%s)]",
		updname, hosttoupd, c->name, c->hostname);

		RSA_free(updkey);
		return true;
	}
	RSA_free(updkey);

	/* neighbours return us our own packets */
_out:	if (!strcmp(updname, myself->name)) return true;

	/* All right, let's start updating */

	xasprintf(&fname, "%s/hosts/%s", confbase, hosttoupd);

	/* Tell others if needed */
	if (!dontforwardhostsupdates()) {
		exceptmasters = true;
		forward_request(c);
	}

	/* Check if it's a START marker */
	if (!strcmp(updname, hosttoupd) && !strcmp(b64host, "START")) {
		/* Run pre-update script (embedded devices do remount,rw fs for example)
		 We really need to run this once, so that's why there are START and END markers */
		run_script("hostsupdate-before");
		/* That's it folks! Waiting for files to arrive */
		free(fname);
		return true;
	}

	/* Check if it's a END marker */
	else if (!strcmp(updname, hosttoupd) && !strcmp(b64host, "END")) {
		/* Run post-update script (embedded devices do remount,ro fs for example) */
		run_script("hostsupdate-after");

		/* Schedule config/host reload */
		schedulereload();

		/* That's it folks! */
		free(fname);
		return true;
	}

	/* Remove unneeded hosts */
	else if (!strcmp(b64host, "DEAD")) {
		unlink(fname);
		/* That's it, waiting for other next request */
		free(fname);
		return true;
	}

	/* We need this early for next test */
	base64_decode(b64host, rawhost, sizeof(rawhost)-1);

	/*
	 * Via broadcasting host files one hosts file master can become config file master.
	 * Reject such a claims even if they're authentic.
	 */
	if (dontverifyupdatepermission()) goto _write;
	if(!getconf_bool_node_offline(updname, "ConfFileMaster")
		&& strcasestr_local(rawhost, "ConfFileMaster")) {
		logger(LOG_WARNING,
		"Ignoring %s which tried to raise privileges for %s to ConfFileMaster!",
		updname, hosttoupd);

		goto _end;
	}

	/* Finally write it to disk */
_write: fp = fopen(fname, "w");
	if (!fp) {
		logger(LOG_ERR, "Unable to write new host file: %s (%s)", fname, strerror(errno));
		free(fname);
		return true;
	}
#ifdef HAVE_FCHMOD
	fchmod(fileno(fp), 0640);
#endif

	fwrite(rawhost, slen, 1, fp);
	fclose(fp);

_end:
	free(fname);
	return true;
}
Example #30
0
static gboolean
cp_internal (GFile         *src,
             GFile         *dest,
             GsCpMode       mode,
             GCancellable  *cancellable,
             GError       **error)
{
  gboolean ret = FALSE;
  GFileEnumerator *enumerator = NULL;
  GFileInfo *src_info = NULL;
  GFile *dest_child = NULL;
  int dest_dfd = -1;
  int r;

  enumerator = g_file_enumerate_children (src, "standard::type,standard::name,unix::uid,unix::gid,unix::mode",
                                          G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                          cancellable, error);
  if (!enumerator)
    goto out;

  src_info = g_file_query_info (src, "standard::name,unix::mode,unix::uid,unix::gid," \
                                "time::modified,time::modified-usec,time::access,time::access-usec",
                                G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                cancellable, error);
  if (!src_info)
    goto out;

  do
    r = mkdir (gs_file_get_path_cached (dest), 0755);
  while (G_UNLIKELY (r == -1 && errno == EINTR));
  if (r == -1)
    {
      gs_set_error_from_errno (error, errno);
      goto out;
    }

  if (mode != GS_CP_MODE_NONE)
    {
      if (!gs_file_open_dir_fd (dest, &dest_dfd,
                                cancellable, error))
        goto out;

      do
        r = fchown (dest_dfd,
                    g_file_info_get_attribute_uint32 (src_info, "unix::uid"),
                    g_file_info_get_attribute_uint32 (src_info, "unix::gid"));
      while (G_UNLIKELY (r == -1 && errno == EINTR));
      if (r == -1)
        {
          gs_set_error_from_errno (error, errno);
          goto out;
        }

      do
        r = fchmod (dest_dfd, g_file_info_get_attribute_uint32 (src_info, "unix::mode"));
      while (G_UNLIKELY (r == -1 && errno == EINTR));

      {
        GError *temp_error = NULL;
        if (!copy_xattrs_from_file_to_fd (src, dest_dfd, cancellable, &temp_error))
          {
            if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED) ||
                g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
              {
                g_clear_error (&temp_error);
              }
            else
              {
                g_propagate_error (error, temp_error);
                goto out;
              }
          }
      }

      if (dest_dfd != -1)
        {
          (void) close (dest_dfd);
          dest_dfd = -1;
        }
    }

  while (TRUE)
    {
      GFileInfo *file_info = NULL;
      GFile *src_child = NULL;

      if (!gs_file_enumerator_iterate (enumerator, &file_info, &src_child,
                                       cancellable, error))
        goto out;
      if (!file_info)
        break;

      if (dest_child) g_object_unref (dest_child);
      dest_child = g_file_get_child (dest, g_file_info_get_name (file_info));

      if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY)
        {
          if (!cp_internal (src_child, dest_child, mode,
                            cancellable, error))
            goto out;
        }
      else
        {
          gboolean did_link = FALSE;
          (void) unlink (gs_file_get_path_cached (dest_child));
          if (mode == GS_CP_MODE_HARDLINK)
            {
              if (link (gs_file_get_path_cached (src_child), gs_file_get_path_cached (dest_child)) == -1)
                {
                  if (!(errno == EMLINK || errno == EXDEV || errno == EPERM))
                    {
                      gs_set_error_from_errno (error, errno);
                      goto out;
                    }
                  /* We failed to hardlink; fall back to copying all; this will
                   * affect subsequent directory copies too.
                   */
                  mode = GS_CP_MODE_COPY_ALL;
                }
              else
                did_link = TRUE;
            }
          if (!did_link)
            {
              GFileCopyFlags copyflags = G_FILE_COPY_OVERWRITE | G_FILE_COPY_NOFOLLOW_SYMLINKS;
              if (mode == GS_CP_MODE_COPY_ALL)
                copyflags |= G_FILE_COPY_ALL_METADATA;
              if (!g_file_copy (src_child, dest_child, copyflags,
                                cancellable, NULL, NULL, error))
                goto out;
            }
        }
    }

  ret = TRUE;
 out:
  if (dest_dfd != -1)
    (void) close (dest_dfd);
  g_clear_object (&src_info);
  g_clear_object (&enumerator);
  g_clear_object (&dest_child);
  return ret;
}