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