示例#1
0
/*
 * nwfs_close(struct vnode *a_vp, int a_fflag)
 */
static int
nwfs_close(struct vop_close_args *ap)
{
	thread_t td = curthread; /* XXX */
	struct vnode *vp = ap->a_vp;
	struct nwnode *np = VTONW(vp);
	int error;

	NCPVNDEBUG("name=%s,td=%p,c=%d\n",np->n_name,ap->a_td,np->opened);

	vn_lock(vp, LK_UPGRADE | LK_RETRY);

	error = 0;
	if (vp->v_type == VDIR)
		goto done;
	if (np->opened == 0)
		goto done;
	error = nwfs_vinvalbuf(vp, V_SAVE, 1);
	if (np->opened == 0) {
		error = 0;	/* huh? */
		goto done;
	}
	if (--np->opened == 0) {
		error = ncp_close_file(NWFSTOCONN(VTONWFS(vp)), &np->n_fh, 
		   td, proc0.p_ucred);
	} 
	np->n_atime = 0;
done:
	vop_stdclose(ap);
	return (error);
}
示例#2
0
/*
 * Defer release of inode_info and file_info structures until the inode
 * has been cleared.  This avoids a race condition allowing the inode to 
 * be put back in use before being cleared. Also, temporarily increment
 * i_count after clear_inode() so that the inode can't be reused.
 */
static void
ncp_put_inode(struct inode *inode)
{
	struct super_block	*sb	= inode->i_sb;
	struct ncp_server	*server	= NCP_SERVER(inode);
	struct ncp_inode_info	*iinfo	= NCP_INOP(inode);
        struct nw_file_info	*finfo	= NCP_FINFO(inode);

	/*
	 * This operation may block, so we lock before checking the count.
	 */
	lock_super(sb);

	if (inode->i_count > 1) {
printk("ncp_put_inode: inode in use device %s, inode %ld, count=%ld\n", 
kdevname(inode->i_dev), inode->i_ino, inode->i_count);
		goto unlock;
	}
	
	DDPRINTK("ncp_put_inode: put %s\n",
		 finfo->i.entryName);
	/*
	 * This operation should never block.
	 */
        if (S_ISDIR(inode->i_mode))
	{
                DDPRINTK("ncp_put_inode: put directory %ld\n",
			 inode->i_ino);
                ncp_invalid_dir_cache(inode);
        }                

	clear_inode(inode);

	/*
	 * After clearing the inode i_count will be 0 in 2.0.xx kernels.
	 * To keep the inode from being reused as free if we block while
	 * closing the file, increment i_count temporarily.
	 */
	inode->i_count++;

	if (finfo->opened != 0)
	{
		if (ncp_close_file(server, finfo->file_handle) != 0)
		{
			/* We can't do anything but complain. */
			printk("ncp_put_inode: could not close %s\n",
		 		finfo->i.entryName);
		}
	}

	ncp_free_inode_info(iinfo);
	inode->i_count--;
		
unlock:
	unlock_super(sb);
}
示例#3
0
/*
 * nwfs_create call
 * Create a regular file. On entry the directory to contain the file being
 * created is locked.  We must release before we return. 
 *
 * nwfs_create(struct vnode *a_dvp, struct vnode **a_vpp,
 *		struct componentname *a_cnpl, struct vattr *a_vap)
 */
static int
nwfs_create(struct vop_old_create_args *ap)
{
	struct vnode *dvp = ap->a_dvp;
	struct vattr *vap = ap->a_vap;
	struct vnode **vpp=ap->a_vpp;
	struct componentname *cnp = ap->a_cnp;
	struct vnode *vp = NULL;
	int error = 0, fmode;
	struct vattr vattr;
	struct nwnode *np;
	struct ncp_open_info no;
	struct nwmount *nmp=VTONWFS(dvp);
	ncpfid fid;
	

	NCPVNDEBUG("\n");
	*vpp = NULL;
	if (vap->va_type == VSOCK)
		return (EOPNOTSUPP);
	if ((error = VOP_GETATTR(dvp, &vattr))) {
		return (error);
	}
	fmode = AR_READ | AR_WRITE;
/*	if (vap->va_vaflags & VA_EXCLUSIVE)
		fmode |= AR_DENY_READ | AR_DENY_WRITE;*/
	
	error = ncp_open_create_file_or_subdir(nmp,dvp,cnp->cn_namelen,cnp->cn_nameptr, 
			   OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
			   0, fmode, &no, cnp->cn_td, cnp->cn_cred);
	if (!error) {
		error = ncp_close_file(NWFSTOCONN(nmp), &no.fh, cnp->cn_td,cnp->cn_cred);
		fid.f_parent = VTONW(dvp)->n_fid.f_id;
		fid.f_id = no.fattr.dirEntNum;
		error = nwfs_nget(VTOVFS(dvp), fid, &no.fattr, dvp, &vp);
		if (!error) {
			np = VTONW(vp);
			np->opened = 0;
			*vpp = vp;
		}
	}
	return (error);
}
示例#4
0
static int
ncp_notify_change(struct inode *inode, struct iattr *attr)
{
	int result = 0;
	int info_mask;
	struct nw_modify_dos_info info;

	if (!ncp_conn_valid(NCP_SERVER(inode)))
	{
		return -EIO;
	}

	if ((result = inode_change_ok(inode, attr)) < 0)
		return result;

	if (((attr->ia_valid & ATTR_UID) && 
	     (attr->ia_uid != NCP_SERVER(inode)->m.uid)))
		return -EPERM;

	if (((attr->ia_valid & ATTR_GID) && 
	     (attr->ia_uid != NCP_SERVER(inode)->m.gid)))
                return -EPERM;

	if (((attr->ia_valid & ATTR_MODE) &&
	     (attr->ia_mode &
	      ~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO))))
		return -EPERM;

	info_mask = 0;
	memset(&info, 0, sizeof(info));

	if ((attr->ia_valid & ATTR_CTIME) != 0)
	{
		info_mask |= (DM_CREATE_TIME|DM_CREATE_DATE);
		ncp_date_unix2dos(attr->ia_ctime,
				  &(info.creationTime), &(info.creationDate));
	}
	
	if ((attr->ia_valid & ATTR_MTIME) != 0)
	{
		info_mask |= (DM_MODIFY_TIME|DM_MODIFY_DATE);
		ncp_date_unix2dos(attr->ia_mtime,
				  &(info.modifyTime), &(info.modifyDate));
	}
	
	if ((attr->ia_valid & ATTR_ATIME) != 0)
	{
		__u16 dummy;
		info_mask |= (DM_LAST_ACCESS_DATE);
		ncp_date_unix2dos(attr->ia_ctime,
				  &(dummy), &(info.lastAccessDate));
	}

	if (info_mask != 0)
	{
		if ((result =
		     ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
							NCP_ISTRUCT(inode),
							info_mask,
							&info)) != 0)
		{
			result = -EACCES;

			if (info_mask == (DM_CREATE_TIME|DM_CREATE_DATE))
			{
				/* NetWare seems not to allow this. I
                                   do not know why. So, just tell the
                                   user everything went fine. This is
                                   a terrible hack, but I do not know
                                   how to do this correctly. */
				result = 0;
			}
		}
	}

        if ((attr->ia_valid & ATTR_SIZE) != 0)
	{
		int written;

		DPRINTK("ncpfs: trying to change size of %s to %ld\n",
			NCP_ISTRUCT(inode)->entryName, attr->ia_size);

		if ((result = ncp_make_open(inode, O_RDWR)) < 0)
		{
			return -EACCES;
		}

		ncp_write(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
			  attr->ia_size, 0, "", &written);

		/* According to ndir, the changes only take effect after
		   closing the file */
		ncp_close_file(NCP_SERVER(inode),
			       NCP_FINFO(inode)->file_handle);
		NCP_FINFO(inode)->opened = 0;

		result = 0;
	}

        ncp_invalid_dir_cache(NCP_INOP(inode)->dir->inode);

	return result;
}
int main(int argc, char *argv[]) {
	NWDSCCODE dserr;
	NWCONN_HANDLE conn;
	char volume[1000];
	char volpath[1000];
	int opt;
	u_int32_t rim = 0;
	u_int32_t destns = NW_NS_DOS;
	u_int32_t searchattr = 0x8006;
	char* s = NULL;
	
	setlocale(LC_ALL, "");
	bindtextdomain(NCPFS_PACKAGE, LOCALEDIR);
	textdomain(NCPFS_PACKAGE);
	
	progname = argv[0];

	NWCallsInit(NULL, NULL);
//	NWDSInitRequester();

	while ((opt = getopt(argc, argv, "h?r:n:s:p:")) != EOF)
	{
		switch (opt)
		{
		case 'r':
			rim = strtoul(optarg, NULL, 0);
			break;
		case 'n':
			destns = strtoul(optarg, NULL, 0);
			break;
		case 's':
			searchattr = strtoul(optarg, NULL, 0);
			break;
		case 'p':
			s = optarg;
			break;
		case 'h':
		case '?':
			help();
			goto finished;
		default:
			usage();
			goto finished;
		}
	}

	dserr = NWParsePath(argv[optind++], NULL, &conn, volume, volpath);
	if (dserr) {
		fprintf(stderr, "NWParsePath failed: %s\n",
			strnwerror(dserr));
		return 123;
	}
	if (!conn) {
		fprintf(stderr, "Path is not remote\n");
		return 124;
	}
	strcpy(volume + 2, s);
	volume[0] = 1;
	volume[1] = strlen(s);
	{
		struct nw_info_struct2 iii;
		u_int8_t fh[10];
		
		memset(&iii, 0xCC, sizeof(iii));

	dserr =	ncp_ns_open_create_entry(conn, destns, searchattr, NCP_DIRSTYLE_DIRBASE, 
			3, rim, volume, strlen(s) + 2, -1, 0x0B, 0, 0, 0xFF, 
			&iii, sizeof(iii), NULL, NULL, fh);
		if (dserr) {
			fprintf(stderr, "Cannot obtain info: %s\n",
				strnwerror(dserr));
		} else {
			printstruct2(0xFF, &iii);
		}
		ncp_close_file(conn, fh);
	}
	ncp_close(conn);
finished:;
	return 0;
}