aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/dir.c')
-rw-r--r--fs/cifs/dir.c54
1 files changed, 45 insertions, 9 deletions
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 3f3538d4a1fa..c619d45060ce 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -43,7 +43,7 @@ renew_parental_timestamps(struct dentry *direntry)
43 43
44/* Note: caller must free return buffer */ 44/* Note: caller must free return buffer */
45char * 45char *
46build_path_from_dentry(struct dentry *direntry) 46build_path_from_dentry(struct dentry *direntry, const struct cifs_sb_info *cifs_sb)
47{ 47{
48 struct dentry *temp; 48 struct dentry *temp;
49 int namelen = 0; 49 int namelen = 0;
@@ -74,7 +74,7 @@ cifs_bp_rename_retry:
74 if (namelen < 0) { 74 if (namelen < 0) {
75 break; 75 break;
76 } else { 76 } else {
77 full_path[namelen] = '\\'; 77 full_path[namelen] = CIFS_DIR_SEP(cifs_sb);
78 strncpy(full_path + namelen + 1, temp->d_name.name, 78 strncpy(full_path + namelen + 1, temp->d_name.name,
79 temp->d_name.len); 79 temp->d_name.len);
80 cFYI(0, (" name: %s ", full_path + namelen)); 80 cFYI(0, (" name: %s ", full_path + namelen));
@@ -138,7 +138,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
138 pTcon = cifs_sb->tcon; 138 pTcon = cifs_sb->tcon;
139 139
140 down(&direntry->d_sb->s_vfs_rename_sem); 140 down(&direntry->d_sb->s_vfs_rename_sem);
141 full_path = build_path_from_dentry(direntry); 141 full_path = build_path_from_dentry(direntry, cifs_sb);
142 up(&direntry->d_sb->s_vfs_rename_sem); 142 up(&direntry->d_sb->s_vfs_rename_sem);
143 if(full_path == NULL) { 143 if(full_path == NULL) {
144 FreeXid(xid); 144 FreeXid(xid);
@@ -209,7 +209,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
209 CIFS_MOUNT_MAP_SPECIAL_CHR); 209 CIFS_MOUNT_MAP_SPECIAL_CHR);
210 } 210 }
211 else { 211 else {
212 /* BB implement via Windows security descriptors */ 212 /* BB implement mode setting via Windows security descriptors */
213 /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/ 213 /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
214 /* could set r/o dos attribute if mode & 0222 == 0 */ 214 /* could set r/o dos attribute if mode & 0222 == 0 */
215 } 215 }
@@ -226,7 +226,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
226 } 226 }
227 227
228 if (rc != 0) { 228 if (rc != 0) {
229 cFYI(1,("Create worked but get_inode_info failed with rc = %d", 229 cFYI(1,
230 ("Create worked but get_inode_info failed rc = %d",
230 rc)); 231 rc));
231 } else { 232 } else {
232 direntry->d_op = &cifs_dentry_ops; 233 direntry->d_op = &cifs_dentry_ops;
@@ -299,12 +300,11 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev
299 pTcon = cifs_sb->tcon; 300 pTcon = cifs_sb->tcon;
300 301
301 down(&direntry->d_sb->s_vfs_rename_sem); 302 down(&direntry->d_sb->s_vfs_rename_sem);
302 full_path = build_path_from_dentry(direntry); 303 full_path = build_path_from_dentry(direntry, cifs_sb);
303 up(&direntry->d_sb->s_vfs_rename_sem); 304 up(&direntry->d_sb->s_vfs_rename_sem);
304 if(full_path == NULL) 305 if(full_path == NULL)
305 rc = -ENOMEM; 306 rc = -ENOMEM;
306 307 else if (pTcon->ses->capabilities & CAP_UNIX) {
307 if (full_path && (pTcon->ses->capabilities & CAP_UNIX)) {
308 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 308 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
309 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, 309 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
310 mode,(__u64)current->euid,(__u64)current->egid, 310 mode,(__u64)current->euid,(__u64)current->egid,
@@ -326,6 +326,42 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev
326 if(rc == 0) 326 if(rc == 0)
327 d_instantiate(direntry, newinode); 327 d_instantiate(direntry, newinode);
328 } 328 }
329 } else {
330 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
331 int oplock = 0;
332 u16 fileHandle;
333 FILE_ALL_INFO * buf;
334
335 cFYI(1,("sfu compat create special file"));
336
337 buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
338 if(buf == NULL) {
339 kfree(full_path);
340 FreeXid(xid);
341 return -ENOMEM;
342 }
343
344 rc = CIFSSMBOpen(xid, pTcon, full_path,
345 FILE_CREATE, /* fail if exists */
346 GENERIC_WRITE /* BB would
347 WRITE_OWNER | WRITE_DAC be better? */,
348 /* Create a file and set the
349 file attribute to SYSTEM */
350 CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
351 &fileHandle, &oplock, buf,
352 cifs_sb->local_nls,
353 cifs_sb->mnt_cifs_flags &
354 CIFS_MOUNT_MAP_SPECIAL_CHR);
355
356 if(!rc) {
357 /* BB Do not bother to decode buf since no
358 local inode yet to put timestamps in */
359 CIFSSMBClose(xid, pTcon, fileHandle);
360 d_drop(direntry);
361 }
362 kfree(buf);
363 /* add code here to set EAs */
364 }
329 } 365 }
330 366
331 kfree(full_path); 367 kfree(full_path);
@@ -360,7 +396,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
360 /* can not grab the rename sem here since it would 396 /* can not grab the rename sem here since it would
361 deadlock in the cases (beginning of sys_rename itself) 397 deadlock in the cases (beginning of sys_rename itself)
362 in which we already have the sb rename sem */ 398 in which we already have the sb rename sem */
363 full_path = build_path_from_dentry(direntry); 399 full_path = build_path_from_dentry(direntry, cifs_sb);
364 if(full_path == NULL) { 400 if(full_path == NULL) {
365 FreeXid(xid); 401 FreeXid(xid);
366 return ERR_PTR(-ENOMEM); 402 return ERR_PTR(-ENOMEM);