Beispiel #1
0
static int
set_attrs(int fd, char *path, mode_t perm, uid_t uid, gid_t gid,
    const struct timespec *ats, const struct timespec *mts)
{

	struct timeval tv[2];
	struct stat st;
	int fdcwd;
#ifdef HAVE_UTIMENSAT
	struct timespec times[2];

	times[0] = *ats;
	times[1] = *mts;
	if (utimensat(fd, RELATIVE_PATH(path), times,
	    AT_SYMLINK_NOFOLLOW) == -1 && errno != EOPNOTSUPP){
		pkg_fatal_errno("Fail to set time on %s", path);
	}
	if (errno == EOPNOTSUPP) {
#endif

	tv[0].tv_sec = ats->tv_sec;
	tv[0].tv_usec = ats->tv_nsec / 1000;
	tv[1].tv_sec = mts->tv_sec;
	tv[1].tv_usec = mts->tv_nsec / 1000;

	fdcwd = open(".", O_DIRECTORY|O_CLOEXEC);
	fchdir(fd);

	if (lutimes(RELATIVE_PATH(path), tv) == -1) {

		if (errno != ENOSYS) {
			pkg_fatal_errno("Fail to set time on %s", path);
		}
		else {
			/* Fallback to utimes */
			if (utimes(RELATIVE_PATH(path), tv) == -1) {
				pkg_fatal_errno("Fail to set time(fallback) on "
				    "%s", path);
			}
		}
	}
	fchdir(fdcwd);
	close(fdcwd);
#ifdef HAVE_UTIMENSAT
	}
#endif

	if (getenv("INSTALL_AS_USER") == NULL) {
		if (fchownat(fd, RELATIVE_PATH(path), uid, gid,
				AT_SYMLINK_NOFOLLOW) == -1) {
			if (errno == ENOTSUP) {
				if (fchownat(fd, RELATIVE_PATH(path), uid, gid, 0) == -1) {
					pkg_fatal_errno("Fail to chown(fallback) %s", path);
				}
			}
			else {
				pkg_fatal_errno("Fail to chown %s", path);
			}
		}
	}

	/* zfs drops the setuid on fchownat */
	if (fchmodat(fd, RELATIVE_PATH(path), perm, AT_SYMLINK_NOFOLLOW) == -1) {
		if (errno == ENOTSUP) {
			/* 
			 * Executing fchmodat on a symbolic link results in
			 * ENOENT (file not found) on platforms that do not
			 * support AT_SYMLINK_NOFOLLOW. The file mode of
			 * symlinks cannot be modified via file descriptor
			 * reference on these systems. The lchmod function is
			 * also not an option because it is not a posix
			 * standard, nor is implemented everywhere. Since
			 * symlink permissions have never been evaluated and
			 * thus cosmetic, just skip them on these systems.
			 */
			if (fstatat(fd, RELATIVE_PATH(path), &st, AT_SYMLINK_NOFOLLOW) == -1) {
				pkg_fatal_errno("Fail to get file status %s", path);
			}
			if (!S_ISLNK(st.st_mode)) {
				if (fchmodat(fd, RELATIVE_PATH(path), perm, 0) == -1) {
					pkg_fatal_errno("Fail to chmod(fallback) %s", path);
				}
			}
		}
		else {
			pkg_fatal_errno("Fail to chmod %s", path);
		}
	}

	return (EPKG_OK);
}
Beispiel #2
0
Datei: sv.c Projekt: Gottox/runit
void done(unsigned int e) { if (curdir != -1) fchdir(curdir); _exit(e); }
Beispiel #3
0
int rm_r(const char *path)
{
    int ret = 0;
    DIR *dir;
    struct dirent *dent;
    int r;

    if (path == NULL) {
        opkg_perror(ERROR, "Missing directory parameter");
        return -1;
    }

    dir = opendir(path);
    if (dir == NULL) {
        opkg_perror(ERROR, "Failed to open dir %s", path);
        return -1;
    }

    r = fchdir(dirfd(dir));
    if (r == -1) {
        opkg_perror(ERROR, "Failed to change to dir %s", path);
        closedir(dir);
        return -1;
    }

    while (1) {
        errno = 0;
        dent = readdir(dir);
        if (dent == NULL) {
            if (errno) {
                opkg_perror(ERROR, "Failed to read dir %s", path);
                ret = -1;
            }
            break;
        }

        if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
            continue;

#ifdef _BSD_SOURCE
        if (dent->d_type == DT_DIR) {
            ret = rm_r(dent->d_name);
            if (ret == -1)
                break;
            continue;
        } else if (dent->d_type == DT_UNKNOWN)
#endif
        {
            struct stat st;
            ret = lstat(dent->d_name, &st);
            if (ret == -1) {
                opkg_perror(ERROR, "Failed to lstat %s", dent->d_name);
                break;
            }
            if (S_ISDIR(st.st_mode)) {
                ret = rm_r(dent->d_name);
                if (ret == -1)
                    break;
                continue;
            }
        }

        ret = unlink(dent->d_name);
        if (ret == -1) {
            opkg_perror(ERROR, "Failed to unlink %s", dent->d_name);
            break;
        }
    }

    r = chdir("..");
    if (r == -1) {
        ret = -1;
        opkg_perror(ERROR, "Failed to change to dir %s/..", path);
    }

    r = rmdir(path);
    if (r == -1) {
        ret = -1;
        opkg_perror(ERROR, "Failed to remove dir %s", path);
    }

    r = closedir(dir);
    if (r == -1) {
        ret = -1;
        opkg_perror(ERROR, "Failed to close dir %s", path);
    }

    return ret;
}
Beispiel #4
0
int runsvdir_main(int argc, char **argv)
{
	struct stat s;
	dev_t last_dev = last_dev; /* for gcc */
	ino_t last_ino = last_ino; /* for gcc */
	time_t last_mtime = 0;
	int wstat;
	int curdir;
	int pid;
	unsigned deadline;
	unsigned now;
	unsigned stampcheck;
	char ch;
	int i;

	argv++;
	if (!*argv)
		bb_show_usage();
	if (argv[0][0] == '-') {
		switch (argv[0][1]) {
		case 'P': set_pgrp = 1;
		case '-': ++argv;
		}
		if (!*argv)
			bb_show_usage();
	}

	sig_catch(SIGTERM, s_term);
	sig_catch(SIGHUP, s_hangup);
	svdir = *argv++;
	if (argv && *argv) {
		rplog = *argv;
		if (setup_log() != 1) {
			rplog = 0;
			warnx("log service disabled");
		}
	}
	curdir = open_read(".");
	if (curdir == -1)
		fatal2_cannot("open current directory", "");
	coe(curdir);

	stampcheck = monotonic_sec();

	for (;;) {
		/* collect children */
		for (;;) {
			pid = wait_nohang(&wstat);
			if (pid <= 0)
				break;
			for (i = 0; i < svnum; i++) {
				if (pid == sv[i].pid) {
					/* runsv has gone */
					sv[i].pid = 0;
					check = 1;
					break;
				}
			}
		}

		now = monotonic_sec();
		if ((int)(now - stampcheck) >= 0) {
			/* wait at least a second */
			stampcheck = now + 1;

			if (stat(svdir, &s) != -1) {
				if (check || s.st_mtime != last_mtime
				 || s.st_ino != last_ino || s.st_dev != last_dev
				) {
					/* svdir modified */
					if (chdir(svdir) != -1) {
						last_mtime = s.st_mtime;
						last_dev = s.st_dev;
						last_ino = s.st_ino;
						check = 0;
						//if (now <= mtime)
						//	sleep(1);
						runsvdir();
						while (fchdir(curdir) == -1) {
							warn2_cannot("change directory, pausing", "");
							sleep(5);
						}
					} else
						warn2_cannot("change directory to ", svdir);
				}
			} else
				warn2_cannot("stat ", svdir);
		}

		if (rplog) {
			if ((int)(now - stamplog) >= 0) {
				write(logpipe[1], ".", 1);
				stamplog = now + 900;
			}
		}
		deadline = now + (check ? 1 : 5);

		pfd[0].revents = 0;
		sig_block(SIGCHLD);
		if (rplog)
			poll(pfd, 1, deadline*1000);
		else
			sleep(deadline);
		sig_unblock(SIGCHLD);

		if (pfd[0].revents & POLLIN) {
			while (read(logpipe[0], &ch, 1) > 0) {
				if (ch) {
					for (i = 6; i < rploglen; i++)
						rplog[i-1] = rplog[i];
					rplog[rploglen-1] = ch;
				}
			}
		}

		switch (exitsoon) {
		case 1:
			_exit(0);
		case 2:
			for (i = 0; i < svnum; i++)
				if (sv[i].pid)
					kill(sv[i].pid, SIGTERM);
			_exit(111);
		}
	}
	/* not reached */
	return 0;
}
Beispiel #5
0
void UnistdFchdir(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
    ReturnValue->Val->Integer = fchdir(Param[0]->Val->Integer);
}
Beispiel #6
0
static void
netifd_dir_pop(int prev_fd)
{
	if (fchdir(prev_fd)) {}
	close(prev_fd);
}
Beispiel #7
0
static int ATTR_NULL(2) ATTR_NOWARN_UNUSED_RESULT
mbox_dotlock_privileged_op(struct mbox_mailbox *mbox,
                           struct dotlock_settings *set,
                           enum mbox_dotlock_op op)
{
    const char *box_path, *dir, *fname;
    int ret = -1, orig_dir_fd, orig_errno;

    orig_dir_fd = open(".", O_RDONLY);
    if (orig_dir_fd == -1) {
        mail_storage_set_critical(&mbox->storage->storage,
                                  "open(.) failed: %m");
        return -1;
    }

    /* allow dotlocks to be created only for files we can read while we're
       unprivileged. to make sure there are no race conditions we first
       have to chdir to the mbox file's directory and then use relative
       paths. unless this is done, users could:
        - create *.lock files to any directory writable by the
          privileged group
        - DoS other users by dotlocking their mailboxes infinitely
    */
    box_path = mailbox_get_path(&mbox->box);
    fname = strrchr(box_path, '/');
    if (fname == NULL) {
        /* already relative */
        fname = box_path;
    } else {
        dir = t_strdup_until(box_path, fname);
        if (chdir(dir) < 0) {
            mail_storage_set_critical(&mbox->storage->storage,
                                      "chdir(%s) failed: %m", dir);
            i_close_fd(&orig_dir_fd);
            return -1;
        }
        fname++;
    }
    if (op == MBOX_DOTLOCK_OP_LOCK) {
        if (access(fname, R_OK) < 0) {
            mail_storage_set_critical(&mbox->storage->storage,
                                      "access(%s) failed: %m", box_path);
            i_close_fd(&orig_dir_fd);
            return -1;
        }
    }

    if (restrict_access_use_priv_gid() < 0) {
        i_close_fd(&orig_dir_fd);
        return -1;
    }

    switch (op) {
    case MBOX_DOTLOCK_OP_LOCK:
        /* we're now privileged - avoid doing as much as possible */
        ret = file_dotlock_create(set, fname, 0, &mbox->mbox_dotlock);
        if (ret > 0)
            mbox->mbox_used_privileges = TRUE;
        else if (ret < 0 && errno == EACCES) {
            const char *errmsg =
                eacces_error_get_creating("file_dotlock_create",
                                          fname);
            mail_storage_set_critical(&mbox->storage->storage,
                                      "%s", errmsg);
        } else {
            mbox_set_syscall_error(mbox, "file_dotlock_create()");
        }
        break;
    case MBOX_DOTLOCK_OP_UNLOCK:
        /* we're now privileged - avoid doing as much as possible */
        ret = file_dotlock_delete(&mbox->mbox_dotlock);
        if (ret < 0)
            mbox_set_syscall_error(mbox, "file_dotlock_delete()");
        mbox->mbox_used_privileges = FALSE;
        break;
    case MBOX_DOTLOCK_OP_TOUCH:
        ret = file_dotlock_touch(mbox->mbox_dotlock);
        if (ret < 0)
            mbox_set_syscall_error(mbox, "file_dotlock_touch()");
        break;
    }

    orig_errno = errno;
    restrict_access_drop_priv_gid();

    if (fchdir(orig_dir_fd) < 0) {
        mail_storage_set_critical(&mbox->storage->storage,
                                  "fchdir() failed: %m");
    }
    i_close_fd(&orig_dir_fd);
    errno = orig_errno;
    return ret;
}
Beispiel #8
0
char *PathResolver::normalizeFilename( const char *path )
{
	switch (path[0])
	{
	case '<': // Input
			return prettyPath(mstrcat(project_root, path+1));
	case '>': // Output
			return prettyPath(mstrcat(out_root, path+1));
	case '~': // Output
		return prettyPath(mstrcat(getenv("HOME"), path+1));
	case '@': // Auto path
		{
			/***** Expand the path *****/
			char *p = mstrdup(path);
			char *pf = p;
			if ( p[1] != '/' ) p[0] = '!';
			else               p++;
			char *b = normalizeFilename(p);
			free(pf);

			char *n = NULL;

			size_t olen = strlen(out_root);
			size_t plen = strlen(project_root);
			size_t blen = strlen(b);

			if (!strncmp(b, out_root, olen))
			{
				n = b; // Already in the out directory.
			}
			else if (!strncmp(b, project_root, plen))
			{
				n = myalloc(blen - plen + olen + 1);

				strcpy(n,      out_root);
				strcpy(n+olen, b+plen);

				free(b);
			}
			else // Outside of our directories
			{
				n = myalloc(olen + blen + 1);

				strcpy(n,      out_root);
				strcpy(n+olen, b);

				free(b);
			}

			return prettyPath(n);
		}
	case '*': // System path
		{
			path = mstrdup(path);

			DIR *cwd  = opendir(".");

			char *pathdir = mstrdup(getenv("PATH"));
			char *nt = pathdir; // NULL-terminator
			bool moredirs = true;

			const char *exename = path + 1;
			while ( moredirs )
			{
				/*** NULL-terminate the end of the next dir ***/
				pathdir = nt;
				while ( *nt != '\0' && *nt != ':' )
					nt++;
				if (!*nt)
					moredirs = false;
				*(nt++) = '\0';

				/*** Check for executable ***/
				chdir(pathdir);
				FILE *e = fopen(exename, "r");
				if (e) // Found it.
				{
					char *n = mstrcat(pathdir, '/', exename);

					fchdir(dirfd(cwd));
					closedir(cwd);

					return prettyPath(n);
				}
			}

			fchdir(dirfd(cwd));
			closedir(cwd);
		}

		msg::error("System path \"%s\" not found.", path);
		exit(EX_DATAERR);
	case '/': // Already absolute
		return prettyPath(mstrdup(path));
	}

	// Regular relative path

	if ( *path == '!' ) path++; // We didn't want the first character
	                            // to be looked at.

	char *n = getcwd(NULL, 0);
	int cwdlen = strlen(n);

	n = (char*)realloc(n, (cwdlen+2+strlen(path))*sizeof(char));
	if ( cwdlen > 1 )
	{
		n[cwdlen]   = '/' ;
		n[cwdlen+1] = '\0';
	}
	strcat(n, path);

	return prettyPath(n);
}
Beispiel #9
0
int runsvdir_main(int argc, char **argv)
{
	struct stat s;
	time_t mtime = 0;
	int wstat;
	int curdir;
	int pid;
	struct taia deadline;
	struct taia now;
	struct taia stampcheck;
	char ch;
	int i;

	argv++;
	if (!argv || !*argv) usage();
	if (**argv == '-') {
		switch (*(*argv + 1)) {
		case 'P': pgrp = 1;
		case '-': ++argv;
		}
		if (!argv || !*argv) usage();
	}

	sig_catch(SIGTERM, s_term);
	sig_catch(SIGHUP, s_hangup);
	svdir = *argv++;
	if (argv && *argv) {
		rplog = *argv;
		if (setup_log() != 1) {
			rplog = 0;
			warnx("log service disabled");
		}
	}
	curdir = open_read(".");
	if (curdir == -1)
		fatal2_cannot("open current directory", "");
	coe(curdir);

	taia_now(&stampcheck);

	for (;;) {
		/* collect children */
		for (;;) {
			pid = wait_nohang(&wstat);
			if (pid <= 0) break;
			for (i = 0; i < svnum; i++) {
				if (pid == sv[i].pid) {
					/* runsv has gone */
					sv[i].pid = 0;
					check = 1;
					break;
				}
			}
		}

		taia_now(&now);
		if (now.sec.x < (stampcheck.sec.x - 3)) {
			/* time warp */
			warnx("time warp: resetting time stamp");
			taia_now(&stampcheck);
			taia_now(&now);
			if (rplog) taia_now(&stamplog);
		}
		if (taia_less(&now, &stampcheck) == 0) {
			/* wait at least a second */
			taia_uint(&deadline, 1);
			taia_add(&stampcheck, &now, &deadline);

			if (stat(svdir, &s) != -1) {
				if (check || s.st_mtime != mtime
				 || s.st_ino != ino || s.st_dev != dev
				) {
					/* svdir modified */
					if (chdir(svdir) != -1) {
						mtime = s.st_mtime;
						dev = s.st_dev;
						ino = s.st_ino;
						check = 0;
						if (now.sec.x <= (4611686018427387914ULL + (uint64_t)mtime))
							sleep(1);
						runsvdir();
						while (fchdir(curdir) == -1) {
							warn2_cannot("change directory, pausing", "");
							sleep(5);
						}
					} else
						warn2_cannot("change directory to ", svdir);
				}
			} else
				warn2_cannot("stat ", svdir);
		}

		if (rplog) {
			if (taia_less(&now, &stamplog) == 0) {
				write(logpipe[1], ".", 1);
				taia_uint(&deadline, 900);
				taia_add(&stamplog, &now, &deadline);
			}
		}
		taia_uint(&deadline, check ? 1 : 5);
		taia_add(&deadline, &now, &deadline);

		sig_block(SIGCHLD);
		if (rplog)
			iopause(io, 1, &deadline, &now);
		else
			iopause(0, 0, &deadline, &now);
		sig_unblock(SIGCHLD);

		if (rplog && (io[0].revents | IOPAUSE_READ))
			while (read(logpipe[0], &ch, 1) > 0)
				if (ch) {
					for (i = 6; i < rploglen; i++)
						rplog[i-1] = rplog[i];
					rplog[rploglen-1] = ch;
				}

		switch (exitsoon) {
		case 1:
			_exit(0);
		case 2:
			for (i = 0; i < svnum; i++)
				if (sv[i].pid)
					kill(sv[i].pid, SIGTERM);
			_exit(111);
		}
	}
	/* not reached */
	return 0;
}
Beispiel #10
0
static void edir(const char *directory_name)
{
	int wdir;
	DIR *dir;
	struct dirent *d;
	int fd;

	wdir = xopen(".", O_RDONLY | O_NDELAY);
	xchdir(directory_name);
	dir = opendir(".");
	if (!dir)
		bb_perror_msg_and_die("opendir %s", directory_name);
	for (;;) {
		char buf[256];
		char *tail;
		int size;

		errno = 0;
		d = readdir(dir);
		if (!d) {
			if (errno)
				bb_perror_msg_and_die("readdir %s",
						directory_name);
			break;
		}
		if (d->d_name[0] == '.')
			continue;
		fd = open(d->d_name, O_RDONLY | O_NDELAY);
		if (fd < 0) {
			if ((errno == EISDIR) && env_dir) {
				if (OPT_verbose)
					bb_perror_msg("warning: %s/%s is a directory",
						directory_name,	d->d_name);
				continue;
			} else
				bb_perror_msg_and_die("open %s/%s",
						directory_name, d->d_name);
		}
		size = full_read(fd, buf, sizeof(buf)-1);
		close(fd);
		if (size < 0)
			bb_perror_msg_and_die("read %s/%s",
					directory_name, d->d_name);
		if (size == 0) {
			unsetenv(d->d_name);
			continue;
		}
		buf[size] = '\n';
		tail = strchr(buf, '\n');
		/* skip trailing whitespace */
		while (1) {
			*tail = '\0';
			tail--;
			if (tail < buf || !isspace(*tail))
				break;
		}
		xsetenv(d->d_name, buf);
	}
	closedir(dir);
	if (fchdir(wdir) == -1)
		bb_perror_msg_and_die("fchdir");
	close(wdir);
}
Beispiel #11
0
static int get_runlevel_sysv (struct runlevel_req *req, struct runlevel_rep **rep, bool suse, const char *init_path, const char *rc_path)
{
	const char runlevel_list[] = {'0', '1', '2', '3', '4', '5', '6'};

	char pathbuf[PATH_MAX];
	DIR *init_dir, *rc_dir;
	struct dirent *init_dp, *rc_dp;
	struct stat init_st, rc_st;
	struct runlevel_rep *rep_lst = NULL;

	_A(req != NULL);
	_A(rep != NULL);

	init_dir = opendir(init_path);
	if (init_dir == NULL) {
		dI("Can't open directory \"%s\": errno=%d, %s.",
		   init_path, errno, strerror (errno));
		return (-1);
	}

	while ((init_dp = readdir(init_dir)) != NULL) {
		char *service_name;
		unsigned int i;
		SEXP_t *r0;

		// Ensure that we are in the expected directory before
		// touching relative paths
		if (fchdir(dirfd(init_dir)) != 0) {
			dI("Can't fchdir to \"%s\": errno=%d, %s.",
			   init_path, errno, strerror (errno));
			closedir(init_dir);
			return -1;
		}

		if (stat(init_dp->d_name, &init_st) != 0) {
			dI("Can't stat file %s/%s: errno=%d, %s.",
			   init_path, init_dp->d_name, errno, strerror(errno));
			continue;
		}

		r0 = SEXP_string_newf("%s", init_dp->d_name);
		if (probe_entobj_cmp(req->service_name_ent, r0) != OVAL_RESULT_TRUE) {
			SEXP_free(r0);
			continue;
		}
		SEXP_free(r0);
		service_name = init_dp->d_name;

		for (i = 0; i < (sizeof (runlevel_list) / sizeof (runlevel_list[0])); ++i) {
			char runlevel[2] = {'\0', '\0'};
			bool start, kill;

			r0 = SEXP_string_newf("%c", runlevel_list[i]);
			if (probe_entobj_cmp(req->runlevel_ent, r0) != OVAL_RESULT_TRUE) {
				SEXP_free(r0);
				continue;
			}
			SEXP_free(r0);
			runlevel[0] = runlevel_list[i];

			snprintf(pathbuf, sizeof (pathbuf), rc_path, runlevel_list[i]);
			rc_dir = opendir(pathbuf);
			if (rc_dir == NULL) {
				dI("Can't open directory \"%s\": errno=%d, %s.",
				   rc_path, errno, strerror (errno));
				continue;
			}
			if (chdir(pathbuf) != 0) {
				dI("Can't fchdir to \"%s\": errno=%d, %s.",
				   rc_path, errno, strerror (errno));
				closedir(rc_dir);
				continue;
			}

			// On SUSE, the presence of a symbolic link to the init.d/<service> in 
			// a runlevel directory rcx.d implies that the sevice is started on x.
			
			if (suse) {			
				start = false;
				kill = true;
			}
			else
				start = kill = false;

			while ((rc_dp = readdir(rc_dir)) != NULL) {
				if (stat(rc_dp->d_name, &rc_st) != 0) {
					dI("Can't stat file %s/%s: errno=%d, %s.",
					   rc_path, rc_dp->d_name, errno, strerror(errno));
					continue;
				}

				if (init_st.st_ino == rc_st.st_ino) {

					if (suse) {
						if (rc_dp->d_name[0] == 'S') {
						
							start = true;
							kill = false;

							break;
						}
					}						
					else {
						if (rc_dp->d_name[0] == 'S') {
							start = true;
							break;
						} else if (rc_dp->d_name[0] == 'K') {
							kill = true;
							break;
						} else {
							dI("Unexpected character in filename: %c, %s/%s.",
							   rc_dp->d_name[0], pathbuf, rc_dp->d_name);
						}
					}
				}
			}
			closedir(rc_dir);

			if (rep_lst == NULL) {
				rep_lst = *rep = oscap_alloc(sizeof (struct runlevel_rep));
			} else {
				rep_lst->next = oscap_alloc(sizeof (struct runlevel_rep));
				rep_lst = rep_lst->next;
			}

			rep_lst->service_name = strdup(service_name);
			rep_lst->runlevel = strdup(runlevel);
			rep_lst->start = start;
			rep_lst->kill = kill;
			rep_lst->next = NULL;
		}
	}
	closedir(init_dir);

	return (1);
}
Beispiel #12
0
static bool
read_conf_file(const char *conf_file)
{
	FILE *stream;
	glob_t globbuf;
	size_t i;
	int	res;
	struct stat stb;
	unsigned num_matches = 0;

	globbuf.gl_offs = 0;
	res = glob(conf_file, GLOB_MARK
#if HAVE_DECL_GLOB_BRACE
					| GLOB_BRACE
#endif
						    , NULL, &globbuf);

	if (res) {
		if (res == GLOB_NOMATCH)
			log_message(LOG_INFO, "No config files matched '%s'.", conf_file);
		else
			log_message(LOG_INFO, "Error reading config file(s): glob(\"%s\") returned %d, skipping.", conf_file, res);
		return true;
	}

	for (i = 0; i < globbuf.gl_pathc; i++) {
		if (globbuf.gl_pathv[i][strlen(globbuf.gl_pathv[i])-1] == '/') {
			/* This is a directory - so skip */
			continue;
		}

		log_message(LOG_INFO, "Opening file '%s'.", globbuf.gl_pathv[i]);
		stream = fopen(globbuf.gl_pathv[i], "r");
		if (!stream) {
			log_message(LOG_INFO, "Configuration file '%s' open problem (%s) - skipping"
				       , globbuf.gl_pathv[i], strerror(errno));
			continue;
		}

		/* Make sure what we have opened is a regular file, and not for example a directory or executable */
		if (fstat(fileno(stream), &stb) ||
		    !S_ISREG(stb.st_mode) ||
		    (stb.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) {
			log_message(LOG_INFO, "Configuration file '%s' is not a regular non-executable file - skipping", globbuf.gl_pathv[i]);
			fclose(stream);
			continue;
		}

		num_matches++;

		current_stream = stream;

		int curdir_fd = -1;
		if (strchr(globbuf.gl_pathv[i], '/')) {
			/* If the filename contains a directory element, change to that directory */
			curdir_fd = open(".", O_RDONLY | O_DIRECTORY | O_PATH);

			char *confpath = strdup(globbuf.gl_pathv[i]);
			dirname(confpath);
			if (chdir(confpath) < 0)
				log_message(LOG_INFO, "chdir(%s) error (%s)", confpath, strerror(errno));
			free(confpath);
		}

		process_stream(current_keywords, 0);
		fclose(stream);

		/* If we changed directory, restore the previous directory */
		if (curdir_fd != -1) {
			if ((res = fchdir(curdir_fd)))
				log_message(LOG_INFO, "Failed to restore previous directory after include");
			close(curdir_fd);
			if (res)
				return true;
		}
	}

	globfree(&globbuf);

	if (!num_matches)
		log_message(LOG_INFO, "No config files matched '%s'.", conf_file);

	return false;
}
Beispiel #13
0
int main(int argc, char *argv[]) 
{
	// set working directory
	char path[128];
	int lenPath = 0;
	char *tmp = argv[0], *pos;
	while (1) 
	{
		pos = strchr(tmp, '/');
		if (pos == NULL)
			break;
		lenPath += pos - tmp + 1;
		tmp = pos + 1;
	}
	strcpy(path, argv[0]);
	path[lenPath] = '\0';
	int d = open(path, O_RDONLY);
    fchdir(d);

    // read config.txt
	char str[64];
	FILE *fp;
	if ((fp = fopen("../config/config.txt", "r")) == NULL) 
	{
		printf("Read config error\n");
		return -1;
	}

	// read and bulid hashtable
	initHashTable();
	while (!feof(fp)) 
	{
		fgets(str, 64, fp);
		char name[64], ip[64];
		char *ptr;
		int lenIP = strchr(str, ' ') - str;
		int lenName;
		if (strchr(str, '\n') != NULL) 
		{
			lenName = strchr(str, '\n') - strchr(str, ' ') - 1;
		}
		else
		{
			lenName = strlen(str) - lenIP - 1;
		}
		ptr = str;
		for (int i = 0; i < lenIP; i++, ptr++)
		{
			ip[i] = *ptr;
		}
		ip[lenIP] = '\0';
		ptr += 1;
		for (int i = 0; i < lenName; i++, ptr++)
		{
			name[i] = *ptr;
		}
		name[lenName] = '\0';
		// printf ("%s --> %s\n", name, ip);
		add(name, ip);
	}
	fclose(fp);

	dispalyTable();

	// bulid socket
	int sockfd;
	struct sockaddr_in serverAddr, clientAddr;

	sockfd = socket(AF_INET, SOCK_DGRAM, 0);

	bzero(&serverAddr, sizeof(struct sockaddr_in));
	serverAddr.sin_family = AF_INET;
	serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
	serverAddr.sin_port = htons(PORT);

	if (bind(sockfd, (struct sockaddr *)(&serverAddr), sizeof(serverAddr)) == -1) 
	{
		printf("Bind Fail\n");
		printf("%s\n", strerror(errno));
		return -1;
	}

	printf("***************************************\n");
	printf("Bind Success!\n");
	printf("***************************************\n");
	printf("listening port %d\n", PORT);

	// recive message from clients
	char message[1024];

	while (1) 
	{
		socklen_t len;
		len = sizeof(clientAddr);
		recvfrom(sockfd, message, sizeof(message), 0, (struct sockaddr *)(&clientAddr), &len);

		//handle message from clients
		char name[64];
		memset(name, 0, sizeof(name));
		printDNSQuery(message, name);
		HashNode* ans = search(name);
		if (ans)
		{
			printf("%s\n", ans->ip);
			char dnsAnswer[1024];
			createDNSAnswer(ans->ip, dnsAnswer, message);
			sendto(sockfd, dnsAnswer, sizeof(dnsAnswer), 0, (struct sockaddr *)&clientAddr, sizeof(clientAddr));
		}
		else 
		{
			printf("DNS request timed out.\n");
		}
	}

	return 0;
}
Beispiel #14
0
/* Call FUNC to operate on a pair of files, where FILE1 is relative to FD1,
   and FILE2 is relative to FD2.  If possible, do it without changing the
   working directory.  Otherwise, resort to using save_cwd/fchdir,
   FUNC, restore_cwd (up to two times).  If either the save_cwd or the
   restore_cwd fails, then give a diagnostic and exit nonzero.  */
int
at_func2 (int fd1, char const *file1,
          int fd2, char const *file2,
          int (*func) (char const *file1, char const *file2))
{
  struct saved_cwd saved_cwd;
  int saved_errno;
  int err;
  char *file1_alt;
  char *file2_alt;
  struct stat st1;
  struct stat st2;

  /* There are 16 possible scenarios, based on whether an fd is
     AT_FDCWD or real, and whether a file is absolute or relative:

         fd1  file1 fd2  file2  action
     0   cwd  abs   cwd  abs    direct call
     1   cwd  abs   cwd  rel    direct call
     2   cwd  abs   fd   abs    direct call
     3   cwd  abs   fd   rel    chdir to fd2
     4   cwd  rel   cwd  abs    direct call
     5   cwd  rel   cwd  rel    direct call
     6   cwd  rel   fd   abs    direct call
     7   cwd  rel   fd   rel    convert file1 to abs, then case 3
     8   fd   abs   cwd  abs    direct call
     9   fd   abs   cwd  rel    direct call
     10  fd   abs   fd   abs    direct call
     11  fd   abs   fd   rel    chdir to fd2
     12  fd   rel   cwd  abs    chdir to fd1
     13  fd   rel   cwd  rel    convert file2 to abs, then case 12
     14  fd   rel   fd   abs    chdir to fd1
     15a fd1  rel   fd1  rel    chdir to fd1
     15b fd1  rel   fd2  rel    chdir to fd1, then case 7

     Try some optimizations to reduce fd to AT_FDCWD, or to at least
     avoid converting an absolute name or doing a double chdir.  */

  if ((fd1 == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file1))
      && (fd2 == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file2)))
    return func (file1, file2); /* Case 0-2, 4-6, 8-10.  */

  /* If /proc/self/fd works, we don't need any stat or chdir.  */
  {
    char proc_buf1[OPENAT_BUFFER_SIZE];
    char *proc_file1 = ((fd1 == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file1))
                        ? (char *) file1
                        : openat_proc_name (proc_buf1, fd1, file1));
    if (proc_file1)
      {
        char proc_buf2[OPENAT_BUFFER_SIZE];
        char *proc_file2 = ((fd2 == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file2))
                            ? (char *) file2
                            : openat_proc_name (proc_buf2, fd2, file2));
        if (proc_file2)
          {
            int proc_result = func (proc_file1, proc_file2);
            int proc_errno = errno;
            if (proc_file1 != proc_buf1 && proc_file1 != file1)
              free (proc_file1);
            if (proc_file2 != proc_buf2 && proc_file2 != file2)
              free (proc_file2);
            /* If the syscall succeeds, or if it fails with an unexpected
               errno value, then return right away.  Otherwise, fall through
               and resort to using save_cwd/restore_cwd.  */
            if (0 <= proc_result)
              return proc_result;
            if (! EXPECTED_ERRNO (proc_errno))
              {
                errno = proc_errno;
                return proc_result;
              }
          }
        else if (proc_file1 != proc_buf1 && proc_file1 != file1)
          free (proc_file1);
      }
  }

  /* Cases 3, 7, 11-15 remain.  Time to normalize directory fds, if
     possible.  */
  if (IS_ABSOLUTE_FILE_NAME (file1))
    fd1 = AT_FDCWD; /* Case 11 reduced to 3.  */
  else if (IS_ABSOLUTE_FILE_NAME (file2))
    fd2 = AT_FDCWD; /* Case 14 reduced to 12.  */

  /* Cases 3, 7, 12, 13, 15 remain.  */

  if (fd1 == AT_FDCWD) /* Cases 3, 7.  */
    {
      if (stat (".", &st1) == -1 || fstat (fd2, &st2) == -1)
        return -1;
      if (!S_ISDIR (st2.st_mode))
        {
          errno = ENOTDIR;
          return -1;
        }
      if (SAME_INODE (st1, st2)) /* Reduced to cases 1, 5.  */
        return func (file1, file2);
    }
  else if (fd2 == AT_FDCWD) /* Cases 12, 13.  */
    {
      if (stat (".", &st2) == -1 || fstat (fd1, &st1) == -1)
        return -1;
      if (!S_ISDIR (st1.st_mode))
        {
          errno = ENOTDIR;
          return -1;
        }
      if (SAME_INODE (st1, st2)) /* Reduced to cases 4, 5.  */
        return func (file1, file2);
    }
  else if (fd1 != fd2) /* Case 15b.  */
    {
      if (fstat (fd1, &st1) == -1 || fstat (fd2, &st2) == -1)
        return -1;
      if (!S_ISDIR (st1.st_mode) || !S_ISDIR (st2.st_mode))
        {
          errno = ENOTDIR;
          return -1;
        }
      if (SAME_INODE (st1, st2)) /* Reduced to case 15a.  */
        {
          fd2 = fd1;
          if (stat (".", &st1) == 0 && SAME_INODE (st1, st2))
            return func (file1, file2); /* Further reduced to case 5.  */
        }
    }
  else /* Case 15a.  */
    {
      if (fstat (fd1, &st1) == -1)
        return -1;
      if (!S_ISDIR (st1.st_mode))
        {
          errno = ENOTDIR;
          return -1;
        }
      if (stat (".", &st2) == 0 && SAME_INODE (st1, st2))
        return func (file1, file2); /* Reduced to case 5.  */
    }

  /* Cases 3, 7, 12, 13, 15a, 15b remain.  With all reductions in
     place, it is time to start changing directories.  */

  if (save_cwd (&saved_cwd) != 0)
    openat_save_fail (errno);

  if (fd1 != AT_FDCWD && fd2 != AT_FDCWD && fd1 != fd2) /* Case 15b.  */
    {
      if (fchdir (fd1) != 0)
        {
          saved_errno = errno;
          free_cwd (&saved_cwd);
          errno = saved_errno;
          return -1;
        }
      fd1 = AT_FDCWD; /* Reduced to case 7.  */
    }

  /* Cases 3, 7, 12, 13, 15a remain.  Convert one relative name to
     absolute, if necessary.  */

  file1_alt = (char *) file1;
  file2_alt = (char *) file2;

  if (fd1 == AT_FDCWD && !IS_ABSOLUTE_FILE_NAME (file1)) /* Case 7.  */
    {
      /* It would be nicer to use:
         file1_alt = file_name_concat (xgetcwd (), file1, NULL);
         but libraries should not call xalloc_die.  */
      char *cwd = getcwd (NULL, 0);
      if (!cwd)
        {
          saved_errno = errno;
          free_cwd (&saved_cwd);
          errno = saved_errno;
          return -1;
        }
      file1_alt = mfile_name_concat (cwd, file1, NULL);
      if (!file1_alt)
        {
          saved_errno = errno;
          free (cwd);
          free_cwd (&saved_cwd);
          errno = saved_errno;
          return -1;
        }
      free (cwd); /* Reduced to case 3.  */
    }
  else if (fd2 == AT_FDCWD && !IS_ABSOLUTE_FILE_NAME (file2)) /* Case 13.  */
    {
      char *cwd = getcwd (NULL, 0);
      if (!cwd)
        {
          saved_errno = errno;
          free_cwd (&saved_cwd);
          errno = saved_errno;
          return -1;
        }
      file2_alt = mfile_name_concat (cwd, file2, NULL);
      if (!file2_alt)
        {
          saved_errno = errno;
          free (cwd);
          free_cwd (&saved_cwd);
          errno = saved_errno;
          return -1;
        }
      free (cwd); /* Reduced to case 12.  */
    }

  /* Cases 3, 12, 15a remain.  Change to the correct directory.  */
  if (fchdir (fd1 == AT_FDCWD ? fd2 : fd1) != 0)
    {
      saved_errno = errno;
      free_cwd (&saved_cwd);
      if (file1 != file1_alt)
        free (file1_alt);
      else if (file2 != file2_alt)
        free (file2_alt);
      errno = saved_errno;
      return -1;
    }

  /* Finally safe to perform the user's function, then clean up.  */

  err = func (file1_alt, file2_alt);
  saved_errno = (err < 0 ? errno : 0);

  if (file1 != file1_alt)
    free (file1_alt);
  else if (file2 != file2_alt)
    free (file2_alt);

  if (restore_cwd (&saved_cwd) != 0)
    openat_restore_fail (errno);

  free_cwd (&saved_cwd);

  if (saved_errno)
    errno = saved_errno;
  return err;
}
Beispiel #15
0
static int mount_fuse(const char *mnt, const char *opts, char *devfd)
{
	int res;
	int fd;
	char *dev;
	struct stat stbuf;
	char *type = NULL;
	char *source = NULL;
	char *mnt_opts = NULL;
	const char *real_mnt = mnt;
	int currdir_fd = -1;
	int mountpoint_fd = -1;

	fd = devfd ? check_fuse_device(devfd, &dev) : open_fuse_device(&dev);
	if (fd == -1)
		return -1;

	drop_privs();
	read_conf();

	if (getuid() != 0 && mount_max != -1) {
		int mount_count = count_fuse_fs();
		if (mount_count >= mount_max) {
			fprintf(stderr, "%s: too many FUSE filesystems mounted; mount_max=N can be set in /etc/fuse.conf\n", progname);
			close(fd);
			return -1;
		}
	}

	res = check_version(dev);
	if (res != -1) {
		res = check_perm(&real_mnt, &stbuf, &currdir_fd,
				 &mountpoint_fd);
		restore_privs();
		if (res != -1)
			res = do_mount(real_mnt, &type, stbuf.st_mode & S_IFMT,
				       fd, opts, dev, &source, &mnt_opts,
				       stbuf.st_size);
	} else
		restore_privs();

	if (currdir_fd != -1) {
		fchdir(currdir_fd);
		close(currdir_fd);
	}
	if (mountpoint_fd != -1)
		close(mountpoint_fd);

	if (res == -1) {
		close(fd);
		return -1;
	}

	if (geteuid() == 0) {
		res = add_mount(source, mnt, type, mnt_opts);
		if (res == -1) {
			umount2(mnt, 2); /* lazy umount */
			close(fd);
			return -1;
		}
	}

	free(source);
	free(type);
	free(mnt_opts);
	free(dev);

	return fd;
}
Beispiel #16
0
int main(int ac, char **av)
{
	int lc;
	const char *msg;
	void check_functionality(void);
	int r_val;

	if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);

	setup();		/* global setup */

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

		/* get the name of the test dirctory */
		if ((temp_dir = (getcwd(temp_dir, 0))) == NULL)
			tst_brkm(TBROK, cleanup, "getcwd failed");

		/*
		 * create a new directory and open it
		 */

		if ((r_val = mkdir(TEST_DIR, MODES)) == -1)
			tst_brkm(TBROK, cleanup, "mkdir failed");

		if ((fd = open(TEST_DIR, O_RDONLY)) == -1)
			tst_brkm(TBROK, cleanup, "open of directory failed");

		TEST(fchdir(fd));

		if (TEST_RETURN == -1) {
			tst_brkm(TFAIL | TTERRNO, cleanup,
				 "fchdir call failed");
		} else {
				check_functionality();
		}

		/*
		 * clean up things in case we are looping
		 */

		/*
		 * NOTE: in case of failure here, we need to use "tst_resm()"
		 * and not "tst_brkm()".  This is because if we get to this
		 * point, we have already set a PASS or FAIL for the test
		 * and "tst_brkm()" won't report as we might expect.
		 */

		/* chdir back to our temporary work directory */
		if ((r_val = chdir("..")) == -1)
			tst_resm(TBROK | TERRNO, "chdir failed");

		if ((r_val = rmdir(TEST_DIR)) == -1)
			tst_resm(TBROK | TERRNO, "rmdir failed");

		free(temp_dir);
		temp_dir = NULL;
	}

	cleanup();
	tst_exit();
}
Beispiel #17
0
int
main(int argc, char *argv[])
{
	int fd;
	int dirfd;
	int i;
	int argslen;
	char *shell;
	char *args[4];
	char *cmdargs;

	if (argc < 2) {
		usage();
		exit(127);
	}

	if ((fd = open64(argv[1], O_RDONLY)) == -1) {
		(void) fprintf(stderr,
		    gettext("runat: cannot open %s: %s\n"), argv[1],
		    strerror(errno));
		exit(125);
	}

	if ((dirfd = openat64(fd, ".", O_RDONLY|O_XATTR)) == -1) {
		(void) fprintf(stderr,
		    gettext("runat: cannot open attribute"
		    " directory for %s: %s\n"), argv[1], strerror(errno));
		exit(125);
	}

	(void) close(fd);

	if (fchdir(dirfd) == -1) {
		(void) fprintf(stderr,
		    gettext("runat: cannot fchdir to attribute"
		    " directory: %s\n"), strerror(errno));
		exit(125);
	}

	if (argc < 3) {
		shell = getenv("SHELL");
		if (shell == NULL) {
			(void) fprintf(stderr,
			    gettext(
			    "runat: shell not found, using /bin/sh\n"));
			shell = "/bin/sh";
		}

		(void) execl(shell, shell, NULL);
		(void) fprintf(stderr,
		    gettext("runat: Failed to exec %s: %s\n"), shell,
		    strerror(errno));
		return (126);
	}

	/*
	 * Count up the size of all of the args
	 */

	for (i = 2, argslen = 0; i < argc; i++) {
		argslen += strlen(argv[i]) + 1;
	}

	cmdargs = calloc(1, argslen);
	if (cmdargs == NULL) {
		(void) fprintf(stderr, gettext(
		    "runat: failed to allocate memory for"
		    " command arguments: %s\n"), strerror(errno));
		exit(126);
	}


	/*
	 * create string with all of the args concatenated together
	 * This is done so that the shell will interpret the args
	 * and do globbing if necessary.
	 */
	for (i = 2; i < argc; i++) {
		if (strlcat(cmdargs, argv[i], argslen) >= argslen) {
			(void) fprintf(stderr, gettext(
			    "runat: arguments won't fit in"
			    " allocated buffer\n"));
			exit(126);
		}

		/*
		 * tack on a space if there are more args
		 */
		if ((i + 1) < argc) {
			if (strlcat(cmdargs, " ", argslen) >= argslen) {
				(void) fprintf(stderr, gettext(
				    "runat: arguments won't fit in"
				    " allocated buffer\n"));
				exit(126);
			}
		}

	}

	args[0] = "/bin/sh";
	args[1] = "-c";
	args[2] = cmdargs;
	args[3] = NULL;
	(void) execvp(args[0], args);
	(void) fprintf(stderr, gettext("runat: Failed to exec %s: %s\n"),
	    argv[0], strerror(errno));
	return (126);
}
Beispiel #18
0
static int prepare_mntns(void)
{
	int dfd, ret;
	char *root, *criu_path;
	char path[PATH_MAX];

	root = getenv("ZDTM_ROOT");
	if (!root) {
		fprintf(stderr, "ZDTM_ROOT isn't set\n");
		return -1;
	}

	/*
	 * In a new userns all mounts are locked to protect what is
	 * under them. So we need to create another mount for the
	 * new root.
	 */
	if (mount(root, root, NULL, MS_SLAVE , NULL)) {
		fprintf(stderr, "Can't bind-mount root: %m\n");
		return -1;
	}

	if (mount(root, root, NULL, MS_BIND | MS_REC, NULL)) {
		fprintf(stderr, "Can't bind-mount root: %m\n");
		return -1;
	}

	criu_path = getenv("ZDTM_CRIU");
	if (criu_path) {
		snprintf(path, sizeof(path), "%s%s", root, criu_path);
		if (mount(criu_path, path, NULL, MS_BIND, NULL) ||
		    mount(NULL, path, NULL, MS_PRIVATE, NULL)) {
			pr_perror("Unable to mount %s", path);
			return -1;
		}
	}

	/* Move current working directory to the new root */
	ret = readlink("/proc/self/cwd", path, sizeof(path) - 1);
	if (ret < 0)
		return -1;
	path[ret] = 0;

	dfd = open(path, O_RDONLY | O_DIRECTORY);
	if (dfd == -1) {
		fprintf(stderr, "open(.) failed: %m\n");
		return -1;
	}

	if (chdir(root)) {
		fprintf(stderr, "chdir(%s) failed: %m\n", root);
		return -1;
	}
	if (mkdir("old", 0777) && errno != EEXIST) {
		fprintf(stderr, "mkdir(old) failed: %m\n");
		return -1;
	}

	if (pivot_root(".", "./old")) {
		fprintf(stderr, "pivot_root(., ./old) failed: %m\n");
		return -1;
	}

	if (mount("./old", "./old", NULL, MS_PRIVATE | MS_REC , NULL)) {
		fprintf(stderr, "Can't bind-mount root: %m\n");
		return -1;
	}

	/*
	 * proc and sysfs can be mounted in an unprivileged namespace,
	 * if they are already mounted when the user namespace is created.
	 * So ./old must be umounted after mounting /proc and /sys.
	 */
	if (mount("proc", "/proc", "proc", MS_MGC_VAL | MS_NOSUID | MS_NOEXEC | MS_NODEV, NULL)) {
		fprintf(stderr, "mount(/proc) failed: %m\n");
		return -1;
	}

	if (umount2("./old", MNT_DETACH)) {
		fprintf(stderr, "umount(./old) failed: %m\n");
		return -1;
	}

	if (mount("pts", "/dev/pts", "devpts", MS_MGC_VAL, "mode=666,ptmxmode=666,newinstance")) {
		fprintf(stderr, "mount(/dev/pts) failed: %m\n");
		return -1;
	}
	/*
	 * If CONFIG_DEVPTS_MULTIPLE_INSTANCES=n, then /dev/pts/ptmx
	 * does not exist. Fall back to creating the device with
	 * mknod() in that case.
	 */
	if (access("/dev/pts/ptmx", F_OK) == 0) {
		if (symlink("pts/ptmx", "/dev/ptmx") && errno != EEXIST) {
			fprintf(stderr, "symlink(/dev/ptmx) failed: %m\n");
			return -1;
		}
	} else {
		if (mknod("/dev/ptmx", 0666 | S_IFCHR, makedev(5, 2)) == 0) {
			chmod("/dev/ptmx", 0666);
		} else if (errno != EEXIST) {
			fprintf(stderr, "mknod(/dev/ptmx) failed: %m\n");
			return -1;
		}
	}

	if (fchdir(dfd)) {
		fprintf(stderr, "fchdir() failed: %m\n");
		return -1;
	}
	close(dfd);

	return 0;
}
Beispiel #19
0
static dvd_reader_t *DVDOpenCommon( const char *ppath,
                                    void *stream,
                                    dvd_reader_stream_cb *stream_cb )
{
  struct stat fileinfo;
  int ret, have_css, retval, cdir = -1;
  dvd_reader_t *ret_val = NULL;
  char *dev_name = NULL;
  char *path = NULL, *new_path = NULL, *path_copy = NULL;

#if defined(_WIN32) || defined(__OS2__)
      int len;
#endif

  /* Try to open DVD using stream_cb functions */
  if( stream != NULL && stream_cb != NULL )
  {
    have_css = dvdinput_setup();
    return DVDOpenImageFile( NULL, stream, stream_cb, have_css );
  }

  if( ppath == NULL )
    goto DVDOpen_error;

  path = strdup(ppath);
  if( path == NULL )
    goto DVDOpen_error;

  /* Try to open libdvdcss or fall back to standard functions */
  have_css = dvdinput_setup();

#if defined(_WIN32) || defined(__OS2__)
  /* Strip off the trailing \ if it is not a drive */
  len = strlen(path);
  if ((len > 1) &&
      (path[len - 1] == '\\')  &&
      (path[len - 2] != ':'))
  {
    path[len-1] = '\0';
  }
#endif

  ret = stat( path, &fileinfo );

  if( ret < 0 ) {

    /* maybe "host:port" url? try opening it with acCeSS library */
    if( strchr(path,':') ) {
      ret_val = DVDOpenImageFile( path, NULL, NULL, have_css );
      free(path);
      return ret_val;
    }

    /* If we can't stat the file, give up */
    fprintf( stderr, "libdvdread: Can't stat %s\n", path );
    perror("");
    goto DVDOpen_error;
  }

  /* First check if this is a block/char device or a file*/
  if( S_ISBLK( fileinfo.st_mode ) ||
      S_ISCHR( fileinfo.st_mode ) ||
      S_ISREG( fileinfo.st_mode ) ) {

    /**
     * Block devices and regular files are assumed to be DVD-Video images.
     */
    dvd_reader_t *dvd = NULL;
#if defined(__sun)
    dev_name = sun_block2char( path );
#elif defined(SYS_BSD)
    dev_name = bsd_block2char( path );
#else
    dev_name = strdup( path );
#endif
    if(!dev_name)
        goto DVDOpen_error;
    dvd = DVDOpenImageFile( dev_name, NULL, NULL, have_css );
    free( dev_name );
    free(path);
    return dvd;
  } else if( S_ISDIR( fileinfo.st_mode ) ) {
    dvd_reader_t *auth_drive = 0;
#if defined(SYS_BSD)
    struct fstab* fe;
#elif defined(__sun) || defined(__linux__)
    FILE *mntfile;
#endif

    /* XXX: We should scream real loud here. */
    if( !(path_copy = strdup( path ) ) )
      goto DVDOpen_error;

#ifndef WIN32 /* don't have fchdir, and getcwd( NULL, ... ) is strange */
              /* Also WIN32 does not have symlinks, so we don't need this bit of code. */

    /* Resolve any symlinks and get the absolute dir name. */
    {
      if( ( cdir  = open( ".", O_RDONLY ) ) >= 0 ) {
        if( chdir( path_copy ) == -1 ) {
          goto DVDOpen_error;
        }
        new_path = malloc(PATH_MAX+1);
        if(!new_path) {
          goto DVDOpen_error;
        }
        if( getcwd( new_path, PATH_MAX ) == NULL ) {
          goto DVDOpen_error;
        }
        retval = fchdir( cdir );
        close( cdir );
        cdir = -1;
        if( retval == -1 ) {
          goto DVDOpen_error;
        }
        free(path_copy);
        path_copy = new_path;
        new_path = NULL;
      }
    }
#endif

    /**
     * If we're being asked to open a directory, check if that directory
     * is the mount point for a DVD-ROM which we can use instead.
     */

    if( strlen( path_copy ) > 1 ) {
      if( path_copy[ strlen( path_copy ) - 1 ] == '/' ) {
        path_copy[ strlen( path_copy ) - 1 ] = '\0';
      }
    }

#if defined(_WIN32) || defined(__OS2__)
    if( strlen( path_copy ) > 9 ) {
      if( !strcasecmp( &(path_copy[ strlen( path_copy ) - 9 ]),
                       "\\video_ts"))
        path_copy[ strlen( path_copy ) - (9-1) ] = '\0';
    }
#endif
    if( strlen( path_copy ) > 9 ) {
      if( !strcasecmp( &(path_copy[ strlen( path_copy ) - 9 ]),
                       "/video_ts" ) ) {
        path_copy[ strlen( path_copy ) - 9 ] = '\0';
      }
    }

    if(path_copy[0] == '\0') {
      free( path_copy );
      if( !(path_copy = strdup( "/" ) ) )
        goto DVDOpen_error;
    }

#if defined(__APPLE__)
    struct statfs s[128];
    int r = getfsstat(NULL, 0, MNT_NOWAIT);
    if (r > 0) {
        if (r > 128)
            r = 128;
        r = getfsstat(s, r * sizeof(s[0]), MNT_NOWAIT);
        int i;
        for (i=0; i<r; i++) {
            if (!strcmp(path_copy, s[i].f_mntonname)) {
                dev_name = bsd_block2char(s[i].f_mntfromname);
                fprintf( stderr,
                        "libdvdread: Attempting to use device %s"
                        " mounted on %s for CSS authentication\n",
                        dev_name,
                        s[i].f_mntonname);
                auth_drive = DVDOpenImageFile( dev_name, NULL, NULL, have_css );
                break;
            }
        }
    }
#elif defined(SYS_BSD)
    if( ( fe = getfsfile( path_copy ) ) ) {
      dev_name = bsd_block2char( fe->fs_spec );
      fprintf( stderr,
               "libdvdread: Attempting to use device %s"
               " mounted on %s for CSS authentication\n",
               dev_name,
               fe->fs_file );
      auth_drive = DVDOpenImageFile( dev_name, NULL, NULL, have_css );
    }
#elif defined(__sun)
    mntfile = fopen( MNTTAB, "r" );
    if( mntfile ) {
      struct mnttab mp;
      int res;

      while( ( res = getmntent( mntfile, &mp ) ) != -1 ) {
        if( res == 0 && !strcmp( mp.mnt_mountp, path_copy ) ) {
          dev_name = sun_block2char( mp.mnt_special );
          fprintf( stderr,
                   "libdvdread: Attempting to use device %s"
                   " mounted on %s for CSS authentication\n",
                   dev_name,
                   mp.mnt_mountp );
          auth_drive = DVDOpenImageFile( dev_name, NULL, NULL, have_css );
          break;
        }
      }
      fclose( mntfile );
    }
#elif defined(__linux__)
    mntfile = fopen( _PATH_MOUNTED, "r" );
    if( mntfile ) {
      struct mntent *me;

      while( ( me = getmntent( mntfile ) ) ) {
        if( !strcmp( me->mnt_dir, path_copy ) ) {
          fprintf( stderr,
                   "libdvdread: Attempting to use device %s"
                   " mounted on %s for CSS authentication\n",
                   me->mnt_fsname,
                   me->mnt_dir );
          auth_drive = DVDOpenImageFile( me->mnt_fsname, NULL, NULL, have_css );
          dev_name = strdup(me->mnt_fsname);
          break;
        }
      }
      fclose( mntfile );
    }
#elif defined(_WIN32) || defined(__OS2__)
#ifdef __OS2__
    /* Use DVDOpenImageFile() only if it is a drive */
    if(isalpha(path[0]) && path[1] == ':' &&
        ( !path[2] ||
          ((path[2] == '\\' || path[2] == '/') && !path[3])))
#endif
    auth_drive = DVDOpenImageFile( path, NULL, NULL, have_css );
#endif

#if !defined(_WIN32) && !defined(__OS2__)
    if( !dev_name ) {
      fprintf( stderr, "libdvdread: Couldn't find device name.\n" );
    } else if( !auth_drive ) {
      fprintf( stderr, "libdvdread: Device %s inaccessible, "
               "CSS authentication not available.\n", dev_name );
    }
#else
    if( !auth_drive ) {
        fprintf( stderr, "libdvdread: Device %s inaccessible, "
                 "CSS authentication not available.\n", path );
    }
#endif

    free( dev_name );
    dev_name = NULL;
    free( path_copy );
    path_copy = NULL;

    /**
     * If we've opened a drive, just use that.
     */
    if( auth_drive ) {
      free(path);
      return auth_drive;
    }
    /**
     * Otherwise, we now try to open the directory tree instead.
     */
    ret_val = DVDOpenPath( path );
      free( path );
      return ret_val;
  }

DVDOpen_error:
  /* If it's none of the above, screw it. */
  fprintf( stderr, "libdvdread: Could not open %s\n", path );
  free( path );
  free( path_copy );
  if ( cdir >= 0 )
    close( cdir );
  free( new_path );
  return NULL;
}
Beispiel #20
0
int
attach_main(int noerror)
{
	struct packet pkt;
	unsigned char buf[BUFSIZE];
	fd_set readfds;
	int s;

	/* Attempt to open the socket. Don't display an error if noerror is 
	** set. */
	s = connect_socket(sockname);
	if (s < 0 && errno == ENAMETOOLONG)
	{
		char *slash = strrchr(sockname, '/');

		/* Try to shorten the socket's path name by using chdir. */
		if (slash)
		{
			int dirfd = open(".", O_RDONLY);

			if (dirfd >= 0)
			{
				*slash = '\0';
				if (chdir(sockname) >= 0)
				{
					s = connect_socket(slash + 1);
					fchdir(dirfd);
				}
				*slash = '/';
				close(dirfd);
			}
		}
	}
	if (s < 0)
	{
		if (!noerror)
			printf("%s: %s: %s\n", progname, sockname,
				strerror(errno));
		return 1;
	}

	/* The current terminal settings are equal to the original terminal
	** settings at this point. */
	cur_term = orig_term;

	/* Set a trap to restore the terminal when we die. */
	atexit(restore_term);

	/* Set some signals. */
	signal(SIGPIPE, SIG_IGN);
	signal(SIGXFSZ, SIG_IGN);
	signal(SIGHUP, die);
	signal(SIGTERM, die);
	signal(SIGINT, die);
	signal(SIGQUIT, die);
	signal(SIGWINCH, win_change);

	/* Set raw mode. */
	cur_term.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL);
	cur_term.c_iflag &= ~(IXON|IXOFF);
	cur_term.c_oflag &= ~(OPOST);
	cur_term.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
	cur_term.c_cflag &= ~(CSIZE|PARENB);
	cur_term.c_cflag |= CS8;
	cur_term.c_cc[VLNEXT] = VDISABLE;
	cur_term.c_cc[VMIN] = 1;
	cur_term.c_cc[VTIME] = 0;
	tcsetattr(0, TCSADRAIN, &cur_term);

	/* Clear the screen. This assumes VT100. */
	write(1, "\33[H\33[J", 6);

	/* Tell the master that we want to attach. */
	memset(&pkt, 0, sizeof(struct packet));
	pkt.type = MSG_ATTACH;
	write(s, &pkt, sizeof(struct packet));

	/* We would like a redraw, too. */
	pkt.type = MSG_REDRAW;
	pkt.len = redraw_method;
	ioctl(0, TIOCGWINSZ, &pkt.u.ws);
	write(s, &pkt, sizeof(struct packet));

	/* Wait for things to happen */
	while (1)
	{
		int n;

		FD_ZERO(&readfds);
		FD_SET(0, &readfds);
		FD_SET(s, &readfds);
		n = select(s + 1, &readfds, NULL, NULL, NULL);
		if (n < 0 && errno != EINTR && errno != EAGAIN)
		{
			printf(EOS "\r\n[select failed]\r\n");
			exit(1);
		}

		/* Pty activity */
		if (n > 0 && FD_ISSET(s, &readfds))
		{
			ssize_t len = read(s, buf, sizeof(buf));

			if (len == 0)
			{
				printf(EOS "\r\n[EOF - dtach terminating]"
					"\r\n");
				exit(0);
			}
			else if (len < 0)
			{
				printf(EOS "\r\n[read returned an error]\r\n");
				exit(1);
			}
			/* Send the data to the terminal. */
			write(1, buf, len);
			n--;
		}
		/* stdin activity */
		if (n > 0 && FD_ISSET(0, &readfds))
		{
			ssize_t len;

			pkt.type = MSG_PUSH;
			memset(pkt.u.buf, 0, sizeof(pkt.u.buf));
			len = read(0, pkt.u.buf, sizeof(pkt.u.buf));

			if (len <= 0)
				exit(1);

			pkt.len = len;
			process_kbd(s, &pkt);
			n--;
		}

		/* Window size changed? */
		if (win_changed)
		{
			win_changed = 0;

			pkt.type = MSG_WINCH;
			ioctl(0, TIOCGWINSZ, &pkt.u.ws);
			write(s, &pkt, sizeof(pkt));
		}
	}
	return 0;
}
int
rpmostree_compose_builtin_tree (int             argc,
                                char          **argv,
                                GCancellable   *cancellable,
                                GError        **error)
{
  int exit_status = EXIT_FAILURE;
  GError *temp_error = NULL;
  GOptionContext *context = g_option_context_new ("TREEFILE - Run yum and commit the result to an OSTree repository");
  RpmOstreeTreeComposeContext selfdata = { NULL, };
  RpmOstreeTreeComposeContext *self = &selfdata;
  JsonNode *treefile_rootval = NULL;
  JsonObject *treefile = NULL;
  gs_free char *cachekey = NULL;
  gs_free char *new_inputhash = NULL;
  gs_unref_object GFile *previous_root = NULL;
  gs_free char *previous_checksum = NULL;
  gs_unref_object GFile *yumroot = NULL;
  gs_unref_object GFile *yumroot_varcache = NULL;
  gs_unref_object OstreeRepo *repo = NULL;
  gs_unref_ptrarray GPtrArray *bootstrap_packages = NULL;
  gs_unref_ptrarray GPtrArray *packages = NULL;
  gs_unref_object GFile *treefile_path = NULL;
  gs_unref_object GFile *treefile_dirpath = NULL;
  gs_unref_object GFile *repo_path = NULL;
  gs_unref_object JsonParser *treefile_parser = NULL;
  gs_unref_variant_builder GVariantBuilder *metadata_builder = 
    g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
  g_autoptr(RpmOstreeContext) corectx = NULL;
  g_autoptr(GHashTable) varsubsts = NULL;
  gboolean workdir_is_tmp = FALSE;

  self->treefile_context_dirs = g_ptr_array_new_with_free_func ((GDestroyNotify)g_object_unref);
  
  if (!rpmostree_option_context_parse (context,
                                       option_entries,
                                       &argc, &argv,
                                       RPM_OSTREE_BUILTIN_FLAG_LOCAL_CMD,
                                       cancellable,
                                       NULL,
                                       error))
    goto out;

  if (argc < 2)
    {
      rpmostree_usage_error (context, "TREEFILE must be specified", error);
      goto out;
    }
  
  if (!opt_repo)
    {
      rpmostree_usage_error (context, "--repo must be specified", error);
      goto out;
    }

  if (getuid () != 0)
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "compose tree must presently be run as uid 0 (root)");
      goto out;
    }

  repo_path = g_file_new_for_path (opt_repo);
  repo = self->repo = ostree_repo_new (repo_path);
  if (!ostree_repo_open (repo, cancellable, error))
    goto out;

  treefile_path = g_file_new_for_path (argv[1]);

  if (opt_workdir)
    {
      self->workdir = g_file_new_for_path (opt_workdir);
    }
  else
    {
      gs_free char *tmpd = NULL;

      if (!rpmostree_mkdtemp ("/var/tmp/rpm-ostree.XXXXXX", &tmpd, NULL, error))
        goto out;

      self->workdir = g_file_new_for_path (tmpd);
      workdir_is_tmp = TRUE;

      if (opt_workdir_tmpfs)
        {
          if (mount ("tmpfs", tmpd, "tmpfs", 0, (const void*)"mode=755") != 0)
            {
              _rpmostree_set_prefix_error_from_errno (error, errno,
                                                      "mount(tmpfs): ");
              goto out;
            }
        }
    }

  if (!glnx_opendirat (AT_FDCWD, gs_file_get_path_cached (self->workdir),
                       FALSE, &self->workdir_dfd, error))
    goto out;

  if (opt_cachedir)
    {
      if (!glnx_opendirat (AT_FDCWD, opt_cachedir, TRUE, &self->cachedir_dfd, error))
        {
          g_prefix_error (error, "Opening cachedir '%s': ", opt_cachedir);
          goto out;
        }
    }
  else
    {
      self->cachedir_dfd = fcntl (self->workdir_dfd, F_DUPFD_CLOEXEC, 3);
      if (self->cachedir_dfd < 0)
        {
          glnx_set_error_from_errno (error);
          goto out;
        }
    }

  if (opt_metadata_strings)
    {
      if (!parse_keyvalue_strings (opt_metadata_strings,
                                   metadata_builder, error))
        goto out;
    }

  if (fchdir (self->workdir_dfd) != 0)
    {
      glnx_set_error_from_errno (error);
      goto out;
    }

  corectx = rpmostree_context_new_unprivileged (self->cachedir_dfd, cancellable, error);
  if (!corectx)
    goto out;

  varsubsts = rpmostree_context_get_varsubsts (corectx);

  treefile_parser = json_parser_new ();
  if (!json_parser_load_from_file (treefile_parser,
                                   gs_file_get_path_cached (treefile_path),
                                   error))
    goto out;

  treefile_rootval = json_parser_get_root (treefile_parser);
  if (!JSON_NODE_HOLDS_OBJECT (treefile_rootval))
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "Treefile root is not an object");
      goto out;
    }
  treefile = json_node_get_object (treefile_rootval);

  if (!process_includes (self, treefile_path, 0, treefile,
                         cancellable, error))
    goto out;

  if (opt_print_only)
    {
      gs_unref_object JsonGenerator *generator = json_generator_new ();
      gs_unref_object GOutputStream *stdout = g_unix_output_stream_new (1, FALSE);

      json_generator_set_pretty (generator, TRUE);
      json_generator_set_root (generator, treefile_rootval);
      (void) json_generator_to_stream (generator, stdout, NULL, NULL);

      exit_status = EXIT_SUCCESS;
      goto out;
    }

  { const char *input_ref = _rpmostree_jsonutil_object_require_string_member (treefile, "ref", error);
    if (!input_ref)
      goto out;
    self->ref = _rpmostree_varsubst_string (input_ref, varsubsts, error);
    if (!self->ref)
      goto out;
  }

  if (!ostree_repo_read_commit (repo, self->ref, &previous_root, &previous_checksum,
                                cancellable, &temp_error))
    {
      if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
        { 
          g_clear_error (&temp_error);
          g_print ("No previous commit for %s\n", self->ref);
        }
      else
        {
          g_propagate_error (error, temp_error);
          goto out;
        }
    }
  else
    g_print ("Previous commit: %s\n", previous_checksum);

  self->previous_checksum = previous_checksum;

  yumroot = g_file_get_child (self->workdir, "rootfs.tmp");
  if (!glnx_shutil_rm_rf_at (self->workdir_dfd, "rootfs.tmp", cancellable, error))
    goto out;

  if (json_object_has_member (treefile, "automatic_version_prefix") &&
      !compose_strv_contains_prefix (opt_metadata_strings, "version="))
    {
      gs_unref_variant GVariant *variant = NULL;
      gs_free char *last_version = NULL;
      gs_free char *next_version = NULL;
      const char *ver_prefix;

      ver_prefix = _rpmostree_jsonutil_object_require_string_member (treefile,
                                                                     "automatic_version_prefix",
                                                                     error);
      if (!ver_prefix)
          goto out;

      if (previous_checksum)
        {
          if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT,
                                         previous_checksum, &variant, error))
            goto out;

          last_version = checksum_version (variant);
        }

      next_version = _rpmostree_util_next_version (ver_prefix, last_version);
      g_variant_builder_add (metadata_builder, "{sv}", "version",
                             g_variant_new_string (next_version));
    }

  bootstrap_packages = g_ptr_array_new ();
  packages = g_ptr_array_new ();

  if (json_object_has_member (treefile, "bootstrap_packages"))
    {
      if (!_rpmostree_jsonutil_append_string_array_to (treefile, "bootstrap_packages", packages, error))
        goto out;
    }
  if (!_rpmostree_jsonutil_append_string_array_to (treefile, "packages", packages, error))
    goto out;
  g_ptr_array_add (packages, NULL);

  { gs_unref_object JsonGenerator *generator = json_generator_new ();
    char *treefile_buf = NULL;
    gsize len;

    json_generator_set_root (generator, treefile_rootval);
    json_generator_set_pretty (generator, TRUE);
    treefile_buf = json_generator_to_data (generator, &len);

    self->serialized_treefile = g_bytes_new_take (treefile_buf, len);
  }

  treefile_dirpath = g_file_get_parent (treefile_path);
  if (TRUE)
    {
      gboolean generate_from_previous = TRUE;

      if (!_rpmostree_jsonutil_object_get_optional_boolean_member (treefile,
                                                                   "preserve-passwd",
                                                                   &generate_from_previous,
                                                                   error))
        goto out;

      if (generate_from_previous)
        {
          if (!rpmostree_generate_passwd_from_previous (repo, yumroot,
                                                        treefile_dirpath,
                                                        previous_root, treefile,
                                                        cancellable, error))
            goto out;
        }
    }

  { gboolean unmodified = FALSE;

    if (!install_packages_in_root (self, corectx, treefile, yumroot,
                                   (char**)packages->pdata,
                                   opt_force_nocache ? NULL : &unmodified,
                                   &new_inputhash,
                                   cancellable, error))
      goto out;

    if (unmodified)
      {
        g_print ("No apparent changes since previous commit; use --force-nocache to override\n");
        exit_status = EXIT_SUCCESS;
        goto out;
      }
    else if (opt_dry_run)
      {
        g_print ("--dry-run complete, exiting\n");
        exit_status = EXIT_SUCCESS;
        goto out;
      }
  }

  if (g_strcmp0 (g_getenv ("RPM_OSTREE_BREAK"), "post-yum") == 0)
    goto out;

  if (!rpmostree_treefile_postprocessing (yumroot, self->treefile_context_dirs->pdata[0],
                                          self->serialized_treefile, treefile,
                                          cancellable, error))
    goto out;

  if (!rpmostree_prepare_rootfs_for_commit (yumroot, treefile, cancellable, error))
    goto out;

  if (!rpmostree_copy_additional_files (yumroot, self->treefile_context_dirs->pdata[0], treefile, cancellable, error))
    goto out;

  if (!rpmostree_check_passwd (repo, yumroot, treefile_dirpath, treefile,
                               previous_checksum,
                               cancellable, error))
    goto out;

  if (!rpmostree_check_groups (repo, yumroot, treefile_dirpath, treefile,
                               previous_checksum,
                               cancellable, error))
    goto out;

  {
    const char *gpgkey;
    gboolean selinux = TRUE;
    gs_unref_variant GVariant *metadata = NULL;

    g_variant_builder_add (metadata_builder, "{sv}",
                           "rpmostree.inputhash",
                           g_variant_new_string (new_inputhash));

    metadata = g_variant_ref_sink (g_variant_builder_end (metadata_builder));

    if (!_rpmostree_jsonutil_object_get_optional_string_member (treefile, "gpg_key", &gpgkey, error))
      goto out;

    if (!_rpmostree_jsonutil_object_get_optional_boolean_member (treefile,
                                                                 "selinux",
                                                                 &selinux,
                                                                 error))
      goto out;

    { g_autofree char *new_revision = NULL;
      glnx_fd_close int rootfs_fd = -1;

      if (!glnx_opendirat (AT_FDCWD, gs_file_get_path_cached (yumroot), TRUE,
                           &rootfs_fd, error))
        goto out;

      g_print ("Committing...\n");
      
      if (!rpmostree_commit (rootfs_fd, repo, self->ref, metadata, gpgkey, selinux, NULL,
                             &new_revision,
                             cancellable, error))
        goto out;

      g_print ("%s => %s\n", self->ref, new_revision);

    }
  }

  if (opt_touch_if_changed)
    {
      gs_fd_close int fd = open (opt_touch_if_changed, O_CREAT|O_WRONLY|O_NOCTTY, 0644);
      if (fd == -1)
        {
          gs_set_error_from_errno (error, errno);
          g_prefix_error (error, "Updating '%s': ", opt_touch_if_changed);
          goto out;
        }
      if (futimens (fd, NULL) == -1)
        {
          gs_set_error_from_errno (error, errno);
          goto out;
        }
    }

  exit_status = EXIT_SUCCESS;

 out:
  /* Explicitly close this one now as it may have references to files
   * we delete below.
   */
  g_clear_object (&corectx);
  
  /* Move back out of the workding directory to ensure unmount works */
  (void )chdir ("/");

  if (self->workdir_dfd != -1)
    (void) close (self->workdir_dfd);

  if (workdir_is_tmp)
    {
      if (opt_workdir_tmpfs)
        if (umount (gs_file_get_path_cached (self->workdir)) != 0)
          {
            fprintf (stderr, "warning: umount failed: %m\n");
          }
      (void) gs_shutil_rm_rf (self->workdir, NULL, NULL);
    }
  if (self)
    {
      g_clear_object (&self->workdir);
      g_clear_pointer (&self->serialized_treefile, g_bytes_unref);
      g_ptr_array_unref (self->treefile_context_dirs);
    }

  return exit_status;
}
Beispiel #22
0
int
push_main()
{
	struct packet pkt;
	int s;

	/* Attempt to open the socket. */
	s = connect_socket(sockname);
	if (s < 0 && errno == ENAMETOOLONG)
	{
		char *slash = strrchr(sockname, '/');

		/* Try to shorten the socket's path name by using chdir. */
		if (slash)
		{
			int dirfd = open(".", O_RDONLY);

			if (dirfd >= 0)
			{
				*slash = '\0';
				if (chdir(sockname) >= 0)
				{
					s = connect_socket(slash + 1);
					fchdir(dirfd);
				}
				*slash = '/';
				close(dirfd);
			}
		}
	}
	if (s < 0)
	{
		printf("%s: %s: %s\n", progname, sockname, strerror(errno));
		return 1;
	}

	/* Set some signals. */
	signal(SIGPIPE, SIG_IGN);

	/* Push the contents of standard input to the socket. */
	pkt.type = MSG_PUSH;
	for (;;)
	{
		ssize_t len;

		memset(pkt.u.buf, 0, sizeof(pkt.u.buf));
		len = read(0, pkt.u.buf, sizeof(pkt.u.buf));

		if (len == 0)
			return 0;
		else if (len < 0)
		{
			printf("%s: %s: %s\n", progname, sockname,
			       strerror(errno));
			return 1;
		}

		pkt.len = len;
		if (write(s, &pkt, sizeof(struct packet)) < 0)
		{
			printf("%s: %s: %s\n", progname, sockname,
			       strerror(errno));
			return 1;
		}
	}
}
Beispiel #23
0
int runsv_main(int argc ATTRIBUTE_UNUSED, char **argv)
{
	struct stat s;
	int fd;
	int r;
	char buf[256];

	INIT_G();

	if (!argv[1] || argv[2])
		bb_show_usage();
	dir = argv[1];

	xpiped_pair(selfpipe);
	close_on_exec_on(selfpipe.rd);
	close_on_exec_on(selfpipe.wr);
	ndelay_on(selfpipe.rd);
	ndelay_on(selfpipe.wr);

	sig_block(SIGCHLD);
	bb_signals_recursive(1 << SIGCHLD, s_child);
	sig_block(SIGTERM);
	bb_signals_recursive(1 << SIGTERM, s_term);

	xchdir(dir);
	/* bss: svd[0].pid = 0; */
	if (S_DOWN) svd[0].state = S_DOWN; /* otherwise already 0 (bss) */
	if (C_NOOP) svd[0].ctrl = C_NOOP;
	if (W_UP) svd[0].want = W_UP;
	/* bss: svd[0].islog = 0; */
	/* bss: svd[1].pid = 0; */
	gettimeofday_ns(&svd[0].start);
	if (stat("down", &s) != -1) svd[0].want = W_DOWN;

	if (stat("log", &s) == -1) {
		if (errno != ENOENT)
			warn_cannot("stat ./log");
	} else {
		if (!S_ISDIR(s.st_mode)) {
			errno = 0;
			warn_cannot("stat log/down: log is not a directory");
		} else {
			haslog = 1;
			svd[1].state = S_DOWN;
			svd[1].ctrl = C_NOOP;
			svd[1].want = W_UP;
			svd[1].islog = 1;
			gettimeofday_ns(&svd[1].start);
			if (stat("log/down", &s) != -1)
				svd[1].want = W_DOWN;
			xpiped_pair(logpipe);
			close_on_exec_on(logpipe.rd);
			close_on_exec_on(logpipe.wr);
		}
	}

	if (mkdir("supervise", 0700) == -1) {
		r = readlink("supervise", buf, sizeof(buf));
		if (r != -1) {
			if (r == sizeof(buf))
				fatal2x_cannot("readlink ./supervise", ": name too long");
			buf[r] = 0;
			mkdir(buf, 0700);
		} else {
			if ((errno != ENOENT) && (errno != EINVAL))
				fatal_cannot("readlink ./supervise");
		}
	}
	svd[0].fdlock = xopen3("log/supervise/lock"+4,
			O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600);
	if (lock_exnb(svd[0].fdlock) == -1)
		fatal_cannot("lock supervise/lock");
	close_on_exec_on(svd[0].fdlock);
	if (haslog) {
		if (mkdir("log/supervise", 0700) == -1) {
			r = readlink("log/supervise", buf, 256);
			if (r != -1) {
				if (r == 256)
					fatal2x_cannot("readlink ./log/supervise", ": name too long");
				buf[r] = 0;
				fd = xopen(".", O_RDONLY|O_NDELAY);
				xchdir("./log");
				mkdir(buf, 0700);
				if (fchdir(fd) == -1)
					fatal_cannot("change back to service directory");
				close(fd);
			}
			else {
				if ((errno != ENOENT) && (errno != EINVAL))
					fatal_cannot("readlink ./log/supervise");
			}
		}
		svd[1].fdlock = xopen3("log/supervise/lock",
				O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600);
		if (lock_ex(svd[1].fdlock) == -1)
			fatal_cannot("lock log/supervise/lock");
		close_on_exec_on(svd[1].fdlock);
	}

	mkfifo("log/supervise/control"+4, 0600);
	svd[0].fdcontrol = xopen("log/supervise/control"+4, O_RDONLY|O_NDELAY);
	close_on_exec_on(svd[0].fdcontrol);
	svd[0].fdcontrolwrite = xopen("log/supervise/control"+4, O_WRONLY|O_NDELAY);
	close_on_exec_on(svd[0].fdcontrolwrite);
	update_status(&svd[0]);
	if (haslog) {
		mkfifo("log/supervise/control", 0600);
		svd[1].fdcontrol = xopen("log/supervise/control", O_RDONLY|O_NDELAY);
		close_on_exec_on(svd[1].fdcontrol);
		svd[1].fdcontrolwrite = xopen("log/supervise/control", O_WRONLY|O_NDELAY);
		close_on_exec_on(svd[1].fdcontrolwrite);
		update_status(&svd[1]);
	}
	mkfifo("log/supervise/ok"+4, 0600);
	fd = xopen("log/supervise/ok"+4, O_RDONLY|O_NDELAY);
	close_on_exec_on(fd);
	if (haslog) {
		mkfifo("log/supervise/ok", 0600);
		fd = xopen("log/supervise/ok", O_RDONLY|O_NDELAY);
		close_on_exec_on(fd);
	}
	for (;;) {
		struct pollfd x[3];
		unsigned deadline;
		char ch;

		if (haslog)
			if (!svd[1].pid && svd[1].want == W_UP)
				startservice(&svd[1]);
		if (!svd[0].pid)
			if (svd[0].want == W_UP || svd[0].state == S_FINISH)
				startservice(&svd[0]);

		x[0].fd = selfpipe.rd;
		x[0].events = POLLIN;
		x[1].fd = svd[0].fdcontrol;
		x[1].events = POLLIN;
		/* x[2] is used only if haslog == 1 */
		x[2].fd = svd[1].fdcontrol;
		x[2].events = POLLIN;
		sig_unblock(SIGTERM);
		sig_unblock(SIGCHLD);
		poll(x, 2 + haslog, 3600*1000);
		sig_block(SIGTERM);
		sig_block(SIGCHLD);

		while (read(selfpipe.rd, &ch, 1) == 1)
			continue;

		for (;;) {
			int child;
			int wstat;

			child = wait_any_nohang(&wstat);
			if (!child)
				break;
			if ((child == -1) && (errno != EINTR))
				break;
			if (child == svd[0].pid) {
				svd[0].pid = 0;
				pidchanged = 1;
				svd[0].ctrl &=~ C_TERM;
				if (svd[0].state != S_FINISH) {
					fd = open_read("finish");
					if (fd != -1) {
						close(fd);
						svd[0].state = S_FINISH;
						update_status(&svd[0]);
						continue;
					}
				}
				svd[0].state = S_DOWN;
				deadline = svd[0].start.tv_sec + 1;
				gettimeofday_ns(&svd[0].start);
				update_status(&svd[0]);
				if (LESS(svd[0].start.tv_sec, deadline))
					sleep(1);
			}
			if (haslog) {
				if (child == svd[1].pid) {
					svd[1].pid = 0;
					pidchanged = 1;
					svd[1].state = S_DOWN;
					svd[1].ctrl &= ~C_TERM;
					deadline = svd[1].start.tv_sec + 1;
					gettimeofday_ns(&svd[1].start);
					update_status(&svd[1]);
					if (LESS(svd[1].start.tv_sec, deadline))
						sleep(1);
				}
			}
		} /* for (;;) */
		if (read(svd[0].fdcontrol, &ch, 1) == 1)
			ctrl(&svd[0], ch);
		if (haslog)
			if (read(svd[1].fdcontrol, &ch, 1) == 1)
				ctrl(&svd[1], ch);

		if (sigterm) {
			ctrl(&svd[0], 'x');
			sigterm = 0;
		}

		if (svd[0].want == W_EXIT && svd[0].state == S_DOWN) {
			if (svd[1].pid == 0)
				_exit(EXIT_SUCCESS);
			if (svd[1].want != W_EXIT) {
				svd[1].want = W_EXIT;
				/* stopservice(&svd[1]); */
				update_status(&svd[1]);
				close(logpipe.wr);
				close(logpipe.rd);
			}
		}
	} /* for (;;) */
	/* not reached */
	return 0;
}
Beispiel #24
0
void
extract(void)
{
	ARCHD *arcn;
	int res;
	off_t cnt;
	ARCHD archd;
	struct stat sb;
	int fd;
	time_t now;

	arcn = &archd;
	/*
	 * figure out archive type; pass any format specific options to the
	 * archive option processing routine; call the format init routine;
	 * start up the directory modification time and access mode database
	 */
	if ((get_arc() < 0) || ((*frmt->options)() < 0) ||
	    ((*frmt->st_rd)() < 0) || (dir_start() < 0))
		return;

	/*
	 * When we are doing interactive rename, we store the mapping of names
	 * so we can fix up hard links files later in the archive.
	 */
	if (iflag && (name_start() < 0))
		return;

	now = time(NULL);

	/*
	 * step through each entry on the archive until the format read routine
	 * says it is done
	 */
	while (next_head(arcn) == 0) {
		if (arcn->type == PAX_GLL || arcn->type == PAX_GLF) {
			/*
			 * we need to read, to get the real filename
			 */
			if (!(*frmt->rd_data)(arcn, arcn->type == PAX_GLF
			    ? -1 : -2, &cnt))
				(void)rd_skip(cnt + arcn->pad);
			continue;
		}

		/*
		 * check for pattern, and user specified options match. When
		 * all the patterns are matched we are done
		 */
		if ((res = pat_match(arcn)) < 0)
			break;

		if ((res > 0) || (sel_chk(arcn) != 0)) {
			/*
			 * file is not selected. skip past any file data and
			 * padding and go back for the next archive member
			 */
			(void)rd_skip(arcn->skip + arcn->pad);
			continue;
		}

		/*
		 * with -u or -D only extract when the archive member is newer
		 * than the file with the same name in the file system (no
		 * test of being the same type is required).
		 * NOTE: this test is done BEFORE name modifications as
		 * specified by pax. this operation can be confusing to the
		 * user who might expect the test to be done on an existing
		 * file AFTER the name mod. In honesty the pax spec is probably
		 * flawed in this respect.
		 */
		if ((uflag || Dflag) && ((lstat(arcn->name, &sb) == 0))) {
			if (uflag && Dflag) {
				if ((arcn->sb.st_mtime <= sb.st_mtime) &&
				    (arcn->sb.st_ctime <= sb.st_ctime)) {
					(void)rd_skip(arcn->skip + arcn->pad);
					continue;
				}
			} else if (Dflag) {
				if (arcn->sb.st_ctime <= sb.st_ctime) {
					(void)rd_skip(arcn->skip + arcn->pad);
					continue;
				}
			} else if (arcn->sb.st_mtime <= sb.st_mtime) {
				(void)rd_skip(arcn->skip + arcn->pad);
				continue;
			}
		}

		/*
		 * this archive member is now been selected. modify the name.
		 */
		if ((pat_sel(arcn) < 0) || ((res = mod_name(arcn)) < 0))
			break;
		if (res > 0) {
			/*
			 * a bad name mod, skip and purge name from link table
			 */
			purg_lnk(arcn);
			(void)rd_skip(arcn->skip + arcn->pad);
			continue;
		}

		/*
		 * Non standard -Y and -Z flag. When the existing file is
		 * same age or newer skip
		 */
		if ((Yflag || Zflag) && ((lstat(arcn->name, &sb) == 0))) {
			if (Yflag && Zflag) {
				if ((arcn->sb.st_mtime <= sb.st_mtime) &&
				    (arcn->sb.st_ctime <= sb.st_ctime)) {
					(void)rd_skip(arcn->skip + arcn->pad);
					continue;
				}
			} else if (Yflag) {
				if (arcn->sb.st_ctime <= sb.st_ctime) {
					(void)rd_skip(arcn->skip + arcn->pad);
					continue;
				}
			} else if (arcn->sb.st_mtime <= sb.st_mtime) {
				(void)rd_skip(arcn->skip + arcn->pad);
				continue;
			}
		}

		if (vflag) {
			if (vflag > 1)
				ls_list(arcn, now, listf);
			else {
				(void)safe_print(arcn->name, listf);
				vfpart = 1;
			}
		}

		/*
		 * if required, chdir around.
		 */
		if ((arcn->pat != NULL) && (arcn->pat->chdname != NULL))
			if (chdir(arcn->pat->chdname) != 0)
				syswarn(1, errno, "Cannot chdir to %s",
				    arcn->pat->chdname);

		/*
		 * all ok, extract this member based on type
		 */
		if ((arcn->type != PAX_REG) && (arcn->type != PAX_CTG)) {
			/*
			 * process archive members that are not regular files.
			 * throw out padding and any data that might follow the
			 * header (as determined by the format).
			 */
			if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG))
				res = lnk_creat(arcn);
			else
				res = node_creat(arcn);

			(void)rd_skip(arcn->skip + arcn->pad);
			if (res < 0)
				purg_lnk(arcn);

			if (vflag && vfpart) {
				(void)putc('\n', listf);
				vfpart = 0;
			}
			goto popd;
		}
		/*
		 * we have a file with data here. If we can not create it, skip
		 * over the data and purge the name from hard link table
		 */
		if ((fd = file_creat(arcn)) < 0) {
			(void)rd_skip(arcn->skip + arcn->pad);
			purg_lnk(arcn);
			goto popd;
		}
		/*
		 * extract the file from the archive and skip over padding and
		 * any unprocessed data
		 */
		res = (*frmt->rd_data)(arcn, fd, &cnt);
		file_close(arcn, fd);
		if (vflag && vfpart) {
			(void)putc('\n', listf);
			vfpart = 0;
		}
		if (!res)
			(void)rd_skip(cnt + arcn->pad);

popd:
		/*
		 * if required, chdir around.
		 */
		if ((arcn->pat != NULL) && (arcn->pat->chdname != NULL))
			if (fchdir(cwdfd) != 0)
				syswarn(1, errno,
				    "Can't fchdir to starting directory");
	}

	/*
	 * all done, restore directory modes and times as required; make sure
	 * all patterns supplied by the user were matched; block off signals
	 * to avoid chance for multiple entry into the cleanup code.
	 */
	(void)(*frmt->end_rd)();
	(void)sigprocmask(SIG_BLOCK, &s_mask, NULL);
	ar_close();
	proc_dir();
	pat_chk();
}
Beispiel #25
0
Datei: sv.c Projekt: Gottox/runit
int main(int argc, char **argv) {
  unsigned int i, done;
  char *x;

  progname =*argv;
  for (i =str_len(*argv); i; --i) if ((*argv)[i -1] == '/') break;
  *argv +=i;
  optprogname =progname =*argv;
  service =argv;
  services =1;
  lsb =(str_diff(progname, "sv"));
  if ((x =env_get("SVDIR"))) varservice =x;
  if ((x =env_get("SVWAIT"))) scan_ulong(x, &wait);
  while ((i =getopt(argc, (const char* const*)argv, "w:vV")) != opteof) {
    switch(i) {
    case 'w': scan_ulong(optarg, &wait);
    case 'v': verbose =1; break;
    case 'V': strerr_warn1(VERSION, 0);
    case '?': usage();
    }
  }
  argv +=optind; argc -=optind;
  if (!(action =*argv++)) usage(); --argc;
  if (!lsb) { service =argv; services =argc; }
  if (!*service) usage();

  taia_now(&tnow); tstart =tnow;
  if ((curdir =open_read(".")) == -1)
    fatal("unable to open current directory");

  act =&control; acts ="s";
  if (verbose) cbk =&check;
  switch (*action) {
  case 'x': case 'e':
    acts ="x"; break;
  case 'X': case 'E':
    acts ="x"; kll =1; cbk =&check; break;
  case 'D':
    acts ="d"; kll =1; cbk =&check; break;
  case 'T':
    acts ="tc"; kll =1; cbk =&check; break;
  case 't':
    if (!str_diff(action, "try-restart")) { acts ="tc"; cbk =&check; break; }
  case 'c':
    if (!str_diff(action, "check")) { act =0; acts ="C"; cbk =&check; break; }
  case 'u': case 'd': case 'o': case 'p': case 'h':
  case 'a': case 'i': case 'k': case 'q': case '1': case '2':
    action[1] =0; acts =action; break;
  case 's':
    if (!str_diff(action, "shutdown")) { acts ="x"; cbk =&check; break; }
    if (!str_diff(action, "start")) { acts ="u"; cbk =&check; break; }
    if (!str_diff(action, "stop")) { acts ="d"; cbk =&check; break; }
    if (lsb && str_diff(action, "status")) usage();
    act =&status; cbk =0; break;
  case 'r':
    if (!str_diff(action, "restart")) { acts ="tcu"; cbk =&check; break; }
    if (!str_diff(action, "reload")) { acts ="h"; cbk =&check; break; }
    usage();
  case 'f':
    if (!str_diff(action, "force-reload"))
      { acts ="tc"; kll =1; cbk =&check; break; }
    if (!str_diff(action, "force-restart"))
      { acts ="tcu"; kll =1; cbk =&check; break; }
    if (!str_diff(action, "force-shutdown"))
      { acts ="x"; kll =1; cbk =&check; break; }
    if (!str_diff(action, "force-stop"))
      { acts ="d"; kll =1; cbk =&check; break; }
  default:
    usage();
  }

  servicex =service;
  for (i =0; i < services; ++i) {
    if ((**service != '/') && (**service != '.') && **service &&
        ((*service)[str_len(*service) -1] != '/')) {
      if ((chdir(varservice) == -1) || (chdir(*service) == -1)) {
        fail("unable to change to service directory");
        *service =0;
      }
    }
    else
      if (chdir(*service) == -1) {
        fail("unable to change to service directory");
        *service =0;
      }
    if (*service) if (act && (act(acts) == -1)) *service =0;
    if (fchdir(curdir) == -1) fatal("unable to change to original directory");
    service++;
  }

  if (*cbk)
    for (;;) {
      taia_sub(&tdiff, &tnow, &tstart);
      service =servicex; done =1;
      for (i =0; i < services; ++i, ++service) {
        if (!*service) continue;
        if ((**service != '/') && (**service != '.')) {
          if ((chdir(varservice) == -1) || (chdir(*service) == -1)) {
            fail("unable to change to service directory");
            *service =0;
          }
        }
        else
          if (chdir(*service) == -1) {
            fail("unable to change to service directory");
            *service =0;
          }
        if (*service) { if (cbk(acts) != 0) *service =0; else done =0; }
        if (*service && taia_approx(&tdiff) > wait) {
          kll ? outs(KILL) : outs(TIMEOUT);
          if (svstatus_get() > 0) { svstatus_print(*service); ++rc; }
          flush("\n");
          if (kll) control("k");
          *service =0;
        }
        if (fchdir(curdir) == -1)
          fatal("unable to change to original directory");
      }
      if (done) break;
      usleep(420000);
      taia_now(&tnow);
    }
  return(rc > 99 ? 99 : rc);
}
Beispiel #26
0
 int _fchdir(int fd)
{
	return fchdir(fd);
}
Beispiel #27
0
FTSENT *
fts_children(FTS *sp, int instr)
{
	FTSENT *p;
	int fd;

	debug("fts_children(&sp, %d)", instr);

	if (instr && instr != FTS_NAMEONLY) {
		errno = EINVAL;
		return (NULL);
	}

	/* Set current node pointer. */
	p = sp->fts_cur;

	/*
	 * Errno set to 0 so user can distinguish empty directory from
	 * an error.
	 */
	errno = 0;

	/* Fatal errors stop here. */
	if (ISSET(FTS_STOP))
		return (NULL);

	/* Return logical hierarchy of user's arguments. */
	if (p->fts_info == FTS_INIT)
		return (p->fts_link);

	/*
	 * If not a directory being visited in pre-order, stop here.  Could
	 * allow FTS_DNR, assuming the user has fixed the problem, but the
	 * same effect is available with FTS_AGAIN.
	 */
	if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */)
		return (NULL);

	/* Free up any previous child list. */
	if (sp->fts_child)
		fts_lfree(sp->fts_child);

	if (instr == FTS_NAMEONLY) {
		SET(FTS_NAMEONLY);
		instr = BNAMES;
	} else
		instr = BCHILD;

	/*
	 * If using chdir on a relative path and called BEFORE fts_read does
	 * its chdir to the root of a traversal, we can lose -- we need to
	 * chdir into the subdirectory, and we don't know where the current
	 * directory is, so we can't get back so that the upcoming chdir by
	 * fts_read will work.
	 */
	if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' ||
	    ISSET(FTS_NOCHDIR))
		return (sp->fts_child = fts_build(sp, instr));

	if ((fd = open(".", O_RDONLY, 0)) < 0)
		return (NULL);
	sp->fts_child = fts_build(sp, instr);
	if (fchdir(fd)) {
		(void)close(fd);
		return (NULL);
	}
	(void)close(fd);
	return (sp->fts_child);
}
Beispiel #28
0
static inline int
cdb_fchdir (struct cd_buf const *cdb)
{
  return fchdir (cdb->fd);
}
Beispiel #29
0
/** External fetch callback */
static int download_with_xfercommand(const char *url, const char *localpath,
		int force)
{
	int ret = 0, retval;
	int usepart = 0;
	int cwdfd;
	struct stat st;
	char *parsedcmd, *tempcmd;
	char *destfile, *tempfile, *filename;

	if(!config->xfercommand) {
		return -1;
	}

	filename = get_filename(url);
	if(!filename) {
		return -1;
	}
	destfile = get_destfile(localpath, filename);
	tempfile = get_tempfile(localpath, filename);

	if(force && stat(tempfile, &st) == 0) {
		unlink(tempfile);
	}
	if(force && stat(destfile, &st) == 0) {
		unlink(destfile);
	}

	tempcmd = strdup(config->xfercommand);
	/* replace all occurrences of %o with fn.part */
	if(strstr(tempcmd, "%o")) {
		usepart = 1;
		parsedcmd = strreplace(tempcmd, "%o", tempfile);
		free(tempcmd);
		tempcmd = parsedcmd;
	}
	/* replace all occurrences of %u with the download URL */
	parsedcmd = strreplace(tempcmd, "%u", url);
	free(tempcmd);

	/* save the cwd so we can restore it later */
	do {
		cwdfd = open(".", O_RDONLY);
	} while(cwdfd == -1 && errno == EINTR);
	if(cwdfd < 0) {
		pm_printf(ALPM_LOG_ERROR, _("could not get current working directory\n"));
	}

	/* cwd to the download directory */
	if(chdir(localpath)) {
		pm_printf(ALPM_LOG_WARNING, _("could not chdir to download directory %s\n"), localpath);
		ret = -1;
		goto cleanup;
	}
	/* execute the parsed command via /bin/sh -c */
	pm_printf(ALPM_LOG_DEBUG, "running command: %s\n", parsedcmd);
	retval = system(parsedcmd);

	if(retval == -1) {
		pm_printf(ALPM_LOG_WARNING, _("running XferCommand: fork failed!\n"));
		ret = -1;
	} else if(retval != 0) {
		/* download failed */
		pm_printf(ALPM_LOG_DEBUG, "XferCommand command returned non-zero status "
				"code (%d)\n", retval);
		ret = -1;
	} else {
		/* download was successful */
		ret = 0;
		if(usepart) {
			if(rename(tempfile, destfile)) {
				pm_printf(ALPM_LOG_ERROR, _("could not rename %s to %s (%s)\n"),
						tempfile, destfile, strerror(errno));
				ret = -1;
			}
		}
	}

cleanup:
	/* restore the old cwd if we have it */
	if(cwdfd >= 0) {
		if(fchdir(cwdfd) != 0) {
			pm_printf(ALPM_LOG_ERROR, _("could not restore working directory (%s)\n"),
					strerror(errno));
		}
		close(cwdfd);
	}

	if(ret == -1) {
		/* hack to let an user the time to cancel a download */
		sleep(2);
	}
	free(destfile);
	free(tempfile);
	free(parsedcmd);

	return ret;
}
Beispiel #30
0
int
savewd_chdir (struct savewd *wd, char const *dir, int options,
              int open_result[2])
{
  int fd = -1;
  int result = 0;

  /* Open the directory if requested, or if avoiding a race condition
     is requested and possible.  */
  if (open_result
      || (options & (HAVE_WORKING_O_NOFOLLOW ? SAVEWD_CHDIR_NOFOLLOW : 0)))
    {
      fd = open (dir,
                 (O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NONBLOCK
                  | (options & SAVEWD_CHDIR_NOFOLLOW ? O_NOFOLLOW : 0)));

      if (open_result)
        {
          open_result[0] = fd;
          open_result[1] = errno;
        }

      if (fd < 0 && (errno != EACCES || (options & SAVEWD_CHDIR_READABLE)))
        result = -1;
    }

  if (result == 0 && ! (0 <= fd && options & SAVEWD_CHDIR_SKIP_READABLE))
    {
      if (savewd_save (wd))
        {
          open_result = NULL;
          result = -2;
        }
      else
        {
          result = (fd < 0 ? chdir (dir) : fchdir (fd));

          if (result == 0)
            switch (wd->state)
              {
              case FD_STATE:
                wd->state = FD_POST_CHDIR_STATE;
                break;

              case ERROR_STATE:
              case FD_POST_CHDIR_STATE:
              case FINAL_STATE:
                break;

              case FORKING_STATE:
                assert (wd->val.child == 0);
                break;

              default:
                assert (false);
              }
        }
    }

  if (0 <= fd && ! open_result)
    {
      int e = errno;
      close (fd);
      errno = e;
    }

  return result;
}