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