int smb2_fix_symlink_target_type(char **target, bool directory, struct cifs_sb_info *cifs_sb)
{ char *buf; int len;
/* * POSIX server does not distinguish between symlinks to file and * symlink directory. So nothing is needed to fix on the client side.
*/ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) return 0;
if (!*target) return -EIO;
len = strlen(*target); if (!len) return -EIO;
/* * If this is directory symlink and it does not have trailing slash then * append it. Trailing slash simulates Windows/SMB behavior which do not * allow resolving directory symlink to file.
*/ if (directory && (*target)[len-1] != '/') {
buf = krealloc(*target, len+2, GFP_KERNEL); if (!buf) return -ENOMEM;
buf[len] = '/';
buf[len+1] = '\0';
*target = buf;
len++;
}
/* * If this is a file (non-directory) symlink and it points to path name * with trailing slash then this is an invalid symlink because file name * cannot contain slash character. File name with slash is invalid on * both Windows and Linux systems. So return an error for such symlink.
*/ if (!directory && (*target)[len-1] == '/') return -EIO;
if (oparms->tcon->use_resilient) { /* default timeout is 0, servers pick default (120 seconds) */
nr_ioctl_req.Timeout =
cpu_to_le32(oparms->tcon->handle_timeout);
nr_ioctl_req.Reserved = 0;
rc = SMB2_ioctl(xid, oparms->tcon, fid->persistent_fid,
fid->volatile_fid, FSCTL_LMR_REQUEST_RESILIENCY,
(char *)&nr_ioctl_req, sizeof(nr_ioctl_req),
CIFSMaxBufSize, NULL, NULL /* no return info */); if (rc == -EOPNOTSUPP) {
cifs_dbg(VFS, "resiliency not supported by server, disabling\n");
oparms->tcon->use_resilient = false;
} elseif (rc)
cifs_dbg(FYI, "error %d setting resiliency\n", rc);
rc = 0;
}
if (smb2_data) { /* if open response does not have IndexNumber field - get it */ if (smb2_data->IndexNumber == 0) {
rc = SMB2_get_srv_num(xid, oparms->tcon,
fid->persistent_fid,
fid->volatile_fid,
&smb2_data->IndexNumber); if (rc) { /* * let get_inode_info disable server inode * numbers
*/
smb2_data->IndexNumber = 0;
rc = 0;
}
}
memcpy(&data->fi, smb2_data, sizeof(data->fi));
}
/* * Accessing maxBuf is racy with cifs_reconnect - need to store value * and check it before using.
*/
max_buf = tcon->ses->server->maxBuf; if (max_buf < sizeof(struct smb2_lock_element)) return -EINVAL;
cifs_down_write(&cinode->lock_sem);
list_for_each_entry_safe(li, tmp, &cfile->llist->locks, llist) { if (flock->fl_start > li->offset ||
(flock->fl_start + length) <
(li->offset + li->length)) continue; if (current->tgid != li->pid) /* * flock and OFD lock are associated with an open * file description, not the process.
*/ if (!(flock->c.flc_flags & (FL_FLOCK | FL_OFDLCK))) continue; if (cinode->can_cache_brlcks) { /* * We can cache brlock requests - simply remove a lock * from the file's list.
*/
list_del(&li->llist);
cifs_del_lock_waiters(li);
kfree(li); continue;
}
cur->Length = cpu_to_le64(li->length);
cur->Offset = cpu_to_le64(li->offset);
cur->Flags = cpu_to_le32(SMB2_LOCKFLAG_UNLOCK); /* * We need to save a lock here to let us add it again to the * file's list if the unlock range request fails on the server.
*/
list_move(&li->llist, &tmp_llist); if (++num == max_num) {
stored_rc = smb2_lockv(xid, tcon,
cfile->fid.persistent_fid,
cfile->fid.volatile_fid,
current->tgid, num, buf); if (stored_rc) { /* * We failed on the unlock range request - add * all locks from the tmp list to the head of * the file's list.
*/
cifs_move_llist(&tmp_llist,
&cfile->llist->locks);
rc = stored_rc;
} else /* * The unlock range request succeed - free the * tmp list.
*/
cifs_free_llist(&tmp_llist);
cur = buf;
num = 0;
} else
cur++;
} if (num) {
stored_rc = smb2_lockv(xid, tcon, cfile->fid.persistent_fid,
cfile->fid.volatile_fid, current->tgid,
num, buf); if (stored_rc) {
cifs_move_llist(&tmp_llist, &cfile->llist->locks);
rc = stored_rc;
} else
cifs_free_llist(&tmp_llist);
}
up_write(&cinode->lock_sem);
/* * Accessing maxBuf is racy with cifs_reconnect - need to store value * and check it for zero before using.
*/
max_buf = tlink_tcon(cfile->tlink)->ses->server->maxBuf; if (max_buf < sizeof(struct smb2_lock_element)) {
free_xid(xid); return -EINVAL;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.