dir.c 21.9 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4
/*
 *   fs/cifs/dir.c
 *
 *   vfs operations that deal with dentries
S
Steve French 已提交
5
 *
6
 *   Copyright (C) International Business Machines  Corp., 2002,2009
L
Linus Torvalds 已提交
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 *   Author(s): Steve French (sfrench@us.ibm.com)
 *
 *   This library is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published
 *   by the Free Software Foundation; either version 2.1 of the License, or
 *   (at your option) any later version.
 *
 *   This library is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
 *   the GNU Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public License
 *   along with this library; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */
#include <linux/fs.h>
#include <linux/stat.h>
#include <linux/slab.h>
#include <linux/namei.h>
27
#include <linux/mount.h>
28
#include <linux/file.h>
L
Linus Torvalds 已提交
29 30 31 32 33 34 35
#include "cifsfs.h"
#include "cifspdu.h"
#include "cifsglob.h"
#include "cifsproto.h"
#include "cifs_debug.h"
#include "cifs_fs_sb.h"

36
static void
L
Linus Torvalds 已提交
37 38
renew_parental_timestamps(struct dentry *direntry)
{
S
Steve French 已提交
39 40
	/* BB check if there is a way to get the kernel to do this or if we
	   really need this */
L
Linus Torvalds 已提交
41 42 43
	do {
		direntry->d_time = jiffies;
		direntry = direntry->d_parent;
S
Steve French 已提交
44
	} while (!IS_ROOT(direntry));
L
Linus Torvalds 已提交
45 46
}

47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
char *
cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
			struct cifs_tcon *tcon)
{
	int pplen = vol->prepath ? strlen(vol->prepath) : 0;
	int dfsplen;
	char *full_path = NULL;

	/* if no prefix path, simply set path to the root of share to "" */
	if (pplen == 0) {
		full_path = kzalloc(1, GFP_KERNEL);
		return full_path;
	}

	if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
		dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
	else
		dfsplen = 0;

	full_path = kmalloc(dfsplen + pplen + 1, GFP_KERNEL);
	if (full_path == NULL)
		return full_path;

	if (dfsplen)
		strncpy(full_path, tcon->treeName, dfsplen);
	strncpy(full_path + dfsplen, vol->prepath, pplen);
	convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
	full_path[dfsplen + pplen] = 0; /* add trailing null */
	return full_path;
}

L
Linus Torvalds 已提交
78 79 80 81 82
/* Note: caller must free return buffer */
char *
build_path_from_dentry(struct dentry *direntry)
{
	struct dentry *temp;
83
	int namelen;
84
	int dfsplen;
L
Linus Torvalds 已提交
85
	char *full_path;
86
	char dirsep;
87
	struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
88
	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
89
	unsigned seq;
L
Linus Torvalds 已提交
90

91
	dirsep = CIFS_DIR_SEP(cifs_sb);
92 93
	if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
		dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
94 95
	else
		dfsplen = 0;
L
Linus Torvalds 已提交
96
cifs_bp_rename_retry:
97
	namelen = dfsplen;
98 99
	seq = read_seqbegin(&rename_lock);
	rcu_read_lock();
L
Linus Torvalds 已提交
100 101 102
	for (temp = direntry; !IS_ROOT(temp);) {
		namelen += (1 + temp->d_name.len);
		temp = temp->d_parent;
S
Steve French 已提交
103
		if (temp == NULL) {
104
			cERROR(1, "corrupt dentry");
105
			rcu_read_unlock();
L
Linus Torvalds 已提交
106 107 108
			return NULL;
		}
	}
109
	rcu_read_unlock();
L
Linus Torvalds 已提交
110 111

	full_path = kmalloc(namelen+1, GFP_KERNEL);
S
Steve French 已提交
112
	if (full_path == NULL)
L
Linus Torvalds 已提交
113 114
		return full_path;
	full_path[namelen] = 0;	/* trailing null */
115
	rcu_read_lock();
L
Linus Torvalds 已提交
116
	for (temp = direntry; !IS_ROOT(temp);) {
117
		spin_lock(&temp->d_lock);
L
Linus Torvalds 已提交
118 119
		namelen -= 1 + temp->d_name.len;
		if (namelen < 0) {
120
			spin_unlock(&temp->d_lock);
L
Linus Torvalds 已提交
121 122
			break;
		} else {
123
			full_path[namelen] = dirsep;
L
Linus Torvalds 已提交
124 125
			strncpy(full_path + namelen + 1, temp->d_name.name,
				temp->d_name.len);
126
			cFYI(0, "name: %s", full_path + namelen);
L
Linus Torvalds 已提交
127
		}
128
		spin_unlock(&temp->d_lock);
L
Linus Torvalds 已提交
129
		temp = temp->d_parent;
S
Steve French 已提交
130
		if (temp == NULL) {
131
			cERROR(1, "corrupt dentry");
132
			rcu_read_unlock();
L
Linus Torvalds 已提交
133 134 135 136
			kfree(full_path);
			return NULL;
		}
	}
137 138
	rcu_read_unlock();
	if (namelen != dfsplen || read_seqretry(&rename_lock, seq)) {
139 140
		cFYI(1, "did not end path lookup where expected. namelen=%d "
			"dfsplen=%d", namelen, dfsplen);
S
Steve French 已提交
141
		/* presumably this is only possible if racing with a rename
L
Linus Torvalds 已提交
142 143 144 145 146
		of one of the parent directories  (we can not lock the dentries
		above us to prevent this, but retrying should be harmless) */
		kfree(full_path);
		goto cifs_bp_rename_retry;
	}
147 148 149 150 151 152
	/* DIR_SEP already set for byte  0 / vs \ but not for
	   subsequent slashes in prepath which currently must
	   be entered the right way - not sure if there is an alternative
	   since the '\' is a valid posix character so we can not switch
	   those safely to '/' if any are found in the middle of the prepath */
	/* BB test paths to Windows with '/' in the midst of prepath */
153 154

	if (dfsplen) {
155
		strncpy(full_path, tcon->treeName, dfsplen);
156 157 158 159 160 161 162 163
		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
			int i;
			for (i = 0; i < dfsplen; i++) {
				if (full_path[i] == '\\')
					full_path[i] = '/';
			}
		}
	}
L
Linus Torvalds 已提交
164 165 166
	return full_path;
}

167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
/*
 * Don't allow the separator character in a path component.
 * The VFS will not allow "/", but "\" is allowed by posix.
 */
static int
check_name(struct dentry *direntry)
{
	struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
	int i;

	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
		for (i = 0; i < direntry->d_name.len; i++) {
			if (direntry->d_name.name[i] == '\\') {
				cFYI(1, "Invalid file name");
				return -EINVAL;
			}
		}
	}
	return 0;
}


189
/* Inode operations in similar order to how they appear in Linux file fs.h */
L
Linus Torvalds 已提交
190

191 192 193
static int
cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
	       struct tcon_link *tlink, unsigned oflags, umode_t mode,
194
	       __u32 *oplock, struct cifs_fid *fid, int *created)
L
Linus Torvalds 已提交
195 196
{
	int rc = -ENOENT;
197
	int create_options = CREATE_NOT_DIR;
198
	int desired_access;
199 200
	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
	struct cifs_tcon *tcon = tlink_tcon(tlink);
L
Linus Torvalds 已提交
201
	char *full_path = NULL;
S
Steve French 已提交
202
	FILE_ALL_INFO *buf = NULL;
L
Linus Torvalds 已提交
203
	struct inode *newinode = NULL;
204
	int disposition;
205
	struct TCP_Server_Info *server = tcon->ses->server;
L
Linus Torvalds 已提交
206

207
	*oplock = 0;
208
	if (tcon->ses->server->oplocks)
209
		*oplock = REQ_OPLOCK;
210

211 212 213
	full_path = build_path_from_dentry(direntry);
	if (full_path == NULL) {
		rc = -ENOMEM;
214
		goto out;
215 216
	}

217
	if (tcon->unix_ext && cap_unix(tcon->ses) && !tcon->broken_posix_open &&
218 219
	    (CIFS_UNIX_POSIX_PATH_OPS_CAP &
			le64_to_cpu(tcon->fsUnixInfo.Capability))) {
220 221
		rc = cifs_posix_open(full_path, &newinode, inode->i_sb, mode,
				     oflags, oplock, &fid->netfid, xid);
222 223 224 225
		switch (rc) {
		case 0:
			if (newinode == NULL) {
				/* query inode info */
226
				goto cifs_create_get_file_info;
227 228 229 230 231 232 233 234 235 236
			}

			if (!S_ISREG(newinode->i_mode)) {
				/*
				 * The server may allow us to open things like
				 * FIFOs, but the client isn't set up to deal
				 * with that. If it's not a regular file, just
				 * close it and proceed as if it were a normal
				 * lookup.
				 */
237
				CIFSSMBClose(xid, tcon, fid->netfid);
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
				goto cifs_create_get_file_info;
			}
			/* success, no need to query */
			goto cifs_create_set_dentry;

		case -ENOENT:
			goto cifs_create_get_file_info;

		case -EIO:
		case -EINVAL:
			/*
			 * EIO could indicate that (posix open) operation is not
			 * supported, despite what server claimed in capability
			 * negotiation.
			 *
			 * POSIX open in samba versions 3.3.1 and earlier could
			 * incorrectly fail with invalid parameter.
			 */
			tcon->broken_posix_open = true;
			break;

		case -EREMOTE:
		case -EOPNOTSUPP:
			/*
			 * EREMOTE indicates DFS junction, which is not handled
			 * in posix open.  If either that or op not supported
			 * returned, follow the normal lookup.
			 */
			break;
M
Miklos Szeredi 已提交
267

268 269 270 271 272 273 274 275 276
		default:
			goto out;
		}
		/*
		 * fallthrough to retry, using older open call, this is case
		 * where server does not support this SMB level, and falsely
		 * claims capability (also get here for DFS case which should be
		 * rare for path not covered on files)
		 */
L
Linus Torvalds 已提交
277 278
	}

279
	desired_access = 0;
280
	if (OPEN_FMODE(oflags) & FMODE_READ)
281
		desired_access |= GENERIC_READ; /* is this too little? */
282
	if (OPEN_FMODE(oflags) & FMODE_WRITE)
283
		desired_access |= GENERIC_WRITE;
284 285 286 287 288 289 290 291 292 293 294

	disposition = FILE_OVERWRITE_IF;
	if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
		disposition = FILE_CREATE;
	else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
		disposition = FILE_OVERWRITE_IF;
	else if ((oflags & O_CREAT) == O_CREAT)
		disposition = FILE_OPEN_IF;
	else
		cFYI(1, "Create flag not set in create function");

295 296 297 298 299 300 301 302 303
	/*
	 * BB add processing to set equivalent of mode - e.g. via CreateX with
	 * ACLs
	 */

	if (!server->ops->open) {
		rc = -ENOSYS;
		goto out;
	}
L
Linus Torvalds 已提交
304

S
Steve French 已提交
305 306
	buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
	if (buf == NULL) {
307
		rc = -ENOMEM;
308
		goto out;
L
Linus Torvalds 已提交
309
	}
310 311 312 313 314

	/*
	 * if we're not using unix extensions, see if we need to set
	 * ATTR_READONLY on the create call
	 */
315
	if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
316 317
		create_options |= CREATE_OPTION_READONLY;

318 319 320
	if (backup_cred(cifs_sb))
		create_options |= CREATE_OPEN_BACKUP_INTENT;

321 322 323
	rc = server->ops->open(xid, tcon, full_path, disposition,
			       desired_access, create_options, fid, oplock,
			       buf, cifs_sb);
L
Linus Torvalds 已提交
324
	if (rc) {
325
		cFYI(1, "cifs_create returned 0x%x", rc);
326
		goto out;
327 328
	}

329 330 331 332
	/*
	 * If Open reported that we actually created a file then we now have to
	 * set the mode if possible.
	 */
333
	if ((tcon->unix_ext) && (*oplock & CIFS_CREATE_ACTION)) {
334
		struct cifs_unix_set_info_args args = {
335 336 337 338 339
				.mode	= mode,
				.ctime	= NO_CHANGE_64,
				.atime	= NO_CHANGE_64,
				.mtime	= NO_CHANGE_64,
				.device	= 0,
340 341
		};

342
		*created |= FILE_CREATED;
343 344 345 346 347 348
		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
			args.uid = (__u64) current_fsuid();
			if (inode->i_mode & S_ISGID)
				args.gid = (__u64) inode->i_gid;
			else
				args.gid = (__u64) current_fsgid();
S
Steve French 已提交
349
		} else {
350 351
			args.uid = NO_CHANGE_64;
			args.gid = NO_CHANGE_64;
L
Linus Torvalds 已提交
352
		}
353 354
		CIFSSMBUnixSetFileInfo(xid, tcon, &args, fid->netfid,
				       current->tgid);
355
	} else {
356 357 358 359
		/*
		 * BB implement mode setting via Windows security
		 * descriptors e.g.
		 */
360 361 362 363
		/* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/

		/* Could set r/o dos attribute if mode & 0222 == 0 */
	}
L
Linus Torvalds 已提交
364

365 366 367
cifs_create_get_file_info:
	/* server might mask mode so we have to query for it */
	if (tcon->unix_ext)
368 369
		rc = cifs_get_inode_info_unix(&newinode, full_path, inode->i_sb,
					      xid);
370
	else {
371 372
		rc = cifs_get_inode_info(&newinode, full_path, buf, inode->i_sb,
					 xid, &fid->netfid);
373
		if (newinode) {
P
Pavel Shilovsky 已提交
374 375
			if (server->ops->set_lease_key)
				server->ops->set_lease_key(newinode, fid);
376 377
			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
				newinode->i_mode = mode;
378
			if ((*oplock & CIFS_CREATE_ACTION) &&
379 380 381 382 383 384
			    (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) {
				newinode->i_uid = current_fsuid();
				if (inode->i_mode & S_ISGID)
					newinode->i_gid = inode->i_gid;
				else
					newinode->i_gid = current_fsgid();
385
			}
L
Linus Torvalds 已提交
386
		}
387
	}
L
Linus Torvalds 已提交
388

389
cifs_create_set_dentry:
390
	if (rc != 0) {
391
		cFYI(1, "Create worked, get_inode_info failed rc = %d", rc);
392 393
		if (server->ops->close)
			server->ops->close(xid, tcon, fid);
394 395 396 397
		goto out;
	}
	d_drop(direntry);
	d_add(direntry, newinode);
398

399 400 401 402 403
out:
	kfree(buf);
	kfree(full_path);
	return rc;
}
404

A
Al Viro 已提交
405
int
406
cifs_atomic_open(struct inode *inode, struct dentry *direntry,
A
Al Viro 已提交
407
		 struct file *file, unsigned oflags, umode_t mode,
408
		 int *opened)
409 410
{
	int rc;
411
	unsigned int xid;
412 413
	struct tcon_link *tlink;
	struct cifs_tcon *tcon;
414
	struct TCP_Server_Info *server;
415
	struct cifs_fid fid;
416
	struct cifs_pending_open open;
417
	__u32 oplock;
418
	struct cifsFileInfo *file_info;
419

420 421
	/*
	 * Posix open is only called (at lookup time) for file create now. For
422 423 424 425 426 427 428 429 430 431
	 * opens (rather than creates), because we do not know if it is a file
	 * or directory yet, and current Samba no longer allows us to do posix
	 * open on dirs, we could end up wasting an open call on what turns out
	 * to be a dir. For file opens, we wait to call posix open till
	 * cifs_open.  It could be added to atomic_open in the future but the
	 * performance tradeoff of the extra network request when EISDIR or
	 * EACCES is returned would have to be weighed against the 50% reduction
	 * in network traffic in the other paths.
	 */
	if (!(oflags & O_CREAT)) {
432 433 434 435 436 437 438 439 440 441
		struct dentry *res;

		/*
		 * Check for hashed negative dentry. We have already revalidated
		 * the dentry and it is fine. No need to perform another lookup.
		 */
		if (!d_unhashed(direntry))
			return -ENOENT;

		res = cifs_lookup(inode, direntry, 0);
442
		if (IS_ERR(res))
A
Al Viro 已提交
443
			return PTR_ERR(res);
444

A
Al Viro 已提交
445
		return finish_no_open(file, res);
446 447 448 449
	}

	rc = check_name(direntry);
	if (rc)
A
Al Viro 已提交
450
		return rc;
451

452
	xid = get_xid();
453 454 455 456 457 458

	cFYI(1, "parent inode = 0x%p name is: %s and dentry = 0x%p",
	     inode, direntry->d_name.name, direntry);

	tlink = cifs_sb_tlink(CIFS_SB(inode->i_sb));
	if (IS_ERR(tlink))
459
		goto out_free_xid;
460 461

	tcon = tlink_tcon(tlink);
462
	server = tcon->ses->server;
463

P
Pavel Shilovsky 已提交
464 465 466
	if (server->ops->new_lease_key)
		server->ops->new_lease_key(&fid);

467 468
	cifs_add_pending_open(&fid, tlink, &open);

469
	rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
470
			    &oplock, &fid, opened);
471

472 473
	if (rc) {
		cifs_del_pending_open(&open);
474
		goto out;
475
	}
476

A
Al Viro 已提交
477 478
	rc = finish_open(file, direntry, generic_file_open, opened);
	if (rc) {
479 480
		if (server->ops->close)
			server->ops->close(xid, tcon, &fid);
481
		cifs_del_pending_open(&open);
482
		goto out;
S
Steve French 已提交
483
	}
484

485 486
	file_info = cifs_new_fileinfo(&fid, file, tlink, oplock);
	if (file_info == NULL) {
487 488
		if (server->ops->close)
			server->ops->close(xid, tcon, &fid);
489
		cifs_del_pending_open(&open);
A
Al Viro 已提交
490
		rc = -ENOMEM;
491 492 493 494
	}

out:
	cifs_put_tlink(tlink);
495 496
out_free_xid:
	free_xid(xid);
A
Al Viro 已提交
497
	return rc;
498 499 500
}

int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
A
Al Viro 已提交
501
		bool excl)
502 503
{
	int rc;
504
	unsigned int xid = get_xid();
505 506 507 508 509 510 511 512 513
	/*
	 * BB below access is probably too much for mknod to request
	 *    but we have to do query and setpathinfo so requesting
	 *    less could fail (unless we want to request getatr and setatr
	 *    permissions (only).  At least for POSIX we do not have to
	 *    request so much.
	 */
	unsigned oflags = O_EXCL | O_CREAT | O_RDWR;
	struct tcon_link *tlink;
514 515 516
	struct cifs_tcon *tcon;
	struct TCP_Server_Info *server;
	struct cifs_fid fid;
517
	__u32 oplock;
518
	int created = FILE_CREATED;
519 520 521 522 523 524 525

	cFYI(1, "cifs_create parent inode = 0x%p name is: %s and dentry = 0x%p",
	     inode, direntry->d_name.name, direntry);

	tlink = cifs_sb_tlink(CIFS_SB(inode->i_sb));
	rc = PTR_ERR(tlink);
	if (IS_ERR(tlink))
526
		goto out_free_xid;
527

528 529
	tcon = tlink_tcon(tlink);
	server = tcon->ses->server;
P
Pavel Shilovsky 已提交
530 531 532 533 534 535

	if (server->ops->new_lease_key)
		server->ops->new_lease_key(&fid);

	rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
			    &oplock, &fid, &created);
536 537
	if (!rc && server->ops->close)
		server->ops->close(xid, tcon, &fid);
538

539
	cifs_put_tlink(tlink);
540 541
out_free_xid:
	free_xid(xid);
L
Linus Torvalds 已提交
542 543 544
	return rc;
}

A
Al Viro 已提交
545
int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
S
Steve French 已提交
546
		dev_t device_number)
L
Linus Torvalds 已提交
547 548
{
	int rc = -EPERM;
549
	unsigned int xid;
550
	int create_options = CREATE_NOT_DIR | CREATE_OPTION_SPECIAL;
L
Linus Torvalds 已提交
551
	struct cifs_sb_info *cifs_sb;
552
	struct tcon_link *tlink;
553
	struct cifs_tcon *pTcon;
554
	struct cifs_io_parms io_parms;
L
Linus Torvalds 已提交
555
	char *full_path = NULL;
S
Steve French 已提交
556
	struct inode *newinode = NULL;
557 558 559 560 561
	int oplock = 0;
	u16 fileHandle;
	FILE_ALL_INFO *buf = NULL;
	unsigned int bytes_written;
	struct win_dev *pdev;
L
Linus Torvalds 已提交
562 563 564 565 566

	if (!old_valid_dev(device_number))
		return -EINVAL;

	cifs_sb = CIFS_SB(inode->i_sb);
567 568 569 570 571 572
	tlink = cifs_sb_tlink(cifs_sb);
	if (IS_ERR(tlink))
		return PTR_ERR(tlink);

	pTcon = tlink_tcon(tlink);

573
	xid = get_xid();
L
Linus Torvalds 已提交
574 575

	full_path = build_path_from_dentry(direntry);
576
	if (full_path == NULL) {
L
Linus Torvalds 已提交
577
		rc = -ENOMEM;
578 579 580 581
		goto mknod_out;
	}

	if (pTcon->unix_ext) {
582
		struct cifs_unix_set_info_args args = {
A
Al Viro 已提交
583
			.mode	= mode & ~current_umask(),
584 585 586 587 588
			.ctime	= NO_CHANGE_64,
			.atime	= NO_CHANGE_64,
			.mtime	= NO_CHANGE_64,
			.device	= device_number,
		};
S
Steve French 已提交
589
		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
590 591
			args.uid = (__u64) current_fsuid();
			args.gid = (__u64) current_fsgid();
L
Linus Torvalds 已提交
592
		} else {
593 594
			args.uid = NO_CHANGE_64;
			args.gid = NO_CHANGE_64;
L
Linus Torvalds 已提交
595
		}
596 597 598 599
		rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args,
					    cifs_sb->local_nls,
					    cifs_sb->mnt_cifs_flags &
						CIFS_MOUNT_MAP_SPECIAL_CHR);
600 601
		if (rc)
			goto mknod_out;
L
Linus Torvalds 已提交
602

603
		rc = cifs_get_inode_info_unix(&newinode, full_path,
S
Steve French 已提交
604
						inode->i_sb, xid);
605

606 607 608
		if (rc == 0)
			d_instantiate(direntry, newinode);
		goto mknod_out;
L
Linus Torvalds 已提交
609 610
	}

611 612 613 614 615 616 617 618 619 620
	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
		goto mknod_out;


	cFYI(1, "sfu compat create special file");

	buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
	if (buf == NULL) {
		kfree(full_path);
		rc = -ENOMEM;
621
		free_xid(xid);
622 623 624
		return rc;
	}

625 626 627
	if (backup_cred(cifs_sb))
		create_options |= CREATE_OPEN_BACKUP_INTENT;

628
	rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_CREATE,
629
			 GENERIC_WRITE, create_options,
630 631 632 633 634 635 636 637 638
			 &fileHandle, &oplock, buf, cifs_sb->local_nls,
			 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
	if (rc)
		goto mknod_out;

	/* BB Do not bother to decode buf since no local inode yet to put
	 * timestamps in, but we can reuse it safely */

	pdev = (struct win_dev *)buf;
639 640 641 642 643
	io_parms.netfid = fileHandle;
	io_parms.pid = current->tgid;
	io_parms.tcon = pTcon;
	io_parms.offset = 0;
	io_parms.length = sizeof(struct win_dev);
644 645 646 647 648 649
	if (S_ISCHR(mode)) {
		memcpy(pdev->type, "IntxCHR", 8);
		pdev->major =
		      cpu_to_le64(MAJOR(device_number));
		pdev->minor =
		      cpu_to_le64(MINOR(device_number));
650 651
		rc = CIFSSMBWrite(xid, &io_parms,
			&bytes_written, (char *)pdev,
652 653 654 655 656 657 658
			NULL, 0);
	} else if (S_ISBLK(mode)) {
		memcpy(pdev->type, "IntxBLK", 8);
		pdev->major =
		      cpu_to_le64(MAJOR(device_number));
		pdev->minor =
		      cpu_to_le64(MINOR(device_number));
659 660
		rc = CIFSSMBWrite(xid, &io_parms,
			&bytes_written, (char *)pdev,
661 662 663 664 665 666 667 668
			NULL, 0);
	} /* else if (S_ISFIFO) */
	CIFSSMBClose(xid, pTcon, fileHandle);
	d_drop(direntry);

	/* FIXME: add code here to set EAs */

mknod_out:
669
	kfree(full_path);
670
	kfree(buf);
671
	free_xid(xid);
672
	cifs_put_tlink(tlink);
L
Linus Torvalds 已提交
673 674 675 676
	return rc;
}

struct dentry *
S
Steve French 已提交
677
cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
A
Al Viro 已提交
678
	    unsigned int flags)
L
Linus Torvalds 已提交
679
{
680
	unsigned int xid;
L
Linus Torvalds 已提交
681 682
	int rc = 0; /* to get around spurious gcc warning, set to zero here */
	struct cifs_sb_info *cifs_sb;
683
	struct tcon_link *tlink;
684
	struct cifs_tcon *pTcon;
L
Linus Torvalds 已提交
685 686 687
	struct inode *newInode = NULL;
	char *full_path = NULL;

688
	xid = get_xid();
L
Linus Torvalds 已提交
689

690 691
	cFYI(1, "parent inode = 0x%p name is: %s and dentry = 0x%p",
	      parent_dir_inode, direntry->d_name.name, direntry);
L
Linus Torvalds 已提交
692 693 694 695

	/* check whether path exists */

	cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
696 697
	tlink = cifs_sb_tlink(cifs_sb);
	if (IS_ERR(tlink)) {
698
		free_xid(xid);
699 700 701
		return (struct dentry *)tlink;
	}
	pTcon = tlink_tcon(tlink);
L
Linus Torvalds 已提交
702

703 704
	rc = check_name(direntry);
	if (rc)
705
		goto lookup_out;
706

L
Linus Torvalds 已提交
707 708 709 710
	/* can not grab the rename sem here since it would
	deadlock in the cases (beginning of sys_rename itself)
	in which we already have the sb rename sem */
	full_path = build_path_from_dentry(direntry);
S
Steve French 已提交
711
	if (full_path == NULL) {
712 713
		rc = -ENOMEM;
		goto lookup_out;
L
Linus Torvalds 已提交
714 715 716
	}

	if (direntry->d_inode != NULL) {
717
		cFYI(1, "non-NULL inode in lookup");
L
Linus Torvalds 已提交
718
	} else {
719
		cFYI(1, "NULL inode in lookup");
L
Linus Torvalds 已提交
720
	}
721
	cFYI(1, "Full path: %s inode = 0x%p", full_path, direntry->d_inode);
L
Linus Torvalds 已提交
722

723
	if (pTcon->unix_ext) {
724 725 726
		rc = cifs_get_inode_info_unix(&newInode, full_path,
					      parent_dir_inode->i_sb, xid);
	} else {
L
Linus Torvalds 已提交
727
		rc = cifs_get_inode_info(&newInode, full_path, NULL,
728
				parent_dir_inode->i_sb, xid, NULL);
729
	}
L
Linus Torvalds 已提交
730 731 732

	if ((rc == 0) && (newInode != NULL)) {
		d_add(direntry, newInode);
S
Steve French 已提交
733
		/* since paths are not looked up by component - the parent
734
		   directories are presumed to be good here */
L
Linus Torvalds 已提交
735 736 737 738
		renew_parental_timestamps(direntry);

	} else if (rc == -ENOENT) {
		rc = 0;
739
		direntry->d_time = jiffies;
L
Linus Torvalds 已提交
740
		d_add(direntry, NULL);
S
Steve French 已提交
741 742
	/*	if it was once a directory (but how can we tell?) we could do
		shrink_dcache_parent(direntry); */
743
	} else if (rc != -EACCES) {
744
		cERROR(1, "Unexpected lookup error %d", rc);
745 746
		/* We special case check for Access Denied - since that
		is a common return code */
L
Linus Torvalds 已提交
747 748
	}

749
lookup_out:
750
	kfree(full_path);
751
	cifs_put_tlink(tlink);
752
	free_xid(xid);
L
Linus Torvalds 已提交
753 754 755 756
	return ERR_PTR(rc);
}

static int
757
cifs_d_revalidate(struct dentry *direntry, unsigned int flags)
L
Linus Torvalds 已提交
758
{
759
	if (flags & LOOKUP_RCU)
760 761
		return -ECHILD;

L
Linus Torvalds 已提交
762
	if (direntry->d_inode) {
763
		if (cifs_revalidate_dentry(direntry))
L
Linus Torvalds 已提交
764
			return 0;
765 766
		else {
			/*
767 768 769 770 771
			 * If the inode wasn't known to be a dfs entry when
			 * the dentry was instantiated, such as when created
			 * via ->readdir(), it needs to be set now since the
			 * attributes will have been updated by
			 * cifs_revalidate_dentry().
772
			 */
773 774 775 776 777 778 779
			if (IS_AUTOMOUNT(direntry->d_inode) &&
			   !(direntry->d_flags & DCACHE_NEED_AUTOMOUNT)) {
				spin_lock(&direntry->d_lock);
				direntry->d_flags |= DCACHE_NEED_AUTOMOUNT;
				spin_unlock(&direntry->d_lock);
			}

780
			return 1;
781
		}
L
Linus Torvalds 已提交
782 783
	}

784 785 786 787
	/*
	 * This may be nfsd (or something), anyway, we can't see the
	 * intent of this. So, since this can be for creation, drop it.
	 */
788
	if (!flags)
789 790 791 792 793 794 795
		return 0;

	/*
	 * Drop the negative dentry, in order to make sure to use the
	 * case sensitive name which is specified by user if this is
	 * for creation.
	 */
796
	if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
797
		return 0;
798 799 800 801 802

	if (time_after(jiffies, direntry->d_time + HZ) || !lookupCacheEnabled)
		return 0;

	return 1;
L
Linus Torvalds 已提交
803 804 805 806 807 808
}

/* static int cifs_d_delete(struct dentry *direntry)
{
	int rc = 0;

809
	cFYI(1, "In cifs d_delete, name = %s", direntry->d_name.name);
L
Linus Torvalds 已提交
810 811 812 813

	return rc;
}     */

A
Al Viro 已提交
814
const struct dentry_operations cifs_dentry_ops = {
L
Linus Torvalds 已提交
815
	.d_revalidate = cifs_d_revalidate,
816
	.d_automount = cifs_dfs_d_automount,
S
Steve French 已提交
817
/* d_delete:       cifs_d_delete,      */ /* not needed except for debugging */
L
Linus Torvalds 已提交
818
};
819

N
Nick Piggin 已提交
820 821
static int cifs_ci_hash(const struct dentry *dentry, const struct inode *inode,
		struct qstr *q)
822
{
N
Nick Piggin 已提交
823
	struct nls_table *codepage = CIFS_SB(dentry->d_sb)->local_nls;
824 825 826 827 828 829 830 831 832 833 834 835
	unsigned long hash;
	int i;

	hash = init_name_hash();
	for (i = 0; i < q->len; i++)
		hash = partial_name_hash(nls_tolower(codepage, q->name[i]),
					 hash);
	q->hash = end_name_hash(hash);

	return 0;
}

N
Nick Piggin 已提交
836 837 838 839
static int cifs_ci_compare(const struct dentry *parent,
		const struct inode *pinode,
		const struct dentry *dentry, const struct inode *inode,
		unsigned int len, const char *str, const struct qstr *name)
840
{
N
Nick Piggin 已提交
841
	struct nls_table *codepage = CIFS_SB(pinode->i_sb)->local_nls;
842

N
Nick Piggin 已提交
843 844
	if ((name->len == len) &&
	    (nls_strnicmp(codepage, name->name, str, len) == 0))
845 846 847 848
		return 0;
	return 1;
}

A
Al Viro 已提交
849
const struct dentry_operations cifs_ci_dentry_ops = {
850 851 852
	.d_revalidate = cifs_d_revalidate,
	.d_hash = cifs_ci_hash,
	.d_compare = cifs_ci_compare,
853
	.d_automount = cifs_dfs_d_automount,
854
};