return close_file_free(req, &fsp, NORMAL_CLOSE);
}
+/****************************************************************************
+ Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
+****************************************************************************/
+
+static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
+ struct smb_request *req,
+ const char *pdata,
+ int total_data,
+ struct smb_filename *new_smb_fname)
+{
+ char *link_target = NULL;
+ struct smb_filename target_fname;
+ TALLOC_CTX *ctx = talloc_tos();
+ NTSTATUS status;
+ int ret;
+ struct smb_filename *parent_fname = NULL;
+ struct smb_filename *base_name = NULL;
+
+ if (!CAN_WRITE(conn)) {
+ return NT_STATUS_DOS(ERRSRV, ERRaccess);
+ }
+
+ /* Set a symbolic link. */
+ /* Don't allow this if follow links is false. */
+
+ if (total_data == 0) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (!lp_follow_symlinks(SNUM(conn))) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
+ total_data, STR_TERMINATE);
+
+ if (!link_target) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ target_fname = (struct smb_filename) {
+ .base_name = link_target,
+ };
+
+ /* Removes @GMT tokens if any */
+ status = canonicalize_snapshot_path(&target_fname, UCF_GMT_PATHNAME, 0);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
+ new_smb_fname->base_name, link_target ));
+
+ status = parent_pathref(talloc_tos(),
+ conn->cwd_fsp,
+ new_smb_fname,
+ &parent_fname,
+ &base_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ ret = SMB_VFS_SYMLINKAT(conn,
+ &target_fname,
+ parent_fname->fsp,
+ base_name);
+ if (ret != 0) {
+ TALLOC_FREE(parent_fname);
+ return map_nt_error_from_unix(errno);
+ }
+
+ TALLOC_FREE(parent_fname);
+ return NT_STATUS_OK;
+}
+
static void call_trans2setpathinfo(
connection_struct *conn,
struct smb_request *req,
status = smb_posix_unlink(
conn, req, *ppdata, total_data, smb_fname);
break;
+
+ case SMB_SET_FILE_UNIX_LINK:
+ status = smb_set_file_unix_link(
+ conn, req, *ppdata, total_data, smb_fname);
+ break;
}
if (info_level_handled) {
* These info levels do not require an existing object.
*/
switch (info_level) {
- case SMB_SET_FILE_UNIX_LINK:
case SMB_SET_FILE_UNIX_BASIC:
case SMB_SET_FILE_UNIX_INFO2:
require_existing_object = false;
return NT_STATUS_OK;
}
-/****************************************************************************
- Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
-****************************************************************************/
-
-static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
- struct smb_request *req,
- const char *pdata,
- int total_data,
- struct smb_filename *new_smb_fname)
-{
- char *link_target = NULL;
- struct smb_filename target_fname;
- TALLOC_CTX *ctx = talloc_tos();
- NTSTATUS status;
- int ret;
- struct smb_filename *parent_fname = NULL;
- struct smb_filename *base_name = NULL;
-
- /* Set a symbolic link. */
- /* Don't allow this if follow links is false. */
-
- if (total_data == 0) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- if (!lp_follow_symlinks(SNUM(conn))) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
- srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
- total_data, STR_TERMINATE);
-
- if (!link_target) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- target_fname = (struct smb_filename) {
- .base_name = link_target,
- };
-
- /* Removes @GMT tokens if any */
- status = canonicalize_snapshot_path(&target_fname, UCF_GMT_PATHNAME, 0);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
- new_smb_fname->base_name, link_target ));
-
- status = parent_pathref(talloc_tos(),
- conn->cwd_fsp,
- new_smb_fname,
- &parent_fname,
- &base_name);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- ret = SMB_VFS_SYMLINKAT(conn,
- &target_fname,
- parent_fname->fsp,
- base_name);
- if (ret != 0) {
- TALLOC_FREE(parent_fname);
- return map_nt_error_from_unix(errno);
- }
-
- TALLOC_FREE(parent_fname);
- return NT_STATUS_OK;
-}
-
/****************************************************************************
Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
****************************************************************************/
break;
}
- case SMB_SET_FILE_UNIX_LINK:
- {
- if (smb_fname == NULL) {
- /* We must have a pathname for this. */
- return NT_STATUS_INVALID_LEVEL;
- }
- status = smb_set_file_unix_link(conn, req, pdata,
- total_data, smb_fname);
- break;
- }
-
case SMB_SET_FILE_UNIX_HLINK:
{
if (smb_fname == NULL) {