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