Fix bug #7410 - samba sends "raw" inode number as uniqueid with unix extensions.
[metze/samba/wip.git] / source3 / smbd / trans2.c
index 6e1defaac2c4bb9e726fc9b27df6a4867fe710f5..8535d46afa43a840cd78ca6c26c898cbc5f645af 100644 (file)
@@ -58,6 +58,23 @@ uint64_t smb_roundup(connection_struct *conn, uint64_t val)
        return val;
 }
 
+/********************************************************************
+ Create a 64 bit FileIndex. If the file is on the same device as
+ the root of the share, just return the 64-bit inode. If it isn't,
+ mangle as we used to do.
+********************************************************************/
+
+uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
+{
+       uint64_t file_index;
+       if (conn->base_share_dev == psbuf->st_ex_dev) {
+               return (uint64_t)psbuf->st_ex_ino;
+       }
+       file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
+       file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
+       return file_index;
+}
+
 /****************************************************************************
  Utility functions for dealing with extended attributes.
 ****************************************************************************/
@@ -1478,6 +1495,7 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
        uint32_t reskey=0;
        uint64_t file_size = 0;
        uint64_t allocation_size = 0;
+       uint64_t file_index = 0;
        uint32_t len;
        struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
        time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
@@ -1500,6 +1518,8 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
        }
        allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
 
+       file_index = get_FileIndex(conn, &smb_fname->st);
+
        mdate_ts = smb_fname->st.st_ex_mtime;
        adate_ts = smb_fname->st.st_ex_atime;
        create_date_ts = get_create_timespec(conn, NULL, smb_fname);
@@ -1886,8 +1906,7 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                        p +=4;
                }
                SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
-               SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
-               SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
+               SBVAL(p,0,file_index); p += 8;
                len = srvstr_push(base_data, flags2, p,
                                  fname, PTR_DIFF(end_data, p),
                                  STR_TERMINATE_ASCII);
@@ -1957,8 +1976,7 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                }
                p += 26;
                SSVAL(p,0,0); p += 2; /* Reserved ? */
-               SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
-               SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
+               SBVAL(p,0,file_index); p += 8;
                len = srvstr_push(base_data, flags2, p,
                                  fname, PTR_DIFF(end_data, p),
                                  STR_TERMINATE_ASCII);
@@ -3890,6 +3908,8 @@ static char *store_file_unix_basic(connection_struct *conn,
                                files_struct *fsp,
                                const SMB_STRUCT_STAT *psbuf)
 {
+       uint64_t file_index = get_FileIndex(conn, psbuf);
+
        DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
        DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
 
@@ -3923,7 +3943,7 @@ static char *store_file_unix_basic(connection_struct *conn,
        SIVAL(pdata,4,0);
        pdata += 8;
 
-       SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino);   /* inode number */
+       SINO_T_VAL(pdata,0,(SMB_INO_T)file_index);   /* inode number */
        pdata += 8;
 
        SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode));     /* Standard UNIX file permissions */
@@ -4319,8 +4339,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
 
           I think this causes us to fail the IFSKIT
           BasicFileInformationTest. -tpot */
-       file_index =  ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
-       file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
+       file_index = get_FileIndex(conn, psbuf);
 
        switch (info_level) {
                case SMB_INFO_STANDARD: