diff options
| -rw-r--r-- | fs/cifs/cifsacl.c | 40 | ||||
| -rw-r--r-- | fs/cifs/cifsglob.h | 14 | ||||
| -rw-r--r-- | fs/cifs/cifsproto.h | 22 | ||||
| -rw-r--r-- | fs/cifs/cifssmb.c | 158 | ||||
| -rw-r--r-- | fs/cifs/dir.c | 59 | ||||
| -rw-r--r-- | fs/cifs/file.c | 2 | ||||
| -rw-r--r-- | fs/cifs/inode.c | 178 | ||||
| -rw-r--r-- | fs/cifs/link.c | 323 | ||||
| -rw-r--r-- | fs/cifs/readdir.c | 2 | ||||
| -rw-r--r-- | fs/cifs/smb1ops.c | 126 | ||||
| -rw-r--r-- | fs/cifs/xattr.c | 49 |
11 files changed, 553 insertions, 420 deletions
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 51f5e0ee7237..8f9b4f710d4a 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
| @@ -895,9 +895,10 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, | |||
| 895 | int oplock = 0; | 895 | int oplock = 0; |
| 896 | unsigned int xid; | 896 | unsigned int xid; |
| 897 | int rc, create_options = 0; | 897 | int rc, create_options = 0; |
| 898 | __u16 fid; | ||
| 899 | struct cifs_tcon *tcon; | 898 | struct cifs_tcon *tcon; |
| 900 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); | 899 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); |
| 900 | struct cifs_fid fid; | ||
| 901 | struct cifs_open_parms oparms; | ||
| 901 | 902 | ||
| 902 | if (IS_ERR(tlink)) | 903 | if (IS_ERR(tlink)) |
| 903 | return ERR_CAST(tlink); | 904 | return ERR_CAST(tlink); |
| @@ -908,12 +909,19 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, | |||
| 908 | if (backup_cred(cifs_sb)) | 909 | if (backup_cred(cifs_sb)) |
| 909 | create_options |= CREATE_OPEN_BACKUP_INTENT; | 910 | create_options |= CREATE_OPEN_BACKUP_INTENT; |
| 910 | 911 | ||
| 911 | rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL, | 912 | oparms.tcon = tcon; |
| 912 | create_options, &fid, &oplock, NULL, cifs_sb->local_nls, | 913 | oparms.cifs_sb = cifs_sb; |
| 913 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 914 | oparms.desired_access = READ_CONTROL; |
| 915 | oparms.create_options = create_options; | ||
| 916 | oparms.disposition = FILE_OPEN; | ||
| 917 | oparms.path = path; | ||
| 918 | oparms.fid = &fid; | ||
| 919 | oparms.reconnect = false; | ||
| 920 | |||
| 921 | rc = CIFS_open(xid, &oparms, &oplock, NULL); | ||
| 914 | if (!rc) { | 922 | if (!rc) { |
| 915 | rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen); | 923 | rc = CIFSSMBGetCIFSACL(xid, tcon, fid.netfid, &pntsd, pacllen); |
| 916 | CIFSSMBClose(xid, tcon, fid); | 924 | CIFSSMBClose(xid, tcon, fid.netfid); |
| 917 | } | 925 | } |
| 918 | 926 | ||
| 919 | cifs_put_tlink(tlink); | 927 | cifs_put_tlink(tlink); |
| @@ -950,10 +958,11 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, | |||
| 950 | int oplock = 0; | 958 | int oplock = 0; |
| 951 | unsigned int xid; | 959 | unsigned int xid; |
| 952 | int rc, access_flags, create_options = 0; | 960 | int rc, access_flags, create_options = 0; |
| 953 | __u16 fid; | ||
| 954 | struct cifs_tcon *tcon; | 961 | struct cifs_tcon *tcon; |
| 955 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 962 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
| 956 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); | 963 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); |
| 964 | struct cifs_fid fid; | ||
| 965 | struct cifs_open_parms oparms; | ||
| 957 | 966 | ||
| 958 | if (IS_ERR(tlink)) | 967 | if (IS_ERR(tlink)) |
| 959 | return PTR_ERR(tlink); | 968 | return PTR_ERR(tlink); |
| @@ -969,18 +978,25 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, | |||
| 969 | else | 978 | else |
| 970 | access_flags = WRITE_DAC; | 979 | access_flags = WRITE_DAC; |
| 971 | 980 | ||
| 972 | rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, access_flags, | 981 | oparms.tcon = tcon; |
| 973 | create_options, &fid, &oplock, NULL, cifs_sb->local_nls, | 982 | oparms.cifs_sb = cifs_sb; |
| 974 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 983 | oparms.desired_access = access_flags; |
| 984 | oparms.create_options = create_options; | ||
| 985 | oparms.disposition = FILE_OPEN; | ||
| 986 | oparms.path = path; | ||
| 987 | oparms.fid = &fid; | ||
| 988 | oparms.reconnect = false; | ||
| 989 | |||
| 990 | rc = CIFS_open(xid, &oparms, &oplock, NULL); | ||
| 975 | if (rc) { | 991 | if (rc) { |
| 976 | cifs_dbg(VFS, "Unable to open file to set ACL\n"); | 992 | cifs_dbg(VFS, "Unable to open file to set ACL\n"); |
| 977 | goto out; | 993 | goto out; |
| 978 | } | 994 | } |
| 979 | 995 | ||
| 980 | rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen, aclflag); | 996 | rc = CIFSSMBSetCIFSACL(xid, tcon, fid.netfid, pnntsd, acllen, aclflag); |
| 981 | cifs_dbg(NOISY, "SetCIFSACL rc = %d\n", rc); | 997 | cifs_dbg(NOISY, "SetCIFSACL rc = %d\n", rc); |
| 982 | 998 | ||
| 983 | CIFSSMBClose(xid, tcon, fid); | 999 | CIFSSMBClose(xid, tcon, fid.netfid); |
| 984 | out: | 1000 | out: |
| 985 | free_xid(xid); | 1001 | free_xid(xid); |
| 986 | cifs_put_tlink(tlink); | 1002 | cifs_put_tlink(tlink); |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index f918a998a087..a245d1809ed8 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
| @@ -370,8 +370,12 @@ struct smb_version_operations { | |||
| 370 | void (*new_lease_key)(struct cifs_fid *); | 370 | void (*new_lease_key)(struct cifs_fid *); |
| 371 | int (*generate_signingkey)(struct cifs_ses *); | 371 | int (*generate_signingkey)(struct cifs_ses *); |
| 372 | int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *); | 372 | int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *); |
| 373 | int (*query_mf_symlink)(const unsigned char *, char *, unsigned int *, | 373 | int (*query_mf_symlink)(unsigned int, struct cifs_tcon *, |
| 374 | struct cifs_sb_info *, unsigned int); | 374 | struct cifs_sb_info *, const unsigned char *, |
| 375 | char *, unsigned int *); | ||
| 376 | int (*create_mf_symlink)(unsigned int, struct cifs_tcon *, | ||
| 377 | struct cifs_sb_info *, const unsigned char *, | ||
| 378 | char *, unsigned int *); | ||
| 375 | /* if we can do cache read operations */ | 379 | /* if we can do cache read operations */ |
| 376 | bool (*is_read_op)(__u32); | 380 | bool (*is_read_op)(__u32); |
| 377 | /* set oplock level for the inode */ | 381 | /* set oplock level for the inode */ |
| @@ -385,6 +389,12 @@ struct smb_version_operations { | |||
| 385 | struct cifsFileInfo *target_file, u64 src_off, u64 len, | 389 | struct cifsFileInfo *target_file, u64 src_off, u64 len, |
| 386 | u64 dest_off); | 390 | u64 dest_off); |
| 387 | int (*validate_negotiate)(const unsigned int, struct cifs_tcon *); | 391 | int (*validate_negotiate)(const unsigned int, struct cifs_tcon *); |
| 392 | ssize_t (*query_all_EAs)(const unsigned int, struct cifs_tcon *, | ||
| 393 | const unsigned char *, const unsigned char *, char *, | ||
| 394 | size_t, const struct nls_table *, int); | ||
| 395 | int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *, | ||
| 396 | const char *, const void *, const __u16, | ||
| 397 | const struct nls_table *, int); | ||
| 388 | }; | 398 | }; |
| 389 | 399 | ||
| 390 | struct smb_version_values { | 400 | struct smb_version_values { |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 2c29db6a247e..79e6e9a93a8c 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
| @@ -362,11 +362,8 @@ extern int CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 362 | const struct nls_table *nls_codepage); | 362 | const struct nls_table *nls_codepage); |
| 363 | extern int CIFSSMB_set_compression(const unsigned int xid, | 363 | extern int CIFSSMB_set_compression(const unsigned int xid, |
| 364 | struct cifs_tcon *tcon, __u16 fid); | 364 | struct cifs_tcon *tcon, __u16 fid); |
| 365 | extern int CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon, | 365 | extern int CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, |
| 366 | const char *fileName, const int disposition, | 366 | int *oplock, FILE_ALL_INFO *buf); |
| 367 | const int access_flags, const int omode, | ||
| 368 | __u16 *netfid, int *pOplock, FILE_ALL_INFO *, | ||
| 369 | const struct nls_table *nls_codepage, int remap); | ||
| 370 | extern int SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon, | 367 | extern int SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon, |
| 371 | const char *fileName, const int disposition, | 368 | const char *fileName, const int disposition, |
| 372 | const int access_flags, const int omode, | 369 | const int access_flags, const int omode, |
| @@ -476,8 +473,8 @@ extern int CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 476 | extern int CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon, | 473 | extern int CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon, |
| 477 | const int netfid, __u64 *pExtAttrBits, __u64 *pMask); | 474 | const int netfid, __u64 *pExtAttrBits, __u64 *pMask); |
| 478 | extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb); | 475 | extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb); |
| 479 | extern bool CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr); | 476 | extern bool couldbe_mf_symlink(const struct cifs_fattr *fattr); |
| 480 | extern int CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon, | 477 | extern int check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, |
| 481 | struct cifs_sb_info *cifs_sb, | 478 | struct cifs_sb_info *cifs_sb, |
| 482 | struct cifs_fattr *fattr, | 479 | struct cifs_fattr *fattr, |
| 483 | const unsigned char *path); | 480 | const unsigned char *path); |
| @@ -496,7 +493,12 @@ void cifs_writev_complete(struct work_struct *work); | |||
| 496 | struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages, | 493 | struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages, |
| 497 | work_func_t complete); | 494 | work_func_t complete); |
| 498 | void cifs_writedata_release(struct kref *refcount); | 495 | void cifs_writedata_release(struct kref *refcount); |
| 499 | int open_query_close_cifs_symlink(const unsigned char *path, char *pbuf, | 496 | int cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, |
| 500 | unsigned int *pbytes_read, struct cifs_sb_info *cifs_sb, | 497 | struct cifs_sb_info *cifs_sb, |
| 501 | unsigned int xid); | 498 | const unsigned char *path, char *pbuf, |
| 499 | unsigned int *pbytes_read); | ||
| 500 | int cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, | ||
| 501 | struct cifs_sb_info *cifs_sb, | ||
| 502 | const unsigned char *path, char *pbuf, | ||
| 503 | unsigned int *pbytes_written); | ||
| 502 | #endif /* _CIFSPROTO_H */ | 504 | #endif /* _CIFSPROTO_H */ |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index d707edb6b852..4d881c35eeca 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
| @@ -1273,104 +1273,124 @@ OldOpenRetry: | |||
| 1273 | } | 1273 | } |
| 1274 | 1274 | ||
| 1275 | int | 1275 | int |
| 1276 | CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon, | 1276 | CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock, |
| 1277 | const char *fileName, const int openDisposition, | 1277 | FILE_ALL_INFO *buf) |
| 1278 | const int access_flags, const int create_options, __u16 *netfid, | ||
| 1279 | int *pOplock, FILE_ALL_INFO *pfile_info, | ||
| 1280 | const struct nls_table *nls_codepage, int remap) | ||
| 1281 | { | 1278 | { |
| 1282 | int rc = -EACCES; | 1279 | int rc = -EACCES; |
| 1283 | OPEN_REQ *pSMB = NULL; | 1280 | OPEN_REQ *req = NULL; |
| 1284 | OPEN_RSP *pSMBr = NULL; | 1281 | OPEN_RSP *rsp = NULL; |
| 1285 | int bytes_returned; | 1282 | int bytes_returned; |
| 1286 | int name_len; | 1283 | int name_len; |
| 1287 | __u16 count; | 1284 | __u16 count; |
| 1285 | struct cifs_sb_info *cifs_sb = oparms->cifs_sb; | ||
| 1286 | struct cifs_tcon *tcon = oparms->tcon; | ||
| 1287 | int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR; | ||
| 1288 | const struct nls_table *nls = cifs_sb->local_nls; | ||
| 1289 | int create_options = oparms->create_options; | ||
| 1290 | int desired_access = oparms->desired_access; | ||
| 1291 | int disposition = oparms->disposition; | ||
| 1292 | const char *path = oparms->path; | ||
| 1288 | 1293 | ||
| 1289 | openRetry: | 1294 | openRetry: |
| 1290 | rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB, | 1295 | rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **)&req, |
| 1291 | (void **) &pSMBr); | 1296 | (void **)&rsp); |
| 1292 | if (rc) | 1297 | if (rc) |
| 1293 | return rc; | 1298 | return rc; |
| 1294 | 1299 | ||
| 1295 | pSMB->AndXCommand = 0xFF; /* none */ | 1300 | /* no commands go after this */ |
| 1301 | req->AndXCommand = 0xFF; | ||
| 1296 | 1302 | ||
| 1297 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 1303 | if (req->hdr.Flags2 & SMBFLG2_UNICODE) { |
| 1298 | count = 1; /* account for one byte pad to word boundary */ | 1304 | /* account for one byte pad to word boundary */ |
| 1299 | name_len = | 1305 | count = 1; |
| 1300 | cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1), | 1306 | name_len = cifsConvertToUTF16((__le16 *)(req->fileName + 1), |
| 1301 | fileName, PATH_MAX, nls_codepage, remap); | 1307 | path, PATH_MAX, nls, remap); |
| 1302 | name_len++; /* trailing null */ | 1308 | /* trailing null */ |
| 1309 | name_len++; | ||
| 1303 | name_len *= 2; | 1310 | name_len *= 2; |
| 1304 | pSMB->NameLength = cpu_to_le16(name_len); | 1311 | req->NameLength = cpu_to_le16(name_len); |
| 1305 | } else { /* BB improve check for buffer overruns BB */ | 1312 | } else { |
| 1306 | count = 0; /* no pad */ | 1313 | /* BB improve check for buffer overruns BB */ |
| 1307 | name_len = strnlen(fileName, PATH_MAX); | 1314 | /* no pad */ |
| 1308 | name_len++; /* trailing null */ | 1315 | count = 0; |
| 1309 | pSMB->NameLength = cpu_to_le16(name_len); | 1316 | name_len = strnlen(path, PATH_MAX); |
| 1310 | strncpy(pSMB->fileName, fileName, name_len); | 1317 | /* trailing null */ |
| 1318 | name_len++; | ||
| 1319 | req->NameLength = cpu_to_le16(name_len); | ||
| 1320 | strncpy(req->fileName, path, name_len); | ||
| 1311 | } | 1321 | } |
| 1312 | if (*pOplock & REQ_OPLOCK) | 1322 | |
| 1313 | pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK); | 1323 | if (*oplock & REQ_OPLOCK) |
| 1314 | else if (*pOplock & REQ_BATCHOPLOCK) | 1324 | req->OpenFlags = cpu_to_le32(REQ_OPLOCK); |
| 1315 | pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK); | 1325 | else if (*oplock & REQ_BATCHOPLOCK) |
| 1316 | pSMB->DesiredAccess = cpu_to_le32(access_flags); | 1326 | req->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK); |
| 1317 | pSMB->AllocationSize = 0; | 1327 | |
| 1318 | /* set file as system file if special file such | 1328 | req->DesiredAccess = cpu_to_le32(desired_access); |
| 1319 | as fifo and server expecting SFU style and | 1329 | req->AllocationSize = 0; |
| 1320 | no Unix extensions */ | 1330 | |
| 1331 | /* | ||
| 1332 | * Set file as system file if special file such as fifo and server | ||
| 1333 | * expecting SFU style and no Unix extensions. | ||
| 1334 | */ | ||
| 1321 | if (create_options & CREATE_OPTION_SPECIAL) | 1335 | if (create_options & CREATE_OPTION_SPECIAL) |
| 1322 | pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM); | 1336 | req->FileAttributes = cpu_to_le32(ATTR_SYSTEM); |
| 1323 | else | 1337 | else |
| 1324 | pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL); | 1338 | req->FileAttributes = cpu_to_le32(ATTR_NORMAL); |
| 1325 | 1339 | ||
| 1326 | /* XP does not handle ATTR_POSIX_SEMANTICS */ | 1340 | /* |
| 1327 | /* but it helps speed up case sensitive checks for other | 1341 | * XP does not handle ATTR_POSIX_SEMANTICS but it helps speed up case |
| 1328 | servers such as Samba */ | 1342 | * sensitive checks for other servers such as Samba. |
| 1343 | */ | ||
| 1329 | if (tcon->ses->capabilities & CAP_UNIX) | 1344 | if (tcon->ses->capabilities & CAP_UNIX) |
| 1330 | pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS); | 1345 | req->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS); |
| 1331 | 1346 | ||
| 1332 | if (create_options & CREATE_OPTION_READONLY) | 1347 | if (create_options & CREATE_OPTION_READONLY) |
| 1333 | pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY); | 1348 | req->FileAttributes |= cpu_to_le32(ATTR_READONLY); |
| 1349 | |||
| 1350 | req->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); | ||
| 1351 | req->CreateDisposition = cpu_to_le32(disposition); | ||
| 1352 | req->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); | ||
| 1334 | 1353 | ||
| 1335 | pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); | ||
| 1336 | pSMB->CreateDisposition = cpu_to_le32(openDisposition); | ||
| 1337 | pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); | ||
| 1338 | /* BB Expirement with various impersonation levels and verify */ | 1354 | /* BB Expirement with various impersonation levels and verify */ |
| 1339 | pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); | 1355 | req->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); |
| 1340 | pSMB->SecurityFlags = | 1356 | req->SecurityFlags = SECURITY_CONTEXT_TRACKING|SECURITY_EFFECTIVE_ONLY; |
| 1341 | SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY; | ||
| 1342 | 1357 | ||
| 1343 | count += name_len; | 1358 | count += name_len; |
| 1344 | inc_rfc1001_len(pSMB, count); | 1359 | inc_rfc1001_len(req, count); |
| 1345 | 1360 | ||
| 1346 | pSMB->ByteCount = cpu_to_le16(count); | 1361 | req->ByteCount = cpu_to_le16(count); |
| 1347 | /* long_op set to 1 to allow for oplock break timeouts */ | 1362 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)req, |
| 1348 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1363 | (struct smb_hdr *)rsp, &bytes_returned, 0); |
| 1349 | (struct smb_hdr *)pSMBr, &bytes_returned, 0); | ||
| 1350 | cifs_stats_inc(&tcon->stats.cifs_stats.num_opens); | 1364 | cifs_stats_inc(&tcon->stats.cifs_stats.num_opens); |
| 1351 | if (rc) { | 1365 | if (rc) { |
| 1352 | cifs_dbg(FYI, "Error in Open = %d\n", rc); | 1366 | cifs_dbg(FYI, "Error in Open = %d\n", rc); |
| 1353 | } else { | 1367 | cifs_buf_release(req); |
| 1354 | *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */ | 1368 | if (rc == -EAGAIN) |
| 1355 | *netfid = pSMBr->Fid; /* cifs fid stays in le */ | 1369 | goto openRetry; |
| 1356 | /* Let caller know file was created so we can set the mode. */ | 1370 | return rc; |
| 1357 | /* Do we care about the CreateAction in any other cases? */ | ||
| 1358 | if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction) | ||
| 1359 | *pOplock |= CIFS_CREATE_ACTION; | ||
| 1360 | if (pfile_info) { | ||
| 1361 | memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime, | ||
| 1362 | 36 /* CreationTime to Attributes */); | ||
| 1363 | /* the file_info buf is endian converted by caller */ | ||
| 1364 | pfile_info->AllocationSize = pSMBr->AllocationSize; | ||
| 1365 | pfile_info->EndOfFile = pSMBr->EndOfFile; | ||
| 1366 | pfile_info->NumberOfLinks = cpu_to_le32(1); | ||
| 1367 | pfile_info->DeletePending = 0; | ||
| 1368 | } | ||
| 1369 | } | 1371 | } |
| 1370 | 1372 | ||
| 1371 | cifs_buf_release(pSMB); | 1373 | /* 1 byte no need to le_to_cpu */ |
| 1372 | if (rc == -EAGAIN) | 1374 | *oplock = rsp->OplockLevel; |
| 1373 | goto openRetry; | 1375 | /* cifs fid stays in le */ |
| 1376 | oparms->fid->netfid = rsp->Fid; | ||
| 1377 | |||
| 1378 | /* Let caller know file was created so we can set the mode. */ | ||
| 1379 | /* Do we care about the CreateAction in any other cases? */ | ||
| 1380 | if (cpu_to_le32(FILE_CREATE) == rsp->CreateAction) | ||
| 1381 | *oplock |= CIFS_CREATE_ACTION; | ||
| 1382 | |||
| 1383 | if (buf) { | ||
| 1384 | /* copy from CreationTime to Attributes */ | ||
| 1385 | memcpy((char *)buf, (char *)&rsp->CreationTime, 36); | ||
| 1386 | /* the file_info buf is endian converted by caller */ | ||
| 1387 | buf->AllocationSize = rsp->AllocationSize; | ||
| 1388 | buf->EndOfFile = rsp->EndOfFile; | ||
| 1389 | buf->NumberOfLinks = cpu_to_le32(1); | ||
| 1390 | buf->DeletePending = 0; | ||
| 1391 | } | ||
| 1392 | |||
| 1393 | cifs_buf_release(req); | ||
| 1374 | return rc; | 1394 | return rc; |
| 1375 | } | 1395 | } |
| 1376 | 1396 | ||
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index a514e0a65f69..d3a6796caa5a 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
| @@ -565,12 +565,13 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, | |||
| 565 | int create_options = CREATE_NOT_DIR | CREATE_OPTION_SPECIAL; | 565 | int create_options = CREATE_NOT_DIR | CREATE_OPTION_SPECIAL; |
| 566 | struct cifs_sb_info *cifs_sb; | 566 | struct cifs_sb_info *cifs_sb; |
| 567 | struct tcon_link *tlink; | 567 | struct tcon_link *tlink; |
| 568 | struct cifs_tcon *pTcon; | 568 | struct cifs_tcon *tcon; |
| 569 | struct cifs_io_parms io_parms; | 569 | struct cifs_io_parms io_parms; |
| 570 | char *full_path = NULL; | 570 | char *full_path = NULL; |
| 571 | struct inode *newinode = NULL; | 571 | struct inode *newinode = NULL; |
| 572 | int oplock = 0; | 572 | int oplock = 0; |
| 573 | u16 fileHandle; | 573 | struct cifs_fid fid; |
| 574 | struct cifs_open_parms oparms; | ||
| 574 | FILE_ALL_INFO *buf = NULL; | 575 | FILE_ALL_INFO *buf = NULL; |
| 575 | unsigned int bytes_written; | 576 | unsigned int bytes_written; |
| 576 | struct win_dev *pdev; | 577 | struct win_dev *pdev; |
| @@ -583,7 +584,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, | |||
| 583 | if (IS_ERR(tlink)) | 584 | if (IS_ERR(tlink)) |
| 584 | return PTR_ERR(tlink); | 585 | return PTR_ERR(tlink); |
| 585 | 586 | ||
| 586 | pTcon = tlink_tcon(tlink); | 587 | tcon = tlink_tcon(tlink); |
| 587 | 588 | ||
| 588 | xid = get_xid(); | 589 | xid = get_xid(); |
| 589 | 590 | ||
| @@ -593,7 +594,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, | |||
| 593 | goto mknod_out; | 594 | goto mknod_out; |
| 594 | } | 595 | } |
| 595 | 596 | ||
| 596 | if (pTcon->unix_ext) { | 597 | if (tcon->unix_ext) { |
| 597 | struct cifs_unix_set_info_args args = { | 598 | struct cifs_unix_set_info_args args = { |
| 598 | .mode = mode & ~current_umask(), | 599 | .mode = mode & ~current_umask(), |
| 599 | .ctime = NO_CHANGE_64, | 600 | .ctime = NO_CHANGE_64, |
| @@ -608,7 +609,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, | |||
| 608 | args.uid = INVALID_UID; /* no change */ | 609 | args.uid = INVALID_UID; /* no change */ |
| 609 | args.gid = INVALID_GID; /* no change */ | 610 | args.gid = INVALID_GID; /* no change */ |
| 610 | } | 611 | } |
| 611 | rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args, | 612 | rc = CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, |
| 612 | cifs_sb->local_nls, | 613 | cifs_sb->local_nls, |
| 613 | cifs_sb->mnt_cifs_flags & | 614 | cifs_sb->mnt_cifs_flags & |
| 614 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 615 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| @@ -640,42 +641,44 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, | |||
| 640 | if (backup_cred(cifs_sb)) | 641 | if (backup_cred(cifs_sb)) |
| 641 | create_options |= CREATE_OPEN_BACKUP_INTENT; | 642 | create_options |= CREATE_OPEN_BACKUP_INTENT; |
| 642 | 643 | ||
| 643 | rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_CREATE, | 644 | oparms.tcon = tcon; |
| 644 | GENERIC_WRITE, create_options, | 645 | oparms.cifs_sb = cifs_sb; |
| 645 | &fileHandle, &oplock, buf, cifs_sb->local_nls, | 646 | oparms.desired_access = GENERIC_WRITE; |
| 646 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 647 | oparms.create_options = create_options; |
| 648 | oparms.disposition = FILE_CREATE; | ||
| 649 | oparms.path = full_path; | ||
| 650 | oparms.fid = &fid; | ||
| 651 | oparms.reconnect = false; | ||
| 652 | |||
| 653 | rc = CIFS_open(xid, &oparms, &oplock, buf); | ||
| 647 | if (rc) | 654 | if (rc) |
| 648 | goto mknod_out; | 655 | goto mknod_out; |
| 649 | 656 | ||
| 650 | /* BB Do not bother to decode buf since no local inode yet to put | 657 | /* |
| 651 | * timestamps in, but we can reuse it safely */ | 658 | * BB Do not bother to decode buf since no local inode yet to put |
| 659 | * timestamps in, but we can reuse it safely. | ||
| 660 | */ | ||
| 652 | 661 | ||
| 653 | pdev = (struct win_dev *)buf; | 662 | pdev = (struct win_dev *)buf; |
| 654 | io_parms.netfid = fileHandle; | 663 | io_parms.netfid = fid.netfid; |
| 655 | io_parms.pid = current->tgid; | 664 | io_parms.pid = current->tgid; |
| 656 | io_parms.tcon = pTcon; | 665 | io_parms.tcon = tcon; |
| 657 | io_parms.offset = 0; | 666 | io_parms.offset = 0; |
| 658 | io_parms.length = sizeof(struct win_dev); | 667 | io_parms.length = sizeof(struct win_dev); |
| 659 | if (S_ISCHR(mode)) { | 668 | if (S_ISCHR(mode)) { |
| 660 | memcpy(pdev->type, "IntxCHR", 8); | 669 | memcpy(pdev->type, "IntxCHR", 8); |
| 661 | pdev->major = | 670 | pdev->major = cpu_to_le64(MAJOR(device_number)); |
| 662 | cpu_to_le64(MAJOR(device_number)); | 671 | pdev->minor = cpu_to_le64(MINOR(device_number)); |
| 663 | pdev->minor = | 672 | rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, (char *)pdev, |
| 664 | cpu_to_le64(MINOR(device_number)); | 673 | NULL, 0); |
| 665 | rc = CIFSSMBWrite(xid, &io_parms, | ||
| 666 | &bytes_written, (char *)pdev, | ||
| 667 | NULL, 0); | ||
| 668 | } else if (S_ISBLK(mode)) { | 674 | } else if (S_ISBLK(mode)) { |
| 669 | memcpy(pdev->type, "IntxBLK", 8); | 675 | memcpy(pdev->type, "IntxBLK", 8); |
| 670 | pdev->major = | 676 | pdev->major = cpu_to_le64(MAJOR(device_number)); |
| 671 | cpu_to_le64(MAJOR(device_number)); | 677 | pdev->minor = cpu_to_le64(MINOR(device_number)); |
| 672 | pdev->minor = | 678 | rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, (char *)pdev, |
| 673 | cpu_to_le64(MINOR(device_number)); | 679 | NULL, 0); |
| 674 | rc = CIFSSMBWrite(xid, &io_parms, | ||
| 675 | &bytes_written, (char *)pdev, | ||
| 676 | NULL, 0); | ||
| 677 | } /* else if (S_ISFIFO) */ | 680 | } /* else if (S_ISFIFO) */ |
| 678 | CIFSSMBClose(xid, pTcon, fileHandle); | 681 | CIFSSMBClose(xid, tcon, fid.netfid); |
| 679 | d_drop(direntry); | 682 | d_drop(direntry); |
| 680 | 683 | ||
| 681 | /* FIXME: add code here to set EAs */ | 684 | /* FIXME: add code here to set EAs */ |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 5a5a87240fe2..853d6d1cc822 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -678,7 +678,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) | |||
| 678 | 678 | ||
| 679 | /* | 679 | /* |
| 680 | * Can not refresh inode by passing in file_info buf to be returned by | 680 | * Can not refresh inode by passing in file_info buf to be returned by |
| 681 | * CIFSSMBOpen and then calling get_inode_info with returned buf since | 681 | * ops->open and then calling get_inode_info with returned buf since |
| 682 | * file might have write behind data that needs to be flushed and server | 682 | * file might have write behind data that needs to be flushed and server |
| 683 | * version of file size can be stale. If we knew for sure that inode was | 683 | * version of file size can be stale. If we knew for sure that inode was |
| 684 | * not dirty locally we could do this. | 684 | * not dirty locally we could do this. |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 49719b8228e5..9cb9679d7357 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
| @@ -383,10 +383,10 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
| 383 | 383 | ||
| 384 | /* check for Minshall+French symlinks */ | 384 | /* check for Minshall+French symlinks */ |
| 385 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { | 385 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { |
| 386 | int tmprc = CIFSCheckMFSymlink(xid, tcon, cifs_sb, &fattr, | 386 | int tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr, |
| 387 | full_path); | 387 | full_path); |
| 388 | if (tmprc) | 388 | if (tmprc) |
| 389 | cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc); | 389 | cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc); |
| 390 | } | 390 | } |
| 391 | 391 | ||
| 392 | if (*pinode == NULL) { | 392 | if (*pinode == NULL) { |
| @@ -404,18 +404,20 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
| 404 | } | 404 | } |
| 405 | 405 | ||
| 406 | static int | 406 | static int |
| 407 | cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, | 407 | cifs_sfu_type(struct cifs_fattr *fattr, const char *path, |
| 408 | struct cifs_sb_info *cifs_sb, unsigned int xid) | 408 | struct cifs_sb_info *cifs_sb, unsigned int xid) |
| 409 | { | 409 | { |
| 410 | int rc; | 410 | int rc; |
| 411 | int oplock = 0; | 411 | int oplock = 0; |
| 412 | __u16 netfid; | ||
| 413 | struct tcon_link *tlink; | 412 | struct tcon_link *tlink; |
| 414 | struct cifs_tcon *tcon; | 413 | struct cifs_tcon *tcon; |
| 414 | struct cifs_fid fid; | ||
| 415 | struct cifs_open_parms oparms; | ||
| 415 | struct cifs_io_parms io_parms; | 416 | struct cifs_io_parms io_parms; |
| 416 | char buf[24]; | 417 | char buf[24]; |
| 417 | unsigned int bytes_read; | 418 | unsigned int bytes_read; |
| 418 | char *pbuf; | 419 | char *pbuf; |
| 420 | int buf_type = CIFS_NO_BUFFER; | ||
| 419 | 421 | ||
| 420 | pbuf = buf; | 422 | pbuf = buf; |
| 421 | 423 | ||
| @@ -436,62 +438,69 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, | |||
| 436 | return PTR_ERR(tlink); | 438 | return PTR_ERR(tlink); |
| 437 | tcon = tlink_tcon(tlink); | 439 | tcon = tlink_tcon(tlink); |
| 438 | 440 | ||
| 439 | rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ, | 441 | oparms.tcon = tcon; |
| 440 | CREATE_NOT_DIR, &netfid, &oplock, NULL, | 442 | oparms.cifs_sb = cifs_sb; |
| 441 | cifs_sb->local_nls, | 443 | oparms.desired_access = GENERIC_READ; |
| 442 | cifs_sb->mnt_cifs_flags & | 444 | oparms.create_options = CREATE_NOT_DIR; |
| 443 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 445 | oparms.disposition = FILE_OPEN; |
| 444 | if (rc == 0) { | 446 | oparms.path = path; |
| 445 | int buf_type = CIFS_NO_BUFFER; | 447 | oparms.fid = &fid; |
| 446 | /* Read header */ | 448 | oparms.reconnect = false; |
| 447 | io_parms.netfid = netfid; | 449 | |
| 448 | io_parms.pid = current->tgid; | 450 | rc = CIFS_open(xid, &oparms, &oplock, NULL); |
| 449 | io_parms.tcon = tcon; | 451 | if (rc) { |
| 450 | io_parms.offset = 0; | 452 | cifs_put_tlink(tlink); |
| 451 | io_parms.length = 24; | 453 | return rc; |
| 452 | rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, | 454 | } |
| 453 | &buf_type); | 455 | |
| 454 | if ((rc == 0) && (bytes_read >= 8)) { | 456 | /* Read header */ |
| 455 | if (memcmp("IntxBLK", pbuf, 8) == 0) { | 457 | io_parms.netfid = fid.netfid; |
| 456 | cifs_dbg(FYI, "Block device\n"); | 458 | io_parms.pid = current->tgid; |
| 457 | fattr->cf_mode |= S_IFBLK; | 459 | io_parms.tcon = tcon; |
| 458 | fattr->cf_dtype = DT_BLK; | 460 | io_parms.offset = 0; |
| 459 | if (bytes_read == 24) { | 461 | io_parms.length = 24; |
| 460 | /* we have enough to decode dev num */ | 462 | |
| 461 | __u64 mjr; /* major */ | 463 | rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, &buf_type); |
| 462 | __u64 mnr; /* minor */ | 464 | if ((rc == 0) && (bytes_read >= 8)) { |
| 463 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); | 465 | if (memcmp("IntxBLK", pbuf, 8) == 0) { |
| 464 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); | 466 | cifs_dbg(FYI, "Block device\n"); |
| 465 | fattr->cf_rdev = MKDEV(mjr, mnr); | 467 | fattr->cf_mode |= S_IFBLK; |
| 466 | } | 468 | fattr->cf_dtype = DT_BLK; |
| 467 | } else if (memcmp("IntxCHR", pbuf, 8) == 0) { | 469 | if (bytes_read == 24) { |
| 468 | cifs_dbg(FYI, "Char device\n"); | 470 | /* we have enough to decode dev num */ |
| 469 | fattr->cf_mode |= S_IFCHR; | 471 | __u64 mjr; /* major */ |
| 470 | fattr->cf_dtype = DT_CHR; | 472 | __u64 mnr; /* minor */ |
| 471 | if (bytes_read == 24) { | 473 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); |
| 472 | /* we have enough to decode dev num */ | 474 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); |
| 473 | __u64 mjr; /* major */ | 475 | fattr->cf_rdev = MKDEV(mjr, mnr); |
| 474 | __u64 mnr; /* minor */ | ||
| 475 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); | ||
| 476 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); | ||
| 477 | fattr->cf_rdev = MKDEV(mjr, mnr); | ||
| 478 | } | ||
| 479 | } else if (memcmp("IntxLNK", pbuf, 7) == 0) { | ||
| 480 | cifs_dbg(FYI, "Symlink\n"); | ||
| 481 | fattr->cf_mode |= S_IFLNK; | ||
| 482 | fattr->cf_dtype = DT_LNK; | ||
| 483 | } else { | ||
| 484 | fattr->cf_mode |= S_IFREG; /* file? */ | ||
| 485 | fattr->cf_dtype = DT_REG; | ||
| 486 | rc = -EOPNOTSUPP; | ||
| 487 | } | 476 | } |
| 477 | } else if (memcmp("IntxCHR", pbuf, 8) == 0) { | ||
| 478 | cifs_dbg(FYI, "Char device\n"); | ||
| 479 | fattr->cf_mode |= S_IFCHR; | ||
| 480 | fattr->cf_dtype = DT_CHR; | ||
| 481 | if (bytes_read == 24) { | ||
| 482 | /* we have enough to decode dev num */ | ||
| 483 | __u64 mjr; /* major */ | ||
| 484 | __u64 mnr; /* minor */ | ||
| 485 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); | ||
| 486 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); | ||
| 487 | fattr->cf_rdev = MKDEV(mjr, mnr); | ||
| 488 | } | ||
| 489 | } else if (memcmp("IntxLNK", pbuf, 7) == 0) { | ||
| 490 | cifs_dbg(FYI, "Symlink\n"); | ||
| 491 | fattr->cf_mode |= S_IFLNK; | ||
| 492 | fattr->cf_dtype = DT_LNK; | ||
| 488 | } else { | 493 | } else { |
| 489 | fattr->cf_mode |= S_IFREG; /* then it is a file */ | 494 | fattr->cf_mode |= S_IFREG; /* file? */ |
| 490 | fattr->cf_dtype = DT_REG; | 495 | fattr->cf_dtype = DT_REG; |
| 491 | rc = -EOPNOTSUPP; /* or some unknown SFU type */ | 496 | rc = -EOPNOTSUPP; |
| 492 | } | 497 | } |
| 493 | CIFSSMBClose(xid, tcon, netfid); | 498 | } else { |
| 499 | fattr->cf_mode |= S_IFREG; /* then it is a file */ | ||
| 500 | fattr->cf_dtype = DT_REG; | ||
| 501 | rc = -EOPNOTSUPP; /* or some unknown SFU type */ | ||
| 494 | } | 502 | } |
| 503 | CIFSSMBClose(xid, tcon, fid.netfid); | ||
| 495 | cifs_put_tlink(tlink); | 504 | cifs_put_tlink(tlink); |
| 496 | return rc; | 505 | return rc; |
| 497 | } | 506 | } |
| @@ -800,10 +809,10 @@ cifs_get_inode_info(struct inode **inode, const char *full_path, | |||
| 800 | 809 | ||
| 801 | /* check for Minshall+French symlinks */ | 810 | /* check for Minshall+French symlinks */ |
| 802 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { | 811 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { |
| 803 | tmprc = CIFSCheckMFSymlink(xid, tcon, cifs_sb, &fattr, | 812 | tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr, |
| 804 | full_path); | 813 | full_path); |
| 805 | if (tmprc) | 814 | if (tmprc) |
| 806 | cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc); | 815 | cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc); |
| 807 | } | 816 | } |
| 808 | 817 | ||
| 809 | if (!*inode) { | 818 | if (!*inode) { |
| @@ -1032,7 +1041,8 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, | |||
| 1032 | { | 1041 | { |
| 1033 | int oplock = 0; | 1042 | int oplock = 0; |
| 1034 | int rc; | 1043 | int rc; |
| 1035 | __u16 netfid; | 1044 | struct cifs_fid fid; |
| 1045 | struct cifs_open_parms oparms; | ||
| 1036 | struct inode *inode = dentry->d_inode; | 1046 | struct inode *inode = dentry->d_inode; |
| 1037 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | 1047 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); |
| 1038 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 1048 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
| @@ -1055,10 +1065,16 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, | |||
| 1055 | goto out; | 1065 | goto out; |
| 1056 | } | 1066 | } |
| 1057 | 1067 | ||
| 1058 | rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, | 1068 | oparms.tcon = tcon; |
| 1059 | DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR, | 1069 | oparms.cifs_sb = cifs_sb; |
| 1060 | &netfid, &oplock, NULL, cifs_sb->local_nls, | 1070 | oparms.desired_access = DELETE | FILE_WRITE_ATTRIBUTES; |
| 1061 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 1071 | oparms.create_options = CREATE_NOT_DIR; |
| 1072 | oparms.disposition = FILE_OPEN; | ||
| 1073 | oparms.path = full_path; | ||
| 1074 | oparms.fid = &fid; | ||
| 1075 | oparms.reconnect = false; | ||
| 1076 | |||
| 1077 | rc = CIFS_open(xid, &oparms, &oplock, NULL); | ||
| 1062 | if (rc != 0) | 1078 | if (rc != 0) |
| 1063 | goto out; | 1079 | goto out; |
| 1064 | 1080 | ||
| @@ -1079,7 +1095,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, | |||
| 1079 | goto out_close; | 1095 | goto out_close; |
| 1080 | } | 1096 | } |
| 1081 | info_buf->Attributes = cpu_to_le32(dosattr); | 1097 | info_buf->Attributes = cpu_to_le32(dosattr); |
| 1082 | rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid, | 1098 | rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid, |
| 1083 | current->tgid); | 1099 | current->tgid); |
| 1084 | /* although we would like to mark the file hidden | 1100 | /* although we would like to mark the file hidden |
| 1085 | if that fails we will still try to rename it */ | 1101 | if that fails we will still try to rename it */ |
| @@ -1090,7 +1106,8 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, | |||
| 1090 | } | 1106 | } |
| 1091 | 1107 | ||
| 1092 | /* rename the file */ | 1108 | /* rename the file */ |
| 1093 | rc = CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls, | 1109 | rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL, |
| 1110 | cifs_sb->local_nls, | ||
| 1094 | cifs_sb->mnt_cifs_flags & | 1111 | cifs_sb->mnt_cifs_flags & |
| 1095 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1112 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 1096 | if (rc != 0) { | 1113 | if (rc != 0) { |
| @@ -1100,7 +1117,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, | |||
| 1100 | 1117 | ||
| 1101 | /* try to set DELETE_ON_CLOSE */ | 1118 | /* try to set DELETE_ON_CLOSE */ |
| 1102 | if (!cifsInode->delete_pending) { | 1119 | if (!cifsInode->delete_pending) { |
| 1103 | rc = CIFSSMBSetFileDisposition(xid, tcon, true, netfid, | 1120 | rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid, |
| 1104 | current->tgid); | 1121 | current->tgid); |
| 1105 | /* | 1122 | /* |
| 1106 | * some samba versions return -ENOENT when we try to set the | 1123 | * some samba versions return -ENOENT when we try to set the |
| @@ -1120,7 +1137,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, | |||
| 1120 | } | 1137 | } |
| 1121 | 1138 | ||
| 1122 | out_close: | 1139 | out_close: |
| 1123 | CIFSSMBClose(xid, tcon, netfid); | 1140 | CIFSSMBClose(xid, tcon, fid.netfid); |
| 1124 | out: | 1141 | out: |
| 1125 | kfree(info_buf); | 1142 | kfree(info_buf); |
| 1126 | cifs_put_tlink(tlink); | 1143 | cifs_put_tlink(tlink); |
| @@ -1132,13 +1149,13 @@ out: | |||
| 1132 | * them anyway. | 1149 | * them anyway. |
| 1133 | */ | 1150 | */ |
| 1134 | undo_rename: | 1151 | undo_rename: |
| 1135 | CIFSSMBRenameOpenFile(xid, tcon, netfid, dentry->d_name.name, | 1152 | CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name, |
| 1136 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 1153 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
| 1137 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1154 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 1138 | undo_setattr: | 1155 | undo_setattr: |
| 1139 | if (dosattr != origattr) { | 1156 | if (dosattr != origattr) { |
| 1140 | info_buf->Attributes = cpu_to_le32(origattr); | 1157 | info_buf->Attributes = cpu_to_le32(origattr); |
| 1141 | if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid, | 1158 | if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid, |
| 1142 | current->tgid)) | 1159 | current->tgid)) |
| 1143 | cifsInode->cifsAttrs = origattr; | 1160 | cifsInode->cifsAttrs = origattr; |
| 1144 | } | 1161 | } |
| @@ -1549,7 +1566,8 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry, | |||
| 1549 | struct tcon_link *tlink; | 1566 | struct tcon_link *tlink; |
| 1550 | struct cifs_tcon *tcon; | 1567 | struct cifs_tcon *tcon; |
| 1551 | struct TCP_Server_Info *server; | 1568 | struct TCP_Server_Info *server; |
| 1552 | __u16 srcfid; | 1569 | struct cifs_fid fid; |
| 1570 | struct cifs_open_parms oparms; | ||
| 1553 | int oplock, rc; | 1571 | int oplock, rc; |
| 1554 | 1572 | ||
| 1555 | tlink = cifs_sb_tlink(cifs_sb); | 1573 | tlink = cifs_sb_tlink(cifs_sb); |
| @@ -1576,17 +1594,23 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry, | |||
| 1576 | if (to_dentry->d_parent != from_dentry->d_parent) | 1594 | if (to_dentry->d_parent != from_dentry->d_parent) |
| 1577 | goto do_rename_exit; | 1595 | goto do_rename_exit; |
| 1578 | 1596 | ||
| 1597 | oparms.tcon = tcon; | ||
| 1598 | oparms.cifs_sb = cifs_sb; | ||
| 1579 | /* open the file to be renamed -- we need DELETE perms */ | 1599 | /* open the file to be renamed -- we need DELETE perms */ |
| 1580 | rc = CIFSSMBOpen(xid, tcon, from_path, FILE_OPEN, DELETE, | 1600 | oparms.desired_access = DELETE; |
| 1581 | CREATE_NOT_DIR, &srcfid, &oplock, NULL, | 1601 | oparms.create_options = CREATE_NOT_DIR; |
| 1582 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 1602 | oparms.disposition = FILE_OPEN; |
| 1583 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1603 | oparms.path = from_path; |
| 1604 | oparms.fid = &fid; | ||
| 1605 | oparms.reconnect = false; | ||
| 1606 | |||
| 1607 | rc = CIFS_open(xid, &oparms, &oplock, NULL); | ||
| 1584 | if (rc == 0) { | 1608 | if (rc == 0) { |
| 1585 | rc = CIFSSMBRenameOpenFile(xid, tcon, srcfid, | 1609 | rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, |
| 1586 | (const char *) to_dentry->d_name.name, | 1610 | (const char *) to_dentry->d_name.name, |
| 1587 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 1611 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
| 1588 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1612 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 1589 | CIFSSMBClose(xid, tcon, srcfid); | 1613 | CIFSSMBClose(xid, tcon, fid.netfid); |
| 1590 | } | 1614 | } |
| 1591 | do_rename_exit: | 1615 | do_rename_exit: |
| 1592 | cifs_put_tlink(tlink); | 1616 | cifs_put_tlink(tlink); |
diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 92aee08483a5..264ece71bdb2 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c | |||
| @@ -29,6 +29,10 @@ | |||
| 29 | #include "cifs_debug.h" | 29 | #include "cifs_debug.h" |
| 30 | #include "cifs_fs_sb.h" | 30 | #include "cifs_fs_sb.h" |
| 31 | 31 | ||
| 32 | /* | ||
| 33 | * M-F Symlink Functions - Begin | ||
| 34 | */ | ||
| 35 | |||
| 32 | #define CIFS_MF_SYMLINK_LEN_OFFSET (4+1) | 36 | #define CIFS_MF_SYMLINK_LEN_OFFSET (4+1) |
| 33 | #define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1)) | 37 | #define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1)) |
| 34 | #define CIFS_MF_SYMLINK_LINK_OFFSET (CIFS_MF_SYMLINK_MD5_OFFSET+(32+1)) | 38 | #define CIFS_MF_SYMLINK_LINK_OFFSET (CIFS_MF_SYMLINK_MD5_OFFSET+(32+1)) |
| @@ -91,10 +95,8 @@ symlink_hash_err: | |||
| 91 | } | 95 | } |
| 92 | 96 | ||
| 93 | static int | 97 | static int |
| 94 | CIFSParseMFSymlink(const u8 *buf, | 98 | parse_mf_symlink(const u8 *buf, unsigned int buf_len, unsigned int *_link_len, |
| 95 | unsigned int buf_len, | 99 | char **_link_str) |
| 96 | unsigned int *_link_len, | ||
| 97 | char **_link_str) | ||
| 98 | { | 100 | { |
| 99 | int rc; | 101 | int rc; |
| 100 | unsigned int link_len; | 102 | unsigned int link_len; |
| @@ -137,7 +139,7 @@ CIFSParseMFSymlink(const u8 *buf, | |||
| 137 | } | 139 | } |
| 138 | 140 | ||
| 139 | static int | 141 | static int |
| 140 | CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str) | 142 | format_mf_symlink(u8 *buf, unsigned int buf_len, const char *link_str) |
| 141 | { | 143 | { |
| 142 | int rc; | 144 | int rc; |
| 143 | unsigned int link_len; | 145 | unsigned int link_len; |
| @@ -180,190 +182,94 @@ CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str) | |||
| 180 | return 0; | 182 | return 0; |
| 181 | } | 183 | } |
| 182 | 184 | ||
| 185 | bool | ||
| 186 | couldbe_mf_symlink(const struct cifs_fattr *fattr) | ||
| 187 | { | ||
| 188 | if (!S_ISREG(fattr->cf_mode)) | ||
| 189 | /* it's not a symlink */ | ||
| 190 | return false; | ||
| 191 | |||
| 192 | if (fattr->cf_eof != CIFS_MF_SYMLINK_FILE_SIZE) | ||
| 193 | /* it's not a symlink */ | ||
| 194 | return false; | ||
| 195 | |||
| 196 | return true; | ||
| 197 | } | ||
| 198 | |||
| 183 | static int | 199 | static int |
| 184 | CIFSCreateMFSymLink(const unsigned int xid, struct cifs_tcon *tcon, | 200 | create_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon, |
| 185 | const char *fromName, const char *toName, | 201 | struct cifs_sb_info *cifs_sb, const char *fromName, |
| 186 | struct cifs_sb_info *cifs_sb) | 202 | const char *toName) |
| 187 | { | 203 | { |
| 188 | int rc; | 204 | int rc; |
| 189 | int oplock = 0; | ||
| 190 | int remap; | ||
| 191 | int create_options = CREATE_NOT_DIR; | ||
| 192 | __u16 netfid = 0; | ||
| 193 | u8 *buf; | 205 | u8 *buf; |
| 194 | unsigned int bytes_written = 0; | 206 | unsigned int bytes_written = 0; |
| 195 | struct cifs_io_parms io_parms; | ||
| 196 | struct nls_table *nls_codepage; | ||
| 197 | |||
| 198 | nls_codepage = cifs_sb->local_nls; | ||
| 199 | remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR; | ||
| 200 | 207 | ||
| 201 | buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); | 208 | buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); |
| 202 | if (!buf) | 209 | if (!buf) |
| 203 | return -ENOMEM; | 210 | return -ENOMEM; |
| 204 | 211 | ||
| 205 | rc = CIFSFormatMFSymlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName); | 212 | rc = format_mf_symlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName); |
| 206 | if (rc != 0) { | 213 | if (rc) |
| 207 | kfree(buf); | 214 | goto out; |
| 208 | return rc; | ||
| 209 | } | ||
| 210 | |||
| 211 | if (backup_cred(cifs_sb)) | ||
| 212 | create_options |= CREATE_OPEN_BACKUP_INTENT; | ||
| 213 | |||
| 214 | rc = CIFSSMBOpen(xid, tcon, fromName, FILE_CREATE, GENERIC_WRITE, | ||
| 215 | create_options, &netfid, &oplock, NULL, | ||
| 216 | nls_codepage, remap); | ||
| 217 | if (rc != 0) { | ||
| 218 | kfree(buf); | ||
| 219 | return rc; | ||
| 220 | } | ||
| 221 | |||
| 222 | io_parms.netfid = netfid; | ||
| 223 | io_parms.pid = current->tgid; | ||
| 224 | io_parms.tcon = tcon; | ||
| 225 | io_parms.offset = 0; | ||
| 226 | io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; | ||
| 227 | 215 | ||
| 228 | rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, buf, NULL, 0); | 216 | rc = tcon->ses->server->ops->create_mf_symlink(xid, tcon, cifs_sb, |
| 229 | CIFSSMBClose(xid, tcon, netfid); | 217 | fromName, buf, &bytes_written); |
| 230 | kfree(buf); | 218 | if (rc) |
| 231 | if (rc != 0) | 219 | goto out; |
| 232 | return rc; | ||
| 233 | 220 | ||
| 234 | if (bytes_written != CIFS_MF_SYMLINK_FILE_SIZE) | 221 | if (bytes_written != CIFS_MF_SYMLINK_FILE_SIZE) |
| 235 | return -EIO; | 222 | rc = -EIO; |
| 236 | 223 | out: | |
| 237 | return 0; | 224 | kfree(buf); |
| 225 | return rc; | ||
| 238 | } | 226 | } |
| 239 | 227 | ||
| 240 | static int | 228 | static int |
| 241 | CIFSQueryMFSymLink(const unsigned int xid, struct cifs_tcon *tcon, | 229 | query_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon, |
| 242 | const unsigned char *searchName, char **symlinkinfo, | 230 | struct cifs_sb_info *cifs_sb, const unsigned char *path, |
| 243 | const struct nls_table *nls_codepage, int remap) | 231 | char **symlinkinfo) |
| 244 | { | 232 | { |
| 245 | int rc; | 233 | int rc; |
| 246 | int oplock = 0; | 234 | u8 *buf = NULL; |
| 247 | __u16 netfid = 0; | ||
| 248 | u8 *buf; | ||
| 249 | char *pbuf; | ||
| 250 | unsigned int bytes_read = 0; | ||
| 251 | int buf_type = CIFS_NO_BUFFER; | ||
| 252 | unsigned int link_len = 0; | 235 | unsigned int link_len = 0; |
| 253 | struct cifs_io_parms io_parms; | 236 | unsigned int bytes_read = 0; |
| 254 | FILE_ALL_INFO file_info; | ||
| 255 | |||
| 256 | rc = CIFSSMBOpen(xid, tcon, searchName, FILE_OPEN, GENERIC_READ, | ||
| 257 | CREATE_NOT_DIR, &netfid, &oplock, &file_info, | ||
| 258 | nls_codepage, remap); | ||
| 259 | if (rc != 0) | ||
| 260 | return rc; | ||
| 261 | |||
| 262 | if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) { | ||
| 263 | CIFSSMBClose(xid, tcon, netfid); | ||
| 264 | /* it's not a symlink */ | ||
| 265 | return -EINVAL; | ||
| 266 | } | ||
| 267 | 237 | ||
| 268 | buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); | 238 | buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); |
| 269 | if (!buf) | 239 | if (!buf) |
| 270 | return -ENOMEM; | 240 | return -ENOMEM; |
| 271 | pbuf = buf; | ||
| 272 | io_parms.netfid = netfid; | ||
| 273 | io_parms.pid = current->tgid; | ||
| 274 | io_parms.tcon = tcon; | ||
| 275 | io_parms.offset = 0; | ||
| 276 | io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; | ||
| 277 | |||
| 278 | rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, &buf_type); | ||
| 279 | CIFSSMBClose(xid, tcon, netfid); | ||
| 280 | if (rc != 0) { | ||
| 281 | kfree(buf); | ||
| 282 | return rc; | ||
| 283 | } | ||
| 284 | |||
| 285 | rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, symlinkinfo); | ||
| 286 | kfree(buf); | ||
| 287 | if (rc != 0) | ||
| 288 | return rc; | ||
| 289 | |||
| 290 | return 0; | ||
| 291 | } | ||
| 292 | |||
| 293 | bool | ||
| 294 | CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr) | ||
| 295 | { | ||
| 296 | if (!(fattr->cf_mode & S_IFREG)) | ||
| 297 | /* it's not a symlink */ | ||
| 298 | return false; | ||
| 299 | 241 | ||
| 300 | if (fattr->cf_eof != CIFS_MF_SYMLINK_FILE_SIZE) | 242 | if (tcon->ses->server->ops->query_mf_symlink) |
| 301 | /* it's not a symlink */ | 243 | rc = tcon->ses->server->ops->query_mf_symlink(xid, tcon, |
| 302 | return false; | 244 | cifs_sb, path, buf, &bytes_read); |
| 303 | 245 | else | |
| 304 | return true; | 246 | rc = -ENOSYS; |
| 305 | } | ||
| 306 | |||
| 307 | int | ||
| 308 | open_query_close_cifs_symlink(const unsigned char *path, char *pbuf, | ||
| 309 | unsigned int *pbytes_read, struct cifs_sb_info *cifs_sb, | ||
| 310 | unsigned int xid) | ||
| 311 | { | ||
| 312 | int rc; | ||
| 313 | int oplock = 0; | ||
| 314 | __u16 netfid = 0; | ||
| 315 | struct tcon_link *tlink; | ||
| 316 | struct cifs_tcon *ptcon; | ||
| 317 | struct cifs_io_parms io_parms; | ||
| 318 | int buf_type = CIFS_NO_BUFFER; | ||
| 319 | FILE_ALL_INFO file_info; | ||
| 320 | |||
| 321 | tlink = cifs_sb_tlink(cifs_sb); | ||
| 322 | if (IS_ERR(tlink)) | ||
| 323 | return PTR_ERR(tlink); | ||
| 324 | ptcon = tlink_tcon(tlink); | ||
| 325 | 247 | ||
| 326 | rc = CIFSSMBOpen(xid, ptcon, path, FILE_OPEN, GENERIC_READ, | 248 | if (rc) |
| 327 | CREATE_NOT_DIR, &netfid, &oplock, &file_info, | 249 | goto out; |
| 328 | cifs_sb->local_nls, | ||
| 329 | cifs_sb->mnt_cifs_flags & | ||
| 330 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
| 331 | if (rc != 0) { | ||
| 332 | cifs_put_tlink(tlink); | ||
| 333 | return rc; | ||
| 334 | } | ||
| 335 | 250 | ||
| 336 | if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) { | 251 | if (bytes_read == 0) { /* not a symlink */ |
| 337 | CIFSSMBClose(xid, ptcon, netfid); | 252 | rc = -EINVAL; |
| 338 | cifs_put_tlink(tlink); | 253 | goto out; |
| 339 | /* it's not a symlink */ | ||
| 340 | return rc; | ||
| 341 | } | 254 | } |
| 342 | 255 | ||
| 343 | io_parms.netfid = netfid; | 256 | rc = parse_mf_symlink(buf, bytes_read, &link_len, symlinkinfo); |
| 344 | io_parms.pid = current->tgid; | 257 | out: |
| 345 | io_parms.tcon = ptcon; | 258 | kfree(buf); |
| 346 | io_parms.offset = 0; | ||
| 347 | io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; | ||
| 348 | |||
| 349 | rc = CIFSSMBRead(xid, &io_parms, pbytes_read, &pbuf, &buf_type); | ||
| 350 | CIFSSMBClose(xid, ptcon, netfid); | ||
| 351 | cifs_put_tlink(tlink); | ||
| 352 | return rc; | 259 | return rc; |
| 353 | } | 260 | } |
| 354 | 261 | ||
| 355 | |||
| 356 | int | 262 | int |
| 357 | CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon, | 263 | check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, |
| 358 | struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, | 264 | struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, |
| 359 | const unsigned char *path) | 265 | const unsigned char *path) |
| 360 | { | 266 | { |
| 361 | int rc; | 267 | int rc; |
| 362 | u8 *buf = NULL; | 268 | u8 *buf = NULL; |
| 363 | unsigned int link_len = 0; | 269 | unsigned int link_len = 0; |
| 364 | unsigned int bytes_read = 0; | 270 | unsigned int bytes_read = 0; |
| 365 | 271 | ||
| 366 | if (!CIFSCouldBeMFSymlink(fattr)) | 272 | if (!couldbe_mf_symlink(fattr)) |
| 367 | /* it's not a symlink */ | 273 | /* it's not a symlink */ |
| 368 | return 0; | 274 | return 0; |
| 369 | 275 | ||
| @@ -372,8 +278,8 @@ CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon, | |||
| 372 | return -ENOMEM; | 278 | return -ENOMEM; |
| 373 | 279 | ||
| 374 | if (tcon->ses->server->ops->query_mf_symlink) | 280 | if (tcon->ses->server->ops->query_mf_symlink) |
| 375 | rc = tcon->ses->server->ops->query_mf_symlink(path, buf, | 281 | rc = tcon->ses->server->ops->query_mf_symlink(xid, tcon, |
| 376 | &bytes_read, cifs_sb, xid); | 282 | cifs_sb, path, buf, &bytes_read); |
| 377 | else | 283 | else |
| 378 | rc = -ENOSYS; | 284 | rc = -ENOSYS; |
| 379 | 285 | ||
| @@ -383,7 +289,7 @@ CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon, | |||
| 383 | if (bytes_read == 0) /* not a symlink */ | 289 | if (bytes_read == 0) /* not a symlink */ |
| 384 | goto out; | 290 | goto out; |
| 385 | 291 | ||
| 386 | rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, NULL); | 292 | rc = parse_mf_symlink(buf, bytes_read, &link_len, NULL); |
| 387 | if (rc == -EINVAL) { | 293 | if (rc == -EINVAL) { |
| 388 | /* it's not a symlink */ | 294 | /* it's not a symlink */ |
| 389 | rc = 0; | 295 | rc = 0; |
| @@ -403,6 +309,95 @@ out: | |||
| 403 | return rc; | 309 | return rc; |
| 404 | } | 310 | } |
| 405 | 311 | ||
| 312 | /* | ||
| 313 | * SMB 1.0 Protocol specific functions | ||
| 314 | */ | ||
| 315 | |||
| 316 | int | ||
| 317 | cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, | ||
| 318 | struct cifs_sb_info *cifs_sb, const unsigned char *path, | ||
| 319 | char *pbuf, unsigned int *pbytes_read) | ||
| 320 | { | ||
| 321 | int rc; | ||
| 322 | int oplock = 0; | ||
| 323 | struct cifs_fid fid; | ||
| 324 | struct cifs_open_parms oparms; | ||
| 325 | struct cifs_io_parms io_parms; | ||
| 326 | int buf_type = CIFS_NO_BUFFER; | ||
| 327 | FILE_ALL_INFO file_info; | ||
| 328 | |||
| 329 | oparms.tcon = tcon; | ||
| 330 | oparms.cifs_sb = cifs_sb; | ||
| 331 | oparms.desired_access = GENERIC_READ; | ||
| 332 | oparms.create_options = CREATE_NOT_DIR; | ||
| 333 | oparms.disposition = FILE_OPEN; | ||
| 334 | oparms.path = path; | ||
| 335 | oparms.fid = &fid; | ||
| 336 | oparms.reconnect = false; | ||
| 337 | |||
| 338 | rc = CIFS_open(xid, &oparms, &oplock, &file_info); | ||
| 339 | if (rc) | ||
| 340 | return rc; | ||
| 341 | |||
| 342 | if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) | ||
| 343 | /* it's not a symlink */ | ||
| 344 | goto out; | ||
| 345 | |||
| 346 | io_parms.netfid = fid.netfid; | ||
| 347 | io_parms.pid = current->tgid; | ||
| 348 | io_parms.tcon = tcon; | ||
| 349 | io_parms.offset = 0; | ||
| 350 | io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; | ||
| 351 | |||
| 352 | rc = CIFSSMBRead(xid, &io_parms, pbytes_read, &pbuf, &buf_type); | ||
| 353 | out: | ||
| 354 | CIFSSMBClose(xid, tcon, fid.netfid); | ||
| 355 | return rc; | ||
| 356 | } | ||
| 357 | |||
| 358 | int | ||
| 359 | cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, | ||
| 360 | struct cifs_sb_info *cifs_sb, const unsigned char *path, | ||
| 361 | char *pbuf, unsigned int *pbytes_written) | ||
| 362 | { | ||
| 363 | int rc; | ||
| 364 | int oplock = 0; | ||
| 365 | struct cifs_fid fid; | ||
| 366 | struct cifs_open_parms oparms; | ||
| 367 | struct cifs_io_parms io_parms; | ||
| 368 | int create_options = CREATE_NOT_DIR; | ||
| 369 | |||
| 370 | if (backup_cred(cifs_sb)) | ||
| 371 | create_options |= CREATE_OPEN_BACKUP_INTENT; | ||
| 372 | |||
| 373 | oparms.tcon = tcon; | ||
| 374 | oparms.cifs_sb = cifs_sb; | ||
| 375 | oparms.desired_access = GENERIC_WRITE; | ||
| 376 | oparms.create_options = create_options; | ||
| 377 | oparms.disposition = FILE_OPEN; | ||
| 378 | oparms.path = path; | ||
| 379 | oparms.fid = &fid; | ||
| 380 | oparms.reconnect = false; | ||
| 381 | |||
| 382 | rc = CIFS_open(xid, &oparms, &oplock, NULL); | ||
| 383 | if (rc) | ||
| 384 | return rc; | ||
| 385 | |||
| 386 | io_parms.netfid = fid.netfid; | ||
| 387 | io_parms.pid = current->tgid; | ||
| 388 | io_parms.tcon = tcon; | ||
| 389 | io_parms.offset = 0; | ||
| 390 | io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; | ||
| 391 | |||
| 392 | rc = CIFSSMBWrite(xid, &io_parms, pbytes_written, pbuf, NULL, 0); | ||
| 393 | CIFSSMBClose(xid, tcon, fid.netfid); | ||
| 394 | return rc; | ||
| 395 | } | ||
| 396 | |||
| 397 | /* | ||
| 398 | * M-F Symlink Functions - End | ||
| 399 | */ | ||
| 400 | |||
| 406 | int | 401 | int |
| 407 | cifs_hardlink(struct dentry *old_file, struct inode *inode, | 402 | cifs_hardlink(struct dentry *old_file, struct inode *inode, |
| 408 | struct dentry *direntry) | 403 | struct dentry *direntry) |
| @@ -438,8 +433,10 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, | |||
| 438 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 433 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 439 | else { | 434 | else { |
| 440 | server = tcon->ses->server; | 435 | server = tcon->ses->server; |
| 441 | if (!server->ops->create_hardlink) | 436 | if (!server->ops->create_hardlink) { |
| 442 | return -ENOSYS; | 437 | rc = -ENOSYS; |
| 438 | goto cifs_hl_exit; | ||
| 439 | } | ||
| 443 | rc = server->ops->create_hardlink(xid, tcon, from_name, to_name, | 440 | rc = server->ops->create_hardlink(xid, tcon, from_name, to_name, |
| 444 | cifs_sb); | 441 | cifs_sb); |
| 445 | if ((rc == -EIO) || (rc == -EINVAL)) | 442 | if ((rc == -EIO) || (rc == -EINVAL)) |
| @@ -530,15 +527,10 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd) | |||
| 530 | * and fallback to UNIX Extensions Symlinks. | 527 | * and fallback to UNIX Extensions Symlinks. |
| 531 | */ | 528 | */ |
| 532 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) | 529 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) |
| 533 | rc = CIFSQueryMFSymLink(xid, tcon, full_path, &target_path, | 530 | rc = query_mf_symlink(xid, tcon, cifs_sb, full_path, |
| 534 | cifs_sb->local_nls, | 531 | &target_path); |
| 535 | cifs_sb->mnt_cifs_flags & | ||
| 536 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
| 537 | 532 | ||
| 538 | if ((rc != 0) && cap_unix(tcon->ses)) | 533 | if (rc != 0 && server->ops->query_symlink) |
| 539 | rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path, | ||
| 540 | cifs_sb->local_nls); | ||
| 541 | else if (rc != 0 && server->ops->query_symlink) | ||
| 542 | rc = server->ops->query_symlink(xid, tcon, full_path, | 534 | rc = server->ops->query_symlink(xid, tcon, full_path, |
| 543 | &target_path, cifs_sb); | 535 | &target_path, cifs_sb); |
| 544 | 536 | ||
| @@ -587,8 +579,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) | |||
| 587 | 579 | ||
| 588 | /* BB what if DFS and this volume is on different share? BB */ | 580 | /* BB what if DFS and this volume is on different share? BB */ |
| 589 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) | 581 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) |
| 590 | rc = CIFSCreateMFSymLink(xid, pTcon, full_path, symname, | 582 | rc = create_mf_symlink(xid, pTcon, cifs_sb, full_path, symname); |
| 591 | cifs_sb); | ||
| 592 | else if (pTcon->unix_ext) | 583 | else if (pTcon->unix_ext) |
| 593 | rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname, | 584 | rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname, |
| 594 | cifs_sb->local_nls); | 585 | cifs_sb->local_nls); |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 5940ecabbe6a..b15862e0f68c 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
| @@ -749,7 +749,7 @@ static int cifs_filldir(char *find_entry, struct file *file, | |||
| 749 | } | 749 | } |
| 750 | 750 | ||
| 751 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) && | 751 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) && |
| 752 | CIFSCouldBeMFSymlink(&fattr)) | 752 | couldbe_mf_symlink(&fattr)) |
| 753 | /* | 753 | /* |
| 754 | * trying to get the type and mode can be slow, | 754 | * trying to get the type and mode can be slow, |
| 755 | * so just call those regular files for now, and mark | 755 | * so just call those regular files for now, and mark |
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index 5f5ba0dc2ee1..9ac5bfc9cc56 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c | |||
| @@ -560,17 +560,24 @@ cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 560 | if (!rc && (le32_to_cpu(data->Attributes) & ATTR_REPARSE)) { | 560 | if (!rc && (le32_to_cpu(data->Attributes) & ATTR_REPARSE)) { |
| 561 | int tmprc; | 561 | int tmprc; |
| 562 | int oplock = 0; | 562 | int oplock = 0; |
| 563 | __u16 netfid; | 563 | struct cifs_fid fid; |
| 564 | struct cifs_open_parms oparms; | ||
| 565 | |||
| 566 | oparms.tcon = tcon; | ||
| 567 | oparms.cifs_sb = cifs_sb; | ||
| 568 | oparms.desired_access = FILE_READ_ATTRIBUTES; | ||
| 569 | oparms.create_options = 0; | ||
| 570 | oparms.disposition = FILE_OPEN; | ||
| 571 | oparms.path = full_path; | ||
| 572 | oparms.fid = &fid; | ||
| 573 | oparms.reconnect = false; | ||
| 564 | 574 | ||
| 565 | /* Need to check if this is a symbolic link or not */ | 575 | /* Need to check if this is a symbolic link or not */ |
| 566 | tmprc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, | 576 | tmprc = CIFS_open(xid, &oparms, &oplock, NULL); |
| 567 | FILE_READ_ATTRIBUTES, 0, &netfid, &oplock, | ||
| 568 | NULL, cifs_sb->local_nls, | ||
| 569 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
| 570 | if (tmprc == -EOPNOTSUPP) | 577 | if (tmprc == -EOPNOTSUPP) |
| 571 | *symlink = true; | 578 | *symlink = true; |
| 572 | else | 579 | else |
| 573 | CIFSSMBClose(xid, tcon, netfid); | 580 | CIFSSMBClose(xid, tcon, fid.netfid); |
| 574 | } | 581 | } |
| 575 | 582 | ||
| 576 | return rc; | 583 | return rc; |
| @@ -705,12 +712,7 @@ cifs_open_file(const unsigned int xid, struct cifs_open_parms *oparms, | |||
| 705 | oparms->cifs_sb->local_nls, | 712 | oparms->cifs_sb->local_nls, |
| 706 | oparms->cifs_sb->mnt_cifs_flags | 713 | oparms->cifs_sb->mnt_cifs_flags |
| 707 | & CIFS_MOUNT_MAP_SPECIAL_CHR); | 714 | & CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 708 | return CIFSSMBOpen(xid, oparms->tcon, oparms->path, | 715 | return CIFS_open(xid, oparms, oplock, buf); |
| 709 | oparms->disposition, oparms->desired_access, | ||
| 710 | oparms->create_options, &oparms->fid->netfid, oplock, | ||
| 711 | buf, oparms->cifs_sb->local_nls, | ||
| 712 | oparms->cifs_sb->mnt_cifs_flags & | ||
| 713 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
| 714 | } | 716 | } |
| 715 | 717 | ||
| 716 | static void | 718 | static void |
| @@ -761,8 +763,9 @@ smb_set_file_info(struct inode *inode, const char *full_path, | |||
| 761 | { | 763 | { |
| 762 | int oplock = 0; | 764 | int oplock = 0; |
| 763 | int rc; | 765 | int rc; |
| 764 | __u16 netfid; | ||
| 765 | __u32 netpid; | 766 | __u32 netpid; |
| 767 | struct cifs_fid fid; | ||
| 768 | struct cifs_open_parms oparms; | ||
| 766 | struct cifsFileInfo *open_file; | 769 | struct cifsFileInfo *open_file; |
| 767 | struct cifsInodeInfo *cinode = CIFS_I(inode); | 770 | struct cifsInodeInfo *cinode = CIFS_I(inode); |
| 768 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 771 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
| @@ -772,7 +775,7 @@ smb_set_file_info(struct inode *inode, const char *full_path, | |||
| 772 | /* if the file is already open for write, just use that fileid */ | 775 | /* if the file is already open for write, just use that fileid */ |
| 773 | open_file = find_writable_file(cinode, true); | 776 | open_file = find_writable_file(cinode, true); |
| 774 | if (open_file) { | 777 | if (open_file) { |
| 775 | netfid = open_file->fid.netfid; | 778 | fid.netfid = open_file->fid.netfid; |
| 776 | netpid = open_file->pid; | 779 | netpid = open_file->pid; |
| 777 | tcon = tlink_tcon(open_file->tlink); | 780 | tcon = tlink_tcon(open_file->tlink); |
| 778 | goto set_via_filehandle; | 781 | goto set_via_filehandle; |
| @@ -796,12 +799,17 @@ smb_set_file_info(struct inode *inode, const char *full_path, | |||
| 796 | goto out; | 799 | goto out; |
| 797 | } | 800 | } |
| 798 | 801 | ||
| 799 | cifs_dbg(FYI, "calling SetFileInfo since SetPathInfo for times not supported by this server\n"); | 802 | oparms.tcon = tcon; |
| 800 | rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, | 803 | oparms.cifs_sb = cifs_sb; |
| 801 | SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR, | 804 | oparms.desired_access = SYNCHRONIZE | FILE_WRITE_ATTRIBUTES; |
| 802 | &netfid, &oplock, NULL, cifs_sb->local_nls, | 805 | oparms.create_options = CREATE_NOT_DIR; |
| 803 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 806 | oparms.disposition = FILE_OPEN; |
| 807 | oparms.path = full_path; | ||
| 808 | oparms.fid = &fid; | ||
| 809 | oparms.reconnect = false; | ||
| 804 | 810 | ||
| 811 | cifs_dbg(FYI, "calling SetFileInfo since SetPathInfo for times not supported by this server\n"); | ||
| 812 | rc = CIFS_open(xid, &oparms, &oplock, NULL); | ||
| 805 | if (rc != 0) { | 813 | if (rc != 0) { |
| 806 | if (rc == -EIO) | 814 | if (rc == -EIO) |
| 807 | rc = -EINVAL; | 815 | rc = -EINVAL; |
| @@ -811,12 +819,12 @@ smb_set_file_info(struct inode *inode, const char *full_path, | |||
| 811 | netpid = current->tgid; | 819 | netpid = current->tgid; |
| 812 | 820 | ||
| 813 | set_via_filehandle: | 821 | set_via_filehandle: |
| 814 | rc = CIFSSMBSetFileInfo(xid, tcon, buf, netfid, netpid); | 822 | rc = CIFSSMBSetFileInfo(xid, tcon, buf, fid.netfid, netpid); |
| 815 | if (!rc) | 823 | if (!rc) |
| 816 | cinode->cifsAttrs = le32_to_cpu(buf->Attributes); | 824 | cinode->cifsAttrs = le32_to_cpu(buf->Attributes); |
| 817 | 825 | ||
| 818 | if (open_file == NULL) | 826 | if (open_file == NULL) |
| 819 | CIFSSMBClose(xid, tcon, netfid); | 827 | CIFSSMBClose(xid, tcon, fid.netfid); |
| 820 | else | 828 | else |
| 821 | cifsFileInfo_put(open_file); | 829 | cifsFileInfo_put(open_file); |
| 822 | out: | 830 | out: |
| @@ -908,33 +916,80 @@ cifs_mand_lock(const unsigned int xid, struct cifsFileInfo *cfile, __u64 offset, | |||
| 908 | } | 916 | } |
| 909 | 917 | ||
| 910 | static int | 918 | static int |
| 919 | cifs_unix_dfs_readlink(const unsigned int xid, struct cifs_tcon *tcon, | ||
| 920 | const unsigned char *searchName, char **symlinkinfo, | ||
| 921 | const struct nls_table *nls_codepage) | ||
| 922 | { | ||
| 923 | #ifdef CONFIG_CIFS_DFS_UPCALL | ||
| 924 | int rc; | ||
| 925 | unsigned int num_referrals = 0; | ||
| 926 | struct dfs_info3_param *referrals = NULL; | ||
| 927 | |||
| 928 | rc = get_dfs_path(xid, tcon->ses, searchName, nls_codepage, | ||
| 929 | &num_referrals, &referrals, 0); | ||
| 930 | |||
| 931 | if (!rc && num_referrals > 0) { | ||
| 932 | *symlinkinfo = kstrndup(referrals->node_name, | ||
| 933 | strlen(referrals->node_name), | ||
| 934 | GFP_KERNEL); | ||
| 935 | if (!*symlinkinfo) | ||
| 936 | rc = -ENOMEM; | ||
| 937 | free_dfs_info_array(referrals, num_referrals); | ||
| 938 | } | ||
| 939 | return rc; | ||
| 940 | #else /* No DFS support */ | ||
| 941 | return -EREMOTE; | ||
| 942 | #endif | ||
| 943 | } | ||
| 944 | |||
| 945 | static int | ||
| 911 | cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, | 946 | cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, |
| 912 | const char *full_path, char **target_path, | 947 | const char *full_path, char **target_path, |
| 913 | struct cifs_sb_info *cifs_sb) | 948 | struct cifs_sb_info *cifs_sb) |
| 914 | { | 949 | { |
| 915 | int rc; | 950 | int rc; |
| 916 | int oplock = 0; | 951 | int oplock = 0; |
| 917 | __u16 netfid; | 952 | struct cifs_fid fid; |
| 953 | struct cifs_open_parms oparms; | ||
| 918 | 954 | ||
| 919 | cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path); | 955 | cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path); |
| 920 | 956 | ||
| 921 | rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, | 957 | /* Check for unix extensions */ |
| 922 | FILE_READ_ATTRIBUTES, OPEN_REPARSE_POINT, &netfid, | 958 | if (cap_unix(tcon->ses)) { |
| 923 | &oplock, NULL, cifs_sb->local_nls, | 959 | rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, target_path, |
| 924 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 960 | cifs_sb->local_nls); |
| 961 | if (rc == -EREMOTE) | ||
| 962 | rc = cifs_unix_dfs_readlink(xid, tcon, full_path, | ||
| 963 | target_path, | ||
| 964 | cifs_sb->local_nls); | ||
| 965 | |||
| 966 | goto out; | ||
| 967 | } | ||
| 968 | |||
| 969 | oparms.tcon = tcon; | ||
| 970 | oparms.cifs_sb = cifs_sb; | ||
| 971 | oparms.desired_access = FILE_READ_ATTRIBUTES; | ||
| 972 | oparms.create_options = OPEN_REPARSE_POINT; | ||
| 973 | oparms.disposition = FILE_OPEN; | ||
| 974 | oparms.path = full_path; | ||
| 975 | oparms.fid = &fid; | ||
| 976 | oparms.reconnect = false; | ||
| 977 | |||
| 978 | rc = CIFS_open(xid, &oparms, &oplock, NULL); | ||
| 925 | if (rc) | 979 | if (rc) |
| 926 | return rc; | 980 | goto out; |
| 927 | 981 | ||
| 928 | rc = CIFSSMBQuerySymLink(xid, tcon, netfid, target_path, | 982 | rc = CIFSSMBQuerySymLink(xid, tcon, fid.netfid, target_path, |
| 929 | cifs_sb->local_nls); | 983 | cifs_sb->local_nls); |
| 930 | if (rc) { | 984 | if (rc) |
| 931 | CIFSSMBClose(xid, tcon, netfid); | 985 | goto out_close; |
| 932 | return rc; | ||
| 933 | } | ||
| 934 | 986 | ||
| 935 | convert_delimiter(*target_path, '/'); | 987 | convert_delimiter(*target_path, '/'); |
| 936 | CIFSSMBClose(xid, tcon, netfid); | 988 | out_close: |
| 937 | cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path); | 989 | CIFSSMBClose(xid, tcon, fid.netfid); |
| 990 | out: | ||
| 991 | if (!rc) | ||
| 992 | cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path); | ||
| 938 | return rc; | 993 | return rc; |
| 939 | } | 994 | } |
| 940 | 995 | ||
| @@ -1009,7 +1064,8 @@ struct smb_version_operations smb1_operations = { | |||
| 1009 | .mand_lock = cifs_mand_lock, | 1064 | .mand_lock = cifs_mand_lock, |
| 1010 | .mand_unlock_range = cifs_unlock_range, | 1065 | .mand_unlock_range = cifs_unlock_range, |
| 1011 | .push_mand_locks = cifs_push_mandatory_locks, | 1066 | .push_mand_locks = cifs_push_mandatory_locks, |
| 1012 | .query_mf_symlink = open_query_close_cifs_symlink, | 1067 | .query_mf_symlink = cifs_query_mf_symlink, |
| 1068 | .create_mf_symlink = cifs_create_mf_symlink, | ||
| 1013 | .is_read_op = cifs_is_read_op, | 1069 | .is_read_op = cifs_is_read_op, |
| 1014 | }; | 1070 | }; |
| 1015 | 1071 | ||
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index 09afda4cc58e..95c43bb20335 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c | |||
| @@ -82,9 +82,11 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name) | |||
| 82 | goto remove_ea_exit; | 82 | goto remove_ea_exit; |
| 83 | 83 | ||
| 84 | ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ | 84 | ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ |
| 85 | rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, NULL, | 85 | if (pTcon->ses->server->ops->set_EA) |
| 86 | (__u16)0, cifs_sb->local_nls, | 86 | rc = pTcon->ses->server->ops->set_EA(xid, pTcon, |
| 87 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 87 | full_path, ea_name, NULL, (__u16)0, |
| 88 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | ||
| 89 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
| 88 | } | 90 | } |
| 89 | remove_ea_exit: | 91 | remove_ea_exit: |
| 90 | kfree(full_path); | 92 | kfree(full_path); |
| @@ -149,18 +151,22 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, | |||
| 149 | cifs_dbg(FYI, "attempt to set cifs inode metadata\n"); | 151 | cifs_dbg(FYI, "attempt to set cifs inode metadata\n"); |
| 150 | 152 | ||
| 151 | ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ | 153 | ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ |
| 152 | rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value, | 154 | if (pTcon->ses->server->ops->set_EA) |
| 153 | (__u16)value_size, cifs_sb->local_nls, | 155 | rc = pTcon->ses->server->ops->set_EA(xid, pTcon, |
| 154 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 156 | full_path, ea_name, ea_value, (__u16)value_size, |
| 157 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | ||
| 158 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
| 155 | } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) | 159 | } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) |
| 156 | == 0) { | 160 | == 0) { |
| 157 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) | 161 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) |
| 158 | goto set_ea_exit; | 162 | goto set_ea_exit; |
| 159 | 163 | ||
| 160 | ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */ | 164 | ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */ |
| 161 | rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value, | 165 | if (pTcon->ses->server->ops->set_EA) |
| 162 | (__u16)value_size, cifs_sb->local_nls, | 166 | rc = pTcon->ses->server->ops->set_EA(xid, pTcon, |
| 163 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 167 | full_path, ea_name, ea_value, (__u16)value_size, |
| 168 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | ||
| 169 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
| 164 | } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL, | 170 | } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL, |
| 165 | strlen(CIFS_XATTR_CIFS_ACL)) == 0) { | 171 | strlen(CIFS_XATTR_CIFS_ACL)) == 0) { |
| 166 | #ifdef CONFIG_CIFS_ACL | 172 | #ifdef CONFIG_CIFS_ACL |
| @@ -272,17 +278,21 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, | |||
| 272 | /* revalidate/getattr then populate from inode */ | 278 | /* revalidate/getattr then populate from inode */ |
| 273 | } /* BB add else when above is implemented */ | 279 | } /* BB add else when above is implemented */ |
| 274 | ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ | 280 | ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ |
| 275 | rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value, | 281 | if (pTcon->ses->server->ops->query_all_EAs) |
| 276 | buf_size, cifs_sb->local_nls, | 282 | rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon, |
| 277 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 283 | full_path, ea_name, ea_value, buf_size, |
| 284 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | ||
| 285 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
| 278 | } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) { | 286 | } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) { |
| 279 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) | 287 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) |
| 280 | goto get_ea_exit; | 288 | goto get_ea_exit; |
| 281 | 289 | ||
| 282 | ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */ | 290 | ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */ |
| 283 | rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value, | 291 | if (pTcon->ses->server->ops->query_all_EAs) |
| 284 | buf_size, cifs_sb->local_nls, | 292 | rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon, |
| 285 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 293 | full_path, ea_name, ea_value, buf_size, |
| 294 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | ||
| 295 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
| 286 | } else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, | 296 | } else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, |
| 287 | strlen(POSIX_ACL_XATTR_ACCESS)) == 0) { | 297 | strlen(POSIX_ACL_XATTR_ACCESS)) == 0) { |
| 288 | #ifdef CONFIG_CIFS_POSIX | 298 | #ifdef CONFIG_CIFS_POSIX |
| @@ -400,11 +410,12 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) | |||
| 400 | /* if proc/fs/cifs/streamstoxattr is set then | 410 | /* if proc/fs/cifs/streamstoxattr is set then |
| 401 | search server for EAs or streams to | 411 | search server for EAs or streams to |
| 402 | returns as xattrs */ | 412 | returns as xattrs */ |
| 403 | rc = CIFSSMBQAllEAs(xid, pTcon, full_path, NULL, data, | ||
| 404 | buf_size, cifs_sb->local_nls, | ||
| 405 | cifs_sb->mnt_cifs_flags & | ||
| 406 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
| 407 | 413 | ||
| 414 | if (pTcon->ses->server->ops->query_all_EAs) | ||
| 415 | rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon, | ||
| 416 | full_path, NULL, data, buf_size, | ||
| 417 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | ||
| 418 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
| 408 | list_ea_exit: | 419 | list_ea_exit: |
| 409 | kfree(full_path); | 420 | kfree(full_path); |
| 410 | free_xid(xid); | 421 | free_xid(xid); |
