#endif
}
+static NTSTATUS smb_q_posix_symlink(
+ struct connection_struct *conn,
+ struct smb_request *req,
+ struct smb_filename *smb_fname,
+ char **ppdata,
+ int *ptotal_data)
+{
+ char buffer[PATH_MAX+1];
+ size_t needed, len;
+ int link_len;
+ char *pdata = NULL;
+ struct smb_filename *parent_fname = NULL;
+ struct smb_filename *base_name = NULL;
+ NTSTATUS status;
+
+ DBG_DEBUG("SMB_QUERY_FILE_UNIX_LINK for file %s\n",
+ smb_fname_str_dbg(smb_fname));
+
+ if (!S_ISLNK(smb_fname->st.st_ex_mode)) {
+ return NT_STATUS_DOS(ERRSRV, ERRbadlink);
+ }
+
+ status = parent_pathref(
+ talloc_tos(),
+ conn->cwd_fsp,
+ smb_fname,
+ &parent_fname,
+ &base_name);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_DEBUG("parent_pathref failed: %s\n", nt_errstr(status));
+ return status;
+ }
+
+ link_len = SMB_VFS_READLINKAT(
+ conn,
+ parent_fname->fsp,
+ base_name,
+ buffer,
+ sizeof(buffer)-1);
+ TALLOC_FREE(parent_fname);
+
+ if (link_len == -1) {
+ status = map_nt_error_from_unix(errno);
+ DBG_DEBUG("READLINKAT failed: %s\n", nt_errstr(status));
+ return status;
+ }
+ if (link_len >= sizeof(buffer)) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ buffer[link_len] = 0;
+
+ needed = (link_len+1)*2;
+
+ pdata = SMB_REALLOC(*ppdata, needed);
+ if (pdata == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ *ppdata = pdata;
+
+ status = srvstr_push(
+ pdata,
+ req->flags2,
+ pdata,
+ buffer,
+ needed,
+ STR_TERMINATE,
+ &len);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ *ptotal_data = len;
+
+ return NT_STATUS_OK;
+}
+
static void call_trans2qpathinfo(
connection_struct *conn,
struct smb_request *req,
smb_fname->fsp,
ppdata,
&total_data);
+ break;
+
+ case SMB_QUERY_FILE_UNIX_LINK:
+ status = smb_q_posix_symlink(
+ conn,
+ req,
+ smb_fname,
+ ppdata,
+ &total_data);
+ break;
}
if (info_level_handled) {
return NT_STATUS_OK;
}
-static NTSTATUS smb_unix_read_symlink(connection_struct *conn,
- struct smb_request *req,
- struct smb_filename *smb_fname,
- char *pdata,
- unsigned int data_size_in,
- unsigned int *pdata_size_out)
-{
- NTSTATUS status;
- size_t len = 0;
- int link_len = 0;
- struct smb_filename *parent_fname = NULL;
- struct smb_filename *base_name = NULL;
-
- char *buffer = talloc_array(talloc_tos(), char, PATH_MAX+1);
-
- if (!buffer) {
- return NT_STATUS_NO_MEMORY;
- }
-
- DBG_DEBUG("SMB_QUERY_FILE_UNIX_LINK for file %s\n",
- smb_fname_str_dbg(smb_fname));
-
- if(!S_ISLNK(smb_fname->st.st_ex_mode)) {
- TALLOC_FREE(buffer);
- return NT_STATUS_DOS(ERRSRV, ERRbadlink);
- }
-
- status = parent_pathref(talloc_tos(),
- conn->cwd_fsp,
- smb_fname,
- &parent_fname,
- &base_name);
- if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(buffer);
- return status;
- }
-
- link_len = SMB_VFS_READLINKAT(conn,
- parent_fname->fsp,
- base_name,
- buffer,
- PATH_MAX);
-
- TALLOC_FREE(parent_fname);
-
- if (link_len == -1) {
- TALLOC_FREE(buffer);
- return map_nt_error_from_unix(errno);
- }
-
- buffer[link_len] = 0;
- status = srvstr_push(pdata,
- req->flags2,
- pdata,
- buffer,
- data_size_in,
- STR_TERMINATE,
- &len);
- TALLOC_FREE(buffer);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- *pdata_size_out = len;
-
- return NT_STATUS_OK;
-}
-
NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
TALLOC_CTX *mem_ctx,
struct smb_request *req,
*fixed_portion = 8;
break;
- /*
- * CIFS UNIX Extensions.
- */
-
- case SMB_QUERY_FILE_UNIX_LINK:
- {
- status = smb_unix_read_symlink(conn,
- req,
- smb_fname,
- pdata,
- data_size,
- &data_size);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- break;
- }
-
/*
* SMB2 UNIX Extensions.
*/