Ejemplo n.º 1
0
Archivo: fs.c Proyecto: glk/puffs
int
psshfs_handshake(struct puffs_usermount *pu, int fd)
{
	struct psshfs_ctx *pctx = puffs_getspecific(pu);
	struct puffs_framebuf *pb;
	struct puffs_pathobj *po_root;
	struct puffs_node *pn_root;
	struct vattr va, *rva;
	const struct extunit *extu;
	char *rootpath;
	char *ext, *val;
	uint32_t count;
	int rv, done;

	pb = psbuf_makeout();
	psbuf_put_1(pb, SSH_FXP_INIT);
	psbuf_put_4(pb, SFTP_PROTOVERSION);
	DO_IO(psbuf_write, pu, pb, fd, &done, rv);

	puffs_framebuf_recycle(pb);
	DO_IO(psbuf_read, pu, pb, fd, &done, rv);
	if (psbuf_get_type(pb) != SSH_FXP_VERSION)
		reterr((stderr, "invalid server response: %d",
		    psbuf_get_type(pb)), EPROTO);
	pctx->protover = psbuf_get_reqid(pb);

	/*
	 * Check out which extensions are available.  Currently
	 * we are only interested in the openssh statvfs extension.
	 */
	for (;;) {
		if (psbuf_get_str(pb, &ext, NULL) != 0)
			break;
		if (psbuf_get_str(pb, &val, NULL) != 0)
			break;

		for (extu = exttable; extu->ext; extu++)
			if (strcmp(ext, extu->ext) == 0
			    && strcmp(val, extu->val) == 0)
				pctx->extensions |= extu->extflag;
	}

	/* scope out our rootpath */
	psbuf_recycleout(pb);
	psbuf_put_1(pb, SSH_FXP_REALPATH);
	psbuf_put_4(pb, NEXTREQ(pctx));
	psbuf_put_str(pb, pctx->mountpath);
	DO_IO(psbuf_write, pu, pb, fd, &done, rv);

	puffs_framebuf_recycle(pb);
	DO_IO(psbuf_read, pu, pb, fd, &done, rv);
	if (psbuf_get_type(pb) != SSH_FXP_NAME)
		reterr((stderr, "invalid server realpath response for \"%s\"",
		    pctx->mountpath), EPROTO);
	if (psbuf_get_4(pb, &count) == -1)
		reterr((stderr, "invalid realpath response: count"), EPROTO);
	if (psbuf_get_str(pb, &rootpath, NULL) == -1)
		reterr((stderr, "invalid realpath response: rootpath"), EPROTO);

	/* stat the rootdir so that we know it's a dir */
	psbuf_recycleout(pb);
	psbuf_req_str(pb, SSH_FXP_LSTAT, NEXTREQ(pctx), rootpath);
	DO_IO(psbuf_write, pu, pb, fd, &done, rv);

	puffs_framebuf_recycle(pb);
	DO_IO(psbuf_read, pu, pb, fd, &done, rv);

	rv = psbuf_expect_attrs(pb, &va);
	if (rv)
		reterr((stderr, "couldn't stat rootpath"), rv);
	puffs_framebuf_destroy(pb);

	if (puffs_mode2vt(va.va_mode) != VDIR)
		reterr((stderr, "remote path (%s) not a directory", rootpath),
		    ENOTDIR);

	pn_root = puffs_getroot(pu);
	rva = &pn_root->pn_va;
	puffs_setvattr(rva, &va);

	po_root = puffs_getrootpathobj(pu);
	if (po_root == NULL)
		err(1, "getrootpathobj");
	po_root->po_path = rootpath;
	po_root->po_len = strlen(rootpath);

	return 0;
}
Ejemplo n.º 2
0
/* flags: 1 - need free sec, 2 - need bad sec */
int fat_dstat(DRIVE *dv, struct fat_dstat *st, int flags)
{
	unsigned clsh = dv->clust_sh - dv->sec_sh;
	struct buf *boot;
	int err;
	u8 *p;

	if(!(dv->flags & DRV_OPEN)) /* XXX ? */
		return reterr(-ENODEV);

	err = get_buf(dv, 0, &boot, 1);
	if(err<0)
		return reterr(err);
	memcpy(st->oemid, boot->data+3, 8);
	st->serial = 0;
	st->label[0] = 0;
	p = boot->data + ((dv->flags&DRV_FAT) != DRV_FAT32 ? 0x26 : 0x42);
	if(*p == 0x29 || *p == 0x28 /*?*/) {
		int l;
		st->serial = get32(p+1);
		p += 5;
		for(l=11; l>0; l--)
			if(p[l-1]!=' ') break;
		memcpy(st->label, p, l);
		st->label[l] = 0;
	}

	st->sector_sh = dv->sec_sh;
	st->cluster_sh = clsh;
	st->size = dv->totsec;
	st->capacity = (dv->clust_max-1)<<clsh;

	st->free = 0;
	st->bad = 0;

/*	if(flags==1 && (dv->flags&DRV_FAT)==DRV_FAT32) {
		int sec = get32(boot->data+48);
		u8 *b = get_fsinfosec(dv, sec);
		if(b) {
			st->free = get32(b+488); 
			flags = 0;
		}
	}*/
	if(flags & 3) {
		int n, m=dv->clust_max;
		unsigned s=0, b=0;
		for(n=2; n<=m; n++) {
			int v = fat_get(dv, n, 1);
			s += (v == FAT_FREE);
			b += (v == FAT_BAD);
		}
		st->free = s<<clsh;
		st->bad = b<<clsh;
	}

	switch(dv->flags & DRV_FAT) {
		case DRV_FAT12: st->fat_type = fat_fat12; break;
		case DRV_FAT16: st->fat_type = fat_fat16; break;
		case DRV_FAT32: st->fat_type = fat_fat32; break;
	}
	return 0;
}