]> git.neil.brown.name Git - history.git/commitdiff
Properly emulate POSIX semantics for deleting of open files and renaming over open...
authorSteve French <stevef@steveft21.ltcsamba>
Thu, 21 Nov 2002 11:02:44 +0000 (05:02 -0600)
committerSteve French <stevef@steveft21.ltcsamba>
Thu, 21 Nov 2002 11:02:44 +0000 (05:02 -0600)
12 files changed:
fs/cifs/CHANGES
fs/cifs/README
fs/cifs/cifs_debug.c
fs/cifs/cifspdu.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/dir.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/link.c
fs/cifs/netmisc.c

index 5e917cc411f17d0161d684b531c3d4bb003f6690..6e69909a2378b8968eb1b067b901cde2119e3393 100644 (file)
@@ -1,3 +1,13 @@
+Version 0.60
+------------
+Fix oops in readpages caused by not setting address space operations in inode in 
+rare code path. 
+
+Version 0.59
+------------
+Includes support for deleting of open files and renaming over existing files (per POSIX
+requirement).  Add readlink support for Windows junction points (directory symlinks).
+
 Version 0.58
 ------------
 Changed read and write to go through pagecache. Added additional address space operations.
index 96370491a0d79f39a79e5a9db43536bcac6e6181..20626fb1aca4a52b123d143d2760d3df6f69f779 100644 (file)
@@ -9,8 +9,8 @@ For questions or bug reports please contact sfrench@samba.org (sfrench@us.ibm.co
 
 Build instructions:
 ==================
-extract the kernel from http://www.cifs.bkbits.net/linux-2.5 or 
-http://www.cifs.bkbits.net/linux-2.4  
+Get the kernel source e.g. http://linux.bkbits.net/linux-2.5 or http://www.kernel.org 
+http://cifs.bkbits.net/linux-2.4  
 make menuconfig (or make xconfig)
 select cifs from within the network filesystem choices
 save and exit
@@ -57,7 +57,9 @@ Some administrators also change the "map archive" and the "create mask" paramete
 from their defaults. For more information on these see the manual pages 
 ("man smb.conf") on the Samba server system.  Note that the cifs vfs, unlike the
 smbfs vfs, does not read the smb.conf on the client system (the few optional settings
-are passed in on mount via -o parameters instead).
+are passed in on mount via -o parameters instead).  Note that Samba 2.2.7 or later
+includes a fix that allows the CIFS VFS to delete open files (required for strict
+POSIX compliance).  Windows Servers already supported this feature.
 
 Use instructions:
 ================
@@ -77,7 +79,7 @@ Servers must support the NTLM SMB dialect (which is the most recent, supported b
 and Windows NT, 2000 and XP and many other SMB/CIFS servers) and servers must support
 either "pure-TCP" (port 445 TCP/IP CIFS connections) or RFC 1001/1002 support for
 "Netbios-Over-TCP/IP."  Neither of these is likely to be a problem as most servers
-support this.  IPv6 support is planned for the future.
+support this.  IPv6 support is planned for the future.  
 
 Misc /proc/fs/cifs Flags and Debug Info
 =======================================
index a9436fa84e89d53a4e80662060b8400a016172ff..b76d73ab17f8d343589e748b45845e70a5a11d7c 100644 (file)
@@ -85,7 +85,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
                ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
                length =
                    sprintf(buf,
-                           "\n%d) Name: %s  Domain: %s HowManyMounts: %d ServerOS: %s  ServerNOS: %s  Capabilities: 0x%x\n",
+                           "\n%d) Name: %s  Domain: %s HowManyMounts: %d ServerOS: %s  ServerNOS: %s\n\tCapabilities: 0x%x",
                                i, ses->serverName, ses->serverDomain, atomic_read(&ses->inUse),
                                ses->serverOS, ses->serverNOS, ses->capabilities);
                buf += length;
@@ -107,7 +107,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
                tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
                length =
                    sprintf(buf,
-                           "\n%d) %s UseCount: %d on FS: %s with characteristics: 0x%x Attributes: 0x%x and PathComponentLengthMax: %d",
+                           "\n%d) %s UseCount: %d on FS: %s with characteristics: 0x%x Attributes: 0x%x\n\tPathComponentLengthMax: %d",
                            i, tcon->treeName,
                            atomic_read(&tcon->useCount),
                            tcon->nativeFileSystem,
index 0954f7a37c0a658674b79d192cf510af0b06529a..dfac5e09e4929f5c55fe833a615246e379e0d42b 100644 (file)
 #define ATTR_NOT_CONTENT_INDEXED 0x2000
 #define ATTR_ENCRYPTED  0x4000
 #define ATTR_POSIX_SEMANTICS 0x01000000
+#define ATTR_BACKUP_SEMANTICS 0x02000000
+#define ATTR_DELETE_ON_CLOSE 0x04000000
 #define ATTR_SEQUENTIAL_SCAN 0x08000000
 #define ATTR_RANDOM_ACCESS   0x10000000
 #define ATTR_NO_BUFFERING    0x20000000
 #define FILE_OVERWRITE_IF 0x00000005
 
 /* CreateOptions */
-#define CREATE_NOT_FILE   0x00000001   /* if set, indicates must not be file */
-#define CREATE_NOT_DIR    0x00000040   /* if set, indicates must not be directory */
+#define CREATE_NOT_FILE                0x00000001      /* if set must not be file */
+#define CREATE_WRITE_THROUGH   0x00000002
+#define CREATE_NOT_DIR         0x00000040      /* if set must not be directory */
+#define CREATE_RANDOM_ACCESS   0x00000800
+#define CREATE_DELETE_ON_CLOSE 0x00001000
+#define OPEN_REPARSE_POINT     0x00200000
 
 /* ImpersonationLevel flags */
 #define SECURITY_ANONYMOUS      0
@@ -743,7 +749,10 @@ typedef struct smb_com_rename_req {
        /* followed by NewFileName */
 } RENAME_REQ;
 
-#define CREATE_HARD_LINK 0x103
+#define CREATE_HARD_LINK               0x103
+#define MOVEFILE_COPY_ALLOWED          0x0002
+#define MOVEFILE_REPLACE_EXISTING      0x0001
+
 typedef struct smb_com_nt_rename_req { /* A5 - also used for create hardlink */
        struct smb_hdr hdr;     /* wct = 4 */
        __u16 SearchAttributes; /* target file attributes */
@@ -798,7 +807,7 @@ typedef struct smb_com_create_directory_rsp {
        __u16 ByteCount;        /* bct = 0 */
 } CREATE_DIRECTORY_RSP;
 
-typedef struct smb_com_nt_transaction_ioctl_req {
+typedef struct smb_com_transaction_ioctl_req {
        struct smb_hdr hdr;     /* wct = 23 */
        __u8 MaxSetupCount;
        __u16 Reserved;
@@ -810,13 +819,13 @@ typedef struct smb_com_nt_transaction_ioctl_req {
        __u32 ParameterOffset;
        __u32 DataCount;
        __u32 DataOffset;
-       __u8 SetupCount;        /* four setup words follow subcommand */
+       __u8 SetupCount; /* four setup words follow subcommand */
        /* SNIA spec incorrectly included spurious pad here */
-       __u16 SubCommand;       /* 2 = IOCTL/FSCTL */
+       __u16 SubCommand;/* 2 = IOCTL/FSCTL */
        __u32 FunctionCode;
        __u16 Fid;
-       __u8 IsFSCTLFlag;       /* 1 = File System Control, 0 = device control (IOCTL)    */
-       __u8 IsRootFlag;        /* 1 = apply command to root of share (must be DFS share) */
+       __u8 IsFsctl;    /* 1 = File System Control, 0 = device control (IOCTL)*/
+       __u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS share)*/
        __u16 ByteCount;
        __u8 Pad[3];
        __u8 Data[1];
@@ -839,6 +848,17 @@ typedef struct smb_com_transaction_ioctl_rsp {
        __u8 Pad[3];
 } TRANSACT_IOCTL_RSP;
 
+struct reparse_data {
+       __u32   ReparseTag;
+       __u16   ReparseDataLength;
+       __u16   Reserved;
+       __u16   AltNameOffset;
+       __u16   AltNameLen;
+       __u16   TargetNameOffset;
+       __u16   TargetNameLen;
+       char    LinkNamesBuf[1];
+};
+
 typedef union smb_com_transaction2 {
        struct {
                struct smb_hdr hdr;     /* wct = 14+ */
@@ -894,7 +914,7 @@ typedef union smb_com_transaction2 {
 #define SMB_QUERY_FILE_UNIX_BASIC    0x200
 #define SMB_QUERY_FILE_UNIX_LINK     0x201
 
-#define SMB_SET_FILE_BASIC_INFO                0x101
+#define SMB_SET_FILE_BASIC_INFO                        0x101
 #define SMB_SET_FILE_DISPOSITION_INFO  0x102
 #define SMB_SET_FILE_ALLOCATION_INFO   0x103
 #define SMB_SET_FILE_END_OF_FILE_INFO  0x104
@@ -908,7 +928,7 @@ typedef union smb_com_transaction2 {
 /* Find File infolevels */
 #define SMB_FIND_FILE_DIRECTORY_INFO     0x101
 #define SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102
-#define SMB_FIND_FILE_NAMES_INFO         0x103
+#define SMB_FIND_FILE_NAMES_INFO               0x103
 #define SMB_FIND_FILE_BOTH_DIRECTORY_INFO 0x104
 #define SMB_FIND_FILE_UNIX                0x202
 
index eabcdee8f2737d4531f1ec0b078b206a3a3b37ff..cd8a7b42419dc53b886361605af8fee605dde3bf 100644 (file)
@@ -184,6 +184,11 @@ extern int CIFSSMBUnixQuerySymLink(const int xid,
                        const unsigned char *searchName,
                        char *syminfo, const int buflen,
                        const struct nls_table *nls_codepage);
+extern int CIFSSMBQueryReparseLinkInfo(const int xid, 
+                       const struct cifsTconInfo *tcon,
+                       const unsigned char *searchName,
+                       char *symlinkinfo, const int buflen, __u16 fid,
+                       const struct nls_table *nls_codepage);
 
 extern int CIFSSMBOpen(const int xid, const struct cifsTconInfo *tcon,
                        const char *fileName, const int disposition,
index c1864e268f20470ebf3ca1917353307dcf64da18..e1aca86ab253876115930532d2dff2dffb5b2eb7 100644 (file)
@@ -390,7 +390,7 @@ CIFSSMBMkDir(const int xid, const struct cifsTconInfo *tcon,
 int
 CIFSSMBOpen(const int xid, const struct cifsTconInfo *tcon,
            const char *fileName, const int openDisposition,
-           const int access_flags, const int omode, __u16 * netfid,
+           const int access_flags, const int create_options, __u16 * netfid,
            int *pOplock, const struct nls_table *nls_codepage)
 {
        int rc = -EACCES;
@@ -436,7 +436,7 @@ CIFSSMBOpen(const int xid, const struct cifsTconInfo *tcon,
        pSMB->FileAttributes = cpu_to_le32(pSMB->FileAttributes);
        pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
        pSMB->CreateDisposition = cpu_to_le32(openDisposition);
-       pSMB->CreateOptions = cpu_to_le32(CREATE_NOT_DIR);      /* BB what are these? BB */
+       pSMB->CreateOptions = cpu_to_le32(create_options);
        pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ?? BB */
        pSMB->SecurityFlags =
            cpu_to_le32(SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY);
@@ -962,7 +962,7 @@ CIFSSMBUnixQuerySymLink(const int xid, const struct cifsTconInfo *tcon,
        int bytes_returned;
        int name_len;
 
-       cFYI(1, ("\nIn QPathSymLinkInfo (Unix) the path %s", searchName));
+       cFYI(1, ("\nIn QPathSymLinkInfo (Unix) for path %s", searchName));
        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
        if (rc)
@@ -1014,7 +1014,8 @@ CIFSSMBUnixQuerySymLink(const int xid, const struct cifsTconInfo *tcon,
        } else {                /* decode response */
                pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
                pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
-               if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))        /* BB also check enough total bytes returned */
+               if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
+               /* BB also check enough total bytes returned */
                        rc = -EIO;      /* bad smb */
                else {
                        if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
@@ -1041,7 +1042,89 @@ CIFSSMBUnixQuerySymLink(const int xid, const struct cifsTconInfo *tcon,
                                                               pSMBr->
                                                               DataCount));
                        }
-                       symlinkinfo[buflen] = 0;        /* just in case so the calling code does not go off the end of the buffer */
+                       symlinkinfo[buflen] = 0;
+       /* just in case so calling code does not go off the end of buffer */
+               }
+       }
+       if (pSMB)
+               buf_release(pSMB);
+       return rc;
+}
+
+
+
+int
+CIFSSMBQueryReparseLinkInfo(const int xid, const struct cifsTconInfo *tcon,
+                       const unsigned char *searchName,
+                       char *symlinkinfo, const int buflen,__u16 fid,
+                       const struct nls_table *nls_codepage)
+{
+       int rc = 0;
+       int bytes_returned;
+       int name_len;
+       struct smb_com_transaction_ioctl_req * pSMB;
+       struct smb_com_transaction_ioctl_rsp * pSMBr;
+
+       cFYI(1, ("\nIn Windows reparse style QueryLink info for path %s", searchName));
+       rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
+                     (void **) &pSMBr);
+       if (rc)
+               return rc;
+
+       pSMB->TotalParameterCount = 0 ;
+       pSMB->TotalDataCount = 0;
+       pSMB->MaxParameterCount = cpu_to_le16(2);
+       pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
+       pSMB->MaxSetupCount = 4;
+       pSMB->Reserved = 0;
+       pSMB->ParameterOffset = 0;
+       pSMB->DataCount = 0;
+       pSMB->DataOffset = 0;
+       pSMB->SetupCount = 4;
+       pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
+       pSMB->ParameterCount = pSMB->TotalParameterCount;
+       pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
+       pSMB->IsFsctl = 1; /* FSCTL */
+       pSMB->IsRootFlag = 0;
+       pSMB->Fid = fid; /* file handle always le */
+       pSMB->ByteCount = 0;
+
+       rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+                        (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+       if (rc) {
+               cFYI(1, ("\nSend error in QueryReparseLinkInfo = %d\n", rc));
+       } else {                /* decode response */
+               pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
+               pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
+               if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
+               /* BB also check enough total bytes returned */
+                       rc = -EIO;      /* bad smb */
+               else {
+                       if(pSMBr->DataCount && (pSMBr->DataCount < 2048)) {
+               /* could also validata reparse tag && better check name length */
+                               struct reparse_data * reparse_buf = (struct reparse_data *)
+                                       ((char *)&pSMBr->hdr.Protocol + pSMBr->DataOffset);
+                               if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
+                                       name_len = UniStrnlen((wchar_t *)
+                                                       (reparse_buf->LinkNamesBuf + 
+                                                       reparse_buf->TargetNameOffset),
+                                                       min(buflen/2, reparse_buf->TargetNameLen / 2)); 
+                                       cifs_strfromUCS_le(symlinkinfo,
+                                               (wchar_t *) (reparse_buf->LinkNamesBuf + 
+                                               reparse_buf->TargetNameOffset),
+                                               name_len, nls_codepage);
+                               } else { /* ASCII names */
+                                       strncpy(symlinkinfo,reparse_buf->LinkNamesBuf + 
+                                               reparse_buf->TargetNameOffset, 
+                                               min(buflen, (int)reparse_buf->TargetNameLen));
+                               }
+                       } else {
+                               rc = -EIO;
+                               cFYI(1,("\nInvalid return data count on get reparse info ioctl"));
+                       }
+                       symlinkinfo[buflen] = 0; /* just in case so the caller
+                                       does not go off the end of the buffer */
+                       cFYI(1,("\nreadlink result - %s ",symlinkinfo));
                }
        }
        if (pSMB)
index 62adcc9f2f8c361874929ed2df6b4edd2dae640a..afb2c3844b0589731200c886e8495e8ad5c98a63 100644 (file)
@@ -561,6 +561,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket)
                if (rc < 0) {
                        cFYI(1, ("Error connecting to socket. %d\n", rc));
                        sock_release(*csocket);
+                       *csocket = NULL;
                        return rc;
                }
        }
@@ -598,6 +599,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
                             ("Error connecting to socket (via ipv6). %d\n",
                              rc));
                        sock_release(*csocket);
+                       *csocket = NULL;
                        return rc;
                }
        }
index 1779c87a68eb07d7b774a3b996ba305a540d45dd..09171f0118c575817c143866e20ea224ec310ce1 100644 (file)
@@ -141,7 +141,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode)
        /* BB add processing for setting the equivalent of mode - e.g. via CreateX with ACLs */
 
        rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OVERWRITE_IF, GENERIC_ALL
-                        /* 0x20197 was used previously */ , mode,
+                        /* 0x20197 was used previously */ , CREATE_NOT_DIR,
                         &fileHandle, &oplock, cifs_sb->local_nls);
        if (rc) {
                cFYI(1, ("\ncifs_create returned 0x%x ", rc));
@@ -267,11 +267,6 @@ cifs_d_revalidate(struct dentry *direntry, int flags)
 /*     lock_kernel(); *//* surely we do not want to lock the kernel for a whole network round trip which could take seconds */
 
        if (direntry->d_inode) {
-               cFYI(1,
-                    ("In cifs_d_revalidate, name = %s and inode = 0x%p with count %d with time %ld and dentry 0x%p with time %ld\n",
-                     direntry->d_name.name, direntry->d_inode,
-                     direntry->d_inode->i_count.counter,
-                     direntry->d_inode->i_atime.tv_sec, direntry, direntry->d_time));
                if (cifs_revalidate(direntry)) {
                        /* unlock_kernel(); */
                        return 0;
index ba34dbc2a47a314ae66803ab65488e85705418bc..0984cb20c8264ce5fac4be736832f6a3e27f889b 100644 (file)
@@ -35,8 +35,6 @@
 #include "cifs_debug.h"
 #include "cifs_fs_sb.h"
 
-
-
 int
 cifs_open(struct inode *inode, struct file *file)
 {
@@ -94,9 +92,8 @@ cifs_open(struct inode *inode, struct file *file)
                oplock = FALSE;
 
        /* BB pass O_SYNC flag through on file attributes .. BB */
-       rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,                      
-                        -1 /* i.e. dummy value, ignored for time being */,
-                        &netfid, &oplock, cifs_sb->local_nls);
+       rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
+                       CREATE_NOT_DIR, &netfid, &oplock, cifs_sb->local_nls);
        if (rc) {
                cFYI(1, ("\ncifs_open returned 0x%x ", rc));
                cFYI(1, (" oplock: %d ", oplock));
@@ -112,7 +109,8 @@ cifs_open(struct inode *inode, struct file *file)
                        pCifsFile->pfile = file; /* needed for writepage */
                        list_add(&pCifsFile->tlist,&pTcon->openFileList);
                        pCifsInode = CIFS_I(file->f_dentry->d_inode);
-                       list_add(&pCifsFile->flist,&pCifsInode->openFileList);
+                       if(pCifsInode->openFileList.next)
+                               list_add(&pCifsFile->flist,&pCifsInode->openFileList);
                        if(file->f_flags & O_CREAT) {           
                                /* time to set mode which we can not set earlier due
                                 to problems creating new read-only files */
@@ -153,7 +151,8 @@ cifs_close(struct inode *inode, struct file *file)
        cifs_sb = CIFS_SB(inode->i_sb);
        pTcon = cifs_sb->tcon;
        if (pSMBFile) {
-               list_del(&pSMBFile->flist);
+               if(pSMBFile->flist.next)
+                       list_del(&pSMBFile->flist);
                list_del(&pSMBFile->tlist);
                rc = CIFSSMBClose(xid, pTcon, pSMBFile->netfid);
                kfree(file->private_data);
@@ -649,6 +648,7 @@ fill_in_inode(struct inode *tmp_inode,
                cFYI(1, (" File inode "));
                tmp_inode->i_op = &cifs_file_inode_ops;
                tmp_inode->i_fop = &cifs_file_ops;
+               tmp_inode->i_data.a_ops = &cifs_addr_ops;
        } else if (S_ISDIR(tmp_inode->i_mode)) {
                cFYI(1, (" Directory inode"));
                tmp_inode->i_op = &cifs_dir_inode_ops;
@@ -716,6 +716,7 @@ unix_fill_in_inode(struct inode *tmp_inode,
                cFYI(1, (" File inode "));
                tmp_inode->i_op = &cifs_file_inode_ops;
                tmp_inode->i_fop = &cifs_file_ops;
+               tmp_inode->i_data.a_ops = &cifs_addr_ops;
        } else if (S_ISDIR(tmp_inode->i_mode)) {
                cFYI(1, (" Directory inode"));
                tmp_inode->i_op = &cifs_dir_inode_ops;
index e31cdddda8cc8ae1c80244e28c9aa5f9761a1fa5..0bacffea346e78997631298555cd9bfda962b53b 100644 (file)
@@ -314,14 +314,24 @@ cifs_unlink(struct inode *inode, struct dentry *direntry)
        cifs_sb = CIFS_SB(inode->i_sb);
        pTcon = cifs_sb->tcon;
 
-       /* BB Should we close the file if it is already open from our client? */
-
        full_path = build_path_from_dentry(direntry);
 
        rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls);
 
        if (!rc) {
                direntry->d_inode->i_nlink--;
+       } else if (rc == -ETXTBSY) {
+               int oplock = FALSE;
+               __u16 netfid;
+
+               rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE, 
+                               CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
+                               &netfid, &oplock, cifs_sb->local_nls);
+               if(rc==0) {
+                       CIFSSMBClose(xid, pTcon, netfid);
+                       /* BB In the future chain close with the NTCreateX to narrow window */
+                       direntry->d_inode->i_nlink--;
+               }
        }
        cifsInode = CIFS_I(direntry->d_inode);
        cifsInode->time = 0;    /* will force revalidate to get info when needed */
@@ -454,6 +464,11 @@ cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
 
        rc = CIFSSMBRename(xid, pTcon, fromName, toName,
                           cifs_sb_source->local_nls);
+       if(rc == -EEXIST) {
+               cifs_unlink(target_inode, target_direntry);
+               rc = CIFSSMBRename(xid, pTcon, fromName, toName,
+                                  cifs_sb_source->local_nls);
+       }
        if (fromName)
                kfree(fromName);
        if (toName)
index 5621cada5ea70e3b672748217914e5e2631c9cbe..fff2f11665932cc36580a03c9aa141462481a6df 100644 (file)
@@ -176,10 +176,12 @@ cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen)
        struct inode *inode = direntry->d_inode;
        int rc = -EACCES;
        int xid;
+       int oplock = FALSE;
        struct cifs_sb_info *cifs_sb;
        struct cifsTconInfo *pTcon;
        char *full_path = NULL;
        char tmpbuffer[256];
+       __u16 fid;
 
        xid = GetXid();
        cifs_sb = CIFS_SB(inode->i_sb);
@@ -192,12 +194,23 @@ cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen)
 /* BB add read reparse point symlink code and Unix extensions symlink code here BB */
        if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
                rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
-                                            tmpbuffer,
-                                            sizeof (tmpbuffer) - 1,
-                                            cifs_sb->local_nls);
+                                       tmpbuffer,
+                                       sizeof (tmpbuffer) - 1,
+                                       cifs_sb->local_nls);
        else {
-               /* rc = CIFSSMBQueryReparseLinkInfo */
-               /* BB Add code to Query ReparsePoint info */
+               rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
+                               OPEN_REPARSE_POINT,&fid, &oplock, cifs_sb->local_nls);
+               if(!rc) {
+                       rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path,
+                               tmpbuffer,
+                               sizeof(tmpbuffer) - 1, 
+                               fid,
+                               cifs_sb->local_nls);
+                       if(CIFSSMBClose(xid, pTcon, fid)) {
+                               cFYI(1,("Error closing junction point (open for ioctl)"));
+                       }
+               }
+
        }
        /* BB Anything else to do to handle recursive links? */
        /* BB Should we be using page ops here? */
index db0a9c6216e151df82fdf4090403232e7d08480f..cf279a4b6d305a975732f2d484ca8af2408d2d89 100644 (file)
@@ -252,7 +252,7 @@ const static struct {
        ERRHRD, ERRgeneral, NT_STATUS_DISK_CORRUPT_ERROR}, {
        ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_INVALID}, {   /* mapping changed since shell does lookup on * and expects file not found */
        ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND}, {
-       ERRDOS, 183, NT_STATUS_OBJECT_NAME_COLLISION}, {
+       ERRDOS, ERRalreadyexists, NT_STATUS_OBJECT_NAME_COLLISION}, {
        ERRHRD, ERRgeneral, NT_STATUS_HANDLE_NOT_WAITABLE}, {
        ERRDOS, ERRbadfid, NT_STATUS_PORT_DISCONNECTED}, {
        ERRHRD, ERRgeneral, NT_STATUS_DEVICE_ALREADY_ATTACHED}, {
@@ -285,7 +285,7 @@ const static struct {
        ERRHRD, ERRgeneral, NT_STATUS_EA_CORRUPT_ERROR}, {
        ERRDOS, ERRlock, NT_STATUS_FILE_LOCK_CONFLICT}, {
        ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED}, {
-       ERRDOS, ERRnoaccess, NT_STATUS_DELETE_PENDING}, {
+       ERRDOS, ERRbadfile, NT_STATUS_DELETE_PENDING}, {
        ERRDOS, ERRunsup, NT_STATUS_CTL_FILE_NOT_SUPPORTED}, {
        ERRHRD, ERRgeneral, NT_STATUS_UNKNOWN_REVISION}, {
        ERRHRD, ERRgeneral, NT_STATUS_REVISION_MISMATCH}, {
@@ -753,7 +753,7 @@ cifs_print_status(__u32 status_code)
 {
        int idx = 0;
 
-       printk("\nStatus code returned: 0x%08x", status_code);
+       printk("\nStatus code returned: 0x%08x ", status_code);
 
        while (nt_errs[idx].nt_errstr != NULL) {
                if (((nt_errs[idx].nt_errcode) & 0xFFFFFF) ==