diff options
| -rw-r--r-- | fs/cifs/dir.c | 149 |
1 files changed, 74 insertions, 75 deletions
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 578d88c5b46e..f17d50047f07 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
| @@ -496,6 +496,11 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, | |||
| 496 | struct cifsTconInfo *pTcon; | 496 | struct cifsTconInfo *pTcon; |
| 497 | char *full_path = NULL; | 497 | char *full_path = NULL; |
| 498 | struct inode *newinode = NULL; | 498 | struct inode *newinode = NULL; |
| 499 | int oplock = 0; | ||
| 500 | u16 fileHandle; | ||
| 501 | FILE_ALL_INFO *buf = NULL; | ||
| 502 | unsigned int bytes_written; | ||
| 503 | struct win_dev *pdev; | ||
| 499 | 504 | ||
| 500 | if (!old_valid_dev(device_number)) | 505 | if (!old_valid_dev(device_number)) |
| 501 | return -EINVAL; | 506 | return -EINVAL; |
| @@ -506,9 +511,12 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, | |||
| 506 | pTcon = cifs_sb->tcon; | 511 | pTcon = cifs_sb->tcon; |
| 507 | 512 | ||
| 508 | full_path = build_path_from_dentry(direntry); | 513 | full_path = build_path_from_dentry(direntry); |
| 509 | if (full_path == NULL) | 514 | if (full_path == NULL) { |
| 510 | rc = -ENOMEM; | 515 | rc = -ENOMEM; |
| 511 | else if (pTcon->unix_ext) { | 516 | goto mknod_out; |
| 517 | } | ||
| 518 | |||
| 519 | if (pTcon->unix_ext) { | ||
| 512 | struct cifs_unix_set_info_args args = { | 520 | struct cifs_unix_set_info_args args = { |
| 513 | .mode = mode & ~current_umask(), | 521 | .mode = mode & ~current_umask(), |
| 514 | .ctime = NO_CHANGE_64, | 522 | .ctime = NO_CHANGE_64, |
| @@ -527,87 +535,78 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, | |||
| 527 | cifs_sb->local_nls, | 535 | cifs_sb->local_nls, |
| 528 | cifs_sb->mnt_cifs_flags & | 536 | cifs_sb->mnt_cifs_flags & |
| 529 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 537 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 538 | if (rc) | ||
| 539 | goto mknod_out; | ||
| 530 | 540 | ||
| 531 | if (!rc) { | 541 | rc = cifs_get_inode_info_unix(&newinode, full_path, |
| 532 | rc = cifs_get_inode_info_unix(&newinode, full_path, | ||
| 533 | inode->i_sb, xid); | 542 | inode->i_sb, xid); |
| 534 | if (pTcon->nocase) | 543 | if (pTcon->nocase) |
| 535 | direntry->d_op = &cifs_ci_dentry_ops; | 544 | direntry->d_op = &cifs_ci_dentry_ops; |
| 536 | else | 545 | else |
| 537 | direntry->d_op = &cifs_dentry_ops; | 546 | 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 | 547 | ||
| 547 | cFYI(1, "sfu compat create special file"); | 548 | if (rc == 0) |
| 549 | d_instantiate(direntry, newinode); | ||
| 550 | goto mknod_out; | ||
| 551 | } | ||
| 548 | 552 | ||
| 549 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); | 553 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) |
| 550 | if (buf == NULL) { | 554 | goto mknod_out; |
| 551 | kfree(full_path); | ||
| 552 | rc = -ENOMEM; | ||
| 553 | FreeXid(xid); | ||
| 554 | return rc; | ||
| 555 | } | ||
| 556 | 555 | ||
| 557 | rc = CIFSSMBOpen(xid, pTcon, full_path, | 556 | |
| 558 | FILE_CREATE, /* fail if exists */ | 557 | cFYI(1, "sfu compat create special file"); |
| 559 | GENERIC_WRITE /* BB would | 558 | |
| 560 | WRITE_OWNER | WRITE_DAC be better? */, | 559 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); |
| 561 | /* Create a file and set the | 560 | if (buf == NULL) { |
| 562 | file attribute to SYSTEM */ | 561 | kfree(full_path); |
| 563 | CREATE_NOT_DIR | CREATE_OPTION_SPECIAL, | 562 | rc = -ENOMEM; |
| 564 | &fileHandle, &oplock, buf, | 563 | FreeXid(xid); |
| 565 | cifs_sb->local_nls, | 564 | 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 | } | 565 | } |
| 609 | 566 | ||
| 567 | /* FIXME: would WRITE_OWNER | WRITE_DAC be better? */ | ||
| 568 | rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_CREATE, | ||
| 569 | GENERIC_WRITE, CREATE_NOT_DIR | CREATE_OPTION_SPECIAL, | ||
| 570 | &fileHandle, &oplock, buf, cifs_sb->local_nls, | ||
| 571 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
| 572 | if (rc) | ||
| 573 | goto mknod_out; | ||
| 574 | |||
| 575 | /* BB Do not bother to decode buf since no local inode yet to put | ||
| 576 | * timestamps in, but we can reuse it safely */ | ||
| 577 | |||
| 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 | /* FIXME: add code here to set EAs */ | ||
| 606 | |||
| 607 | mknod_out: | ||
| 610 | kfree(full_path); | 608 | kfree(full_path); |
| 609 | kfree(buf); | ||
| 611 | FreeXid(xid); | 610 | FreeXid(xid); |
| 612 | return rc; | 611 | return rc; |
| 613 | } | 612 | } |
