diff options
Diffstat (limited to 'fs/cifs/dir.c')
-rw-r--r-- | fs/cifs/dir.c | 184 |
1 files changed, 94 insertions, 90 deletions
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index e5210519ac4b..8e86aaceb68a 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * fs/cifs/dir.c | 2 | * fs/cifs/dir.c |
3 | * | 3 | * |
4 | * vfs operations that deal with dentries | 4 | * vfs operations that deal with dentries |
5 | * | 5 | * |
6 | * Copyright (C) International Business Machines Corp., 2002,2005 | 6 | * Copyright (C) International Business Machines Corp., 2002,2005 |
7 | * Author(s): Steve French (sfrench@us.ibm.com) | 7 | * Author(s): Steve French (sfrench@us.ibm.com) |
8 | * | 8 | * |
@@ -34,11 +34,12 @@ | |||
34 | static void | 34 | static void |
35 | renew_parental_timestamps(struct dentry *direntry) | 35 | renew_parental_timestamps(struct dentry *direntry) |
36 | { | 36 | { |
37 | /* BB check if there is a way to get the kernel to do this or if we really need this */ | 37 | /* BB check if there is a way to get the kernel to do this or if we |
38 | really need this */ | ||
38 | do { | 39 | do { |
39 | direntry->d_time = jiffies; | 40 | direntry->d_time = jiffies; |
40 | direntry = direntry->d_parent; | 41 | direntry = direntry->d_parent; |
41 | } while (!IS_ROOT(direntry)); | 42 | } while (!IS_ROOT(direntry)); |
42 | } | 43 | } |
43 | 44 | ||
44 | /* Note: caller must free return buffer */ | 45 | /* Note: caller must free return buffer */ |
@@ -51,7 +52,7 @@ build_path_from_dentry(struct dentry *direntry) | |||
51 | char *full_path; | 52 | char *full_path; |
52 | char dirsep; | 53 | char dirsep; |
53 | 54 | ||
54 | if(direntry == NULL) | 55 | if (direntry == NULL) |
55 | return NULL; /* not much we can do if dentry is freed and | 56 | return NULL; /* not much we can do if dentry is freed and |
56 | we need to reopen the file after it was closed implicitly | 57 | we need to reopen the file after it was closed implicitly |
57 | when the server crashed */ | 58 | when the server crashed */ |
@@ -59,18 +60,18 @@ build_path_from_dentry(struct dentry *direntry) | |||
59 | dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb)); | 60 | dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb)); |
60 | pplen = CIFS_SB(direntry->d_sb)->prepathlen; | 61 | pplen = CIFS_SB(direntry->d_sb)->prepathlen; |
61 | cifs_bp_rename_retry: | 62 | cifs_bp_rename_retry: |
62 | namelen = pplen; | 63 | namelen = pplen; |
63 | for (temp = direntry; !IS_ROOT(temp);) { | 64 | for (temp = direntry; !IS_ROOT(temp);) { |
64 | namelen += (1 + temp->d_name.len); | 65 | namelen += (1 + temp->d_name.len); |
65 | temp = temp->d_parent; | 66 | temp = temp->d_parent; |
66 | if(temp == NULL) { | 67 | if (temp == NULL) { |
67 | cERROR(1,("corrupt dentry")); | 68 | cERROR(1, ("corrupt dentry")); |
68 | return NULL; | 69 | return NULL; |
69 | } | 70 | } |
70 | } | 71 | } |
71 | 72 | ||
72 | full_path = kmalloc(namelen+1, GFP_KERNEL); | 73 | full_path = kmalloc(namelen+1, GFP_KERNEL); |
73 | if(full_path == NULL) | 74 | if (full_path == NULL) |
74 | return full_path; | 75 | return full_path; |
75 | full_path[namelen] = 0; /* trailing null */ | 76 | full_path[namelen] = 0; /* trailing null */ |
76 | for (temp = direntry; !IS_ROOT(temp);) { | 77 | for (temp = direntry; !IS_ROOT(temp);) { |
@@ -84,8 +85,8 @@ cifs_bp_rename_retry: | |||
84 | cFYI(0, ("name: %s", full_path + namelen)); | 85 | cFYI(0, ("name: %s", full_path + namelen)); |
85 | } | 86 | } |
86 | temp = temp->d_parent; | 87 | temp = temp->d_parent; |
87 | if(temp == NULL) { | 88 | if (temp == NULL) { |
88 | cERROR(1,("corrupt dentry")); | 89 | cERROR(1, ("corrupt dentry")); |
89 | kfree(full_path); | 90 | kfree(full_path); |
90 | return NULL; | 91 | return NULL; |
91 | } | 92 | } |
@@ -94,7 +95,7 @@ cifs_bp_rename_retry: | |||
94 | cERROR(1, | 95 | cERROR(1, |
95 | ("did not end path lookup where expected namelen is %d", | 96 | ("did not end path lookup where expected namelen is %d", |
96 | namelen)); | 97 | namelen)); |
97 | /* presumably this is only possible if racing with a rename | 98 | /* presumably this is only possible if racing with a rename |
98 | of one of the parent directories (we can not lock the dentries | 99 | of one of the parent directories (we can not lock the dentries |
99 | above us to prevent this, but retrying should be harmless) */ | 100 | above us to prevent this, but retrying should be harmless) */ |
100 | kfree(full_path); | 101 | kfree(full_path); |
@@ -106,7 +107,7 @@ cifs_bp_rename_retry: | |||
106 | since the '\' is a valid posix character so we can not switch | 107 | since the '\' is a valid posix character so we can not switch |
107 | those safely to '/' if any are found in the middle of the prepath */ | 108 | those safely to '/' if any are found in the middle of the prepath */ |
108 | /* BB test paths to Windows with '/' in the midst of prepath */ | 109 | /* BB test paths to Windows with '/' in the midst of prepath */ |
109 | strncpy(full_path,CIFS_SB(direntry->d_sb)->prepath,pplen); | 110 | strncpy(full_path, CIFS_SB(direntry->d_sb)->prepath, pplen); |
110 | return full_path; | 111 | return full_path; |
111 | } | 112 | } |
112 | 113 | ||
@@ -147,12 +148,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
147 | pTcon = cifs_sb->tcon; | 148 | pTcon = cifs_sb->tcon; |
148 | 149 | ||
149 | full_path = build_path_from_dentry(direntry); | 150 | full_path = build_path_from_dentry(direntry); |
150 | if(full_path == NULL) { | 151 | if (full_path == NULL) { |
151 | FreeXid(xid); | 152 | FreeXid(xid); |
152 | return -ENOMEM; | 153 | return -ENOMEM; |
153 | } | 154 | } |
154 | 155 | ||
155 | if(nd && (nd->flags & LOOKUP_OPEN)) { | 156 | if (nd && (nd->flags & LOOKUP_OPEN)) { |
156 | int oflags = nd->intent.open.flags; | 157 | int oflags = nd->intent.open.flags; |
157 | 158 | ||
158 | desiredAccess = 0; | 159 | desiredAccess = 0; |
@@ -164,28 +165,29 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
164 | write_only = TRUE; | 165 | write_only = TRUE; |
165 | } | 166 | } |
166 | 167 | ||
167 | if((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) | 168 | if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) |
168 | disposition = FILE_CREATE; | 169 | disposition = FILE_CREATE; |
169 | else if((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC)) | 170 | else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC)) |
170 | disposition = FILE_OVERWRITE_IF; | 171 | disposition = FILE_OVERWRITE_IF; |
171 | else if((oflags & O_CREAT) == O_CREAT) | 172 | else if ((oflags & O_CREAT) == O_CREAT) |
172 | disposition = FILE_OPEN_IF; | 173 | disposition = FILE_OPEN_IF; |
173 | else { | 174 | else { |
174 | cFYI(1,("Create flag not set in create function")); | 175 | cFYI(1, ("Create flag not set in create function")); |
175 | } | 176 | } |
176 | } | 177 | } |
177 | 178 | ||
178 | /* BB add processing to set equivalent of mode - e.g. via CreateX with ACLs */ | 179 | /* BB add processing to set equivalent of mode - e.g. via CreateX with |
180 | ACLs */ | ||
179 | if (oplockEnabled) | 181 | if (oplockEnabled) |
180 | oplock = REQ_OPLOCK; | 182 | oplock = REQ_OPLOCK; |
181 | 183 | ||
182 | buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL); | 184 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); |
183 | if(buf == NULL) { | 185 | if (buf == NULL) { |
184 | kfree(full_path); | 186 | kfree(full_path); |
185 | FreeXid(xid); | 187 | FreeXid(xid); |
186 | return -ENOMEM; | 188 | return -ENOMEM; |
187 | } | 189 | } |
188 | if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS) | 190 | if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS) |
189 | rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, | 191 | rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, |
190 | desiredAccess, CREATE_NOT_DIR, | 192 | desiredAccess, CREATE_NOT_DIR, |
191 | &fileHandle, &oplock, buf, cifs_sb->local_nls, | 193 | &fileHandle, &oplock, buf, cifs_sb->local_nls, |
@@ -193,27 +195,28 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
193 | else | 195 | else |
194 | rc = -EIO; /* no NT SMB support fall into legacy open below */ | 196 | rc = -EIO; /* no NT SMB support fall into legacy open below */ |
195 | 197 | ||
196 | if(rc == -EIO) { | 198 | if (rc == -EIO) { |
197 | /* old server, retry the open legacy style */ | 199 | /* old server, retry the open legacy style */ |
198 | rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, | 200 | rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, |
199 | desiredAccess, CREATE_NOT_DIR, | 201 | desiredAccess, CREATE_NOT_DIR, |
200 | &fileHandle, &oplock, buf, cifs_sb->local_nls, | 202 | &fileHandle, &oplock, buf, cifs_sb->local_nls, |
201 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 203 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
202 | } | 204 | } |
203 | if (rc) { | 205 | if (rc) { |
204 | cFYI(1, ("cifs_create returned 0x%x", rc)); | 206 | cFYI(1, ("cifs_create returned 0x%x", rc)); |
205 | } else { | 207 | } else { |
206 | /* If Open reported that we actually created a file | 208 | /* If Open reported that we actually created a file |
207 | then we now have to set the mode if possible */ | 209 | then we now have to set the mode if possible */ |
208 | if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) && | 210 | if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) && |
209 | (oplock & CIFS_CREATE_ACTION)) | 211 | (oplock & CIFS_CREATE_ACTION)) { |
210 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { | 212 | mode &= ~current->fs->umask; |
213 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { | ||
211 | CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, | 214 | CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, |
212 | (__u64)current->fsuid, | 215 | (__u64)current->fsuid, |
213 | (__u64)current->fsgid, | 216 | (__u64)current->fsgid, |
214 | 0 /* dev */, | 217 | 0 /* dev */, |
215 | cifs_sb->local_nls, | 218 | cifs_sb->local_nls, |
216 | cifs_sb->mnt_cifs_flags & | 219 | cifs_sb->mnt_cifs_flags & |
217 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 220 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
218 | } else { | 221 | } else { |
219 | CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, | 222 | CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, |
@@ -221,26 +224,28 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
221 | (__u64)-1, | 224 | (__u64)-1, |
222 | 0 /* dev */, | 225 | 0 /* dev */, |
223 | cifs_sb->local_nls, | 226 | cifs_sb->local_nls, |
224 | cifs_sb->mnt_cifs_flags & | 227 | cifs_sb->mnt_cifs_flags & |
225 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 228 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
226 | } | 229 | } |
227 | else { | 230 | } else { |
228 | /* BB implement mode setting via Windows security descriptors */ | 231 | /* BB implement mode setting via Windows security |
229 | /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/ | 232 | descriptors e.g. */ |
230 | /* could set r/o dos attribute if mode & 0222 == 0 */ | 233 | /* CIFSSMBWinSetPerms(xid,pTcon,path,mode,-1,-1,nls);*/ |
234 | |||
235 | /* Could set r/o dos attribute if mode & 0222 == 0 */ | ||
231 | } | 236 | } |
232 | 237 | ||
233 | /* BB server might mask mode so we have to query for Unix case*/ | 238 | /* BB server might mask mode so we have to query for Unix case*/ |
234 | if (pTcon->ses->capabilities & CAP_UNIX) | 239 | if (pTcon->ses->capabilities & CAP_UNIX) |
235 | rc = cifs_get_inode_info_unix(&newinode, full_path, | 240 | rc = cifs_get_inode_info_unix(&newinode, full_path, |
236 | inode->i_sb,xid); | 241 | inode->i_sb, xid); |
237 | else { | 242 | else { |
238 | rc = cifs_get_inode_info(&newinode, full_path, | 243 | rc = cifs_get_inode_info(&newinode, full_path, |
239 | buf, inode->i_sb,xid); | 244 | buf, inode->i_sb, xid); |
240 | if(newinode) { | 245 | if (newinode) { |
241 | newinode->i_mode = mode; | 246 | newinode->i_mode = mode; |
242 | if((oplock & CIFS_CREATE_ACTION) && | 247 | if ((oplock & CIFS_CREATE_ACTION) && |
243 | (cifs_sb->mnt_cifs_flags & | 248 | (cifs_sb->mnt_cifs_flags & |
244 | CIFS_MOUNT_SET_UID)) { | 249 | CIFS_MOUNT_SET_UID)) { |
245 | newinode->i_uid = current->fsuid; | 250 | newinode->i_uid = current->fsuid; |
246 | newinode->i_gid = current->fsgid; | 251 | newinode->i_gid = current->fsgid; |
@@ -259,14 +264,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
259 | direntry->d_op = &cifs_dentry_ops; | 264 | direntry->d_op = &cifs_dentry_ops; |
260 | d_instantiate(direntry, newinode); | 265 | d_instantiate(direntry, newinode); |
261 | } | 266 | } |
262 | if((nd->flags & LOOKUP_OPEN) == FALSE) { | 267 | if ((nd->flags & LOOKUP_OPEN) == FALSE) { |
263 | /* mknod case - do not leave file open */ | 268 | /* mknod case - do not leave file open */ |
264 | CIFSSMBClose(xid, pTcon, fileHandle); | 269 | CIFSSMBClose(xid, pTcon, fileHandle); |
265 | } else if(newinode) { | 270 | } else if (newinode) { |
266 | pCifsFile = | 271 | pCifsFile = |
267 | kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); | 272 | kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); |
268 | 273 | ||
269 | if(pCifsFile == NULL) | 274 | if (pCifsFile == NULL) |
270 | goto cifs_create_out; | 275 | goto cifs_create_out; |
271 | pCifsFile->netfid = fileHandle; | 276 | pCifsFile->netfid = fileHandle; |
272 | pCifsFile->pid = current->tgid; | 277 | pCifsFile->pid = current->tgid; |
@@ -276,33 +281,33 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
276 | init_MUTEX(&pCifsFile->fh_sem); | 281 | init_MUTEX(&pCifsFile->fh_sem); |
277 | mutex_init(&pCifsFile->lock_mutex); | 282 | mutex_init(&pCifsFile->lock_mutex); |
278 | INIT_LIST_HEAD(&pCifsFile->llist); | 283 | INIT_LIST_HEAD(&pCifsFile->llist); |
279 | atomic_set(&pCifsFile->wrtPending,0); | 284 | atomic_set(&pCifsFile->wrtPending, 0); |
280 | 285 | ||
281 | /* set the following in open now | 286 | /* set the following in open now |
282 | pCifsFile->pfile = file; */ | 287 | pCifsFile->pfile = file; */ |
283 | write_lock(&GlobalSMBSeslock); | 288 | write_lock(&GlobalSMBSeslock); |
284 | list_add(&pCifsFile->tlist,&pTcon->openFileList); | 289 | list_add(&pCifsFile->tlist, &pTcon->openFileList); |
285 | pCifsInode = CIFS_I(newinode); | 290 | pCifsInode = CIFS_I(newinode); |
286 | if(pCifsInode) { | 291 | if (pCifsInode) { |
287 | /* if readable file instance put first in list*/ | 292 | /* if readable file instance put first in list*/ |
288 | if (write_only == TRUE) { | 293 | if (write_only == TRUE) { |
289 | list_add_tail(&pCifsFile->flist, | 294 | list_add_tail(&pCifsFile->flist, |
290 | &pCifsInode->openFileList); | 295 | &pCifsInode->openFileList); |
291 | } else { | 296 | } else { |
292 | list_add(&pCifsFile->flist, | 297 | list_add(&pCifsFile->flist, |
293 | &pCifsInode->openFileList); | 298 | &pCifsInode->openFileList); |
294 | } | 299 | } |
295 | if((oplock & 0xF) == OPLOCK_EXCLUSIVE) { | 300 | if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { |
296 | pCifsInode->clientCanCacheAll = TRUE; | 301 | pCifsInode->clientCanCacheAll = TRUE; |
297 | pCifsInode->clientCanCacheRead = TRUE; | 302 | pCifsInode->clientCanCacheRead = TRUE; |
298 | cFYI(1,("Exclusive Oplock for inode %p", | 303 | cFYI(1, ("Exclusive Oplock inode %p", |
299 | newinode)); | 304 | newinode)); |
300 | } else if((oplock & 0xF) == OPLOCK_READ) | 305 | } else if ((oplock & 0xF) == OPLOCK_READ) |
301 | pCifsInode->clientCanCacheRead = TRUE; | 306 | pCifsInode->clientCanCacheRead = TRUE; |
302 | } | 307 | } |
303 | write_unlock(&GlobalSMBSeslock); | 308 | write_unlock(&GlobalSMBSeslock); |
304 | } | 309 | } |
305 | } | 310 | } |
306 | cifs_create_out: | 311 | cifs_create_out: |
307 | kfree(buf); | 312 | kfree(buf); |
308 | kfree(full_path); | 313 | kfree(full_path); |
@@ -310,8 +315,8 @@ cifs_create_out: | |||
310 | return rc; | 315 | return rc; |
311 | } | 316 | } |
312 | 317 | ||
313 | int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, | 318 | int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, |
314 | dev_t device_number) | 319 | dev_t device_number) |
315 | { | 320 | { |
316 | int rc = -EPERM; | 321 | int rc = -EPERM; |
317 | int xid; | 322 | int xid; |
@@ -329,43 +334,45 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, | |||
329 | pTcon = cifs_sb->tcon; | 334 | pTcon = cifs_sb->tcon; |
330 | 335 | ||
331 | full_path = build_path_from_dentry(direntry); | 336 | full_path = build_path_from_dentry(direntry); |
332 | if(full_path == NULL) | 337 | if (full_path == NULL) |
333 | rc = -ENOMEM; | 338 | rc = -ENOMEM; |
334 | else if (pTcon->ses->capabilities & CAP_UNIX) { | 339 | else if (pTcon->ses->capabilities & CAP_UNIX) { |
335 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { | 340 | mode &= ~current->fs->umask; |
341 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { | ||
336 | rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, | 342 | rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, |
337 | mode,(__u64)current->fsuid,(__u64)current->fsgid, | 343 | mode, (__u64)current->fsuid, |
344 | (__u64)current->fsgid, | ||
338 | device_number, cifs_sb->local_nls, | 345 | device_number, cifs_sb->local_nls, |
339 | cifs_sb->mnt_cifs_flags & | 346 | cifs_sb->mnt_cifs_flags & |
340 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 347 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
341 | } else { | 348 | } else { |
342 | rc = CIFSSMBUnixSetPerms(xid, pTcon, | 349 | rc = CIFSSMBUnixSetPerms(xid, pTcon, |
343 | full_path, mode, (__u64)-1, (__u64)-1, | 350 | full_path, mode, (__u64)-1, (__u64)-1, |
344 | device_number, cifs_sb->local_nls, | 351 | device_number, cifs_sb->local_nls, |
345 | cifs_sb->mnt_cifs_flags & | 352 | cifs_sb->mnt_cifs_flags & |
346 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 353 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
347 | } | 354 | } |
348 | 355 | ||
349 | if(!rc) { | 356 | if (!rc) { |
350 | rc = cifs_get_inode_info_unix(&newinode, full_path, | 357 | rc = cifs_get_inode_info_unix(&newinode, full_path, |
351 | inode->i_sb,xid); | 358 | inode->i_sb, xid); |
352 | if (pTcon->nocase) | 359 | if (pTcon->nocase) |
353 | direntry->d_op = &cifs_ci_dentry_ops; | 360 | direntry->d_op = &cifs_ci_dentry_ops; |
354 | else | 361 | else |
355 | direntry->d_op = &cifs_dentry_ops; | 362 | direntry->d_op = &cifs_dentry_ops; |
356 | if(rc == 0) | 363 | if (rc == 0) |
357 | d_instantiate(direntry, newinode); | 364 | d_instantiate(direntry, newinode); |
358 | } | 365 | } |
359 | } else { | 366 | } else { |
360 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { | 367 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { |
361 | int oplock = 0; | 368 | int oplock = 0; |
362 | u16 fileHandle; | 369 | u16 fileHandle; |
363 | FILE_ALL_INFO * buf; | 370 | FILE_ALL_INFO * buf; |
364 | 371 | ||
365 | cFYI(1,("sfu compat create special file")); | 372 | cFYI(1, ("sfu compat create special file")); |
366 | 373 | ||
367 | buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL); | 374 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); |
368 | if(buf == NULL) { | 375 | if (buf == NULL) { |
369 | kfree(full_path); | 376 | kfree(full_path); |
370 | FreeXid(xid); | 377 | FreeXid(xid); |
371 | return -ENOMEM; | 378 | return -ENOMEM; |
@@ -373,39 +380,38 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, | |||
373 | 380 | ||
374 | rc = CIFSSMBOpen(xid, pTcon, full_path, | 381 | rc = CIFSSMBOpen(xid, pTcon, full_path, |
375 | FILE_CREATE, /* fail if exists */ | 382 | FILE_CREATE, /* fail if exists */ |
376 | GENERIC_WRITE /* BB would | 383 | GENERIC_WRITE /* BB would |
377 | WRITE_OWNER | WRITE_DAC be better? */, | 384 | WRITE_OWNER | WRITE_DAC be better? */, |
378 | /* Create a file and set the | 385 | /* Create a file and set the |
379 | file attribute to SYSTEM */ | 386 | file attribute to SYSTEM */ |
380 | CREATE_NOT_DIR | CREATE_OPTION_SPECIAL, | 387 | CREATE_NOT_DIR | CREATE_OPTION_SPECIAL, |
381 | &fileHandle, &oplock, buf, | 388 | &fileHandle, &oplock, buf, |
382 | cifs_sb->local_nls, | 389 | cifs_sb->local_nls, |
383 | cifs_sb->mnt_cifs_flags & | 390 | cifs_sb->mnt_cifs_flags & |
384 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 391 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
385 | 392 | ||
386 | /* BB FIXME - add handling for backlevel servers | 393 | /* BB FIXME - add handling for backlevel servers |
387 | which need legacy open and check for all | 394 | which need legacy open and check for all |
388 | calls to SMBOpen for fallback to | 395 | calls to SMBOpen for fallback to SMBLeagcyOpen */ |
389 | SMBLeagcyOpen */ | 396 | if (!rc) { |
390 | if(!rc) { | ||
391 | /* BB Do not bother to decode buf since no | 397 | /* BB Do not bother to decode buf since no |
392 | local inode yet to put timestamps in, | 398 | local inode yet to put timestamps in, |
393 | but we can reuse it safely */ | 399 | but we can reuse it safely */ |
394 | int bytes_written; | 400 | int bytes_written; |
395 | struct win_dev *pdev; | 401 | struct win_dev *pdev; |
396 | pdev = (struct win_dev *)buf; | 402 | pdev = (struct win_dev *)buf; |
397 | if(S_ISCHR(mode)) { | 403 | if (S_ISCHR(mode)) { |
398 | memcpy(pdev->type, "IntxCHR", 8); | 404 | memcpy(pdev->type, "IntxCHR", 8); |
399 | pdev->major = | 405 | pdev->major = |
400 | cpu_to_le64(MAJOR(device_number)); | 406 | cpu_to_le64(MAJOR(device_number)); |
401 | pdev->minor = | 407 | pdev->minor = |
402 | cpu_to_le64(MINOR(device_number)); | 408 | cpu_to_le64(MINOR(device_number)); |
403 | rc = CIFSSMBWrite(xid, pTcon, | 409 | rc = CIFSSMBWrite(xid, pTcon, |
404 | fileHandle, | 410 | fileHandle, |
405 | sizeof(struct win_dev), | 411 | sizeof(struct win_dev), |
406 | 0, &bytes_written, (char *)pdev, | 412 | 0, &bytes_written, (char *)pdev, |
407 | NULL, 0); | 413 | NULL, 0); |
408 | } else if(S_ISBLK(mode)) { | 414 | } else if (S_ISBLK(mode)) { |
409 | memcpy(pdev->type, "IntxBLK", 8); | 415 | memcpy(pdev->type, "IntxBLK", 8); |
410 | pdev->major = | 416 | pdev->major = |
411 | cpu_to_le64(MAJOR(device_number)); | 417 | cpu_to_le64(MAJOR(device_number)); |
@@ -432,7 +438,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, | |||
432 | 438 | ||
433 | 439 | ||
434 | struct dentry * | 440 | struct dentry * |
435 | cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct nameidata *nd) | 441 | cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, |
442 | struct nameidata *nd) | ||
436 | { | 443 | { |
437 | int xid; | 444 | int xid; |
438 | int rc = 0; /* to get around spurious gcc warning, set to zero here */ | 445 | int rc = 0; /* to get around spurious gcc warning, set to zero here */ |
@@ -447,8 +454,6 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name | |||
447 | (" parent inode = 0x%p name is: %s and dentry = 0x%p", | 454 | (" parent inode = 0x%p name is: %s and dentry = 0x%p", |
448 | parent_dir_inode, direntry->d_name.name, direntry)); | 455 | parent_dir_inode, direntry->d_name.name, direntry)); |
449 | 456 | ||
450 | /* BB Add check of incoming data - e.g. frame not longer than maximum SMB - let server check the namelen BB */ | ||
451 | |||
452 | /* check whether path exists */ | 457 | /* check whether path exists */ |
453 | 458 | ||
454 | cifs_sb = CIFS_SB(parent_dir_inode->i_sb); | 459 | cifs_sb = CIFS_SB(parent_dir_inode->i_sb); |
@@ -472,7 +477,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name | |||
472 | deadlock in the cases (beginning of sys_rename itself) | 477 | deadlock in the cases (beginning of sys_rename itself) |
473 | in which we already have the sb rename sem */ | 478 | in which we already have the sb rename sem */ |
474 | full_path = build_path_from_dentry(direntry); | 479 | full_path = build_path_from_dentry(direntry); |
475 | if(full_path == NULL) { | 480 | if (full_path == NULL) { |
476 | FreeXid(xid); | 481 | FreeXid(xid); |
477 | return ERR_PTR(-ENOMEM); | 482 | return ERR_PTR(-ENOMEM); |
478 | } | 483 | } |
@@ -487,10 +492,10 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name | |||
487 | 492 | ||
488 | if (pTcon->ses->capabilities & CAP_UNIX) | 493 | if (pTcon->ses->capabilities & CAP_UNIX) |
489 | rc = cifs_get_inode_info_unix(&newInode, full_path, | 494 | rc = cifs_get_inode_info_unix(&newInode, full_path, |
490 | parent_dir_inode->i_sb,xid); | 495 | parent_dir_inode->i_sb, xid); |
491 | else | 496 | else |
492 | rc = cifs_get_inode_info(&newInode, full_path, NULL, | 497 | rc = cifs_get_inode_info(&newInode, full_path, NULL, |
493 | parent_dir_inode->i_sb,xid); | 498 | parent_dir_inode->i_sb, xid); |
494 | 499 | ||
495 | if ((rc == 0) && (newInode != NULL)) { | 500 | if ((rc == 0) && (newInode != NULL)) { |
496 | if (pTcon->nocase) | 501 | if (pTcon->nocase) |
@@ -499,7 +504,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name | |||
499 | direntry->d_op = &cifs_dentry_ops; | 504 | direntry->d_op = &cifs_dentry_ops; |
500 | d_add(direntry, newInode); | 505 | d_add(direntry, newInode); |
501 | 506 | ||
502 | /* since paths are not looked up by component - the parent | 507 | /* since paths are not looked up by component - the parent |
503 | directories are presumed to be good here */ | 508 | directories are presumed to be good here */ |
504 | renew_parental_timestamps(direntry); | 509 | renew_parental_timestamps(direntry); |
505 | 510 | ||
@@ -511,13 +516,13 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name | |||
511 | else | 516 | else |
512 | direntry->d_op = &cifs_dentry_ops; | 517 | direntry->d_op = &cifs_dentry_ops; |
513 | d_add(direntry, NULL); | 518 | d_add(direntry, NULL); |
514 | /* if it was once a directory (but how can we tell?) we could do | 519 | /* if it was once a directory (but how can we tell?) we could do |
515 | shrink_dcache_parent(direntry); */ | 520 | shrink_dcache_parent(direntry); */ |
516 | } else { | 521 | } else { |
517 | cERROR(1,("Error 0x%x on cifs_get_inode_info in lookup of %s", | 522 | cERROR(1, ("Error 0x%x on cifs_get_inode_info in lookup of %s", |
518 | rc,full_path)); | 523 | rc, full_path)); |
519 | /* BB special case check for Access Denied - watch security | 524 | /* BB special case check for Access Denied - watch security |
520 | exposure of returning dir info implicitly via different rc | 525 | exposure of returning dir info implicitly via different rc |
521 | if file exists or not but no access BB */ | 526 | if file exists or not but no access BB */ |
522 | } | 527 | } |
523 | 528 | ||
@@ -538,11 +543,11 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) | |||
538 | } else { | 543 | } else { |
539 | cFYI(1, ("neg dentry 0x%p name = %s", | 544 | cFYI(1, ("neg dentry 0x%p name = %s", |
540 | direntry, direntry->d_name.name)); | 545 | direntry, direntry->d_name.name)); |
541 | if(time_after(jiffies, direntry->d_time + HZ) || | 546 | if (time_after(jiffies, direntry->d_time + HZ) || |
542 | !lookupCacheEnabled) { | 547 | !lookupCacheEnabled) { |
543 | d_drop(direntry); | 548 | d_drop(direntry); |
544 | isValid = 0; | 549 | isValid = 0; |
545 | } | 550 | } |
546 | } | 551 | } |
547 | 552 | ||
548 | return isValid; | 553 | return isValid; |
@@ -559,8 +564,7 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) | |||
559 | 564 | ||
560 | struct dentry_operations cifs_dentry_ops = { | 565 | struct dentry_operations cifs_dentry_ops = { |
561 | .d_revalidate = cifs_d_revalidate, | 566 | .d_revalidate = cifs_d_revalidate, |
562 | /* d_delete: cifs_d_delete, *//* not needed except for debugging */ | 567 | /* d_delete: cifs_d_delete, */ /* not needed except for debugging */ |
563 | /* no need for d_hash, d_compare, d_release, d_iput ... yet. BB confirm this BB */ | ||
564 | }; | 568 | }; |
565 | 569 | ||
566 | static int cifs_ci_hash(struct dentry *dentry, struct qstr *q) | 570 | static int cifs_ci_hash(struct dentry *dentry, struct qstr *q) |