]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - fs/cifs/dir.c
cifs: don't update uniqueid in cifs_fattr_to_inode
[mirror_ubuntu-artful-kernel.git] / fs / cifs / dir.c
CommitLineData
1da177e4
LT
1/*
2 * fs/cifs/dir.c
3 *
4 * vfs operations that deal with dentries
5fdae1f6 5 *
c3b2a0c6 6 * Copyright (C) International Business Machines Corp., 2002,2009
1da177e4
LT
7 * Author(s): Steve French (sfrench@us.ibm.com)
8 *
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23#include <linux/fs.h>
24#include <linux/stat.h>
25#include <linux/slab.h>
26#include <linux/namei.h>
3bc303c2 27#include <linux/mount.h>
1da177e4
LT
28#include "cifsfs.h"
29#include "cifspdu.h"
30#include "cifsglob.h"
31#include "cifsproto.h"
32#include "cifs_debug.h"
33#include "cifs_fs_sb.h"
34
99ee4dbd 35static void
1da177e4
LT
36renew_parental_timestamps(struct dentry *direntry)
37{
5fdae1f6
SF
38 /* BB check if there is a way to get the kernel to do this or if we
39 really need this */
1da177e4
LT
40 do {
41 direntry->d_time = jiffies;
42 direntry = direntry->d_parent;
5fdae1f6 43 } while (!IS_ROOT(direntry));
1da177e4
LT
44}
45
46/* Note: caller must free return buffer */
47char *
48build_path_from_dentry(struct dentry *direntry)
49{
50 struct dentry *temp;
2fe87f02
SF
51 int namelen;
52 int pplen;
646dd539 53 int dfsplen;
1da177e4 54 char *full_path;
88274815 55 char dirsep;
646dd539 56 struct cifs_sb_info *cifs_sb;
1da177e4 57
5fdae1f6 58 if (direntry == NULL)
1da177e4
LT
59 return NULL; /* not much we can do if dentry is freed and
60 we need to reopen the file after it was closed implicitly
61 when the server crashed */
62
646dd539
SF
63 cifs_sb = CIFS_SB(direntry->d_sb);
64 dirsep = CIFS_DIR_SEP(cifs_sb);
65 pplen = cifs_sb->prepathlen;
66 if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS))
67 dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1);
68 else
69 dfsplen = 0;
1da177e4 70cifs_bp_rename_retry:
646dd539 71 namelen = pplen + dfsplen;
1da177e4
LT
72 for (temp = direntry; !IS_ROOT(temp);) {
73 namelen += (1 + temp->d_name.len);
74 temp = temp->d_parent;
5fdae1f6 75 if (temp == NULL) {
b6b38f70 76 cERROR(1, "corrupt dentry");
1da177e4
LT
77 return NULL;
78 }
79 }
80
81 full_path = kmalloc(namelen+1, GFP_KERNEL);
5fdae1f6 82 if (full_path == NULL)
1da177e4
LT
83 return full_path;
84 full_path[namelen] = 0; /* trailing null */
1da177e4
LT
85 for (temp = direntry; !IS_ROOT(temp);) {
86 namelen -= 1 + temp->d_name.len;
87 if (namelen < 0) {
88 break;
89 } else {
7f57356b 90 full_path[namelen] = dirsep;
1da177e4
LT
91 strncpy(full_path + namelen + 1, temp->d_name.name,
92 temp->d_name.len);
b6b38f70 93 cFYI(0, "name: %s", full_path + namelen);
1da177e4
LT
94 }
95 temp = temp->d_parent;
5fdae1f6 96 if (temp == NULL) {
b6b38f70 97 cERROR(1, "corrupt dentry");
1da177e4
LT
98 kfree(full_path);
99 return NULL;
100 }
101 }
646dd539 102 if (namelen != pplen + dfsplen) {
b6b38f70
JP
103 cERROR(1, "did not end path lookup where expected namelen is %d",
104 namelen);
5fdae1f6 105 /* presumably this is only possible if racing with a rename
1da177e4
LT
106 of one of the parent directories (we can not lock the dentries
107 above us to prevent this, but retrying should be harmless) */
108 kfree(full_path);
1da177e4
LT
109 goto cifs_bp_rename_retry;
110 }
2fe87f02
SF
111 /* DIR_SEP already set for byte 0 / vs \ but not for
112 subsequent slashes in prepath which currently must
113 be entered the right way - not sure if there is an alternative
114 since the '\' is a valid posix character so we can not switch
115 those safely to '/' if any are found in the middle of the prepath */
116 /* BB test paths to Windows with '/' in the midst of prepath */
646dd539
SF
117
118 if (dfsplen) {
119 strncpy(full_path, cifs_sb->tcon->treeName, dfsplen);
120 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
121 int i;
122 for (i = 0; i < dfsplen; i++) {
123 if (full_path[i] == '\\')
124 full_path[i] = '/';
125 }
126 }
127 }
128 strncpy(full_path + dfsplen, CIFS_SB(direntry->d_sb)->prepath, pplen);
1da177e4
LT
129 return full_path;
130}
131
fae683f7
SJ
132/*
133 * When called with struct file pointer set to NULL, there is no way we could
134 * update file->private_data, but getting it stuck on openFileList provides a
135 * way to access it from cifs_fill_filedata and thereby set file->private_data
136 * from cifs_open.
137 */
086f68bd
JL
138struct cifsFileInfo *
139cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle,
140 struct file *file, struct vfsmount *mnt, unsigned int oflags)
a6ce4932
SF
141{
142 int oplock = 0;
143 struct cifsFileInfo *pCifsFile;
144 struct cifsInodeInfo *pCifsInode;
3bc303c2 145 struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb);
a6ce4932
SF
146
147 pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
a6ce4932 148 if (pCifsFile == NULL)
086f68bd 149 return pCifsFile;
a6ce4932
SF
150
151 if (oplockEnabled)
152 oplock = REQ_OPLOCK;
153
154 pCifsFile->netfid = fileHandle;
155 pCifsFile->pid = current->tgid;
48541bd3 156 pCifsFile->pInode = igrab(newinode);
3bc303c2 157 pCifsFile->mnt = mnt;
086f68bd 158 pCifsFile->pfile = file;
a6ce4932 159 pCifsFile->invalidHandle = false;
bc8cd439 160 pCifsFile->closePend = false;
a6ce4932
SF
161 mutex_init(&pCifsFile->fh_mutex);
162 mutex_init(&pCifsFile->lock_mutex);
163 INIT_LIST_HEAD(&pCifsFile->llist);
6ab409b5 164 atomic_set(&pCifsFile->count, 1);
3bc303c2 165 slow_work_init(&pCifsFile->oplock_break, &cifs_oplock_break_ops);
a6ce4932 166
a6ce4932 167 write_lock(&GlobalSMBSeslock);
3bc303c2 168 list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList);
a6ce4932
SF
169 pCifsInode = CIFS_I(newinode);
170 if (pCifsInode) {
171 /* if readable file instance put first in list*/
086f68bd
JL
172 if (oflags & FMODE_READ)
173 list_add(&pCifsFile->flist, &pCifsInode->openFileList);
174 else
a6ce4932
SF
175 list_add_tail(&pCifsFile->flist,
176 &pCifsInode->openFileList);
bc8cd439 177
a6ce4932
SF
178 if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
179 pCifsInode->clientCanCacheAll = true;
180 pCifsInode->clientCanCacheRead = true;
b6b38f70 181 cFYI(1, "Exclusive Oplock inode %p", newinode);
a6ce4932 182 } else if ((oplock & 0xF) == OPLOCK_READ)
bc8cd439 183 pCifsInode->clientCanCacheRead = true;
a6ce4932
SF
184 }
185 write_unlock(&GlobalSMBSeslock);
086f68bd
JL
186
187 return pCifsFile;
a6ce4932
SF
188}
189
7fc8f4e9 190int cifs_posix_open(char *full_path, struct inode **pinode,
fa588e0c
SF
191 struct vfsmount *mnt, struct super_block *sb,
192 int mode, int oflags,
193 __u32 *poplock, __u16 *pnetfid, int xid)
c3b2a0c6
SF
194{
195 int rc;
c3b2a0c6
SF
196 FILE_UNIX_BASIC_INFO *presp_data;
197 __u32 posix_flags = 0;
fa588e0c 198 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
cc0bad75 199 struct cifs_fattr fattr;
c3b2a0c6 200
b6b38f70 201 cFYI(1, "posix open %s", full_path);
c3b2a0c6
SF
202
203 presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
204 if (presp_data == NULL)
205 return -ENOMEM;
206
207/* So far cifs posix extensions can only map the following flags.
208 There are other valid fmode oflags such as FMODE_LSEEK, FMODE_PREAD, but
209 so far we do not seem to need them, and we can treat them as local only */
210 if ((oflags & (FMODE_READ | FMODE_WRITE)) ==
211 (FMODE_READ | FMODE_WRITE))
212 posix_flags = SMB_O_RDWR;
213 else if (oflags & FMODE_READ)
214 posix_flags = SMB_O_RDONLY;
215 else if (oflags & FMODE_WRITE)
216 posix_flags = SMB_O_WRONLY;
217 if (oflags & O_CREAT)
218 posix_flags |= SMB_O_CREAT;
219 if (oflags & O_EXCL)
220 posix_flags |= SMB_O_EXCL;
221 if (oflags & O_TRUNC)
222 posix_flags |= SMB_O_TRUNC;
6b2f3d1f
CH
223 /* be safe and imply O_SYNC for O_DSYNC */
224 if (oflags & O_DSYNC)
c3b2a0c6
SF
225 posix_flags |= SMB_O_SYNC;
226 if (oflags & O_DIRECTORY)
227 posix_flags |= SMB_O_DIRECTORY;
228 if (oflags & O_NOFOLLOW)
229 posix_flags |= SMB_O_NOFOLLOW;
230 if (oflags & O_DIRECT)
231 posix_flags |= SMB_O_DIRECT;
232
703a3b8e 233 mode &= ~current_umask();
c3b2a0c6 234 rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode,
590a3fe0 235 pnetfid, presp_data, poplock, full_path,
c3b2a0c6
SF
236 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
237 CIFS_MOUNT_MAP_SPECIAL_CHR);
238 if (rc)
239 goto posix_open_ret;
240
241 if (presp_data->Type == cpu_to_le32(-1))
242 goto posix_open_ret; /* open ok, caller does qpathinfo */
243
c3b2a0c6
SF
244 if (!pinode)
245 goto posix_open_ret; /* caller does not need info */
246
cc0bad75
JL
247 cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb);
248
249 /* get new inode and set it up */
85a6dac5 250 if (*pinode == NULL) {
fa588e0c 251 *pinode = cifs_iget(sb, &fattr);
cc0bad75
JL
252 if (!*pinode) {
253 rc = -ENOMEM;
254 goto posix_open_ret;
255 }
256 } else {
257 cifs_fattr_to_inode(*pinode, &fattr);
85a6dac5 258 }
c3b2a0c6 259
fae683f7
SJ
260 /*
261 * cifs_fill_filedata() takes care of setting cifsFileInfo pointer to
262 * file->private_data.
263 */
fdb36038
SJ
264 if (mnt) {
265 struct cifsFileInfo *pfile_info;
266
267 pfile_info = cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt,
268 oflags);
269 if (pfile_info == NULL)
270 rc = -ENOMEM;
271 }
a6ce4932 272
c3b2a0c6
SF
273posix_open_ret:
274 kfree(presp_data);
275 return rc;
276}
277
f818dd55
SF
278static void setup_cifs_dentry(struct cifsTconInfo *tcon,
279 struct dentry *direntry,
280 struct inode *newinode)
281{
282 if (tcon->nocase)
283 direntry->d_op = &cifs_ci_dentry_ops;
284 else
285 direntry->d_op = &cifs_dentry_ops;
286 d_instantiate(direntry, newinode);
287}
288
3979877e 289/* Inode operations in similar order to how they appear in Linux file fs.h */
1da177e4
LT
290
291int
292cifs_create(struct inode *inode, struct dentry *direntry, int mode,
293 struct nameidata *nd)
294{
295 int rc = -ENOENT;
296 int xid;
67750fb9 297 int create_options = CREATE_NOT_DIR;
590a3fe0 298 __u32 oplock = 0;
c3b2a0c6 299 int oflags;
90e4ee5d 300 bool posix_create = false;
c3b2a0c6
SF
301 /*
302 * BB below access is probably too much for mknod to request
303 * but we have to do query and setpathinfo so requesting
304 * less could fail (unless we want to request getatr and setatr
305 * permissions (only). At least for POSIX we do not have to
306 * request so much.
307 */
1da177e4
LT
308 int desiredAccess = GENERIC_READ | GENERIC_WRITE;
309 __u16 fileHandle;
310 struct cifs_sb_info *cifs_sb;
f818dd55 311 struct cifsTconInfo *tcon;
1da177e4 312 char *full_path = NULL;
fb8c4b14 313 FILE_ALL_INFO *buf = NULL;
1da177e4 314 struct inode *newinode = NULL;
1da177e4 315 int disposition = FILE_OVERWRITE_IF;
1da177e4
LT
316
317 xid = GetXid();
318
319 cifs_sb = CIFS_SB(inode->i_sb);
f818dd55 320 tcon = cifs_sb->tcon;
1da177e4 321
1da177e4 322 full_path = build_path_from_dentry(direntry);
5fdae1f6 323 if (full_path == NULL) {
0f3bc09e 324 rc = -ENOMEM;
1da177e4 325 FreeXid(xid);
0f3bc09e 326 return rc;
1da177e4
LT
327 }
328
c3b2a0c6
SF
329 if (oplockEnabled)
330 oplock = REQ_OPLOCK;
f818dd55 331
c3b2a0c6
SF
332 if (nd && (nd->flags & LOOKUP_OPEN))
333 oflags = nd->intent.open.flags;
334 else
fa588e0c 335 oflags = FMODE_READ | SMB_O_CREAT;
c3b2a0c6
SF
336
337 if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
338 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
339 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
fa588e0c
SF
340 rc = cifs_posix_open(full_path, &newinode,
341 nd ? nd->path.mnt : NULL,
342 inode->i_sb, mode, oflags, &oplock, &fileHandle, xid);
c3b2a0c6
SF
343 /* EIO could indicate that (posix open) operation is not
344 supported, despite what server claimed in capability
345 negotation. EREMOTE indicates DFS junction, which is not
346 handled in posix open */
347
90e4ee5d
SF
348 if (rc == 0) {
349 posix_create = true;
350 if (newinode == NULL) /* query inode info */
351 goto cifs_create_get_file_info;
352 else /* success, no need to query */
353 goto cifs_create_set_dentry;
354 } else if ((rc != -EIO) && (rc != -EREMOTE) &&
703a3b8e 355 (rc != -EOPNOTSUPP) && (rc != -EINVAL))
c3b2a0c6
SF
356 goto cifs_create_out;
357 /* else fallthrough to retry, using older open call, this is
358 case where server does not support this SMB level, and
359 falsely claims capability (also get here for DFS case
360 which should be rare for path not covered on files) */
361 }
e08fc045 362
c3b2a0c6
SF
363 if (nd && (nd->flags & LOOKUP_OPEN)) {
364 /* if the file is going to stay open, then we
365 need to set the desired access properly */
e08fc045
MS
366 desiredAccess = 0;
367 if (oflags & FMODE_READ)
c3b2a0c6 368 desiredAccess |= GENERIC_READ; /* is this too little? */
086f68bd 369 if (oflags & FMODE_WRITE)
e08fc045 370 desiredAccess |= GENERIC_WRITE;
1da177e4 371
5fdae1f6 372 if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
1da177e4 373 disposition = FILE_CREATE;
5fdae1f6 374 else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
1da177e4 375 disposition = FILE_OVERWRITE_IF;
5fdae1f6 376 else if ((oflags & O_CREAT) == O_CREAT)
1da177e4 377 disposition = FILE_OPEN_IF;
ad7a2926 378 else
b6b38f70 379 cFYI(1, "Create flag not set in create function");
1da177e4
LT
380 }
381
5fdae1f6
SF
382 /* BB add processing to set equivalent of mode - e.g. via CreateX with
383 ACLs */
1da177e4 384
5fdae1f6
SF
385 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
386 if (buf == NULL) {
1da177e4
LT
387 kfree(full_path);
388 FreeXid(xid);
389 return -ENOMEM;
390 }
67750fb9 391
67750fb9
JL
392 /*
393 * if we're not using unix extensions, see if we need to set
394 * ATTR_READONLY on the create call
395 */
f818dd55 396 if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
67750fb9
JL
397 create_options |= CREATE_OPTION_READONLY;
398
5fdae1f6 399 if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
f818dd55 400 rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
67750fb9 401 desiredAccess, create_options,
737b758c
SF
402 &fileHandle, &oplock, buf, cifs_sb->local_nls,
403 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
5bafd765
SF
404 else
405 rc = -EIO; /* no NT SMB support fall into legacy open below */
406
5fdae1f6 407 if (rc == -EIO) {
a9d02ad4 408 /* old server, retry the open legacy style */
f818dd55 409 rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
67750fb9 410 desiredAccess, create_options,
a9d02ad4
SF
411 &fileHandle, &oplock, buf, cifs_sb->local_nls,
412 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
5fdae1f6 413 }
1da177e4 414 if (rc) {
b6b38f70 415 cFYI(1, "cifs_create returned 0x%x", rc);
c3b2a0c6
SF
416 goto cifs_create_out;
417 }
418
419 /* If Open reported that we actually created a file
420 then we now have to set the mode if possible */
421 if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
422 struct cifs_unix_set_info_args args = {
4e1e7fb9
JL
423 .mode = mode,
424 .ctime = NO_CHANGE_64,
425 .atime = NO_CHANGE_64,
426 .mtime = NO_CHANGE_64,
427 .device = 0,
c3b2a0c6
SF
428 };
429
430 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
431 args.uid = (__u64) current_fsuid();
432 if (inode->i_mode & S_ISGID)
433 args.gid = (__u64) inode->i_gid;
434 else
435 args.gid = (__u64) current_fsgid();
3ce53fc4 436 } else {
c3b2a0c6
SF
437 args.uid = NO_CHANGE_64;
438 args.gid = NO_CHANGE_64;
1da177e4 439 }
01ea95e3
JL
440 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
441 cifs_sb->local_nls,
442 cifs_sb->mnt_cifs_flags &
443 CIFS_MOUNT_MAP_SPECIAL_CHR);
c3b2a0c6
SF
444 } else {
445 /* BB implement mode setting via Windows security
446 descriptors e.g. */
447 /* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/
448
449 /* Could set r/o dos attribute if mode & 0222 == 0 */
450 }
1da177e4 451
c3b2a0c6
SF
452cifs_create_get_file_info:
453 /* server might mask mode so we have to query for it */
454 if (tcon->unix_ext)
455 rc = cifs_get_inode_info_unix(&newinode, full_path,
456 inode->i_sb, xid);
457 else {
458 rc = cifs_get_inode_info(&newinode, full_path, buf,
459 inode->i_sb, xid, &fileHandle);
460 if (newinode) {
461 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
462 newinode->i_mode = mode;
463 if ((oplock & CIFS_CREATE_ACTION) &&
464 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) {
465 newinode->i_uid = current_fsuid();
466 if (inode->i_mode & S_ISGID)
467 newinode->i_gid = inode->i_gid;
468 else
469 newinode->i_gid = current_fsgid();
6473a559 470 }
1da177e4 471 }
c3b2a0c6 472 }
1da177e4 473
c3b2a0c6
SF
474cifs_create_set_dentry:
475 if (rc == 0)
476 setup_cifs_dentry(tcon, direntry, newinode);
477 else
b6b38f70 478 cFYI(1, "Create worked, get_inode_info failed rc = %d", rc);
c3b2a0c6
SF
479
480 /* nfsd case - nfs srv does not set nd */
481 if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) {
482 /* mknod case - do not leave file open */
483 CIFSSMBClose(xid, tcon, fileHandle);
90e4ee5d 484 } else if (!(posix_create) && (newinode)) {
fdb36038 485 struct cifsFileInfo *pfile_info;
fae683f7
SJ
486 /*
487 * cifs_fill_filedata() takes care of setting cifsFileInfo
488 * pointer to file->private_data.
489 */
fdb36038
SJ
490 pfile_info = cifs_new_fileinfo(newinode, fileHandle, NULL,
491 nd->path.mnt, oflags);
492 if (pfile_info == NULL)
493 rc = -ENOMEM;
5fdae1f6 494 }
d14537f1
SF
495cifs_create_out:
496 kfree(buf);
497 kfree(full_path);
1da177e4 498 FreeXid(xid);
1da177e4
LT
499 return rc;
500}
501
5fdae1f6
SF
502int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
503 dev_t device_number)
1da177e4
LT
504{
505 int rc = -EPERM;
506 int xid;
507 struct cifs_sb_info *cifs_sb;
508 struct cifsTconInfo *pTcon;
509 char *full_path = NULL;
fb8c4b14 510 struct inode *newinode = NULL;
1da177e4
LT
511
512 if (!old_valid_dev(device_number))
513 return -EINVAL;
514
515 xid = GetXid();
516
517 cifs_sb = CIFS_SB(inode->i_sb);
518 pTcon = cifs_sb->tcon;
519
1da177e4 520 full_path = build_path_from_dentry(direntry);
5fdae1f6 521 if (full_path == NULL)
1da177e4 522 rc = -ENOMEM;
c18c842b 523 else if (pTcon->unix_ext) {
4e1e7fb9 524 struct cifs_unix_set_info_args args = {
ce3b0f8d 525 .mode = mode & ~current_umask(),
4e1e7fb9
JL
526 .ctime = NO_CHANGE_64,
527 .atime = NO_CHANGE_64,
528 .mtime = NO_CHANGE_64,
529 .device = device_number,
530 };
5fdae1f6 531 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
a001e5b5
DH
532 args.uid = (__u64) current_fsuid();
533 args.gid = (__u64) current_fsgid();
1da177e4 534 } else {
4e1e7fb9
JL
535 args.uid = NO_CHANGE_64;
536 args.gid = NO_CHANGE_64;
1da177e4 537 }
01ea95e3
JL
538 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args,
539 cifs_sb->local_nls,
540 cifs_sb->mnt_cifs_flags &
541 CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4 542
5fdae1f6 543 if (!rc) {
1da177e4 544 rc = cifs_get_inode_info_unix(&newinode, full_path,
5fdae1f6 545 inode->i_sb, xid);
b92327fe
SF
546 if (pTcon->nocase)
547 direntry->d_op = &cifs_ci_dentry_ops;
548 else
549 direntry->d_op = &cifs_dentry_ops;
5fdae1f6 550 if (rc == 0)
1da177e4
LT
551 d_instantiate(direntry, newinode);
552 }
d7245c2c 553 } else {
5fdae1f6 554 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
eda3c029
SF
555 int oplock = 0;
556 u16 fileHandle;
ad7a2926 557 FILE_ALL_INFO *buf;
d7245c2c 558
b6b38f70 559 cFYI(1, "sfu compat create special file");
d7245c2c 560
5fdae1f6
SF
561 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
562 if (buf == NULL) {
eda3c029 563 kfree(full_path);
0f3bc09e 564 rc = -ENOMEM;
eda3c029 565 FreeXid(xid);
0f3bc09e 566 return rc;
eda3c029
SF
567 }
568
569 rc = CIFSSMBOpen(xid, pTcon, full_path,
570 FILE_CREATE, /* fail if exists */
5fdae1f6 571 GENERIC_WRITE /* BB would
eda3c029
SF
572 WRITE_OWNER | WRITE_DAC be better? */,
573 /* Create a file and set the
574 file attribute to SYSTEM */
575 CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
576 &fileHandle, &oplock, buf,
577 cifs_sb->local_nls,
5fdae1f6 578 cifs_sb->mnt_cifs_flags &
eda3c029
SF
579 CIFS_MOUNT_MAP_SPECIAL_CHR);
580
5bafd765
SF
581 /* BB FIXME - add handling for backlevel servers
582 which need legacy open and check for all
5fdae1f6
SF
583 calls to SMBOpen for fallback to SMBLeagcyOpen */
584 if (!rc) {
eda3c029 585 /* BB Do not bother to decode buf since no
86c96b4b
SF
586 local inode yet to put timestamps in,
587 but we can reuse it safely */
77159b4d 588 unsigned int bytes_written;
86c96b4b
SF
589 struct win_dev *pdev;
590 pdev = (struct win_dev *)buf;
5fdae1f6 591 if (S_ISCHR(mode)) {
86c96b4b
SF
592 memcpy(pdev->type, "IntxCHR", 8);
593 pdev->major =
594 cpu_to_le64(MAJOR(device_number));
5fdae1f6 595 pdev->minor =
86c96b4b
SF
596 cpu_to_le64(MINOR(device_number));
597 rc = CIFSSMBWrite(xid, pTcon,
598 fileHandle,
599 sizeof(struct win_dev),
600 0, &bytes_written, (char *)pdev,
601 NULL, 0);
5fdae1f6 602 } else if (S_ISBLK(mode)) {
86c96b4b
SF
603 memcpy(pdev->type, "IntxBLK", 8);
604 pdev->major =
605 cpu_to_le64(MAJOR(device_number));
606 pdev->minor =
607 cpu_to_le64(MINOR(device_number));
608 rc = CIFSSMBWrite(xid, pTcon,
609 fileHandle,
610 sizeof(struct win_dev),
611 0, &bytes_written, (char *)pdev,
612 NULL, 0);
613 } /* else if(S_ISFIFO */
eda3c029
SF
614 CIFSSMBClose(xid, pTcon, fileHandle);
615 d_drop(direntry);
616 }
617 kfree(buf);
d7245c2c
SF
618 /* add code here to set EAs */
619 }
1da177e4
LT
620 }
621
d14537f1 622 kfree(full_path);
1da177e4 623 FreeXid(xid);
1da177e4
LT
624 return rc;
625}
626
1da177e4 627struct dentry *
5fdae1f6
SF
628cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
629 struct nameidata *nd)
1da177e4
LT
630{
631 int xid;
632 int rc = 0; /* to get around spurious gcc warning, set to zero here */
590a3fe0 633 __u32 oplock = 0;
a6ce4932
SF
634 __u16 fileHandle = 0;
635 bool posix_open = false;
1da177e4
LT
636 struct cifs_sb_info *cifs_sb;
637 struct cifsTconInfo *pTcon;
638 struct inode *newInode = NULL;
639 char *full_path = NULL;
a6ce4932 640 struct file *filp;
1da177e4
LT
641
642 xid = GetXid();
643
b6b38f70
JP
644 cFYI(1, "parent inode = 0x%p name is: %s and dentry = 0x%p",
645 parent_dir_inode, direntry->d_name.name, direntry);
1da177e4 646
1da177e4
LT
647 /* check whether path exists */
648
649 cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
650 pTcon = cifs_sb->tcon;
651
296034f7
SF
652 /*
653 * Don't allow the separator character in a path component.
654 * The VFS will not allow "/", but "\" is allowed by posix.
655 */
656 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
657 int i;
658 for (i = 0; i < direntry->d_name.len; i++)
659 if (direntry->d_name.name[i] == '\\') {
b6b38f70 660 cFYI(1, "Invalid file name");
296034f7
SF
661 FreeXid(xid);
662 return ERR_PTR(-EINVAL);
663 }
664 }
665
5ddf1e0f
JL
666 /*
667 * O_EXCL: optimize away the lookup, but don't hash the dentry. Let
668 * the VFS handle the create.
669 */
8e6c0332 670 if (nd && (nd->flags & LOOKUP_EXCL)) {
5ddf1e0f 671 d_instantiate(direntry, NULL);
2f81e752 672 return NULL;
5ddf1e0f
JL
673 }
674
1da177e4
LT
675 /* can not grab the rename sem here since it would
676 deadlock in the cases (beginning of sys_rename itself)
677 in which we already have the sb rename sem */
678 full_path = build_path_from_dentry(direntry);
5fdae1f6 679 if (full_path == NULL) {
1da177e4
LT
680 FreeXid(xid);
681 return ERR_PTR(-ENOMEM);
682 }
683
684 if (direntry->d_inode != NULL) {
b6b38f70 685 cFYI(1, "non-NULL inode in lookup");
1da177e4 686 } else {
b6b38f70 687 cFYI(1, "NULL inode in lookup");
1da177e4 688 }
b6b38f70 689 cFYI(1, "Full path: %s inode = 0x%p", full_path, direntry->d_inode);
1da177e4 690
8db14ca1
SF
691 /* Posix open is only called (at lookup time) for file create now.
692 * For opens (rather than creates), because we do not know if it
693 * is a file or directory yet, and current Samba no longer allows
694 * us to do posix open on dirs, we could end up wasting an open call
695 * on what turns out to be a dir. For file opens, we wait to call posix
696 * open till cifs_open. It could be added here (lookup) in the future
697 * but the performance tradeoff of the extra network request when EISDIR
698 * or EACCES is returned would have to be weighed against the 50%
699 * reduction in network traffic in the other paths.
700 */
a6ce4932 701 if (pTcon->unix_ext) {
8e6c0332 702 if (nd && !(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
8db14ca1
SF
703 (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
704 (nd->intent.open.flags & O_CREAT)) {
3bc303c2 705 rc = cifs_posix_open(full_path, &newInode, nd->path.mnt,
fa588e0c 706 parent_dir_inode->i_sb,
703a3b8e 707 nd->intent.open.create_mode,
a6ce4932
SF
708 nd->intent.open.flags, &oplock,
709 &fileHandle, xid);
8db14ca1
SF
710 /*
711 * The check below works around a bug in POSIX
712 * open in samba versions 3.3.1 and earlier where
713 * open could incorrectly fail with invalid parameter.
714 * If either that or op not supported returned, follow
715 * the normal lookup.
716 */
717 if ((rc == 0) || (rc == -ENOENT))
718 posix_open = true;
719 else if ((rc == -EINVAL) || (rc != -EOPNOTSUPP))
720 pTcon->broken_posix_open = true;
a6ce4932
SF
721 }
722 if (!posix_open)
723 rc = cifs_get_inode_info_unix(&newInode, full_path,
724 parent_dir_inode->i_sb, xid);
725 } else
1da177e4 726 rc = cifs_get_inode_info(&newInode, full_path, NULL,
a6ce4932 727 parent_dir_inode->i_sb, xid, NULL);
1da177e4
LT
728
729 if ((rc == 0) && (newInode != NULL)) {
b92327fe
SF
730 if (pTcon->nocase)
731 direntry->d_op = &cifs_ci_dentry_ops;
732 else
733 direntry->d_op = &cifs_dentry_ops;
1da177e4 734 d_add(direntry, newInode);
a6ce4932
SF
735 if (posix_open)
736 filp = lookup_instantiate_filp(nd, direntry, NULL);
5fdae1f6 737 /* since paths are not looked up by component - the parent
3abb9272 738 directories are presumed to be good here */
1da177e4
LT
739 renew_parental_timestamps(direntry);
740
741 } else if (rc == -ENOENT) {
742 rc = 0;
3abb9272
SF
743 direntry->d_time = jiffies;
744 if (pTcon->nocase)
745 direntry->d_op = &cifs_ci_dentry_ops;
746 else
747 direntry->d_op = &cifs_dentry_ops;
1da177e4 748 d_add(direntry, NULL);
5fdae1f6
SF
749 /* if it was once a directory (but how can we tell?) we could do
750 shrink_dcache_parent(direntry); */
ed2b9170 751 } else if (rc != -EACCES) {
b6b38f70 752 cERROR(1, "Unexpected lookup error %d", rc);
ed2b9170
SF
753 /* We special case check for Access Denied - since that
754 is a common return code */
1da177e4
LT
755 }
756
d14537f1 757 kfree(full_path);
1da177e4
LT
758 FreeXid(xid);
759 return ERR_PTR(rc);
760}
761
1da177e4
LT
762static int
763cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
764{
765 int isValid = 1;
766
1da177e4 767 if (direntry->d_inode) {
df2cf170 768 if (cifs_revalidate_dentry(direntry))
1da177e4 769 return 0;
1da177e4 770 } else {
b6b38f70
JP
771 cFYI(1, "neg dentry 0x%p name = %s",
772 direntry, direntry->d_name.name);
5fdae1f6 773 if (time_after(jiffies, direntry->d_time + HZ) ||
3abb9272
SF
774 !lookupCacheEnabled) {
775 d_drop(direntry);
776 isValid = 0;
5fdae1f6 777 }
1da177e4
LT
778 }
779
1da177e4
LT
780 return isValid;
781}
782
783/* static int cifs_d_delete(struct dentry *direntry)
784{
785 int rc = 0;
786
b6b38f70 787 cFYI(1, "In cifs d_delete, name = %s", direntry->d_name.name);
1da177e4
LT
788
789 return rc;
790} */
791
4fd03e84 792const struct dentry_operations cifs_dentry_ops = {
1da177e4 793 .d_revalidate = cifs_d_revalidate,
5fdae1f6 794/* d_delete: cifs_d_delete, */ /* not needed except for debugging */
1da177e4 795};
b92327fe
SF
796
797static int cifs_ci_hash(struct dentry *dentry, struct qstr *q)
798{
799 struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
800 unsigned long hash;
801 int i;
802
803 hash = init_name_hash();
804 for (i = 0; i < q->len; i++)
805 hash = partial_name_hash(nls_tolower(codepage, q->name[i]),
806 hash);
807 q->hash = end_name_hash(hash);
808
809 return 0;
810}
811
812static int cifs_ci_compare(struct dentry *dentry, struct qstr *a,
813 struct qstr *b)
814{
815 struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
816
817 if ((a->len == b->len) &&
818 (nls_strnicmp(codepage, a->name, b->name, a->len) == 0)) {
819 /*
820 * To preserve case, don't let an existing negative dentry's
821 * case take precedence. If a is not a negative dentry, this
822 * should have no side effects
823 */
c3291637 824 memcpy((void *)a->name, b->name, a->len);
b92327fe
SF
825 return 0;
826 }
827 return 1;
828}
829
4fd03e84 830const struct dentry_operations cifs_ci_dentry_ops = {
b92327fe
SF
831 .d_revalidate = cifs_d_revalidate,
832 .d_hash = cifs_ci_hash,
833 .d_compare = cifs_ci_compare,
834};