]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - fs/cifs/inode.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[karo-tx-linux.git] / fs / cifs / inode.c
index 8b7305e73d7eab00188b0aa50569fd05b5271d62..f247da9f4edc2a650f7e59c559f17767d1f8dccd 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/inode.c
  *
- *   Copyright (C) International Business Machines  Corp., 2002,2007
+ *   Copyright (C) International Business Machines  Corp., 2002,2008
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -621,6 +621,47 @@ static const struct inode_operations cifs_ipc_inode_ops = {
        .lookup = cifs_lookup,
 };
 
+static char *build_path_to_root(struct cifs_sb_info *cifs_sb)
+{
+       int pplen = cifs_sb->prepathlen;
+       int dfsplen;
+       char *full_path = NULL;
+
+       /* if no prefix path, simply set path to the root of share to "" */
+       if (pplen == 0) {
+               full_path = kmalloc(1, GFP_KERNEL);
+               if (full_path)
+                       full_path[0] = 0;
+               return full_path;
+       }
+
+       if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS))
+               dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1);
+       else
+               dfsplen = 0;
+
+       full_path = kmalloc(dfsplen + pplen + 1, GFP_KERNEL);
+       if (full_path == NULL)
+               return full_path;
+
+       if (dfsplen) {
+               strncpy(full_path, cifs_sb->tcon->treeName, dfsplen);
+               /* switch slash direction in prepath depending on whether
+                * windows or posix style path names
+                */
+               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
+                       int i;
+                       for (i = 0; i < dfsplen; i++) {
+                               if (full_path[i] == '\\')
+                                       full_path[i] = '/';
+                       }
+               }
+       }
+       strncpy(full_path + dfsplen, cifs_sb->prepath, pplen);
+       full_path[dfsplen + pplen] = 0; /* add trailing null */
+       return full_path;
+}
+
 /* gets root inode */
 struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
 {
@@ -628,6 +669,7 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
        struct cifs_sb_info *cifs_sb;
        struct inode *inode;
        long rc;
+       char *full_path;
 
        inode = iget_locked(sb, ino);
        if (!inode)
@@ -636,13 +678,17 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
                return inode;
 
        cifs_sb = CIFS_SB(inode->i_sb);
-       xid = GetXid();
+       full_path = build_path_to_root(cifs_sb);
+       if (full_path == NULL)
+               return ERR_PTR(-ENOMEM);
 
+       xid = GetXid();
        if (cifs_sb->tcon->unix_ext)
-               rc = cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid);
+               rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,
+                                               xid);
        else
-               rc = cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid,
-                                        NULL);
+               rc = cifs_get_inode_info(&inode, full_path, NULL, inode->i_sb,
+                                               xid, NULL);
        if (rc && cifs_sb->tcon->ipc) {
                cFYI(1, ("ipc connection - fake read inode"));
                inode->i_mode |= S_IFDIR;
@@ -652,6 +698,7 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
                inode->i_uid = cifs_sb->mnt_uid;
                inode->i_gid = cifs_sb->mnt_gid;
        } else if (rc) {
+               kfree(full_path);
                _FreeXid(xid);
                iget_failed(inode);
                return ERR_PTR(rc);
@@ -659,6 +706,7 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
 
        unlock_new_inode(inode);
 
+       kfree(full_path);
        /* can not call macro FreeXid here since in a void func
         * TODO: This is no longer true
         */