Ejemplo n.º 1
0
Archivo: file.c Proyecto: hgn/netsend
/* open our outfile */
int
open_output_file(void)
{
	int fd = 0;

	if (!opts.outfile)
		return STDOUT_FILENO;

	if (!strncmp(opts.outfile, "-", 1))
		return STDOUT_FILENO;

	umask(0);

	fd = open(opts.outfile, O_WRONLY | O_CREAT | O_EXCL,
			  S_IRUSR | S_IWUSR | S_IRGRP);
	if (fd == -1) {
		struct stat s;
		if (errno != EEXIST)
			err_sys_die(EXIT_FAILOPT, "Can't create outputfile: %s", opts.outfile);

		fd = open(opts.outfile, O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP);
		if (fd == -1)
			err_sys_die(EXIT_FAILOPT, "Can't open outputfile: %s", opts.outfile);

		xfstat(fd, &s, opts.outfile);

		if (S_ISREG(s.st_mode)) /* symblic link that pointed to regular file */
			err_sys_die(EXIT_FAILOPT, "Can't create outputfile: %s", opts.outfile);
		/* else file is a named pipe, socket, etc. */
	}

	return fd;
}
Ejemplo n.º 2
0
static int write_ar_archive(archive_handle_t *handle)
{
    struct stat st;
    archive_handle_t *out_handle;
    char *temp_fn = NULL;

    xfstat(handle->src_fd, &st, handle->ar__name);

    /* if archive exists, create a new handle for output.
     * we create it in place of the old one.
     */
    if (st.st_size != 0) {
        out_handle = init_handle();
#if !ENABLE_PLATFORM_MINGW32
        xunlink(handle->ar__name);
        out_handle->src_fd = xopen(handle->ar__name, O_WRONLY | O_CREAT | O_TRUNC);
#else
        /* can't unlink open file, create temporary output file */
        temp_fn = xasprintf("%sXXXXXX", handle->ar__name);
        out_handle->src_fd = xmkstemp(temp_fn);
#endif
        out_handle->accept = handle->accept;
    } else {
        out_handle = handle;
    }

    handle->ar__out = out_handle;

    xwrite(out_handle->src_fd, AR_MAGIC "\n", AR_MAGIC_LEN + 1);
    out_handle->offset += AR_MAGIC_LEN + 1;

    /* skip to the end of the archive if we have to append stuff */
    if (st.st_size != 0) {
        handle->filter = filter_replaceable;
        handle->action_data = copy_data;
        unpack_ar_archive(handle);
    }

    while (write_ar_header(out_handle) == 0)
        continue;

    /* optional, since we exit right after we return */
    if (ENABLE_FEATURE_CLEAN_UP || ENABLE_PLATFORM_MINGW32) {
        close(handle->src_fd);
        if (out_handle->src_fd != handle->src_fd)
            close(out_handle->src_fd);
    }

#if ENABLE_PLATFORM_MINGW32
    if ( temp_fn != NULL ) {
        xrename(temp_fn, handle->ar__name);
        free(temp_fn);
    }
#endif

    return EXIT_SUCCESS;
}
Ejemplo n.º 3
0
static int
creat(int n, Rpccall *cmd, Rpccall *reply, int chdir)
{
	Xfid *xf, *newxf;
	Xfile *xp;
	String elem;
	Dir dir; Sattr sattr;
	uchar *argptr = cmd->args;
	uchar *dataptr = reply->results;
	int trunced;

	if(n <= FHSIZE)
		return garbage(reply, "count too small");
	xf = rpc2xfid(cmd, 0);
	argptr += FHSIZE;
	argptr += string2S(argptr, &elem);
	argptr += convM2sattr(argptr, &sattr);
	if(argptr != &((uchar *)cmd->args)[n])
		return garbage(reply, "bad count");
	if(xf == 0)
		return error(reply, NFSERR_STALE);
	xp = xf->xp;
	if(!(xp->qid.type & QTDIR))
		return error(reply, NFSERR_NOTDIR);
	chat("%s/%.*s...", xp->name, utfnlen(elem.s, elem.n), elem.s);
	trunced = 0;
	if(xp->parent == xp && elem.s[0] == '#'){
		newxf = xfauth(xp, &elem);
		if(newxf == 0)
			return error(reply, NFSERR_PERM);
		if(xfauthremove(newxf, cmd->user) < 0)
			return error(reply, NFSERR_PERM);
		trunced = 1;
	}else
		newxf = xfwalkcr(Twalk, xf, &elem, 0);
	if(newxf == 0){
		newxf = xfwalkcr(Tcreate, xf, &elem, chdir|(sattr.mode&0777));
		if(newxf)
			trunced = 1;
		else
			newxf = xfwalkcr(Twalk, xf, &elem, 0);
	}
	if(newxf == 0)
		return error(reply, NFSERR_PERM);
	if(!trunced && chdir)
		return error(reply, NFSERR_EXIST);
	if(!trunced && xfopen(newxf, Trunc|Oread|Owrite) < 0)
		return error(reply, NFSERR_PERM);
	if(xfstat(newxf, &dir) < 0)
		return error(reply, NFSERR_IO);

	PLONG(NFS_OK);
	dataptr += xp2fhandle(newxf->xp, dataptr);
	dataptr += dir2fattr(cmd->up, &dir, dataptr);
	chat("OK\n");
	return dataptr - (uchar *)reply->results;
}
Ejemplo n.º 4
0
static void	*init(char *file, struct stat *s)
{
  int		fd;
  void		*buf;

  fd = xopen(file, O_RDONLY);
  xfstat(fd, s);
  buf = xmmap(NULL, s->st_size, PROT_READ, MAP_PRIVATE, fd, 0);
  return (buf);
}
Ejemplo n.º 5
0
static int
nfssetattr(int n, Rpccall *cmd, Rpccall *reply)
{
	Xfid *xf;
	Dir dir, nd;
	Sattr sattr;
	int r;
	uchar *argptr = cmd->args;
	uchar *dataptr = reply->results;

	chat("setattr...");
	if(n <= FHSIZE)
		return garbage(reply, "count too small");
	xf = rpc2xfid(cmd, &dir);
	argptr += FHSIZE;
	argptr += convM2sattr(argptr, &sattr);
	if(argptr != &((uchar *)cmd->args)[n])
		return garbage(reply, "bad count");
	chat("mode=0%lo,u=%ld,g=%ld,size=%ld,atime=%ld,mtime=%ld...",
		sattr.mode, sattr.uid, sattr.gid, sattr.size,
		sattr.atime, sattr.mtime);
	if(xf == 0)
		return error(reply, NFSERR_STALE);
	if(sattr.uid != NOATTR || sattr.gid != NOATTR)
		return error(reply, NFSERR_PERM);
	if(sattr.size == 0){
		if(xf->xp->s != xf->xp->parent->s){
			if(xfauthremove(xf, cmd->user) < 0)
				return error(reply, NFSERR_PERM);
		}else if(dir.length && xfopen(xf, Trunc|Oread|Owrite) < 0)
			return error(reply, NFSERR_PERM);
	}else if(sattr.size != NOATTR)
		return error(reply, NFSERR_PERM);
	r = 0;
	nulldir(&nd);
	if(sattr.mode != NOATTR)
		++r, nd.mode = (dir.mode & ~0777) | (sattr.mode & 0777);
	if(sattr.atime != NOATTR)
		++r, nd.atime = sattr.atime;
	if(sattr.mtime != NOATTR)
		++r, nd.mtime = sattr.mtime;
	chat("sattr.mode=%luo dir.mode=%luo nd.mode=%luo...", sattr.mode, dir.mode, nd.mode);
	if(r){
		r = xfwstat(xf, &nd);
		if(r < 0)
			return error(reply, NFSERR_PERM);
	}
	if(xfstat(xf, &dir) < 0)
		return error(reply, NFSERR_STALE);
	PLONG(NFS_OK);
	dataptr += dir2fattr(cmd->up, &dir, dataptr);
	chat("OK\n");
	return dataptr - (uchar *)reply->results;
}
Ejemplo n.º 6
0
/* if fn is NULL then input is stdin and output is stdout */
static void convert(char *fn, int conv_type)
{
	FILE *in, *out;
	int ch;
	char *temp_fn = temp_fn; /* for compiler */
	char *resolved_fn = resolved_fn;

	in = stdin;
	out = stdout;
	if (fn != NULL) {
		struct stat st;
		int fd;

		resolved_fn = xmalloc_follow_symlinks(fn);
		if (resolved_fn == NULL)
			bb_simple_perror_msg_and_die(fn);
		in = xfopen_for_read(resolved_fn);
		xfstat(fileno(in), &st, resolved_fn);

		temp_fn = xasprintf("%sXXXXXX", resolved_fn);
		fd = xmkstemp(temp_fn);
		if (fchmod(fd, st.st_mode) == -1)
			bb_simple_perror_msg_and_die(temp_fn);
		fchown(fd, st.st_uid, st.st_gid);

		out = xfdopen_for_write(fd);
	}

	while ((ch = fgetc(in)) != EOF) {
		if (ch == '\r')
			continue;
		if (ch == '\n')
			if (conv_type == CT_UNIX2DOS)
				fputc('\r', out);
		fputc(ch, out);
	}

	if (fn != NULL) {
		if (fclose(in) < 0 || fclose(out) < 0) {
			unlink(temp_fn);
			bb_perror_nomsg_and_die();
		}
		xrename(temp_fn, resolved_fn);
		free(temp_fn);
		free(resolved_fn);
	}
}
Ejemplo n.º 7
0
static int
nfsread(int n, Rpccall *cmd, Rpccall *reply)
{
	Session *s;
	Xfid *xf;
	Dir dir;
	int offset, count;
	uchar *argptr = cmd->args;
	uchar *dataptr = reply->results;
	uchar *readptr = dataptr + 4 + 17*4 + 4;

	chat("read...");
	if(n != FHSIZE+12)
		return garbage(reply, "bad count");
	xf = rpc2xfid(cmd, 0);
	argptr += FHSIZE;
	offset = GLONG();
	count = GLONG();
	if(xf == 0)
		return error(reply, NFSERR_STALE);
	chat("%s %d %d...", xf->xp->name, offset, count);
	if(xf->xp->s != xf->xp->parent->s){
		count = xfauthread(xf, offset, readptr, count);
	}else{
		if(xfopen(xf, Oread) < 0)
			return error(reply, NFSERR_PERM);
		if(count > 8192)
			count = 8192;
		s = xf->xp->s;
		setfid(s, xf->opfid);
		xf->opfid->tstale = nfstime + 60;
		s->f.offset = offset;
		s->f.count = count;
		if(xmesg(s, Tread) < 0)
			return error(reply, NFSERR_IO);
		count = s->f.count;
		memmove(readptr, s->f.data, count);
	}
	if(xfstat(xf, &dir) < 0)
		return error(reply, NFSERR_IO);
	PLONG(NFS_OK);
	dataptr += dir2fattr(cmd->up, &dir, dataptr);
	PLONG(count);
	dataptr += ROUNDUP(count);
	chat("%d OK\n", count);
	return dataptr - (uchar *)reply->results;
}
Ejemplo n.º 8
0
static int
nfsrename(int n, Rpccall *cmd, Rpccall *reply)
{
	Xfid *xf, *newxf;
	Xfile *xp;
	uchar *fromdir, *todir;
	String fromelem, toelem;
	Dir dir;
	uchar *argptr = cmd->args;
	uchar *dataptr = reply->results;

	chat("rename...");
	if(n <= FHSIZE)
		return garbage(reply, "count too small");
	xf = rpc2xfid(cmd, 0);
	fromdir = argptr;
	argptr += FHSIZE;
	argptr += string2S(argptr, &fromelem);
	todir = argptr;
	argptr += FHSIZE;
	argptr += string2S(argptr, &toelem);
	if(argptr != &((uchar *)cmd->args)[n])
		return garbage(reply, "bad count");
	if(xf == 0)
		return error(reply, NFSERR_STALE);
	xp = xf->xp;
	if(!(xp->qid.type & QTDIR))
		return error(reply, NFSERR_NOTDIR);
	if(memcmp(fromdir, todir, FHSIZE) != 0)
		return error(reply, NFSERR_NXIO);
	newxf = xfwalkcr(Twalk, xf, &fromelem, 0);
	if(newxf == 0)
		return error(reply, NFSERR_NOENT);
	if(xfstat(newxf, &dir) < 0)
		return error(reply, NFSERR_IO);

	if(xp->parent == xp && toelem.s[0] == '#')
		return error(reply, NFSERR_PERM);
	nulldir(&dir);
	dir.name = toelem.s;
	if(xfwstat(newxf, &dir) < 0)
		return error(reply, NFSERR_PERM);
	PLONG(NFS_OK);
	chat("OK\n");
	return dataptr - (uchar *)reply->results;
}
Ejemplo n.º 9
0
static int
nfswrite(int n, Rpccall *cmd, Rpccall *reply)
{
	Session *s;
	Xfid *xf;
	Dir dir;
	int offset, count;
	uchar *argptr = cmd->args;
	uchar *dataptr = reply->results;

	chat("write...");
	if(n < FHSIZE+16)
		return garbage(reply, "count too small");
	xf = rpc2xfid(cmd, 0);
	argptr += FHSIZE + 4;
	offset = GLONG();
	argptr += 4;
	count = GLONG();
	if(xf == 0)
		return error(reply, NFSERR_STALE);
	chat("%s %d %d...", xf->xp->name, offset, count);
	if(xf->xp->s != xf->xp->parent->s){
		if(xfauthwrite(xf, offset, argptr, count) < 0)
			return error(reply, NFSERR_IO);
	}else{
		if(xfopen(xf, Owrite) < 0)
			return error(reply, NFSERR_PERM);
		s = xf->xp->s;
		setfid(s, xf->opfid);
		xf->opfid->tstale = nfstime + 60;
		s->f.offset = offset;
		s->f.count = count;
		s->f.data = (char *)argptr;
		if(xmesg(s, Twrite) < 0)
			return error(reply, NFSERR_IO);
	}
	if(xfstat(xf, &dir) < 0)
		return error(reply, NFSERR_IO);
	PLONG(NFS_OK);
	dataptr += dir2fattr(cmd->up, &dir, dataptr);
	chat("OK\n");
	return dataptr - (uchar *)reply->results;
}
Ejemplo n.º 10
0
static void do_skip(priv_dumper_t *dumper, const char *fname, int statok)
{
	struct stat sbuf;

	if (statok) {
		xfstat(STDIN_FILENO, &sbuf, fname);
		if (!(S_ISCHR(sbuf.st_mode) || S_ISBLK(sbuf.st_mode) || S_ISFIFO(sbuf.st_mode))
		 && dumper->pub.dump_skip >= sbuf.st_size
		) {
			/* If bb_dump_size valid and pub.dump_skip >= size */
			dumper->pub.dump_skip -= sbuf.st_size;
			dumper->address += sbuf.st_size;
			return;
		}
	}
	if (fseek(stdin, dumper->pub.dump_skip, SEEK_SET)) {
		bb_simple_perror_msg_and_die(fname);
	}
	dumper->address += dumper->pub.dump_skip;
	dumper->savaddress = dumper->address;
	dumper->pub.dump_skip = 0;
}
Ejemplo n.º 11
0
static int
nfslookup(int n, Rpccall *cmd, Rpccall *reply)
{
	Xfile *xp;
	Xfid *xf, *newxf;
	String elem;
	Dir dir;
	uchar *argptr = cmd->args;
	uchar *dataptr = reply->results;

	chat("lookup...");
	if(n <= FHSIZE)
		return garbage(reply, "count too small");
	xf = rpc2xfid(cmd, 0);
	argptr += FHSIZE;
	argptr += string2S(argptr, &elem);
	if(argptr != &((uchar *)cmd->args)[n])
		return garbage(reply, "bad count");
	if(xf == 0)
		return error(reply, NFSERR_STALE);
	xp = xf->xp;
	if(!(xp->qid.type & QTDIR))
		return error(reply, NFSERR_NOTDIR);
	chat("%s -> \"%.*s\"...", xp->name, utfnlen(elem.s, elem.n), elem.s);
	if(xp->s->noauth == 0 && xp->parent == xp && elem.s[0] == '#')
		newxf = xfauth(xp, &elem);
	else
		newxf = xfwalkcr(Twalk, xf, &elem, 0);
	if(newxf == 0)
		return error(reply, NFSERR_NOENT);
	if(xfstat(newxf, &dir) < 0)
		return error(reply, NFSERR_IO);
	PLONG(NFS_OK);
	dataptr += xp2fhandle(newxf->xp, dataptr);
	dataptr += dir2fattr(cmd->up, &dir, dataptr);
	chat("OK\n");
	return dataptr - (uchar *)reply->results;
}
Ejemplo n.º 12
0
static void mkswap_selinux_setcontext(int fd, const char *path)
{
	struct stat stbuf;

	if (!is_selinux_enabled())
		return;

	xfstat(fd, &stbuf, path);
	if (S_ISREG(stbuf.st_mode)) {
		security_context_t newcon;
		security_context_t oldcon = NULL;
		context_t context;

		if (fgetfilecon(fd, &oldcon) < 0) {
			if (errno != ENODATA)
				goto error;
			if (matchpathcon(path, stbuf.st_mode, &oldcon) < 0)
				goto error;
		}
		context = context_new(oldcon);
		if (!context || context_type_set(context, "swapfile_t"))
			goto error;
		newcon = context_str(context);
		if (!newcon)
			goto error;
		/* fsetfilecon_raw is hidden */
		if (strcmp(oldcon, newcon) != 0 && fsetfilecon(fd, newcon) < 0)
			goto error;
		if (ENABLE_FEATURE_CLEAN_UP) {
			context_free(context);
			freecon(oldcon);
		}
	}
	return;
 error:
	bb_perror_msg_and_die("SELinux relabeling failed");
}
Ejemplo n.º 13
0
int add_remove_shell_main(int argc UNUSED_PARAM, char **argv)
{
	FILE *orig_fp;
	char *orig_fn;
	char *new_fn;
	struct stat sb;

	sb.st_mode = 0666;

	argv++;

	orig_fn = xmalloc_follow_symlinks(SHELLS_FILE);
	if (!orig_fn)
		return EXIT_FAILURE;
	orig_fp = fopen_for_read(orig_fn);
	if (orig_fp)
		xfstat(fileno(orig_fp), &sb, orig_fn);

	new_fn = xasprintf("%s.tmp", orig_fn);
	/*
	 * O_TRUNC or O_EXCL? At the first glance, O_EXCL looks better,
	 * since it prevents races. But: (1) it requires a retry loop,
	 * (2) if /etc/shells.tmp is *stale*, then retry loop
	 * with O_EXCL will never succeed - it should have a timeout,
	 * after which it should revert to O_TRUNC.
	 * For now, I settle for O_TRUNC instead.
	 */
	xmove_fd(xopen3(new_fn, O_WRONLY | O_CREAT | O_TRUNC, sb.st_mode), STDOUT_FILENO);
	/* TODO?
	xfchown(STDOUT_FILENO, sb.st_uid, sb.st_gid);
	*/

	if (orig_fp) {
		/* Copy old file, possibly skipping removed shell names */
		char *line;
		while ((line = xmalloc_fgetline(orig_fp)) != NULL) {
			char **cpp = argv;
			while (*cpp) {
				if (*cpp != dont_add && strcmp(*cpp, line) == 0) {
					/* Old file has this shell name */
					if (REMOVE_SHELL) {
						/* we are remove-shell */
						/* delete this name by not copying it */
						goto next_line;
					}
					/* we are add-shell */
					/* mark this name as "do not add" */
					*cpp = dont_add;
				}
				cpp++;
			}
			/* copy shell name from old to new file */
			puts(line);
 next_line:
			free(line);
		}
		if (ENABLE_FEATURE_CLEAN_UP)
			fclose(orig_fp);
	}

	if (ADD_SHELL) {
		char **cpp = argv;
		while (*cpp) {
			if (*cpp != dont_add)
				puts(*cpp);
			cpp++;
		}
	}

	/* Ensure we wrote out everything */
	if (fclose(stdout) != 0) {
		xunlink(new_fn);
		bb_perror_msg_and_die("%s: write error", new_fn);
	}

	/* Small hole: if rename fails, /etc/shells.tmp is not removed */
	xrename(new_fn, orig_fn);

	if (ENABLE_FEATURE_CLEAN_UP) {
		free(orig_fn);
		free(new_fn);
	}

	return EXIT_SUCCESS;
}
Ejemplo n.º 14
0
int
meta_exchange_snd(int connected_fd, int file_fd)
{
	int ret = 0;
	ssize_t len;
	ssize_t file_size;
	struct ns_hdr ns_hdr;
	struct stat stat_buf;
	int perform_rtt;

	memset(&ns_hdr, 0, sizeof(struct ns_hdr));

	/* fetch file size */
	xfstat(file_fd, &stat_buf, opts.infile);

	file_size = S_ISREG(stat_buf.st_mode) ? stat_buf.st_size : 0;


	ns_hdr.magic = htons(NS_MAGIC);
	/* FIXME: catch overflow */
	ns_hdr.version = htons((uint16_t) strtol(VERSIONSTRING, (char **)NULL, 10));
	ns_hdr.data_size = htonl(file_size);

	perform_rtt = (opts.rtt_probe_opt.iterations > 0) ? 1 : 0;


	ns_hdr.nse_nxt_hdr = perform_rtt ? htons(NSE_NXT_RTT_PROBE) : htons(NSE_NXT_DATA);

	len = sizeof(struct ns_hdr);
	if (writen(connected_fd, &ns_hdr, len) != len)
		err_msg_die(EXIT_FAILHEADER, "Can't send netsend header!\n");

	/* probe for effective round trip time */
	if (opts.rtt_probe_opt.iterations > 0) {

		int flag_old;
		struct sigaction sa;

		/* initialize signalhandler for timeout handling */
		sigemptyset(&sa.sa_mask);
		sa.sa_flags = SA_INTERRUPT;	/* don't restart system calls */
		sa.sa_handler = timout_handler;
		if (sigaction(SIGALRM, &sa, NULL) != 0)
			err_sys("Can't add signal handler");

		/* set TCP_NODELAY so tcp writes dont get buffered */
		if (opts.protocol == IPPROTO_TCP) {
			if ((flag_old = set_nodelay(connected_fd, 1)) < 0) {
				err_sys("Can't set TCP_NODELAY for socket (ret: %d)",
						flag_old);
			}
		}

		alarm(TIMEOUT_SEC);
		probe_rtt(connected_fd, NSE_NXT_DATA,
				opts.rtt_probe_opt.iterations, opts.rtt_probe_opt.data_size);
		alarm(0);

		/* and restore TCP_NOPUSH */
		if (opts.protocol == IPPROTO_TCP) {
			if ((set_nodelay(connected_fd, flag_old)) < 0) {
				err_sys("Can't set TCP_NODELAY for socket");
			}
		}

		/* transmitt our rtt probe results to our peer */
		send_rtt_info(connected_fd, NSE_NXT_DATA, &net_stat.rtt_probe);

	}

	/* XXX: add shasum next header if opts.sha, modify nse_nxt_hdr processing */

	return ret;
}
Ejemplo n.º 15
0
static void
do_xfer_recv(const struct xfer_opts xfer_opts,
             const char* filename,
             const char* desired_basename,
             int from_peer)
{
    struct xfer_msg statm = recv_xfer_msg(from_peer);
    if (statm.type != XFER_MSG_STAT)
        die(ECOMM, "expected stat msg");

    struct cleanup* error_cl = cleanup_allocate();
    struct stat st;
    const char* parent_directory = NULL;
    const char* rename_to = NULL;
    const char* write_mode = NULL;
    int dest_fd;

    if (stat(filename, &st) == 0) {
        if (S_ISDIR(st.st_mode)) {
            if (desired_basename == NULL)
                die(EISDIR, "\"%s\" is a directory", filename);
            parent_directory = filename;
            filename = xaprintf("%s/%s",
                                parent_directory,
                                desired_basename);
        } else if (S_ISREG(st.st_mode)) {
            if (st.st_nlink > 1)
                write_mode = "inplace";
        } else {
            write_mode = "inplace";
        }
    }

    if (parent_directory == NULL)
        parent_directory = xdirname(filename);

    if (write_mode == NULL)
        write_mode = xfer_opts.write_mode;

    bool atomic;
    bool automatic_mode = false;
    if (write_mode == NULL) {
        automatic_mode = true;
        atomic = true;
    } else if (strcmp(write_mode, "atomic") == 0) {
        atomic = true;
    } else if (strcmp(write_mode, "inplace") == 0) {
        atomic = false;
    } else {
        die(EINVAL, "unknown write mode \"%s\"", write_mode);
    }

    bool regular_file = true;
    bool preallocated = false;
    bool chmod_explicit = false;
    mode_t chmod_explicit_modes = 0;

    if (xfer_opts.preserve) {
        chmod_explicit = true;
        chmod_explicit_modes = statm.u.stat.ugo_bits;
    }

    if (xfer_opts.mode) {
        char* endptr = NULL;
        errno = 0;
        unsigned long omode = strtoul(xfer_opts.mode, &endptr, 8);
        if (errno != 0 || *endptr != '\0' || (omode &~ 0777) != 0)
            die(EINVAL, "invalid mode bits: %s", xfer_opts.mode);
        chmod_explicit = true;
        chmod_explicit_modes = (mode_t) omode;
    }

    mode_t creat_mode = (chmod_explicit_modes ? 0200 : 0666);

    if (atomic) {
        rename_to = filename;
        filename =
            xaprintf("%s.fb-adb-%s",
                     filename,
                     gen_hex_random(ENOUGH_ENTROPY));
        dest_fd = try_xopen(
            filename,
            O_CREAT | O_WRONLY | O_EXCL,
            creat_mode);
        if (dest_fd == -1) {
            if (errno == EACCES && automatic_mode) {
                atomic = false;
                filename = rename_to;
                rename_to = NULL;
            } else {
                die_errno("open(\"%s\")", filename);
            }
        }
    }

    if (!atomic) {
        dest_fd = xopen(filename, O_WRONLY | O_CREAT | O_TRUNC, creat_mode);
        if (!S_ISREG(xfstat(dest_fd).st_mode))
            regular_file = false;
    }

    if (regular_file)
        cleanup_commit(error_cl, unlink_cleanup, filename);

    if (regular_file && statm.u.stat.size > 0)
        preallocated = fallocate_if_supported(
            dest_fd,
            statm.u.stat.size);

    uint64_t total_written = copy_loop_posix_recv(from_peer, dest_fd);

    if (preallocated && total_written < statm.u.stat.size)
        xftruncate(dest_fd, total_written);

    if (xfer_opts.preserve) {
        struct timeval times[2] = {
            { statm.u.stat.atime, statm.u.stat.atime_ns / 1000 },
            { statm.u.stat.mtime, statm.u.stat.mtime_ns / 1000 },
        };
#ifdef HAVE_FUTIMES
        if (futimes(dest_fd, times) == -1)
            die_errno("futimes");
#else
        if (utimes(filename, times) == -1)
            die_errno("times");
#endif
    }

    if (chmod_explicit)
        if (fchmod(dest_fd, chmod_explicit_modes) == -1)
            die_errno("fchmod");

    if (xfer_opts.sync)
        xfsync(dest_fd);

    if (rename_to)
        xrename(filename, rename_to);

    if (xfer_opts.sync)
        xfsync(xopen(parent_directory, O_DIRECTORY|O_RDONLY, 0));

    cleanup_forget(error_cl);
}
Ejemplo n.º 16
0
Xfid *
rpc2xfid(Rpccall *cmd, Dir *dp)
{
	char *argptr = cmd->args;
	Xfile *xp;
	Xfid *xf;
	Session *s;
	char *service;
	Authunix au;
	Qid qid;
	char client[256], *user;
	Unixidmap *m;
	int i;
	uvlong x1, x2;

	chat("rpc2xfid %.8lux %.8lux %p %p\n", *((ulong*)argptr), *((ulong*)argptr+1), buf, argptr);
	if(argptr[0] == 0 && argptr[1] == 0){	/* root */
		chat("root...");
		xp = xfroot(&argptr[2], 0);
		s = xp ? xp->s : 0;
	}else{
		ulong ul;
		chat("noroot %.8lux...", *((ulong*)argptr));
		if((ul=GLONG()) != starttime){
			chat("bad tag %lux %lux...", ul, starttime);
			return 0;
		}
		s = (Session *)GLONG();
		x1 = GLONG();
		x2 = GLONG();
		qid.path = x1 | (x2<<32);
		qid.vers = 0;
		qid.type = GBYTE();
		xp = xfile(&qid, s, 0);
	}
	if(xp == 0){
		chat("no xfile...");
		return 0;
	}
	if(auth2unix(&cmd->cred, &au) != 0){
		chat("auth flavor=%ld, count=%ld\n",
			cmd->cred.flavor, cmd->cred.count);
		for(i=0; i<cmd->cred.count; i++)
			chat(" %.2ux", ((uchar *)cmd->cred.data)[i]);
		chat("...");
		return 0;
	}else{
/*		chat("auth: %d %.*s u=%d g=%d",
 *			au.stamp, utfnlen(au.mach.s, au.mach.n), au.mach.s, au.uid, au.gid);
 *		for(i=0; i<au.gidlen; i++)
 *			chat(", %d", au.gids[i]);
 *		chat("...");
 */
		char *p = memchr(au.mach.s, '.', au.mach.n);
		chat("%ld@%.*s...", au.uid, utfnlen(au.mach.s, (p ? p-au.mach.s : au.mach.n)), au.mach.s);
	}
	if(au.mach.n >= sizeof client){
		chat("client name too long...");
		return 0;
	}
	memcpy(client, au.mach.s, au.mach.n);
	client[au.mach.n] = 0;
	service = xp->parent->s->service;
	cmd->up = m = pair2idmap(service, cmd->host);
	if(m == 0){
		chat("no map for pair (%s,%s)...", service, client);
		/*chat("getdom %d.%d.%d.%d", cmd->host&0xFF, (cmd->host>>8)&0xFF,
			(cmd->host>>16)&0xFF, (cmd->host>>24)&0xFF);/**/
		/*if(getdom(cmd->host, client, sizeof(client))<0)
			return 0;/**/
		return 0;
	}
	/*chat("map=(%s,%s)...", m->server, m->client);/**/
	cmd->user = user = id2name(&m->u.ids, au.uid);
	if(user == 0){
		chat("no user for id %ld...", au.uid);
		return 0;
	}
	chat("user=%s...", user);/**/
	xf = 0;
	if(s == xp->parent->s){
		if(!s->noauth)
			xf = setuser(xp, user);
		if(xf == 0)
			xf = setuser(xp, "none");
		if(xf == 0)
			chat("can't set user none...");
	}else
		xf = xp->users;
	if(xf)
		chat("uid=%s...", xf->uid);
	if(xf && dp && xfstat(xf, dp) < 0){
		chat("can't stat %s...", xp->name);
		return 0;
	}
	return xf;
}