diff options
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/inode.c | 48 |
1 files changed, 44 insertions, 4 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index ba9eae56d011..93dd705577bc 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -228,9 +228,20 @@ static int decode_sfu_inode(struct inode * inode, __u64 size, | |||
228 | 8 /* length */, 0 /* offset */, | 228 | 8 /* length */, 0 /* offset */, |
229 | &bytes_read, &pbuf); | 229 | &bytes_read, &pbuf); |
230 | if((rc == 0) && (bytes_read == 8)) { | 230 | if((rc == 0) && (bytes_read == 8)) { |
231 | /* if memcmp(IntxCHR\000, pbuf, 8) | 231 | cERROR(1,("intx %s" ,pbuf)); |
232 | else if memcmp(IntxBLK\000, pbuf, 8) | 232 | if(memcmp("IntxBLK", pbuf, 8) == 0) { |
233 | else if memcmp(IntxLNK\001, pbuf, 8) */ | 233 | cFYI(1,("Block device")); |
234 | inode->i_mode = S_IFBLK; | ||
235 | } else if(memcmp("IntxCHR", pbuf, 8) == 0) { | ||
236 | cFYI(1,("Char device")); | ||
237 | inode->i_mode = S_IFCHR; | ||
238 | } else if(memcmp("IntxLNK", pbuf, 7) == 0) { | ||
239 | cFYI(1,("Symlink")); | ||
240 | inode->i_mode = S_IFLNK; | ||
241 | } else | ||
242 | inode->i_mode = S_IFREG; /* then it is a file */ | ||
243 | rc = -EOPNOTSUPP; /* or some unknown SFU type */ | ||
244 | |||
234 | } | 245 | } |
235 | 246 | ||
236 | CIFSSMBClose(xid, pTcon, netfid); | 247 | CIFSSMBClose(xid, pTcon, netfid); |
@@ -244,6 +255,32 @@ static int decode_sfu_inode(struct inode * inode, __u64 size, | |||
244 | 255 | ||
245 | } | 256 | } |
246 | 257 | ||
258 | #define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */ | ||
259 | |||
260 | static int get_sfu_uid_mode(struct inode * inode, | ||
261 | const unsigned char *path, | ||
262 | struct cifs_sb_info *cifs_sb, int xid) | ||
263 | { | ||
264 | ssize_t rc; | ||
265 | char ea_value[4]; | ||
266 | __u32 mode; | ||
267 | |||
268 | rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS", | ||
269 | ea_value, 4 /* size of buf */, cifs_sb->local_nls, | ||
270 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
271 | if(rc < 0) | ||
272 | return (int)rc; | ||
273 | else if (rc > 3) { | ||
274 | mode = le32_to_cpu(*((__le32 *)ea_value)); | ||
275 | inode->i_mode = (mode & SFBITS_MASK) | inode->i_mode; | ||
276 | cFYI(1,("special mode bits 0%o", mode)); | ||
277 | return 0; | ||
278 | } else { | ||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | } | ||
283 | |||
247 | int cifs_get_inode_info(struct inode **pinode, | 284 | int cifs_get_inode_info(struct inode **pinode, |
248 | const unsigned char *search_path, FILE_ALL_INFO *pfindData, | 285 | const unsigned char *search_path, FILE_ALL_INFO *pfindData, |
249 | struct super_block *sb, int xid) | 286 | struct super_block *sb, int xid) |
@@ -427,7 +464,10 @@ int cifs_get_inode_info(struct inode **pinode, | |||
427 | 464 | ||
428 | /* BB fill in uid and gid here? with help from winbind? | 465 | /* BB fill in uid and gid here? with help from winbind? |
429 | or retrieve from NTFS stream extended attribute */ | 466 | or retrieve from NTFS stream extended attribute */ |
430 | if (atomic_read(&cifsInfo->inUse) == 0) { | 467 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { |
468 | /* fill in uid, gid, mode from server ACL */ | ||
469 | get_sfu_uid_mode(inode, search_path, cifs_sb, xid); | ||
470 | } else if (atomic_read(&cifsInfo->inUse) == 0) { | ||
431 | inode->i_uid = cifs_sb->mnt_uid; | 471 | inode->i_uid = cifs_sb->mnt_uid; |
432 | inode->i_gid = cifs_sb->mnt_gid; | 472 | inode->i_gid = cifs_sb->mnt_gid; |
433 | /* set so we do not keep refreshing these fields with | 473 | /* set so we do not keep refreshing these fields with |