Exemple #1
0
int sftp_cmd_rmdir(struct sftp_command *cmd)
{
    char *dir;
    int result;

    if (back == NULL) {
	printf("psftp: not connected to a host; use \"open host.name\"\n");
	return 0;
    }

    if (cmd->nwords < 2) {
	printf("rmdir: expects a directory\n");
	return 0;
    }

    dir = canonify(cmd->words[1]);
    if (!dir) {
	printf("%s: %s\n", dir, fxp_error());
	return 0;
    }

    result = fxp_rmdir(dir);
    if (!result) {
	printf("rmdir %s: %s\n", dir, fxp_error());
	sfree(dir);
	return 0;
    }

    sfree(dir);
    return 1;
}
Exemple #2
0
int sftp_cmd_rm(struct sftp_command *cmd)
{
    char *fname;
    int result;

    if (back == NULL) {
	printf("psftp: not connected to a host; use \"open host.name\"\n");
	return 0;
    }

    if (cmd->nwords < 2) {
	printf("rm: expects a filename\n");
	return 0;
    }

    fname = canonify(cmd->words[1]);
    if (!fname) {
	printf("%s: %s\n", fname, fxp_error());
	return 0;
    }

    result = fxp_remove(fname);
    if (!result) {
	printf("rm %s: %s\n", fname, fxp_error());
	sfree(fname);
	return 0;
    }

    sfree(fname);
    return 1;
}
Exemple #3
0
/*
 * Change directories. We do this by canonifying the new name, then
 * trying to OPENDIR it. Only if that succeeds do we set the new pwd.
 */
int sftp_cmd_cd(struct sftp_command *cmd)
{
    struct fxp_handle *dirh;
    char *dir;

    if (back == NULL) {
	printf("psftp: not connected to a host; use \"open host.name\"\n");
	return 0;
    }

    if (cmd->nwords < 2)
	dir = dupstr(homedir);
    else
	dir = canonify(cmd->words[1]);

    if (!dir) {
	printf("%s: %s\n", dir, fxp_error());
	return 0;
    }

    dirh = fxp_opendir(dir);
    if (!dirh) {
	printf("Directory %s: %s\n", dir, fxp_error());
	sfree(dir);
	return 0;
    }

    fxp_close(dirh);

    sfree(pwd);
    pwd = dir;
    printf("Remote directory is now %s\n", pwd);

    return 1;
}
Exemple #4
0
int
main(int argc, char **argv)
{
	int ch;
	int rc = 0;
	struct rule *r;
	fn_list *pre_input = NULL;
  
#ifdef YYDEBUG
	extern int yydebug;

	yydebug = 0;
#endif
	hcreate(MAXRULE);

	while ((ch = getopt(argc, argv, "cdi:kntqS:")) != -1) {
		switch (ch) {
		case 'c':
			cflag++;
			break;

		case 'd':
#ifdef YYDEBUG
			yydebug = 1;
#else
			fprintf(stderr, "Rebuild with -DYYDEBUG to use -d.\n");
#endif
			break;

		case 'k':
			c2flag++;
			break;

		case 'n':
			canon = 0;
			break;

		case 'i': {
			fn_list *ifile = calloc(sizeof(fn_list), 1);
			ifile->filename = optarg;
			ifile->next = pre_input;
			pre_input = ifile;
			break;
		}
      
		case 't':
			tflag++;
			break;

		case 'p':
			permissive = 0;
			break;

		case 'q':
			qflag++;
			break;

		case 'S': 
			top_rule_name = optarg;
			break;
      
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;

	if (argc > 1)
		usage();

	predefine(pre_input);    
  
	/* Parse the grammar, perhaps spouting errors. */
	parse_from((argc > 0)? argv[0] : NULL);

	/* If we're not quiet, then output the grammar again. */
	if (!qflag) {
		if (canon)
			canonify(rules);
		for (r = rules; r; r = r->next) {
			if (r->predefined) {
				/* do not output */
			}
			else if (r->rule) {
				printf("%s = ", r->name);
				printobj(r->rule, tflag);
				if (cflag)
					printf(" ; line %d", r->line);
				printf("\n");
			} else {
				printf("; %s UNDEFINED\n", r->name);
			}
			if (r->next == rules)
				break;
		}
		for (r = rules; r; r = r->next) {
			if (r->used == 0 
				&& r->predefined == 0 
				&& r->rule 
				&& strcmp(r->name, top_rule_name))
				printf("; %s defined but not used\n", r->name);
			if (r->next == rules)
				break;
		}
	}
  
	rc = summary();
	hdestroy();
	exit(rc);
}
Exemple #5
0
int sftp_cmd_chmod(struct sftp_command *cmd)
{
    char *fname, *mode;
    int result;
    struct fxp_attrs attrs;
    unsigned attrs_clr, attrs_xor, oldperms, newperms;

    if (back == NULL) {
	printf("psftp: not connected to a host; use \"open host.name\"\n");
	return 0;
    }

    if (cmd->nwords < 3) {
	printf("chmod: expects a mode specifier and a filename\n");
	return 0;
    }

    /*
     * Attempt to parse the mode specifier in cmd->words[1]. We
     * don't support the full horror of Unix chmod; instead we
     * support a much simpler syntax in which the user can either
     * specify an octal number, or a comma-separated sequence of
     * [ugoa]*[-+=][rwxst]+. (The initial [ugoa] sequence may
     * _only_ be omitted if the only attribute mentioned is t,
     * since all others require a user/group/other specification.
     * Additionally, the s attribute may not be specified for any
     * [ugoa] specifications other than exactly u or exactly g.
     */
    attrs_clr = attrs_xor = 0;
    mode = cmd->words[1];
    if (mode[0] >= '0' && mode[0] <= '9') {
	if (mode[strspn(mode, "01234567")]) {
	    printf("chmod: numeric file modes should"
		   " contain digits 0-7 only\n");
	    return 0;
	}
	attrs_clr = 07777;
	sscanf(mode, "%o", &attrs_xor);
	attrs_xor &= attrs_clr;
    } else {
	while (*mode) {
	    char *modebegin = mode;
	    unsigned subset, perms;
	    int action;

	    subset = 0;
	    while (*mode && *mode != ',' &&
		   *mode != '+' && *mode != '-' && *mode != '=') {
		switch (*mode) {
		  case 'u': subset |= 04700; break; /* setuid, user perms */
		  case 'g': subset |= 02070; break; /* setgid, group perms */
		  case 'o': subset |= 00007; break; /* just other perms */
		  case 'a': subset |= 06777; break; /* all of the above */
		  default:
		    printf("chmod: file mode '%.*s' contains unrecognised"
			   " user/group/other specifier '%c'\n",
			   strcspn(modebegin, ","), modebegin, *mode);
		    return 0;
		}
		mode++;
	    }
	    if (!*mode || *mode == ',') {
		printf("chmod: file mode '%.*s' is incomplete\n",
		       strcspn(modebegin, ","), modebegin);
		return 0;
	    }
	    action = *mode++;
	    if (!*mode || *mode == ',') {
		printf("chmod: file mode '%.*s' is incomplete\n",
		       strcspn(modebegin, ","), modebegin);
		return 0;
	    }
	    perms = 0;
	    while (*mode && *mode != ',') {
		switch (*mode) {
		  case 'r': perms |= 00444; break;
		  case 'w': perms |= 00222; break;
		  case 'x': perms |= 00111; break;
		  case 't': perms |= 01000; subset |= 01000; break;
		  case 's':
		    if ((subset & 06777) != 04700 &&
			(subset & 06777) != 02070) {
			printf("chmod: file mode '%.*s': set[ug]id bit should"
			       " be used with exactly one of u or g only\n",
			       strcspn(modebegin, ","), modebegin);
			return 0;
		    }
		    perms |= 06000;
		    break;
		  default:
		    printf("chmod: file mode '%.*s' contains unrecognised"
			   " permission specifier '%c'\n",
			   strcspn(modebegin, ","), modebegin, *mode);
		    return 0;
		}
		mode++;
	    }
	    if (!(subset & 06777) && (perms &~ subset)) {
		printf("chmod: file mode '%.*s' contains no user/group/other"
		       " specifier and permissions other than 't' \n",
		       strcspn(modebegin, ","), modebegin, *mode);
		return 0;
	    }
	    perms &= subset;
	    switch (action) {
	      case '+':
		attrs_clr |= perms;
		attrs_xor |= perms;
		break;
	      case '-':
		attrs_clr |= perms;
		attrs_xor &= ~perms;
		break;
	      case '=':
		attrs_clr |= subset;
		attrs_xor |= perms;
		break;
	    }
	    if (*mode) mode++;	       /* eat comma */
	}
    }

    fname = canonify(cmd->words[2]);
    if (!fname) {
	printf("%s: %s\n", fname, fxp_error());
	return 0;
    }

    result = fxp_stat(fname, &attrs);
    if (!result || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS)) {
	printf("get attrs for %s: %s\n", fname,
	       result ? "file permissions not provided" : fxp_error());
	sfree(fname);
	return 0;
    }

    attrs.flags = SSH_FILEXFER_ATTR_PERMISSIONS;   /* perms _only_ */
    oldperms = attrs.permissions & 07777;
    attrs.permissions &= ~attrs_clr;
    attrs.permissions ^= attrs_xor;
    newperms = attrs.permissions & 07777;

    result = fxp_setstat(fname, attrs);

    if (!result) {
	printf("set attrs for %s: %s\n", fname, fxp_error());
	sfree(fname);
	return 0;
    }

    printf("%s: %04o -> %04o\n", fname, oldperms, newperms);

    sfree(fname);
    return 1;
}
Exemple #6
0
int sftp_cmd_mv(struct sftp_command *cmd)
{
    char *srcfname, *dstfname;
    int result;

    if (back == NULL) {
	printf("psftp: not connected to a host; use \"open host.name\"\n");
	return 0;
    }

    if (cmd->nwords < 3) {
	printf("mv: expects two filenames\n");
	return 0;
    }
    srcfname = canonify(cmd->words[1]);
    if (!srcfname) {
	printf("%s: %s\n", srcfname, fxp_error());
	return 0;
    }

    dstfname = canonify(cmd->words[2]);
    if (!dstfname) {
	printf("%s: %s\n", dstfname, fxp_error());
	return 0;
    }

    result = fxp_rename(srcfname, dstfname);
    if (!result) {
	char const *error = fxp_error();
	struct fxp_attrs attrs;

	/*
	 * The move might have failed because dstfname pointed at a
	 * directory. We check this possibility now: if dstfname
	 * _is_ a directory, we re-attempt the move by appending
	 * the basename of srcfname to dstfname.
	 */
	result = fxp_stat(dstfname, &attrs);
	if (result &&
	    (attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS) &&
	    (attrs.permissions & 0040000)) {
	    char *p;
	    char *newname, *newcanon;
	    printf("(destination %s is a directory)\n", dstfname);
	    p = srcfname + strlen(srcfname);
	    while (p > srcfname && p[-1] != '/') p--;
	    newname = dupcat(dstfname, "/", p, NULL);
	    newcanon = canonify(newname);
	    sfree(newname);
	    if (newcanon) {
		sfree(dstfname);
		dstfname = newcanon;
		result = fxp_rename(srcfname, dstfname);
		error = result ? NULL : fxp_error();
	    }
	}
	if (error) {
	    printf("mv %s %s: %s\n", srcfname, dstfname, error);
	    sfree(srcfname);
	    sfree(dstfname);
	    return 0;
	}
    }
    printf("%s -> %s\n", srcfname, dstfname);

    sfree(srcfname);
    sfree(dstfname);
    return 1;
}
Exemple #7
0
/*
 * Send a file and store it at the remote end. We have two very
 * similar commands here: `put' and `reput', which differ in that
 * `reput' checks for the existence of the destination file and
 * starts from where a previous aborted transfer left off.
 */
int sftp_general_put(struct sftp_command *cmd, int restart)
{
    struct fxp_handle *fh;
    char *fname, *origoutfname, *outfname;
    uint64 offset;
    FILE *fp;
    int ret;

    if (back == NULL) {
	printf("psftp: not connected to a host; use \"open host.name\"\n");
	return 0;
    }

    if (cmd->nwords < 2) {
	printf("put: expects a filename\n");
	return 0;
    }

    fname = cmd->words[1];
    origoutfname = (cmd->nwords == 2 ?
		    stripslashes(cmd->words[1], 1) : cmd->words[2]);
    outfname = canonify(origoutfname);
    if (!outfname) {
	printf("%s: %s\n", origoutfname, fxp_error());
	return 0;
    }

    fp = fopen(fname, "rb");
    if (!fp) {
	printf("local: unable to open %s\n", fname);
	sfree(outfname);
	return 0;
    }
    if (restart) {
	fh = fxp_open(outfname,
		      SSH_FXF_WRITE);
    } else {
	fh = fxp_open(outfname,
		      SSH_FXF_WRITE | SSH_FXF_CREAT | SSH_FXF_TRUNC);
    }
    if (!fh) {
	printf("%s: %s\n", outfname, fxp_error());
	sfree(outfname);
	return 0;
    }

    if (restart) {
	char decbuf[30];
	struct fxp_attrs attrs;
	if (!fxp_fstat(fh, &attrs)) {
	    printf("read size of %s: %s\n", outfname, fxp_error());
	    sfree(outfname);
	    return 0;
	}
	if (!(attrs.flags & SSH_FILEXFER_ATTR_SIZE)) {
	    printf("read size of %s: size was not given\n", outfname);
	    sfree(outfname);
	    return 0;
	}
	offset = attrs.size;
	uint64_decimal(offset, decbuf);
	printf("reput: restarting at file position %s\n", decbuf);
	if (uint64_compare(offset, uint64_make(0, LONG_MAX)) > 0) {
	    printf("reput: remote file is larger than we can deal with\n");
	    sfree(outfname);
	    return 0;
	}
	if (fseek(fp, offset.lo, SEEK_SET) != 0)
	    fseek(fp, 0, SEEK_END);    /* *shrug* */
    } else {
	offset = uint64_make(0, 0);
    }

    printf("local:%s => remote:%s\n", fname, outfname);

    /*
     * FIXME: we can use FXP_FSTAT here to get the file size, and
     * thus put up a progress bar.
     */
    ret = 1;
    while (1) {
	char buffer[4096];
	int len;

	len = fread(buffer, 1, sizeof(buffer), fp);
	if (len == -1) {
	    printf("error while reading local file\n");
	    ret = 0;
	    break;
	} else if (len == 0) {
	    break;
	}
	if (!fxp_write(fh, buffer, offset, len)) {
	    printf("error while writing: %s\n", fxp_error());
	    ret = 0;
	    break;
	}
	offset = uint64_add32(offset, len);
    }

    fxp_close(fh);
    fclose(fp);
    sfree(outfname);

    return ret;
}
Exemple #8
0
/*
 * Get a file and save it at the local end. We have two very
 * similar commands here: `get' and `reget', which differ in that
 * `reget' checks for the existence of the destination file and
 * starts from where a previous aborted transfer left off.
 */
int sftp_general_get(struct sftp_command *cmd, int restart)
{
    struct fxp_handle *fh;
    char *fname, *outfname;
    uint64 offset;
    FILE *fp;
    int ret;

    if (back == NULL) {
	printf("psftp: not connected to a host; use \"open host.name\"\n");
	return 0;
    }

    if (cmd->nwords < 2) {
	printf("get: expects a filename\n");
	return 0;
    }

    fname = canonify(cmd->words[1]);
    if (!fname) {
	printf("%s: %s\n", cmd->words[1], fxp_error());
	return 0;
    }
    outfname = (cmd->nwords == 2 ?
		stripslashes(cmd->words[1], 0) : cmd->words[2]);

    fh = fxp_open(fname, SSH_FXF_READ);
    if (!fh) {
	printf("%s: %s\n", fname, fxp_error());
	sfree(fname);
	return 0;
    }

    if (restart) {
	fp = fopen(outfname, "rb+");
    } else {
	fp = fopen(outfname, "wb");
    }

    if (!fp) {
	printf("local: unable to open %s\n", outfname);
	fxp_close(fh);
	sfree(fname);
	return 0;
    }

    if (restart) {
	long posn;
	fseek(fp, 0L, SEEK_END);
	posn = ftell(fp);
	printf("reget: restarting at file position %ld\n", posn);
	offset = uint64_make(0, posn);
    } else {
	offset = uint64_make(0, 0);
    }

    printf("remote:%s => local:%s\n", fname, outfname);

    /*
     * FIXME: we can use FXP_FSTAT here to get the file size, and
     * thus put up a progress bar.
     */
    ret = 1;
    while (1) {
	char buffer[4096];
	int len;
	int wpos, wlen;

	len = fxp_read(fh, buffer, offset, sizeof(buffer));
	if ((len == -1 && fxp_error_type() == SSH_FX_EOF) || len == 0)
	    break;
	if (len == -1) {
	    printf("error while reading: %s\n", fxp_error());
	    ret = 0;
	    break;
	}

	wpos = 0;
	while (wpos < len) {
	    wlen = fwrite(buffer, 1, len - wpos, fp);
	    if (wlen <= 0) {
		printf("error while writing local file\n");
		ret = 0;
		break;
	    }
	    wpos += wlen;
	}
	if (wpos < len) {	       /* we had an error */
	    ret = 0;
	    break;
	}
	offset = uint64_add32(offset, len);
    }

    fclose(fp);
    fxp_close(fh);
    sfree(fname);

    return ret;
}
Exemple #9
0
int sftp_cmd_ls(struct sftp_command *cmd)
{
    struct fxp_handle *dirh;
    struct fxp_names *names;
    struct fxp_name *ournames;
    int nnames, namesize;
    char *dir, *cdir;
    int i;

    if (back == NULL) {
	printf("psftp: not connected to a host; use \"open host.name\"\n");
	return 0;
    }

    if (cmd->nwords < 2)
	dir = ".";
    else
	dir = cmd->words[1];

    cdir = canonify(dir);
    if (!cdir) {
	printf("%s: %s\n", dir, fxp_error());
	return 0;
    }

    printf("Listing directory %s\n", cdir);

    dirh = fxp_opendir(cdir);
    if (dirh == NULL) {
	printf("Unable to open %s: %s\n", dir, fxp_error());
    } else {
	nnames = namesize = 0;
	ournames = NULL;

	while (1) {

	    names = fxp_readdir(dirh);
	    if (names == NULL) {
		if (fxp_error_type() == SSH_FX_EOF)
		    break;
		printf("Reading directory %s: %s\n", dir, fxp_error());
		break;
	    }
	    if (names->nnames == 0) {
		fxp_free_names(names);
		break;
	    }

	    if (nnames + names->nnames >= namesize) {
		namesize += names->nnames + 128;
		ournames =
		    srealloc(ournames, namesize * sizeof(*ournames));
	    }

	    for (i = 0; i < names->nnames; i++)
		ournames[nnames++] = names->names[i];

	    names->nnames = 0;	       /* prevent free_names */
	    fxp_free_names(names);
	}
	fxp_close(dirh);

	/*
	 * Now we have our filenames. Sort them by actual file
	 * name, and then output the longname parts.
	 */
	qsort(ournames, nnames, sizeof(*ournames), sftp_ls_compare);

	/*
	 * And print them.
	 */
	for (i = 0; i < nnames; i++)
	    printf("%s\n", ournames[i].longname);
    }

    sfree(cdir);

    return 1;
}
Exemple #10
0
/** Perform a path lookup.
 *
 * @param path    Path to be resolved; it must be a NULL-terminated
 *                string.
 * @param lflag   Flags to be used during lookup.
 * @param result  Empty structure where the lookup result will be stored.
 *                Can be NULL.
 * @param altroot If non-empty, will be used instead of rootfs as the root
 *                of the whole VFS tree.
 *
 * @return EOK on success or an error code from errno.h.
 *
 */
int vfs_lookup_internal(char *path, int lflag, vfs_lookup_res_t *result,
    vfs_pair_t *altroot, ...)
{
	vfs_pair_t *root;

	if (altroot)
		root = altroot;
	else
		root = &rootfs;

	if (!root->fs_handle)
		return ENOENT;
	
	size_t len;
	path = canonify(path, &len);
	if (!path)
		return EINVAL;
	
	fs_index_t index = 0;
	if (lflag & L_LINK) {
		va_list ap;

		va_start(ap, altroot);
		index = va_arg(ap, fs_index_t);
		va_end(ap);
	}
	
	fibril_mutex_lock(&plb_mutex);

	plb_entry_t entry;
	link_initialize(&entry.plb_link);
	entry.len = len;

	size_t first;	/* the first free index */
	size_t last;	/* the last free index */

	if (list_empty(&plb_entries)) {
		first = 0;
		last = PLB_SIZE - 1;
	} else {
		plb_entry_t *oldest = list_get_instance(
		    list_first(&plb_entries), plb_entry_t, plb_link);
		plb_entry_t *newest = list_get_instance(
		    list_last(&plb_entries), plb_entry_t, plb_link);

		first = (newest->index + newest->len) % PLB_SIZE;
		last = (oldest->index - 1) % PLB_SIZE;
	}

	if (first <= last) {
		if ((last - first) + 1 < len) {
			/*
			 * The buffer cannot absorb the path.
			 */
			fibril_mutex_unlock(&plb_mutex);
			return ELIMIT;
		}
	} else {
		if (PLB_SIZE - ((first - last) + 1) < len) {
			/*
			 * The buffer cannot absorb the path.
			 */
			fibril_mutex_unlock(&plb_mutex);
			return ELIMIT;
		}
	}

	/*
	 * We know the first free index in PLB and we also know that there is
	 * enough space in the buffer to hold our path.
	 */

	entry.index = first;
	entry.len = len;

	/*
	 * Claim PLB space by inserting the entry into the PLB entry ring
	 * buffer.
	 */
	list_append(&entry.plb_link, &plb_entries);
	
	fibril_mutex_unlock(&plb_mutex);

	/*
	 * Copy the path into PLB.
	 */
	size_t cnt1 = min(len, (PLB_SIZE - first) + 1);
	size_t cnt2 = len - cnt1;
	
	memcpy(&plb[first], path, cnt1);
	memcpy(plb, &path[cnt1], cnt2);

	ipc_call_t answer;
	async_exch_t *exch = vfs_exchange_grab(root->fs_handle);
	aid_t req = async_send_5(exch, VFS_OUT_LOOKUP, (sysarg_t) first,
	    (sysarg_t) (first + len - 1) % PLB_SIZE,
	    (sysarg_t) root->service_id, (sysarg_t) lflag, (sysarg_t) index,
	    &answer);
	
	sysarg_t rc;
	async_wait_for(req, &rc);
	vfs_exchange_release(exch);
	
	fibril_mutex_lock(&plb_mutex);
	list_remove(&entry.plb_link);
	/*
	 * Erasing the path from PLB will come handy for debugging purposes.
	 */
	memset(&plb[first], 0, cnt1);
	memset(plb, 0, cnt2);
	fibril_mutex_unlock(&plb_mutex);
	
	if ((int) rc < EOK)
		return (int) rc;

	if (!result)
		return EOK;
	
	result->triplet.fs_handle = (fs_handle_t) rc;
	result->triplet.service_id = (service_id_t) IPC_GET_ARG1(answer);
	result->triplet.index = (fs_index_t) IPC_GET_ARG2(answer);
	result->size =
	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(answer), IPC_GET_ARG4(answer));
	result->lnkcnt = (unsigned int) IPC_GET_ARG5(answer);
	
	if (lflag & L_FILE)
		result->type = VFS_NODE_FILE;
	else if (lflag & L_DIRECTORY)
		result->type = VFS_NODE_DIRECTORY;
	else
		result->type = VFS_NODE_UNKNOWN;
	
	return EOK;
}