diff options
Diffstat (limited to 'fs/cifs/dir.c')
| -rw-r--r-- | fs/cifs/dir.c | 157 |
1 files changed, 77 insertions, 80 deletions
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 578d88c5b46e..f9ed0751cc12 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
| @@ -305,8 +305,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
| 305 | full_path = build_path_from_dentry(direntry); | 305 | full_path = build_path_from_dentry(direntry); |
| 306 | if (full_path == NULL) { | 306 | if (full_path == NULL) { |
| 307 | rc = -ENOMEM; | 307 | rc = -ENOMEM; |
| 308 | FreeXid(xid); | 308 | goto cifs_create_out; |
| 309 | return rc; | ||
| 310 | } | 309 | } |
| 311 | 310 | ||
| 312 | if (oplockEnabled) | 311 | if (oplockEnabled) |
| @@ -365,9 +364,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
| 365 | 364 | ||
| 366 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); | 365 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); |
| 367 | if (buf == NULL) { | 366 | if (buf == NULL) { |
| 368 | kfree(full_path); | 367 | rc = -ENOMEM; |
| 369 | FreeXid(xid); | 368 | goto cifs_create_out; |
| 370 | return -ENOMEM; | ||
| 371 | } | 369 | } |
| 372 | 370 | ||
| 373 | /* | 371 | /* |
| @@ -496,6 +494,11 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, | |||
| 496 | struct cifsTconInfo *pTcon; | 494 | struct cifsTconInfo *pTcon; |
| 497 | char *full_path = NULL; | 495 | char *full_path = NULL; |
| 498 | struct inode *newinode = NULL; | 496 | struct inode *newinode = NULL; |
| 497 | int oplock = 0; | ||
| 498 | u16 fileHandle; | ||
| 499 | FILE_ALL_INFO *buf = NULL; | ||
| 500 | unsigned int bytes_written; | ||
| 501 | struct win_dev *pdev; | ||
| 499 | 502 | ||
| 500 | if (!old_valid_dev(device_number)) | 503 | if (!old_valid_dev(device_number)) |
| 501 | return -EINVAL; | 504 | return -EINVAL; |
| @@ -506,9 +509,12 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, | |||
| 506 | pTcon = cifs_sb->tcon; | 509 | pTcon = cifs_sb->tcon; |
| 507 | 510 | ||
| 508 | full_path = build_path_from_dentry(direntry); | 511 | full_path = build_path_from_dentry(direntry); |
| 509 | if (full_path == NULL) | 512 | if (full_path == NULL) { |
| 510 | rc = -ENOMEM; | 513 | rc = -ENOMEM; |
| 511 | else if (pTcon->unix_ext) { | 514 | goto mknod_out; |
| 515 | } | ||
| 516 | |||
| 517 | if (pTcon->unix_ext) { | ||
| 512 | struct cifs_unix_set_info_args args = { | 518 | struct cifs_unix_set_info_args args = { |
| 513 | .mode = mode & ~current_umask(), | 519 | .mode = mode & ~current_umask(), |
| 514 | .ctime = NO_CHANGE_64, | 520 | .ctime = NO_CHANGE_64, |
| @@ -527,87 +533,78 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, | |||
| 527 | cifs_sb->local_nls, | 533 | cifs_sb->local_nls, |
| 528 | cifs_sb->mnt_cifs_flags & | 534 | cifs_sb->mnt_cifs_flags & |
| 529 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 535 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 536 | if (rc) | ||
| 537 | goto mknod_out; | ||
| 530 | 538 | ||
| 531 | if (!rc) { | 539 | rc = cifs_get_inode_info_unix(&newinode, full_path, |
| 532 | rc = cifs_get_inode_info_unix(&newinode, full_path, | ||
| 533 | inode->i_sb, xid); | 540 | inode->i_sb, xid); |
| 534 | if (pTcon->nocase) | 541 | if (pTcon->nocase) |
| 535 | direntry->d_op = &cifs_ci_dentry_ops; | 542 | direntry->d_op = &cifs_ci_dentry_ops; |
| 536 | else | 543 | else |
| 537 | direntry->d_op = &cifs_dentry_ops; | 544 | direntry->d_op = &cifs_dentry_ops; |
| 538 | if (rc == 0) | ||
| 539 | d_instantiate(direntry, newinode); | ||
| 540 | } | ||
| 541 | } else { | ||
| 542 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { | ||
| 543 | int oplock = 0; | ||
| 544 | u16 fileHandle; | ||
| 545 | FILE_ALL_INFO *buf; | ||
| 546 | 545 | ||
| 547 | cFYI(1, "sfu compat create special file"); | 546 | if (rc == 0) |
| 547 | d_instantiate(direntry, newinode); | ||
| 548 | goto mknod_out; | ||
| 549 | } | ||
| 548 | 550 | ||
| 549 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); | 551 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) |
| 550 | if (buf == NULL) { | 552 | goto mknod_out; |
| 551 | kfree(full_path); | ||
| 552 | rc = -ENOMEM; | ||
| 553 | FreeXid(xid); | ||
| 554 | return rc; | ||
| 555 | } | ||
| 556 | 553 | ||
| 557 | rc = CIFSSMBOpen(xid, pTcon, full_path, | 554 | |
| 558 | FILE_CREATE, /* fail if exists */ | 555 | cFYI(1, "sfu compat create special file"); |
| 559 | GENERIC_WRITE /* BB would | 556 | |
| 560 | WRITE_OWNER | WRITE_DAC be better? */, | 557 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); |
| 561 | /* Create a file and set the | 558 | if (buf == NULL) { |
| 562 | file attribute to SYSTEM */ | 559 | kfree(full_path); |
| 563 | CREATE_NOT_DIR | CREATE_OPTION_SPECIAL, | 560 | rc = -ENOMEM; |
| 564 | &fileHandle, &oplock, buf, | 561 | FreeXid(xid); |
| 565 | cifs_sb->local_nls, | 562 | return rc; |
| 566 | cifs_sb->mnt_cifs_flags & | ||
| 567 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
| 568 | |||
| 569 | /* BB FIXME - add handling for backlevel servers | ||
| 570 | which need legacy open and check for all | ||
| 571 | calls to SMBOpen for fallback to SMBLeagcyOpen */ | ||
| 572 | if (!rc) { | ||
| 573 | /* BB Do not bother to decode buf since no | ||
| 574 | local inode yet to put timestamps in, | ||
| 575 | but we can reuse it safely */ | ||
| 576 | unsigned int bytes_written; | ||
| 577 | struct win_dev *pdev; | ||
| 578 | pdev = (struct win_dev *)buf; | ||
| 579 | if (S_ISCHR(mode)) { | ||
| 580 | memcpy(pdev->type, "IntxCHR", 8); | ||
| 581 | pdev->major = | ||
| 582 | cpu_to_le64(MAJOR(device_number)); | ||
| 583 | pdev->minor = | ||
| 584 | cpu_to_le64(MINOR(device_number)); | ||
| 585 | rc = CIFSSMBWrite(xid, pTcon, | ||
| 586 | fileHandle, | ||
| 587 | sizeof(struct win_dev), | ||
| 588 | 0, &bytes_written, (char *)pdev, | ||
| 589 | NULL, 0); | ||
| 590 | } else if (S_ISBLK(mode)) { | ||
| 591 | memcpy(pdev->type, "IntxBLK", 8); | ||
| 592 | pdev->major = | ||
| 593 | cpu_to_le64(MAJOR(device_number)); | ||
| 594 | pdev->minor = | ||
| 595 | cpu_to_le64(MINOR(device_number)); | ||
| 596 | rc = CIFSSMBWrite(xid, pTcon, | ||
| 597 | fileHandle, | ||
| 598 | sizeof(struct win_dev), | ||
| 599 | 0, &bytes_written, (char *)pdev, | ||
| 600 | NULL, 0); | ||
| 601 | } /* else if(S_ISFIFO */ | ||
| 602 | CIFSSMBClose(xid, pTcon, fileHandle); | ||
| 603 | d_drop(direntry); | ||
| 604 | } | ||
| 605 | kfree(buf); | ||
| 606 | /* add code here to set EAs */ | ||
| 607 | } | ||
| 608 | } | 563 | } |
| 609 | 564 | ||
| 565 | /* FIXME: would WRITE_OWNER | WRITE_DAC be better? */ | ||
| 566 | rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_CREATE, | ||
| 567 | GENERIC_WRITE, CREATE_NOT_DIR | CREATE_OPTION_SPECIAL, | ||
| 568 | &fileHandle, &oplock, buf, cifs_sb->local_nls, | ||
| 569 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
| 570 | if (rc) | ||
| 571 | goto mknod_out; | ||
| 572 | |||
| 573 | /* BB Do not bother to decode buf since no local inode yet to put | ||
| 574 | * timestamps in, but we can reuse it safely */ | ||
| 575 | |||
| 576 | pdev = (struct win_dev *)buf; | ||
| 577 | if (S_ISCHR(mode)) { | ||
| 578 | memcpy(pdev->type, "IntxCHR", 8); | ||
| 579 | pdev->major = | ||
| 580 | cpu_to_le64(MAJOR(device_number)); | ||
| 581 | pdev->minor = | ||
| 582 | cpu_to_le64(MINOR(device_number)); | ||
| 583 | rc = CIFSSMBWrite(xid, pTcon, | ||
| 584 | fileHandle, | ||
| 585 | sizeof(struct win_dev), | ||
| 586 | 0, &bytes_written, (char *)pdev, | ||
| 587 | NULL, 0); | ||
| 588 | } else if (S_ISBLK(mode)) { | ||
| 589 | memcpy(pdev->type, "IntxBLK", 8); | ||
| 590 | pdev->major = | ||
| 591 | cpu_to_le64(MAJOR(device_number)); | ||
| 592 | pdev->minor = | ||
| 593 | cpu_to_le64(MINOR(device_number)); | ||
| 594 | rc = CIFSSMBWrite(xid, pTcon, | ||
| 595 | fileHandle, | ||
| 596 | sizeof(struct win_dev), | ||
| 597 | 0, &bytes_written, (char *)pdev, | ||
| 598 | NULL, 0); | ||
| 599 | } /* else if (S_ISFIFO) */ | ||
| 600 | CIFSSMBClose(xid, pTcon, fileHandle); | ||
| 601 | d_drop(direntry); | ||
| 602 | |||
| 603 | /* FIXME: add code here to set EAs */ | ||
| 604 | |||
| 605 | mknod_out: | ||
| 610 | kfree(full_path); | 606 | kfree(full_path); |
| 607 | kfree(buf); | ||
| 611 | FreeXid(xid); | 608 | FreeXid(xid); |
| 612 | return rc; | 609 | return rc; |
| 613 | } | 610 | } |
