summaryrefslogtreecommitdiff
path: root/source3/modules
diff options
context:
space:
mode:
Diffstat (limited to 'source3/modules')
-rw-r--r--source3/modules/onefs.h185
-rw-r--r--source3/modules/onefs_acl.c979
-rw-r--r--source3/modules/onefs_cbrl.c593
-rw-r--r--source3/modules/onefs_config.c278
-rw-r--r--source3/modules/onefs_config.h160
-rw-r--r--source3/modules/onefs_dir.c622
-rw-r--r--source3/modules/onefs_notify.c682
-rw-r--r--source3/modules/onefs_open.c2200
-rw-r--r--source3/modules/onefs_shadow_copy.c783
-rw-r--r--source3/modules/onefs_shadow_copy.h32
-rw-r--r--source3/modules/onefs_streams.c771
-rw-r--r--source3/modules/onefs_system.c782
-rw-r--r--source3/modules/perfcount_onefs.c481
-rw-r--r--source3/modules/vfs_onefs.c299
-rw-r--r--source3/modules/vfs_onefs_shadow_copy.c685
-rw-r--r--source3/modules/wscript_build28
16 files changed, 0 insertions, 9560 deletions
diff --git a/source3/modules/onefs.h b/source3/modules/onefs.h
deleted file mode 100644
index b12a67e367..0000000000
--- a/source3/modules/onefs.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Unix SMB/CIFS implementation.
- * Support for OneFS
- *
- * Copyright (C) Steven Danneman, 2008
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef _ONEFS_H
-#define _ONEFS_H
-
-/*
- * vfs interface handlers
- */
-DIR *onefs_opendir(struct vfs_handle_struct *handle,
- const char *fname, const char *mask,
- uint32 attributes);
-
-struct dirent *onefs_readdir(struct vfs_handle_struct *handle,
- DIR *dirp, SMB_STRUCT_STAT *sbuf);
-
-void onefs_seekdir(struct vfs_handle_struct *handle, DIR *dirp,
- long offset);
-
-long onefs_telldir(struct vfs_handle_struct *handle, DIR *dirp);
-
-void onefs_rewinddir(struct vfs_handle_struct *handle, DIR *dirp);
-
-int onefs_closedir(struct vfs_handle_struct *handle, DIR *dir);
-
-void onefs_init_search_op(struct vfs_handle_struct *handle,
- DIR *dirp);
-
-NTSTATUS onefs_create_file(vfs_handle_struct *handle,
- struct smb_request *req,
- uint16_t root_dir_fid,
- struct smb_filename *smb_fname,
- uint32_t access_mask,
- uint32_t share_access,
- uint32_t create_disposition,
- uint32_t create_options,
- uint32_t file_attributes,
- uint32_t oplock_request,
- uint64_t allocation_size,
- struct security_descriptor *sd,
- struct ea_list *ea_list,
- files_struct **result,
- int *pinfo);
-
-int onefs_close(vfs_handle_struct *handle, struct files_struct *fsp);
-
-int onefs_rename(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname_src,
- const struct smb_filename *smb_fname_dst);
-
-int onefs_stat(vfs_handle_struct *handle, struct smb_filename *smb_fname);
-
-int onefs_fstat(vfs_handle_struct *handle, struct files_struct *fsp,
- SMB_STRUCT_STAT *sbuf);
-
-int onefs_lstat(vfs_handle_struct *handle, struct smb_filename *smb_fname);
-
-int onefs_unlink(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname);
-
-NTSTATUS onefs_streaminfo(vfs_handle_struct *handle,
- struct files_struct *fsp,
- const char *fname,
- TALLOC_CTX *mem_ctx,
- unsigned int *num_streams,
- struct stream_struct **streams);
-
-int onefs_vtimes_streams(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- int flags, struct timespec times[3]);
-
-NTSTATUS onefs_brl_lock_windows(vfs_handle_struct *handle,
- struct byte_range_lock *br_lck,
- struct lock_struct *plock,
- bool blocking_lock,
- struct blocking_lock_record *blr);
-
-bool onefs_brl_unlock_windows(vfs_handle_struct *handle,
- struct messaging_context *msg_ctx,
- struct byte_range_lock *br_lck,
- const struct lock_struct *plock);
-
-bool onefs_brl_cancel_windows(vfs_handle_struct *handle,
- struct byte_range_lock *br_lck,
- struct lock_struct *plock,
- struct blocking_lock_record *blr);
-
-bool onefs_strict_lock(vfs_handle_struct *handle,
- files_struct *fsp,
- struct lock_struct *plock);
-
-void onefs_strict_unlock(vfs_handle_struct *handle,
- files_struct *fsp,
- struct lock_struct *plock);
-
-NTSTATUS onefs_notify_watch(vfs_handle_struct *vfs_handle,
- struct sys_notify_context *ctx,
- struct notify_entry *e,
- void (*callback)(struct sys_notify_context *ctx,
- void *private_data,
- struct notify_event *ev),
- void *private_data,
- void *handle_p);
-
-NTSTATUS onefs_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
- uint32 security_info, struct security_descriptor **ppdesc);
-
-NTSTATUS onefs_get_nt_acl(vfs_handle_struct *handle, const char* name,
- uint32 security_info, struct security_descriptor **ppdesc);
-
-NTSTATUS onefs_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
- uint32 security_info_sent,
- const struct security_descriptor *psd);
-
-/*
- * Utility functions
- */
-struct ifs_security_descriptor;
-NTSTATUS onefs_samba_sd_to_sd(uint32_t security_info_sent,
- const struct security_descriptor *psd,
- struct ifs_security_descriptor *sd, int snum,
- uint32_t *security_info_effective);
-
-NTSTATUS onefs_stream_prep_smb_fname(TALLOC_CTX *ctx,
- const struct smb_filename *smb_fname_in,
- struct smb_filename **smb_fname_out);
-
-int onefs_rdp_add_dir_state(connection_struct *conn, DIR *dirp);
-
-/*
- * System Interfaces
- */
-int onefs_sys_create_file(connection_struct *conn,
- int base_fd,
- const char *path,
- uint32_t access_mask,
- uint32_t open_access_mask,
- uint32_t share_access,
- uint32_t create_options,
- int flags,
- mode_t mode,
- int oplock_request,
- uint64_t id,
- struct security_descriptor *sd,
- uint32_t ntfs_flags,
- int *granted_oplock);
-
-ssize_t onefs_sys_sendfile(connection_struct *conn, int tofd, int fromfd,
- const DATA_BLOB *header, off_t offset,
- size_t count);
-
-ssize_t onefs_sys_recvfile(int fromfd, int tofd, off_t offset,
- size_t count);
-
-void init_stat_ex_from_onefs_stat(struct stat_ex *dst, const struct stat *src);
-
-int onefs_sys_stat(const char *fname, SMB_STRUCT_STAT *sbuf);
-
-int onefs_sys_fstat(int fd, SMB_STRUCT_STAT *sbuf);
-
-int onefs_sys_fstat_at(int base_fd, const char *fname, SMB_STRUCT_STAT *sbuf,
- int flags);
-
-int onefs_sys_lstat(const char *fname, SMB_STRUCT_STAT *sbuf);
-
-
-
-#endif /* _ONEFS_H */
diff --git a/source3/modules/onefs_acl.c b/source3/modules/onefs_acl.c
deleted file mode 100644
index 749ddec3da..0000000000
--- a/source3/modules/onefs_acl.c
+++ /dev/null
@@ -1,979 +0,0 @@
-/*
- * Unix SMB/CIFS implementation.
- *
- * Support for OneFS native NTFS ACLs
- *
- * Copyright (C) Steven Danneman, 2008
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "includes.h"
-#include "smbd/smbd.h"
-#include "onefs.h"
-#include "onefs_config.h"
-
-#include <isi_acl/isi_acl_util.h>
-#include <ifs/ifs_syscalls.h>
-#include <sys/isi_acl.h>
-
-const struct enum_list enum_onefs_acl_wire_format[] = {
- {ACL_FORMAT_RAW, "No Format"},
- {ACL_FORMAT_WINDOWS_SD, "Format Windows SD"},
- {ACL_FORMAT_ALWAYS, "Always Format SD"},
- {-1, NULL}
-};
-
-/**
- * Turn SID into UID/GID and setup a struct ifs_identity
- */
-static bool
-onefs_sid_to_identity(const struct dom_sid *sid, struct ifs_identity *id,
- bool is_group)
-{
- enum ifs_identity_type type = IFS_ID_TYPE_LAST+1;
- uid_t uid = 0;
- gid_t gid = 0;
-
- if (!sid || dom_sid_equal(sid, &global_sid_NULL))
- type = IFS_ID_TYPE_NULL;
- else if (dom_sid_equal(sid, &global_sid_World))
- type = IFS_ID_TYPE_EVERYONE;
- else if (dom_sid_equal(sid, &global_sid_Creator_Owner))
- type = IFS_ID_TYPE_CREATOR_OWNER;
- else if (dom_sid_equal(sid, &global_sid_Creator_Group))
- type = IFS_ID_TYPE_CREATOR_GROUP;
- else if (is_group) {
- if (!sid_to_gid(sid, &gid))
- return false;
- type = IFS_ID_TYPE_GID;
- } else {
- if (sid_to_uid(sid, &uid))
- type = IFS_ID_TYPE_UID;
- else if (sid_to_gid(sid, &gid))
- type = IFS_ID_TYPE_GID;
- else
- return false;
- }
-
- if (aclu_initialize_identity(id, type, uid, gid, is_group)) {
- DEBUG(3, ("Call to aclu_initialize_identity failed! id=%x, "
- "type=%d, uid=%u, gid=%u, is_group=%d\n",
- (unsigned int)id, type, uid, gid, is_group));
- return false;
- }
-
- return true;
-}
-
-/**
- * Turn struct ifs_identity into SID
- */
-static bool
-onefs_identity_to_sid(struct ifs_identity *id, struct dom_sid *sid)
-{
- if (!id || !sid)
- return false;
-
- if (id->type >= IFS_ID_TYPE_LAST)
- return false;
-
- switch (id->type) {
- case IFS_ID_TYPE_UID:
- uid_to_sid(sid, id->id.uid);
- break;
- case IFS_ID_TYPE_GID:
- gid_to_sid(sid, id->id.gid);
- break;
- case IFS_ID_TYPE_EVERYONE:
- sid_copy(sid, &global_sid_World);
- break;
- case IFS_ID_TYPE_NULL:
- sid_copy(sid, &global_sid_NULL);
- break;
- case IFS_ID_TYPE_CREATOR_OWNER:
- sid_copy(sid, &global_sid_Creator_Owner);
- break;
- case IFS_ID_TYPE_CREATOR_GROUP:
- sid_copy(sid, &global_sid_Creator_Group);
- break;
- default:
- DEBUG(0, ("Unknown identity type: %d\n", id->type));
- return false;
- }
-
- return true;
-}
-
-static bool
-onefs_og_to_identity(struct dom_sid *sid, struct ifs_identity * ident,
- bool is_group, int snum)
-{
- const struct dom_sid *b_admin_sid = &global_sid_Builtin_Administrators;
-
- if (!onefs_sid_to_identity(sid, ident, is_group)) {
- if (!lp_parm_bool(snum, PARM_ONEFS_TYPE,
- PARM_UNMAPPABLE_SIDS_IGNORE,
- PARM_UNMAPPABLE_SIDS_IGNORE_DEFAULT)) {
- DEBUG(3, ("Unresolvable SID (%s) found.\n",
- sid_string_dbg(sid)));
- return false;
- }
- if (!onefs_sid_to_identity(b_admin_sid, ident, is_group)) {
- return false;
- }
- DEBUG(3, ("Mapping unresolvable owner SID (%s) to Builtin "
- "Administrators group.\n",
- sid_string_dbg(sid)));
- }
- return true;
-}
-
-static bool
-sid_in_ignore_list(struct dom_sid * sid, int snum)
-{
- const char ** sid_list = NULL;
- struct dom_sid match;
-
- sid_list = lp_parm_string_list(snum, PARM_ONEFS_TYPE,
- PARM_UNMAPPABLE_SIDS_IGNORE_LIST,
- PARM_UNMAPPABLE_SIDS_IGNORE_LIST_DEFAULT);
-
- /* Fast path a NULL list */
- if (!sid_list || *sid_list == NULL)
- return false;
-
- while (*sid_list) {
- if (string_to_sid(&match, *sid_list))
- if (dom_sid_equal(sid, &match))
- return true;
- sid_list++;
- }
-
- return false;
-}
-
-/**
- * Convert a trustee to a struct identity
- */
-static bool
-onefs_samba_ace_to_ace(struct security_ace * samba_ace, struct ifs_ace * ace,
- bool *mapped, int snum)
-{
- struct ifs_identity ident = {.type=IFS_ID_TYPE_LAST, .id.uid=0};
-
- SMB_ASSERT(ace);
- SMB_ASSERT(mapped);
- SMB_ASSERT(samba_ace);
-
- if (onefs_sid_to_identity(&samba_ace->trustee, &ident, false)) {
- *mapped = true;
- } else {
-
- SMB_ASSERT(ident.id.uid >= 0);
-
- /* Ignore the sid if it's in the list */
- if (sid_in_ignore_list(&samba_ace->trustee, snum)) {
- DEBUG(3, ("Silently failing to set ACE for SID (%s) "
- "because it is in the ignore sids list\n",
- sid_string_dbg(&samba_ace->trustee)));
- *mapped = false;
- } else if ((samba_ace->type == SEC_ACE_TYPE_ACCESS_DENIED) &&
- lp_parm_bool(snum, PARM_ONEFS_TYPE,
- PARM_UNMAPPABLE_SIDS_DENY_EVERYONE,
- PARM_UNMAPPABLE_SIDS_DENY_EVERYONE_DEFAULT)) {
- /* If the ace is deny translated to Everyone */
- DEBUG(3, ("Mapping unresolvable deny ACE SID (%s) "
- "to Everyone.\n",
- sid_string_dbg(&samba_ace->trustee)));
- if (aclu_initialize_identity(&ident,
- IFS_ID_TYPE_EVERYONE, 0, 0, False) != 0) {
- DEBUG(2, ("aclu_initialize_identity() "
- "failed making Everyone\n"));
- return false;
- }
- *mapped = true;
- } else if (lp_parm_bool(snum, PARM_ONEFS_TYPE,
- PARM_UNMAPPABLE_SIDS_IGNORE,
- PARM_UNMAPPABLE_SIDS_IGNORE_DEFAULT)) {
- DEBUG(3, ("Silently failing to set ACE for SID (%s) "
- "because it is unresolvable\n",
- sid_string_dbg(&samba_ace->trustee)));
- *mapped = false;
- } else {
- /* Fail for lack of a better option */
- return false;
- }
- }
-
- if (*mapped) {
- if (aclu_initialize_ace(ace, samba_ace->type,
- samba_ace->access_mask, samba_ace->flags, 0,
- &ident))
- return false;
-
- if ((ace->trustee.type == IFS_ID_TYPE_CREATOR_OWNER ||
- ace->trustee.type == IFS_ID_TYPE_CREATOR_GROUP) &&
- nt4_compatible_acls())
- ace->flags |= SEC_ACE_FLAG_INHERIT_ONLY;
- }
-
- return true;
-}
-
-/**
- * Convert a struct security_acl to a struct ifs_security_acl
- */
-static bool
-onefs_samba_acl_to_acl(struct security_acl *samba_acl, struct ifs_security_acl **acl,
- bool * ignore_aces, int snum)
-{
- int num_aces = 0;
- struct ifs_ace *aces = NULL;
- struct security_ace *samba_aces;
- bool mapped;
- int i, j;
-
- SMB_ASSERT(ignore_aces);
-
- if ((!acl) || (!samba_acl))
- return false;
-
- samba_aces = samba_acl->aces;
-
- if (samba_acl->num_aces > 0 && samba_aces) {
- /* Setup ACES */
- num_aces = samba_acl->num_aces;
- aces = SMB_MALLOC_ARRAY(struct ifs_ace, num_aces);
-
- for (i = 0, j = 0; j < num_aces; i++, j++) {
- if (!onefs_samba_ace_to_ace(&samba_aces[j],
- &aces[i], &mapped, snum))
- goto err_free;
-
- if (!mapped)
- i--;
- }
- num_aces = i;
- }
-
- /* If aces are given but we cannot apply them due to the reasons
- * above we do not change the SD. However, if we are told to
- * explicitly set an SD with 0 aces we honor this operation */
- *ignore_aces = samba_acl->num_aces > 0 && num_aces < 1;
-
- if (*ignore_aces == false)
- if (aclu_initialize_acl(acl, aces, num_aces))
- goto err_free;
-
- /* Currently aclu_initialize_acl should copy the aces over, allowing
- * us to immediately free */
- free(aces);
- return true;
-
-err_free:
- free(aces);
- return false;
-}
-
-/**
- * Convert a struct ifs_security_acl to a struct security_acl
- */
-static bool
-onefs_acl_to_samba_acl(struct ifs_security_acl *acl, struct security_acl **samba_acl)
-{
- struct security_ace *samba_aces = NULL;
- struct security_acl *tmp_samba_acl = NULL;
- int i, num_aces = 0;
-
- if (!samba_acl)
- return false;
-
- /* NULL ACL */
- if (!acl) {
- *samba_acl = NULL;
- return true;
- }
-
- /* Determine number of aces in ACL */
- if (!acl->aces)
- num_aces = 0;
- else
- num_aces = acl->num_aces;
-
- /* Allocate the ace list. */
- if (num_aces > 0) {
- if ((samba_aces = SMB_MALLOC_ARRAY(struct security_ace, num_aces)) == NULL)
- {
- DEBUG(0, ("Unable to malloc space for %d aces.\n",
- num_aces));
- return false;
- }
- memset(samba_aces, '\0', (num_aces) * sizeof(struct security_ace));
- }
-
- for (i = 0; i < num_aces; i++) {
- struct dom_sid sid;
-
- if (!onefs_identity_to_sid(&acl->aces[i].trustee, &sid))
- goto err_free;
-
- init_sec_ace(&samba_aces[i], &sid, acl->aces[i].type,
- acl->aces[i].access_mask, acl->aces[i].flags);
- }
-
- if ((tmp_samba_acl = make_sec_acl(talloc_tos(), acl->revision, num_aces,
- samba_aces)) == NULL) {
- DEBUG(0, ("Unable to malloc space for acl.\n"));
- goto err_free;
- }
-
- *samba_acl = tmp_samba_acl;
- SAFE_FREE(samba_aces);
- return true;
-err_free:
- SAFE_FREE(samba_aces);
- return false;
-}
-
-/**
- * @brief Reorder ACLs into the "correct" order for Windows Explorer.
- *
- * Windows Explorer expects ACLs to be in a standard order (inherited first,
- * then deny, then permit.) When ACLs are composed from POSIX file permissions
- * bits, they may not match these expectations, generating an annoying warning
- * dialog for the user. This function will, if configured appropriately,
- * reorder the ACLs for these "synthetic" (POSIX-derived) descriptors to prevent
- * this. The list is changed within the security descriptor passed in.
- *
- * @param fsp files_struct with service configs; must not be NULL
- * @param sd security descriptor being normalized;
- * sd->dacl->aces is rewritten in-place, so must not be NULL
- * @return true on success, errno will be set on error
- *
- * @bug Although Windows Explorer likes the reordering, they seem to cause
- * problems with Excel and Word sending back the reordered ACLs to us and
- * changing policy; see Isilon bug 30165.
- */
-static bool
-onefs_canon_acl(files_struct *fsp, struct ifs_security_descriptor *sd)
-{
- int error = 0;
- int cur;
- struct ifs_ace *new_aces = NULL;
- int new_aces_count = 0;
- SMB_STRUCT_STAT sbuf;
-
- if (sd == NULL || sd->dacl == NULL || sd->dacl->num_aces == 0)
- return true;
-
- /*
- * Find out if this is a windows bit, and if the smb policy wants us to
- * lie about the sd.
- */
- SMB_ASSERT(fsp != NULL);
- switch (lp_parm_enum(SNUM(fsp->conn), PARM_ONEFS_TYPE,
- PARM_ACL_WIRE_FORMAT, enum_onefs_acl_wire_format,
- PARM_ACL_WIRE_FORMAT_DEFAULT)) {
- case ACL_FORMAT_RAW:
- return true;
-
- case ACL_FORMAT_WINDOWS_SD:
- error = SMB_VFS_FSTAT(fsp, &sbuf);
- if (error)
- return false;
-
- if ((sbuf.st_ex_flags & SF_HASNTFSACL) != 0) {
- DEBUG(10, ("Did not canonicalize ACLs because a "
- "Windows ACL set was found for file %s\n",
- fsp_str_dbg(fsp)));
- return true;
- }
- break;
-
- case ACL_FORMAT_ALWAYS:
- break;
-
- default:
- SMB_ASSERT(false);
- return false;
- }
-
- new_aces = SMB_MALLOC_ARRAY(struct ifs_ace, sd->dacl->num_aces);
- if (new_aces == NULL)
- return false;
-
- /*
- * By walking down the list 3 separate times, we can avoid the need
- * to create multiple temp buffers and extra copies.
- */
-
- /* Explict deny aces first */
- for (cur = 0; cur < sd->dacl->num_aces; cur++) {
- if (!(sd->dacl->aces[cur].flags & IFS_ACE_FLAG_INHERITED_ACE) &&
- (sd->dacl->aces[cur].type == IFS_ACE_TYPE_ACCESS_DENIED))
- new_aces[new_aces_count++] = sd->dacl->aces[cur];
- }
-
- /* Explict allow aces second */
- for (cur = 0; cur < sd->dacl->num_aces; cur++) {
- if (!(sd->dacl->aces[cur].flags & IFS_ACE_FLAG_INHERITED_ACE) &&
- !(sd->dacl->aces[cur].type == IFS_ACE_TYPE_ACCESS_DENIED))
- new_aces[new_aces_count++] = sd->dacl->aces[cur];
- }
-
- /* Inherited deny/allow aces third */
- for (cur = 0; cur < sd->dacl->num_aces; cur++) {
- if ((sd->dacl->aces[cur].flags & IFS_ACE_FLAG_INHERITED_ACE))
- new_aces[new_aces_count++] = sd->dacl->aces[cur];
- }
-
- SMB_ASSERT(new_aces_count == sd->dacl->num_aces);
- DEBUG(10, ("Performed canonicalization of ACLs for file %s\n",
- fsp_str_dbg(fsp)));
-
- /*
- * At this point you would think we could just do this:
- * SAFE_FREE(sd->dacl->aces);
- * sd->dacl->aces = new_aces;
- * However, in some cases the existing aces pointer does not point
- * to the beginning of an allocated block. So we have to do a more
- * expensive memcpy()
- */
- memcpy(sd->dacl->aces, new_aces,
- sizeof(struct ifs_ace) * new_aces_count);
-
- SAFE_FREE(new_aces);
- return true;
-}
-
-
-/**
- * This enum is a helper for onefs_fget_nt_acl() to communicate with
- * onefs_init_ace().
- */
-enum mode_ident { USR, GRP, OTH };
-
-/**
- * Initializes an ACE for addition to a synthetic ACL.
- */
-static struct ifs_ace onefs_init_ace(struct connection_struct *conn,
- mode_t mode,
- bool isdir,
- enum mode_ident ident)
-{
- struct ifs_ace result;
- enum ifs_ace_rights r,w,x;
-
- r = isdir ? UNIX_DIRECTORY_ACCESS_R : UNIX_ACCESS_R;
- w = isdir ? UNIX_DIRECTORY_ACCESS_W : UNIX_ACCESS_W;
- x = isdir ? UNIX_DIRECTORY_ACCESS_X : UNIX_ACCESS_X;
-
- result.type = IFS_ACE_TYPE_ACCESS_ALLOWED;
- result.ifs_flags = 0;
- result.flags = isdir ? IFS_ACE_FLAG_CONTAINER_INHERIT :
- IFS_ACE_FLAG_OBJECT_INHERIT;
- result.flags |= IFS_ACE_FLAG_INHERIT_ONLY;
-
- switch (ident) {
- case USR:
- result.access_mask =
- ((mode & S_IRUSR) ? r : 0 ) |
- ((mode & S_IWUSR) ? w : 0 ) |
- ((mode & S_IXUSR) ? x : 0 );
- if (lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE,
- PARM_CREATOR_OWNER_GETS_FULL_CONTROL,
- PARM_CREATOR_OWNER_GETS_FULL_CONTROL_DEFAULT))
- result.access_mask |= GENERIC_ALL_ACCESS;
- result.trustee.type = IFS_ID_TYPE_CREATOR_OWNER;
- break;
- case GRP:
- result.access_mask =
- ((mode & S_IRGRP) ? r : 0 ) |
- ((mode & S_IWGRP) ? w : 0 ) |
- ((mode & S_IXGRP) ? x : 0 );
- result.trustee.type = IFS_ID_TYPE_CREATOR_GROUP;
- break;
- case OTH:
- result.access_mask =
- ((mode & S_IROTH) ? r : 0 ) |
- ((mode & S_IWOTH) ? w : 0 ) |
- ((mode & S_IXOTH) ? x : 0 );
- result.trustee.type = IFS_ID_TYPE_EVERYONE;
- break;
- }
-
- return result;
-}
-
-/**
- * This adds inheritable ACEs to the end of the DACL, with the ACEs
- * being derived from the mode bits. This is useful for clients that have the
- * MoveSecurityAttributes regkey set to 0 or are in Simple File Sharing Mode.
- *
- * On these clients, when copying files from one folder to another inside the
- * same volume/share, the DACL is explicitely cleared. Without inheritable
- * aces on the target folder the mode bits of the copied file are set to 000.
- *
- * See Isilon Bug 27990
- *
- * Note: This function allocates additional memory onto sd->dacl->aces, that
- * must be freed by the caller.
- */
-static bool add_sfs_aces(files_struct *fsp, struct ifs_security_descriptor *sd)
-{
- int error;
- SMB_STRUCT_STAT sbuf;
-
- error = SMB_VFS_FSTAT(fsp, &sbuf);
- if (error) {
- DEBUG(0, ("Failed to stat %s in simple files sharing "
- "compatibility mode. errno=%d\n",
- fsp_str_dbg(fsp), errno));
- return false;
- }
-
- /* Only continue if this is a synthetic ACL and a directory. */
- if (S_ISDIR(sbuf.st_ex_mode) &&
- (sbuf.st_ex_flags & SF_HASNTFSACL) == 0) {
- struct ifs_ace new_aces[6];
- struct ifs_ace *old_aces;
- int i, num_aces_to_add = 0;
- mode_t file_mode = 0, dir_mode = 0;
-
- /* Use existing samba logic to derive the mode bits. */
- file_mode = unix_mode(fsp->conn, 0, fsp->fsp_name, NULL);
- dir_mode = unix_mode(fsp->conn, FILE_ATTRIBUTE_DIRECTORY, fsp->fsp_name, NULL);
-
- /* Initialize ACEs. */
- new_aces[0] = onefs_init_ace(fsp->conn, file_mode, false, USR);
- new_aces[1] = onefs_init_ace(fsp->conn, file_mode, false, GRP);
- new_aces[2] = onefs_init_ace(fsp->conn, file_mode, false, OTH);
- new_aces[3] = onefs_init_ace(fsp->conn, dir_mode, true, USR);
- new_aces[4] = onefs_init_ace(fsp->conn, dir_mode, true, GRP);
- new_aces[5] = onefs_init_ace(fsp->conn, dir_mode, true, OTH);
-
- for (i = 0; i < 6; i++)
- if (new_aces[i].access_mask != 0)
- num_aces_to_add++;
-
- /* Expand the ACEs array */
- if (num_aces_to_add != 0) {
- old_aces = sd->dacl->aces;
-
- sd->dacl->aces = SMB_MALLOC_ARRAY(struct ifs_ace,
- sd->dacl->num_aces + num_aces_to_add);
- if (!sd->dacl->aces) {
- DEBUG(0, ("Unable to malloc space for "
- "new_aces: %d.\n",
- sd->dacl->num_aces + num_aces_to_add));
- return false;
- }
- memcpy(sd->dacl->aces, old_aces,
- sizeof(struct ifs_ace) * sd->dacl->num_aces);
-
- /* Add the new ACEs to the DACL. */
- for (i = 0; i < 6; i++) {
- if (new_aces[i].access_mask != 0) {
- sd->dacl->aces[sd->dacl->num_aces] =
- new_aces[i];
- sd->dacl->num_aces++;
- }
- }
- }
- }
- return true;
-}
-
-/**
- * Isilon-specific function for getting an NTFS ACL from an open file.
- *
- * @param[out] ppdesc SecDesc to allocate and fill in
- *
- * @return NTSTATUS based off errno on error
- */
-NTSTATUS
-onefs_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
- uint32 security_info, struct security_descriptor **ppdesc)
-{
- int error;
- uint32_t sd_size = 0;
- size_t size = 0;
- struct ifs_security_descriptor *sd = NULL;
- struct dom_sid owner_sid, group_sid;
- struct dom_sid *ownerp, *groupp;
- struct security_acl *dacl, *sacl;
- struct security_descriptor *pdesc;
- bool alloced = false;
- bool new_aces_alloced = false;
- bool fopened = false;
- NTSTATUS status = NT_STATUS_OK;
-
- START_PROFILE(syscall_get_sd);
-
- *ppdesc = NULL;
-
- DEBUG(5, ("Getting sd for file %s. security_info=%u\n",
- fsp_str_dbg(fsp), security_info));
-
- if (lp_parm_bool(SNUM(fsp->conn), PARM_ONEFS_TYPE,
- PARM_IGNORE_SACLS, PARM_IGNORE_SACLS_DEFAULT)) {
- DEBUG(5, ("Ignoring SACL on %s.\n", fsp_str_dbg(fsp)));
- security_info &= ~SECINFO_SACL;
- }
-
- if (fsp->fh->fd == -1) {
- if ((fsp->fh->fd = onefs_sys_create_file(handle->conn,
- -1,
- fsp->fsp_name->base_name,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- INTERNAL_OPEN_ONLY,
- 0,
- NULL,
- 0,
- NULL)) == -1) {
- DEBUG(0, ("Error opening file %s. errno=%d (%s)\n",
- fsp_str_dbg(fsp), errno, strerror(errno)));
- status = map_nt_error_from_unix(errno);
- goto out;
- }
- fopened = true;
- }
-
- /* Get security descriptor */
- sd_size = 0;
- do {
- /* Allocate memory for get_security_descriptor */
- if (sd_size > 0) {
- sd = SMB_REALLOC(sd, sd_size);
- if (!sd) {
- DEBUG(0, ("Unable to malloc %u bytes of space "
- "for security descriptor.\n", sd_size));
- status = map_nt_error_from_unix(errno);
- goto out;
- }
-
- alloced = true;
- }
-
- error = ifs_get_security_descriptor(fsp->fh->fd, security_info,
- sd_size, &sd_size, sd);
- if (error && (errno != EMSGSIZE)) {
- DEBUG(0, ("Failed getting size of security descriptor! "
- "errno=%d\n", errno));
- status = map_nt_error_from_unix(errno);
- goto out;
- }
- } while (error);
-
- DEBUG(5, ("Got sd, size=%u:\n", sd_size));
-
- if (lp_parm_bool(SNUM(fsp->conn),
- PARM_ONEFS_TYPE,
- PARM_SIMPLE_FILE_SHARING_COMPATIBILITY_MODE,
- PARM_SIMPLE_FILE_SHARING_COMPATIBILITY_MODE_DEFAULT) &&
- sd->dacl) {
- if(!(new_aces_alloced = add_sfs_aces(fsp, sd)))
- goto out;
- }
-
- if (!(onefs_canon_acl(fsp, sd))) {
- status = map_nt_error_from_unix(errno);
- goto out;
- }
-
- DEBUG(5, ("Finished canonicalizing ACL\n"));
-
- ownerp = NULL;
- groupp = NULL;
- dacl = NULL;
- sacl = NULL;
-
- /* Copy owner into ppdesc */
- if (security_info & SECINFO_OWNER) {
- if (!onefs_identity_to_sid(sd->owner, &owner_sid)) {
- status = NT_STATUS_INVALID_PARAMETER;
- goto out;
- }
-
- ownerp = &owner_sid;
- }
-
- /* Copy group into ppdesc */
- if (security_info & SECINFO_GROUP) {
- if (!onefs_identity_to_sid(sd->group, &group_sid)) {
- status = NT_STATUS_INVALID_PARAMETER;
- goto out;
- }
-
- groupp = &group_sid;
- }
-
- /* Copy DACL into ppdesc */
- if (security_info & SECINFO_DACL) {
- if (!onefs_acl_to_samba_acl(sd->dacl, &dacl)) {
- status = NT_STATUS_INVALID_PARAMETER;
- goto out;
- }
- }
-
- /* Copy SACL into ppdesc */
- if (security_info & SECINFO_SACL) {
- if (!onefs_acl_to_samba_acl(sd->sacl, &sacl)) {
- status = NT_STATUS_INVALID_PARAMETER;
- goto out;
- }
- }
-
- /* AUTO_INHERIT_REQ bits are not returned over the wire so strip them
- * off. Eventually we should stop storing these in the kernel
- * all together. See Isilon bug 40364 */
- sd->control &= ~(IFS_SD_CTRL_DACL_AUTO_INHERIT_REQ |
- IFS_SD_CTRL_SACL_AUTO_INHERIT_REQ);
-
- pdesc = make_sec_desc(talloc_tos(), sd->revision, sd->control,
- ownerp, groupp, sacl, dacl, &size);
-
- if (!pdesc) {
- DEBUG(0, ("Problem with make_sec_desc. Memory?\n"));
- status = map_nt_error_from_unix(errno);
- goto out;
- }
-
- *ppdesc = pdesc;
-
- DEBUG(5, ("Finished retrieving/canonicalizing SD!\n"));
- /* FALLTHROUGH */
-out:
-
- END_PROFILE(syscall_get_sd);
-
- if (alloced && sd) {
- if (new_aces_alloced && sd->dacl->aces)
- SAFE_FREE(sd->dacl->aces);
-
- SAFE_FREE(sd);
- }
-
- if (fopened) {
- close(fsp->fh->fd);
- fsp->fh->fd = -1;
- }
-
- return status;
-}
-
-/**
- * Isilon-specific function for getting an NTFS ACL from a file path.
- *
- * Since onefs_fget_nt_acl() needs to open a filepath if the fd is invalid,
- * we just mock up a files_struct with the path and bad fd and call into it.
- *
- * @param[out] ppdesc SecDesc to allocate and fill in
- *
- * @return NTSTATUS based off errno on error
- */
-NTSTATUS
-onefs_get_nt_acl(vfs_handle_struct *handle, const char* name,
- uint32 security_info, struct security_descriptor **ppdesc)
-{
- files_struct finfo;
- struct fd_handle fh;
- NTSTATUS status;
-
- ZERO_STRUCT(finfo);
- ZERO_STRUCT(fh);
-
- finfo.fnum = -1;
- finfo.conn = handle->conn;
- finfo.fh = &fh;
- finfo.fh->fd = -1;
- status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
- &finfo.fsp_name);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- status = onefs_fget_nt_acl(handle, &finfo, security_info, ppdesc);
-
- TALLOC_FREE(finfo.fsp_name);
- return status;
-}
-
-/**
- * Isilon-specific function for setting up an ifs_security_descriptor, given a
- * samba struct security_descriptor
- *
- * @param[out] sd ifs_security_descriptor to fill in
- *
- * @return NTSTATUS_OK if successful
- */
-NTSTATUS onefs_samba_sd_to_sd(uint32_t security_info_sent,
- const struct security_descriptor *psd,
- struct ifs_security_descriptor *sd, int snum,
- uint32_t *security_info_effective)
-{
- struct ifs_security_acl *daclp, *saclp;
- struct ifs_identity owner, group, *ownerp, *groupp;
- bool ignore_aces;
-
- ownerp = NULL;
- groupp = NULL;
- daclp = NULL;
- saclp = NULL;
-
- *security_info_effective = security_info_sent;
-
- /* Setup owner */
- if (security_info_sent & SECINFO_OWNER) {
- if (!onefs_og_to_identity(psd->owner_sid, &owner, false, snum))
- return NT_STATUS_ACCESS_DENIED;
-
- SMB_ASSERT(owner.id.uid >= 0);
-
- ownerp = &owner;
- }
-
- /* Setup group */
- if (security_info_sent & SECINFO_GROUP) {
- if (!onefs_og_to_identity(psd->group_sid, &group, true, snum))
- return NT_STATUS_ACCESS_DENIED;
-
- SMB_ASSERT(group.id.gid >= 0);
-
- groupp = &group;
- }
-
- /* Setup DACL */
- if ((security_info_sent & SECINFO_DACL) && (psd->dacl)) {
- if (!onefs_samba_acl_to_acl(psd->dacl, &daclp, &ignore_aces,
- snum))
- return NT_STATUS_ACCESS_DENIED;
-
- if (ignore_aces == true)
- *security_info_effective &= ~SECINFO_DACL;
- }
-
- /* Setup SACL */
- if (security_info_sent & SECINFO_SACL) {
-
- if (lp_parm_bool(snum, PARM_ONEFS_TYPE,
- PARM_IGNORE_SACLS, PARM_IGNORE_SACLS_DEFAULT)) {
- DEBUG(5, ("Ignoring SACL.\n"));
- *security_info_effective &= ~SECINFO_SACL;
- } else {
- if (psd->sacl) {
- if (!onefs_samba_acl_to_acl(psd->sacl,
- &saclp, &ignore_aces, snum))
- return NT_STATUS_ACCESS_DENIED;
-
- if (ignore_aces == true) {
- *security_info_effective &=
- ~SECINFO_SACL;
- }
- }
- }
- }
-
- /* Setup ifs_security_descriptor */
- DEBUG(5,("Setting up SD\n"));
- if (aclu_initialize_sd(sd, psd->type, ownerp, groupp,
- (daclp ? &daclp : NULL), (saclp ? &saclp : NULL), false))
- return NT_STATUS_ACCESS_DENIED;
-
- DEBUG(10, ("sec_info_sent: 0x%x, sec_info_effective: 0x%x.\n",
- security_info_sent, *security_info_effective));
-
- return NT_STATUS_OK;
-}
-
-/**
- * Isilon-specific function for setting an NTFS ACL on an open file.
- *
- * @return NT_STATUS_UNSUCCESSFUL for userspace errors, NTSTATUS based off
- * errno on syscall errors
- */
-NTSTATUS
-onefs_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
- uint32_t sec_info_sent, const struct security_descriptor *psd)
-{
- struct ifs_security_descriptor sd = {};
- int fd = -1;
- bool fopened = false;
- NTSTATUS status;
- uint32_t sec_info_effective = 0;
-
- START_PROFILE(syscall_set_sd);
-
- DEBUG(5,("Setting SD on file %s.\n", fsp_str_dbg(fsp)));
-
- status = onefs_samba_sd_to_sd(sec_info_sent, psd, &sd,
- SNUM(handle->conn), &sec_info_effective);
-
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(3, ("SD initialization failure: %s\n", nt_errstr(status)));
- goto out;
- }
-
- fd = fsp->fh->fd;
- if (fd == -1) {
- DEBUG(10,("Reopening file %s.\n", fsp_str_dbg(fsp)));
- if ((fd = onefs_sys_create_file(handle->conn,
- -1,
- fsp->fsp_name->base_name,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- INTERNAL_OPEN_ONLY,
- 0,
- NULL,
- 0,
- NULL)) == -1) {
- DEBUG(0, ("Error opening file %s. errno=%d (%s)\n",
- fsp_str_dbg(fsp), errno, strerror(errno)));
- status = map_nt_error_from_unix(errno);
- goto out;
- }
- fopened = true;
- }
-
- errno = 0;
- if (ifs_set_security_descriptor(fd, sec_info_effective, &sd)) {
- DEBUG(0, ("Error setting security descriptor = %s\n",
- strerror(errno)));
- status = map_nt_error_from_unix(errno);
- goto out;
- }
-
- DEBUG(5, ("Security descriptor set correctly!\n"));
- status = NT_STATUS_OK;
-
- /* FALLTHROUGH */
-out:
- END_PROFILE(syscall_set_sd);
-
- if (fopened)
- close(fd);
-
- aclu_free_sd(&sd, false);
- return status;
-}
diff --git a/source3/modules/onefs_cbrl.c b/source3/modules/onefs_cbrl.c
deleted file mode 100644
index 2f20d04ddb..0000000000
--- a/source3/modules/onefs_cbrl.c
+++ /dev/null
@@ -1,593 +0,0 @@
-/*
- * Unix SMB/CIFS implementation.
- * Support for OneFS system interfaces.
- *
- * Copyright (C) Zack Kirsch, 2009
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "includes.h"
-#include "smbd/smbd.h"
-#include "onefs.h"
-
-#include <ifs/ifs_syscalls.h>
-#include <sys/isi_cifs_brl.h>
-#include <isi_ecs/isi_ecs_cbrl.h>
-
-#undef DBGC_CLASS
-#define DBGC_CLASS DBGC_LOCKING
-
-static uint64_t onefs_get_new_id(void) {
- static uint64_t id = 0;
-
- id++;
-
- return id;
-}
-
-enum onefs_cbrl_lock_state {ONEFS_CBRL_NONE, ONEFS_CBRL_ASYNC, ONEFS_CBRL_DONE,
- ONEFS_CBRL_ERROR};
-
-struct onefs_cbrl_blr_state {
- uint64_t id;
- enum onefs_cbrl_lock_state state;
-};
-
-static char *onefs_cbrl_blr_state_str(const struct blocking_lock_record *blr)
-{
- static fstring result;
- struct onefs_cbrl_blr_state *bs;
-
- SMB_ASSERT(blr);
-
- bs = (struct onefs_cbrl_blr_state *)blr->blr_private;
-
- if (bs == NULL) {
- fstrcpy(result, "NULL CBRL BLR state - Posix lock?");
- return result;
- }
-
- switch (bs->state) {
- case ONEFS_CBRL_NONE:
- fstr_sprintf(result, "CBRL BLR id=%llu: state=NONE", bs->id);
- break;
- case ONEFS_CBRL_ASYNC:
- fstr_sprintf(result, "CBRL BLR id=%llu: state=ASYNC", bs->id);
- break;
- case ONEFS_CBRL_DONE:
- fstr_sprintf(result, "CBRL BLR id=%llu: state=DONE", bs->id);
- break;
- case ONEFS_CBRL_ERROR:
- fstr_sprintf(result, "CBRL BLR id=%llu: state=ERROR", bs->id);
- break;
- default:
- fstr_sprintf(result, "CBRL BLR id=%llu: unknown state %d",
- bs->id, bs->state);
- break;
- }
-
- return result;
-}
-
-static void onefs_cbrl_enumerate_blq(const char *fn)
-{
- struct smbd_server_connection *sconn = smbd_server_conn;
- struct blocking_lock_record *blr;
-
- if (DEBUGLVL(10))
- return;
-
- DEBUG(10, ("CBRL BLR records (%s):\n", fn));
-
- if (sconn->using_smb2) {
- struct smbd_smb2_request *smb2req;
- for (smb2req = sconn->smb2.requests; smb2req; smb2req = nextreq) {
- blr = get_pending_smb2req_blr(smb2req);
- if (blr) {
- DEBUGADD(10, ("%s\n", onefs_cbrl_blr_state_str(blr)));
- }
- }
- } else {
- for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = blr->next)
- DEBUGADD(10, ("%s\n", onefs_cbrl_blr_state_str(blr)));
- }
-}
-
-static struct blocking_lock_record *onefs_cbrl_find_blr(uint64_t id)
-{
- struct smbd_server_connection *sconn = smbd_server_conn;
- struct blocking_lock_record *blr;
- struct onefs_cbrl_blr_state *bs;
-
- onefs_cbrl_enumerate_blq("onefs_cbrl_find_blr");
-
- if (sconn->using_smb2) {
- struct smbd_smb2_request *smb2req;
- for (smb2req = sconn->smb2.requests; smb2req; smb2req = nextreq) {
- blr = get_pending_smb2req_blr(smb2req);
- if (!blr) {
- continue;
- }
- bs = (struct onefs_cbrl_blr_state *)blr->blr_private;
- if (bs == NULL) {
- continue;
- }
- if (bs->id == id) {
- DEBUG(10, ("found %s\n",
- onefs_cbrl_blr_state_str(blr)));
- break;
- }
- }
- } else {
- for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = blr->next) {
- bs = (struct onefs_cbrl_blr_state *)blr->blr_private;
-
- /* We don't control all of the BLRs on the BLQ. */
- if (bs == NULL)
- continue;
-
- if (bs->id == id) {
- DEBUG(10, ("found %s\n",
- onefs_cbrl_blr_state_str(blr)));
- break;
- }
- }
- }
-
- if (blr == NULL) {
- DEBUG(5, ("Could not find CBRL BLR for id %llu\n", id));
- return NULL;
- }
-
- return blr;
-}
-
-static void onefs_cbrl_async_success(uint64_t id)
-{
- struct blocking_lock_record *blr;
- struct onefs_cbrl_blr_state *bs;
- uint16 num_locks;
-
- DEBUG(10, ("CBRL async success!\n"));
-
- /* Find BLR with id. Its okay not to find one (race with cancel) */
- blr = onefs_cbrl_find_blr(id);
- if (blr == NULL)
- return;
-
- bs = (struct onefs_cbrl_blr_state *)blr->blr_private;
- SMB_ASSERT(bs);
- SMB_ASSERT(bs->state == ONEFS_CBRL_ASYNC);
-
- blr->lock_num++;
-
- num_locks = SVAL(blr->req->vwv+7, 0);
-
- if (blr->lock_num == num_locks)
- bs->state = ONEFS_CBRL_DONE;
- else
- bs->state = ONEFS_CBRL_NONE;
-
- /* Self contend our own level 2 oplock. The kernel handles
- * contention of other opener's level 2 oplocks. */
- contend_level2_oplocks_begin(blr->fsp,
- LEVEL2_CONTEND_WINDOWS_BRL);
-
- /* Process the queue, to try the next lock or finish up. */
- process_blocking_lock_queue(smbd_server_conn);
-}
-
-static void onefs_cbrl_async_failure(uint64_t id)
-{
- struct blocking_lock_record *blr;
- struct onefs_cbrl_blr_state *bs;
-
- DEBUG(10, ("CBRL async failure!\n"));
-
- /* Find BLR with id. Its okay not to find one (race with cancel) */
- blr = onefs_cbrl_find_blr(id);
- if (blr == NULL)
- return;
-
- bs = (struct onefs_cbrl_blr_state *)blr->blr_private;
- SMB_ASSERT(bs);
-
- SMB_ASSERT(bs->state == ONEFS_CBRL_ASYNC);
- bs->state = ONEFS_CBRL_ERROR;
-
- /* Process the queue. It will end up trying to retake the same lock,
- * see the error in onefs_cbrl_lock_windows() and fail. */
- process_blocking_lock_queue(smbd_server_conn);
-}
-
-static struct cbrl_event_ops cbrl_ops =
- {.cbrl_async_success = onefs_cbrl_async_success,
- .cbrl_async_failure = onefs_cbrl_async_failure};
-
-static void onefs_cbrl_events_handler(struct event_context *ev,
- struct fd_event *fde,
- uint16_t flags,
- void *private_data)
-{
- DEBUG(10, ("onefs_cbrl_events_handler\n"));
-
- if (cbrl_event_dispatcher(&cbrl_ops)) {
- DEBUG(0, ("cbrl_event_dispatcher failed: %s\n",
- strerror(errno)));
- }
-}
-
-static void onefs_init_cbrl(void)
-{
- static bool init_done = false;
- static int cbrl_event_fd;
- static struct fd_event *cbrl_fde;
-
- if (init_done)
- return;
-
- DEBUG(10, ("onefs_init_cbrl\n"));
-
- /* Register the event channel for CBRL. */
- cbrl_event_fd = cbrl_event_register();
- if (cbrl_event_fd == -1) {
- DEBUG(0, ("cbrl_event_register failed: %s\n",
- strerror(errno)));
- return;
- }
-
- DEBUG(10, ("cbrl_event_fd = %d\n", cbrl_event_fd));
-
- /* Register the CBRL event_fd with samba's event system */
- cbrl_fde = event_add_fd(server_event_context(),
- NULL,
- cbrl_event_fd,
- EVENT_FD_READ,
- onefs_cbrl_events_handler,
- NULL);
-
- init_done = true;
- return;
-}
-
-/**
- * Blocking PID. As far as I can tell, the blocking_pid is only used to tell
- * whether a posix lock or a CIFS lock blocked us. If it was a posix lock,
- * Samba polls every 10 seconds, which we don't want. -zkirsch
- */
-#define ONEFS_BLOCKING_PID 0xABCDABCD
-
-/**
- * @param[in] br_lck Contains the fsp.
- * @param[in] plock Lock request.
- * @param[in] blocking_lock Only used for figuring out the error.
- * @param[in,out] blr The BLR for the already-deferred operation.
- */
-NTSTATUS onefs_brl_lock_windows(vfs_handle_struct *handle,
- struct byte_range_lock *br_lck,
- struct lock_struct *plock,
- bool blocking_lock,
- struct blocking_lock_record *blr)
-{
- int fd = br_lck->fsp->fh->fd;
- uint64_t id = 0;
- enum cbrl_lock_type type;
- bool async = false;
- bool pending = false;
- bool pending_async = false;
- int error;
- struct onefs_cbrl_blr_state *bs;
- NTSTATUS status;
-
- START_PROFILE(syscall_brl_lock);
-
- SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
- SMB_ASSERT(plock->lock_type != UNLOCK_LOCK);
-
- onefs_cbrl_enumerate_blq("onefs_brl_lock_windows");
-
- /* Will only initialize the first time its called. */
- onefs_init_cbrl();
-
- switch (plock->lock_type) {
- case WRITE_LOCK:
- type = CBRL_LK_EX;
- break;
- case READ_LOCK:
- type = CBRL_LK_SH;
- break;
- case PENDING_WRITE_LOCK:
- /* Called when a blocking lock request is added - do an
- * async lock. */
- type = CBRL_LK_EX;
- pending = true;
- async = true;
- break;
- case PENDING_READ_LOCK:
- /* Called when a blocking lock request is added - do an
- * async lock. */
- type = CBRL_LK_SH;
- pending = true;
- async = true;
- break;
- default:
- /* UNLOCK_LOCK: should only be used for a POSIX_LOCK */
- smb_panic("Invalid plock->lock_type passed in to "
- "onefs_brl_lock_windows");
- }
-
- /* Figure out if we're actually doing the lock or a no-op. We need to
- * do a no-op when process_blocking_lock_queue calls back into us.
- *
- * We know process_* is calling into us if a blr is passed in and
- * pending is false. */
- if (!pending && blr) {
- /* Check the BLR state. */
- bs = (struct onefs_cbrl_blr_state *)blr->blr_private;
- SMB_ASSERT(bs);
-
- /* ASYNC still in progress: The process_* calls will keep
- * calling even if we haven't gotten the lock. Keep erroring
- * without calling ifs_cbrl, or getting/setting an id. */
- if (bs->state == ONEFS_CBRL_ASYNC) {
- goto failure;
- }
- else if (bs->state == ONEFS_CBRL_ERROR) {
- END_PROFILE(syscall_brl_lock);
- return NT_STATUS_NO_MEMORY;
- }
-
- SMB_ASSERT(bs->state == ONEFS_CBRL_NONE);
- async = true;
- }
-
- if (async) {
- SMB_ASSERT(blocking_lock);
- SMB_ASSERT(blr);
- id = onefs_get_new_id();
- }
-
- DEBUG(10, ("Calling ifs_cbrl(LOCK)...\n"));
- error = ifs_cbrl(fd, CBRL_OP_LOCK, type, plock->start,
- plock->size, async, id, plock->context.smbpid, plock->context.tid,
- plock->fnum);
- if (!error) {
- goto success;
- } else if (errno == EWOULDBLOCK) {
- SMB_ASSERT(!async);
- } else if (errno == EINPROGRESS) {
- SMB_ASSERT(async);
-
- if (pending) {
- /* Talloc a new BLR private state. */
- blr->blr_private = talloc(blr, struct onefs_cbrl_blr_state);
- pending_async = true;
- }
-
- /* Store the new id in the BLR private state. */
- bs = (struct onefs_cbrl_blr_state *)blr->blr_private;
- bs->id = id;
- bs->state = ONEFS_CBRL_ASYNC;
- } else {
- DEBUG(0, ("onefs_brl_lock_windows failure: error=%d (%s).\n",
- errno, strerror(errno)));
- }
-
-failure:
-
- END_PROFILE(syscall_brl_lock);
-
- /* Failure - error or async. */
- plock->context.smbpid = (uint32) ONEFS_BLOCKING_PID;
-
- if (pending_async)
- status = NT_STATUS_OK;
- else
- status = brl_lock_failed(br_lck->fsp, plock, blocking_lock);
-
- DEBUG(10, ("returning %s.\n", nt_errstr(status)));
- return status;
-
-success:
- /* Self contend our own level 2 oplock. The kernel handles
- * contention of other opener's level 2 oplocks. */
- contend_level2_oplocks_begin(br_lck->fsp,
- LEVEL2_CONTEND_WINDOWS_BRL);
-
- END_PROFILE(syscall_brl_lock);
-
- /* Success. */
- onefs_cbrl_enumerate_blq("onefs_brl_unlock_windows");
- DEBUG(10, ("returning NT_STATUS_OK.\n"));
- return NT_STATUS_OK;
-}
-
-bool onefs_brl_unlock_windows(vfs_handle_struct *handle,
- struct messaging_context *msg_ctx,
- struct byte_range_lock *br_lck,
- const struct lock_struct *plock)
-{
- int error;
- int fd = br_lck->fsp->fh->fd;
-
- START_PROFILE(syscall_brl_unlock);
-
- SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
- SMB_ASSERT(plock->lock_type == UNLOCK_LOCK);
-
- DEBUG(10, ("Calling ifs_cbrl(UNLOCK)...\n"));
- error = ifs_cbrl(fd, CBRL_OP_UNLOCK, CBRL_LK_SH,
- plock->start, plock->size, false, 0, plock->context.smbpid,
- plock->context.tid, plock->fnum);
-
- END_PROFILE(syscall_brl_unlock);
-
- if (error) {
- DEBUG(10, ("returning false.\n"));
- return false;
- }
-
- /* For symmetry purposes, end our oplock contention even though its
- * currently a no-op. */
- contend_level2_oplocks_end(br_lck->fsp, LEVEL2_CONTEND_WINDOWS_BRL);
-
- DEBUG(10, ("returning true.\n"));
- return true;
-
- /* Problem with storing things in TDB: I won't know what BRL to unlock in the TDB.
- * - I could fake it?
- * - I could send Samba a message with which lock is being unlocked?
- * - I could *easily* make the "id" something you always pass in to
- * lock, unlock or cancel -- it identifies a lock. Makes sense!
- */
-}
-
-/* Default implementation only calls this on PENDING locks. */
-bool onefs_brl_cancel_windows(vfs_handle_struct *handle,
- struct byte_range_lock *br_lck,
- struct lock_struct *plock,
- struct blocking_lock_record *blr)
-{
- int error;
- int fd = br_lck->fsp->fh->fd;
- struct onefs_cbrl_blr_state *bs;
-
- START_PROFILE(syscall_brl_cancel);
-
- SMB_ASSERT(plock);
- SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
- SMB_ASSERT(blr);
-
- onefs_cbrl_enumerate_blq("onefs_brl_cancel_windows");
-
- bs = ((struct onefs_cbrl_blr_state *)blr->blr_private);
- SMB_ASSERT(bs);
-
- if (bs->state == ONEFS_CBRL_DONE || bs->state == ONEFS_CBRL_ERROR) {
- /* No-op. */
- DEBUG(10, ("State=%d, returning true\n", bs->state));
- END_PROFILE(syscall_brl_cancel);
- return true;
- }
-
- SMB_ASSERT(bs->state == ONEFS_CBRL_NONE ||
- bs->state == ONEFS_CBRL_ASYNC);
-
- /* A real cancel. */
- DEBUG(10, ("Calling ifs_cbrl(CANCEL)...\n"));
- error = ifs_cbrl(fd, CBRL_OP_CANCEL, CBRL_LK_UNSPEC, plock->start,
- plock->size, false, bs->id, plock->context.smbpid,
- plock->context.tid, plock->fnum);
-
- END_PROFILE(syscall_brl_cancel);
-
- if (error) {
- DEBUG(10, ("returning false\n"));
- bs->state = ONEFS_CBRL_ERROR;
- return false;
- }
-
- bs->state = ONEFS_CBRL_DONE;
- onefs_cbrl_enumerate_blq("onefs_brl_cancel_windows");
- DEBUG(10, ("returning true\n"));
- return true;
-}
-
-bool onefs_strict_lock(vfs_handle_struct *handle,
- files_struct *fsp,
- struct lock_struct *plock)
-{
- int error;
-
- START_PROFILE(syscall_strict_lock);
-
- SMB_ASSERT(plock->lock_type == READ_LOCK ||
- plock->lock_type == WRITE_LOCK);
-
- if (!lp_locking(handle->conn->params) ||
- !lp_strict_locking(handle->conn->params)) {
- END_PROFILE(syscall_strict_lock);
- return True;
- }
-
- if (plock->lock_flav == POSIX_LOCK) {
- END_PROFILE(syscall_strict_lock);
- return SMB_VFS_NEXT_STRICT_LOCK(handle, fsp, plock);
- }
-
- if (plock->size == 0) {
- END_PROFILE(syscall_strict_lock);
- return True;
- }
-
- error = ifs_cbrl(fsp->fh->fd, CBRL_OP_LOCK,
- plock->lock_type == READ_LOCK ? CBRL_LK_RD : CBRL_LK_WR,
- plock->start, plock->size, 0, 0, plock->context.smbpid,
- plock->context.tid, plock->fnum);
-
- END_PROFILE(syscall_strict_lock);
-
- return (error == 0);
-}
-
-void onefs_strict_unlock(vfs_handle_struct *handle,
- files_struct *fsp,
- struct lock_struct *plock)
-{
- START_PROFILE(syscall_strict_unlock);
-
- SMB_ASSERT(plock->lock_type == READ_LOCK ||
- plock->lock_type == WRITE_LOCK);
-
- if (!lp_locking(handle->conn->params) ||
- !lp_strict_locking(handle->conn->params)) {
- END_PROFILE(syscall_strict_unlock);
- return;
- }
-
- if (plock->lock_flav == POSIX_LOCK) {
- SMB_VFS_NEXT_STRICT_UNLOCK(handle, fsp, plock);
- END_PROFILE(syscall_strict_unlock);
- return;
- }
-
- if (plock->size == 0) {
- END_PROFILE(syscall_strict_unlock);
- return;
- }
-
- if (fsp->fh) {
- ifs_cbrl(fsp->fh->fd, CBRL_OP_UNLOCK,
- plock->lock_type == READ_LOCK ? CBRL_LK_RD : CBRL_LK_WR,
- plock->start, plock->size, 0, 0, plock->context.smbpid,
- plock->context.tid, plock->fnum);
- }
-
- END_PROFILE(syscall_strict_unlock);
-}
-
-/* TODO Optimization: Abstract out brl_get_locks() in the Windows case.
- * We'll malloc some memory or whatever (can't return NULL), but not actually
- * touch the TDB. */
-
-/* XXX brl_locktest: CBRL does not support calling this, but its only for
- * strict locking. Add empty VOP? */
-
-/* XXX brl_lockquery: CBRL does not support calling this for WINDOWS LOCKS, but
- * its only called for POSIX LOCKS. Add empty VOP? */
-
-/* XXX brl_close_fnum: CBRL will do this automatically. I think this is a NO-OP
- * for us, we could add an empty VOP. */
-
diff --git a/source3/modules/onefs_config.c b/source3/modules/onefs_config.c
deleted file mode 100644
index 8b34d7cd45..0000000000
--- a/source3/modules/onefs_config.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Unix SMB/CIFS implementation.
- * Support for OneFS
- *
- * Copyright (C) Todd Stecher, 2009
- * Copyright (C) Tim Prouty, 2009
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "includes.h"
-#include "smbd/smbd.h"
-#include "onefs_config.h"
-
-#include <ifs/ifs_syscalls.h>
-
-#define ONEFS_DATA_FASTBUF 10
-
-struct onefs_vfs_share_config vfs_share_config[ONEFS_DATA_FASTBUF];
-struct onefs_vfs_share_config *pvfs_share_config;
-
-static void onefs_load_faketimestamp_config(struct connection_struct *conn,
- struct onefs_vfs_share_config *cfg)
-{
- const char **parm;
- int snum = SNUM(conn);
-
- parm = lp_parm_string_list(snum, PARM_ONEFS_TYPE, PARM_ATIME_NOW,
- PARM_ATIME_NOW_DEFAULT);
-
- if (parm) {
- cfg->init_flags |= ONEFS_VFS_CONFIG_FAKETIMESTAMPS;
- set_namearray(&cfg->atime_now_list,*parm);
- }
-
- parm = lp_parm_string_list(snum, PARM_ONEFS_TYPE, PARM_CTIME_NOW,
- PARM_CTIME_NOW_DEFAULT);
-
- if (parm) {
- cfg->init_flags |= ONEFS_VFS_CONFIG_FAKETIMESTAMPS;
- set_namearray(&cfg->ctime_now_list,*parm);
- }
-
- parm = lp_parm_string_list(snum, PARM_ONEFS_TYPE, PARM_MTIME_NOW,
- PARM_MTIME_NOW_DEFAULT);
-
- if (parm) {
- cfg->init_flags |= ONEFS_VFS_CONFIG_FAKETIMESTAMPS;
- set_namearray(&cfg->mtime_now_list,*parm);
- }
-
- parm = lp_parm_string_list(snum, PARM_ONEFS_TYPE, PARM_ATIME_STATIC,
- PARM_ATIME_STATIC_DEFAULT);
-
- if (parm) {
- cfg->init_flags |= ONEFS_VFS_CONFIG_FAKETIMESTAMPS;
- set_namearray(&cfg->atime_static_list,*parm);
- }
-
- parm = lp_parm_string_list(snum, PARM_ONEFS_TYPE, PARM_MTIME_STATIC,
- PARM_MTIME_STATIC_DEFAULT);
-
- if (parm) {
- cfg->init_flags |= ONEFS_VFS_CONFIG_FAKETIMESTAMPS;
- set_namearray(&cfg->mtime_static_list,*parm);
- }
-
- cfg->atime_slop = lp_parm_int(snum, PARM_ONEFS_TYPE, PARM_ATIME_SLOP,
- PARM_ATIME_SLOP_DEFAULT);
- cfg->ctime_slop = lp_parm_int(snum, PARM_ONEFS_TYPE, PARM_CTIME_SLOP,
- PARM_CTIME_SLOP_DEFAULT);
- cfg->mtime_slop = lp_parm_int(snum, PARM_ONEFS_TYPE, PARM_MTIME_SLOP,
- PARM_MTIME_SLOP_DEFAULT);
-}
-
-/**
- * Set onefs-specific vfs global config parameters.
- *
- * Since changes in these parameters require calling syscalls, we only want to
- * call them when the configuration actually changes.
- */
-static void onefs_load_global_config(connection_struct *conn)
-{
- static struct onefs_vfs_global_config global_config;
- bool dot_snap_child_accessible;
- bool dot_snap_child_visible;
- bool dot_snap_root_accessible;
- bool dot_snap_root_visible;
- bool dot_snap_tilde;
- bool reconfig_dso = false;
- bool reconfig_tilde = false;
-
- /* Check if this is the first time setting the config options. */
- if (!(global_config.init_flags & ONEFS_VFS_CONFIG_INITIALIZED)) {
- global_config.init_flags |= ONEFS_VFS_CONFIG_INITIALIZED;
-
- /* Set process encoding */
- onefs_sys_config_enc();
-
- reconfig_dso = true;
- reconfig_tilde = true;
- }
-
- /* Get the dot snap options from the conf. */
- dot_snap_child_accessible =
- lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE,
- PARM_DOT_SNAP_CHILD_ACCESSIBLE,
- PARM_DOT_SNAP_CHILD_ACCESSIBLE_DEFAULT);
- dot_snap_child_visible =
- lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE,
- PARM_DOT_SNAP_CHILD_VISIBLE,
- PARM_DOT_SNAP_CHILD_VISIBLE_DEFAULT);
- dot_snap_root_accessible =
- lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE,
- PARM_DOT_SNAP_ROOT_ACCESSIBLE,
- PARM_DOT_SNAP_ROOT_ACCESSIBLE_DEFAULT);
- dot_snap_root_visible =
- lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE,
- PARM_DOT_SNAP_ROOT_VISIBLE,
- PARM_DOT_SNAP_ROOT_VISIBLE_DEFAULT);
- dot_snap_tilde =
- lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE,
- PARM_DOT_SNAP_TILDE,
- PARM_DOT_SNAP_TILDE_DEFAULT);
-
- /* Check if any of the dot snap options need updating. */
- if (dot_snap_child_accessible !=
- global_config.dot_snap_child_accessible) {
- global_config.dot_snap_child_accessible =
- dot_snap_child_accessible;
- reconfig_dso = true;
- }
- if (dot_snap_child_visible !=
- global_config.dot_snap_child_visible) {
- global_config.dot_snap_child_visible =
- dot_snap_child_visible;
- reconfig_dso = true;
- }
- if (dot_snap_root_accessible !=
- global_config.dot_snap_root_accessible) {
- global_config.dot_snap_root_accessible =
- dot_snap_root_accessible;
- reconfig_dso = true;
- }
- if (dot_snap_root_visible !=
- global_config.dot_snap_root_visible) {
- global_config.dot_snap_root_visible =
- dot_snap_root_visible;
- reconfig_dso = true;
- }
- if (dot_snap_tilde != global_config.dot_snap_tilde) {
- global_config.dot_snap_tilde = dot_snap_tilde;
- reconfig_tilde = true;
- }
-
- /* If a dot snap option has changed update the process. */
- if (reconfig_dso) {
- onefs_sys_config_snap_opt(&global_config);
- }
-
- /* If the dot snap tilde option has changed update the process. */
- if (reconfig_tilde) {
- onefs_sys_config_tilde(&global_config);
- }
-}
-
-int onefs_load_config(connection_struct *conn)
-{
- int snum = SNUM(conn);
- int share_count = lp_numservices();
-
- /* Share config */
- if (!pvfs_share_config) {
-
- if (share_count <= ONEFS_DATA_FASTBUF)
- pvfs_share_config = vfs_share_config;
- else {
- pvfs_share_config =
- SMB_MALLOC_ARRAY(struct onefs_vfs_share_config,
- share_count);
- if (!pvfs_share_config) {
- errno = ENOMEM;
- return -1;
- }
-
- memset(pvfs_share_config, 0,
- (sizeof(struct onefs_vfs_share_config) *
- share_count));
- }
- }
-
- if ((pvfs_share_config[snum].init_flags &
- ONEFS_VFS_CONFIG_INITIALIZED) == 0) {
- pvfs_share_config[snum].init_flags =
- ONEFS_VFS_CONFIG_INITIALIZED;
- onefs_load_faketimestamp_config(conn,
- &pvfs_share_config[snum]);
- }
-
- /* Global config */
- onefs_load_global_config(conn);
-
- return 0;
-}
-
-bool onefs_get_config(int snum, int config_type,
- struct onefs_vfs_share_config *cfg)
-{
- if ((pvfs_share_config != NULL) &&
- (pvfs_share_config[snum].init_flags & config_type))
- *cfg = pvfs_share_config[snum];
- else
- return false;
-
- return true;
-}
-
-
-/**
- * Set the per-process encoding, ignoring errors.
- */
-void onefs_sys_config_enc(void)
-{
- int ret;
-
- ret = enc_set_proc(ENC_UTF8);
- if (ret) {
- DEBUG(0, ("Setting process encoding failed: %s\n",
- strerror(errno)));
- }
-}
-
-/**
- * Set the per-process .snpashot directory options, ignoring errors.
- */
-void onefs_sys_config_snap_opt(struct onefs_vfs_global_config *global_config)
-{
- struct ifs_dotsnap_options dso;
- int ret;
-
- dso.per_proc = 1;
- dso.sub_accessible = global_config->dot_snap_child_accessible;
- dso.sub_visible = global_config->dot_snap_child_visible;
- dso.root_accessible = global_config->dot_snap_root_accessible;
- dso.root_visible = global_config->dot_snap_root_visible;
-
- ret = ifs_set_dotsnap_options(&dso);
- if (ret) {
- DEBUG(0, ("Setting snapshot visibility/accessibility "
- "failed: %s\n", strerror(errno)));
- }
-}
-
-/**
- * Set the per-process flag saying whether or not to accept ~snapshot
- * as an alternative name for .snapshot directories.
- */
-void onefs_sys_config_tilde(struct onefs_vfs_global_config *global_config)
-{
- int ret;
-
- ret = ifs_tilde_snapshot(global_config->dot_snap_tilde);
- if (ret) {
- DEBUG(0, ("Setting snapshot tilde failed: %s\n",
- strerror(errno)));
- }
-}
diff --git a/source3/modules/onefs_config.h b/source3/modules/onefs_config.h
deleted file mode 100644
index f0f48e6379..0000000000
--- a/source3/modules/onefs_config.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Unix SMB/CIFS implementation.
- * OneFS vfs module configuration and defaults
- *
- * Copyright (C) Steven Danneman, 2008
- * Copyright (C) Tim Prouty, 2009
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef _ONEFS_CONFIG_H
-#define _ONEFS_CONFIG_H
-
-/**
-* Specifies when ACLs presented to Windows should be canonicalized
-* into the ordering which Explorer expects.
-*/
-enum onefs_acl_wire_format
-{
- ACL_FORMAT_RAW, /**< Never canonicalize */
- ACL_FORMAT_WINDOWS_SD, /**< Only canonicalize synthetic ACLs */
- ACL_FORMAT_ALWAYS /**< Always canonicalize */
-};
-
-#define PARM_ONEFS_TYPE "onefs"
-#define PARM_ACL_WIRE_FORMAT "acl wire format"
-#define PARM_ACL_WIRE_FORMAT_DEFAULT ACL_FORMAT_WINDOWS_SD
-#define PARM_ALLOW_EXECUTE_ALWAYS "allow execute always"
-#define PARM_ALLOW_EXECUTE_ALWAYS_DEFAULT false
-#define PARM_ATIME_NOW "atime now files"
-#define PARM_ATIME_NOW_DEFAULT NULL
-#define PARM_ATIME_STATIC "atime static files"
-#define PARM_ATIME_STATIC_DEFAULT NULL
-#define PARM_ATIME_SLOP "atime now slop"
-#define PARM_ATIME_SLOP_DEFAULT 0
-#define PARM_ATOMIC_SENDFILE "atomic sendfile"
-#define PARM_ATOMIC_SENDFILE_DEFAULT true
-#define PARM_CREATOR_OWNER_GETS_FULL_CONTROL "creator owner gets full control"
-#define PARM_CREATOR_OWNER_GETS_FULL_CONTROL_DEFAULT true
-#define PARM_CTIME_NOW "ctime now files"
-#define PARM_CTIME_NOW_DEFAULT NULL
-#define PARM_CTIME_SLOP "ctime now slop"
-#define PARM_CTIME_SLOP_DEFAULT 0
-#define PARM_DOT_SNAP_CHILD_ACCESSIBLE "dot snap child accessible"
-#define PARM_DOT_SNAP_CHILD_ACCESSIBLE_DEFAULT true
-#define PARM_DOT_SNAP_CHILD_VISIBLE "dot snap child visible"
-#define PARM_DOT_SNAP_CHILD_VISIBLE_DEFAULT false
-#define PARM_DOT_SNAP_ROOT_ACCESSIBLE "dot snap root accessible"
-#define PARM_DOT_SNAP_ROOT_ACCESSIBLE_DEFAULT true
-#define PARM_DOT_SNAP_ROOT_VISIBLE "dot snap root visible"
-#define PARM_DOT_SNAP_ROOT_VISIBLE_DEFAULT true
-#define PARM_DOT_SNAP_TILDE "dot snap tilde"
-#define PARM_DOT_SNAP_TILDE_DEFAULT true
-#define PARM_IGNORE_SACLS "ignore sacls"
-#define PARM_IGNORE_SACLS_DEFAULT false
-#define PARM_IGNORE_STREAMS "ignore streams"
-#define PARM_IGNORE_STREAMS_DEFAULT false
-#define PARM_MTIME_NOW "mtime now files"
-#define PARM_MTIME_NOW_DEFAULT NULL
-#define PARM_MTIME_STATIC "mtime static files"
-#define PARM_MTIME_STATIC_DEFAULT NULL
-#define PARM_MTIME_SLOP "mtime now slop"
-#define PARM_MTIME_SLOP_DEFAULT 0
-#define PARM_USE_READDIRPLUS "use readdirplus"
-#define PARM_USE_READDIRPLUS_DEFAULT true
-#define PARM_SENDFILE_LARGE_READS "sendfile large reads"
-#define PARM_SENDFILE_LARGE_READS_DEFAULT false
-#define PARM_SENDFILE_SAFE "sendfile safe"
-#define PARM_SENDFILE_SAFE_DEFAULT true
-#define PARM_SIMPLE_FILE_SHARING_COMPATIBILITY_MODE "simple file sharing compatibility mode"
-#define PARM_SIMPLE_FILE_SHARING_COMPATIBILITY_MODE_DEFAULT false
-#define PARM_UNMAPPABLE_SIDS_DENY_EVERYONE "unmappable sids deny everyone"
-#define PARM_UNMAPPABLE_SIDS_DENY_EVERYONE_DEFAULT false
-#define PARM_UNMAPPABLE_SIDS_IGNORE "ignore unmappable sids"
-#define PARM_UNMAPPABLE_SIDS_IGNORE_DEFAULT false
-#define PARM_UNMAPPABLE_SIDS_IGNORE_LIST "unmappable sids ignore list"
-#define PARM_UNMAPPABLE_SIDS_IGNORE_LIST_DEFAULT NULL
-
-#define IS_CTIME_NOW_PATH(conn,cfg,path) ((conn) && is_in_path((path),\
- (cfg)->ctime_now_list,(conn)->case_sensitive))
-#define IS_MTIME_NOW_PATH(conn,cfg,path) ((conn) && is_in_path((path),\
- (cfg)->mtime_now_list,(conn)->case_sensitive))
-#define IS_ATIME_NOW_PATH(conn,cfg,path) ((conn) && is_in_path((path),\
- (cfg)->atime_now_list,(conn)->case_sensitive))
-#define IS_MTIME_STATIC_PATH(conn,cfg,path) ((conn) && is_in_path((path),\
- (cfg)->mtime_static_list,(conn)->case_sensitive))
-#define IS_ATIME_STATIC_PATH(conn,cfg,path) ((conn) && is_in_path((path),\
- (cfg)->atime_static_list,(conn)->case_sensitive))
-
-/*
- * Store some commonly evaluated parameters to avoid loadparm pain.
- */
-
-#define ONEFS_VFS_CONFIG_INITIALIZED 0x00010000
-
-#define ONEFS_VFS_CONFIG_FAKETIMESTAMPS 0x00000001
-
-struct onefs_vfs_share_config
-{
- uint32_t init_flags;
-
- /* data for fake timestamps */
- int atime_slop;
- int ctime_slop;
- int mtime_slop;
-
- /* Per-share list of files to fake the create time for. */
- name_compare_entry *ctime_now_list;
-
- /* Per-share list of files to fake the modification time for. */
- name_compare_entry *mtime_now_list;
-
- /* Per-share list of files to fake the access time for. */
- name_compare_entry *atime_now_list;
-
- /* Per-share list of files to fake the modification time for. */
- name_compare_entry *mtime_static_list;
-
- /* The access time will equal the create time. */
- /* The modification time will equal the create time.*/
-
- /* Per-share list of files to fake the access time for. */
- name_compare_entry *atime_static_list;
-};
-
-struct onefs_vfs_global_config
-{
- uint32_t init_flags;
-
- /* Snapshot options */
- bool dot_snap_child_accessible;
- bool dot_snap_child_visible;
- bool dot_snap_root_accessible;
- bool dot_snap_root_visible;
- bool dot_snap_tilde;
-};
-
-int onefs_load_config(connection_struct *conn);
-
-bool onefs_get_config(int snum, int config_type,
- struct onefs_vfs_share_config *cfg);
-
-void onefs_sys_config_enc(void);
-
-void onefs_sys_config_snap_opt(struct onefs_vfs_global_config *global_config);
-
-void onefs_sys_config_tilde(struct onefs_vfs_global_config *global_config);
-
-#endif /* _ONEFS_CONFIG_H */
diff --git a/source3/modules/onefs_dir.c b/source3/modules/onefs_dir.c
deleted file mode 100644
index 1a0f4819fe..0000000000
--- a/source3/modules/onefs_dir.c
+++ /dev/null
@@ -1,622 +0,0 @@
-/*
- * Unix SMB/CIFS implementation.
- *
- * Support for OneFS bulk directory enumeration API
- *
- * Copyright (C) Steven Danneman, 2009
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "includes.h"
-#include "smbd/smbd.h"
-#include "onefs.h"
-#include "onefs_config.h"
-
-#include <ifs/ifs_syscalls.h>
-#include <isi_util/isi_dir.h>
-
-/* The OneFS filesystem provides a readdirplus() syscall, equivalent to the
- * NFSv3 PDU, which retrieves bulk directory listings with stat information
- * in a single syscall.
- *
- * This file hides this bulk interface underneath Samba's very POSIX like
- * opendir/readdir/telldir VFS interface. This is done to provide a
- * significant performance improvement when listing the contents of large
- * directories, which also require file meta information. ie a typical
- * Windows Explorer request.
- */
-
-#define RDP_RESUME_KEY_START 0x1
-
-#define RDP_BATCH_SIZE 128
-#define RDP_DIRENTRIES_SIZE ((size_t)(RDP_BATCH_SIZE * sizeof(struct dirent)))
-
-static char *rdp_direntries = NULL;
-static struct stat *rdp_stats = NULL;
-static uint64_t *rdp_cookies = NULL;
-
-struct rdp_dir_state {
- struct rdp_dir_state *next, *prev;
- DIR *dirp;
- char *direntries_cursor; /* cursor to last returned direntry in cache */
- size_t stat_count; /* number of entries stored in the cache */
- size_t stat_cursor; /* cursor to last returned stat in the cache */
- uint64_t resume_cookie; /* cookie from the last entry returned from the
- cache */
-};
-
-static struct rdp_dir_state *dirstatelist = NULL;
-
-DIR *rdp_last_dirp = NULL;
-
-/**
- * Given a DIR pointer, return our internal state.
- *
- * This function also tells us whether the given DIR is the same as we saw
- * during the last call. Because we use a single globally allocated buffer
- * for readdirplus entries we must check every call into this API to see if
- * it's for the same directory listing, or a new one. If it's the same we can
- * maintain our current cached entries, otherwise we must go to the kernel.
- *
- * @return 0 on success, 1 on failure
- */
-static int
-rdp_retrieve_dir_state(DIR *dirp, struct rdp_dir_state **dir_state,
- bool *same_as_last)
-{
- struct rdp_dir_state *dsp;
-
- /* Is this directory the same as the last call */
- *same_as_last = (dirp == rdp_last_dirp);
-
- for(dsp = dirstatelist; dsp; dsp = dsp->next)
- if (dsp->dirp == dirp) {
- *dir_state = dsp;
- return 0;
- }
-
- /* Couldn't find existing dir_state for the given directory
- * pointer. */
- return 1;
-}
-
-/**
- * Initialize the global readdirplus buffers.
- *
- * These same buffers are used for all calls into readdirplus.
- *
- * @return 0 on success, errno value on failure
- */
-static int
-rdp_init(struct rdp_dir_state *dsp)
-{
- /* Unfortunately, there is no good way to free these buffers. If we
- * allocated and freed for every DIR handle performance would be
- * adversely affected. For now these buffers will be leaked and only
- * freed when the smbd process dies. */
- if (!rdp_direntries) {
- rdp_direntries = SMB_MALLOC(RDP_DIRENTRIES_SIZE);
- if (!rdp_direntries)
- return ENOMEM;
- }
-
- if (!rdp_stats) {
- rdp_stats =
- SMB_MALLOC(RDP_BATCH_SIZE * sizeof(struct stat));
- if (!rdp_stats)
- return ENOMEM;
- }
-
- if (!rdp_cookies) {
- rdp_cookies = SMB_MALLOC(RDP_BATCH_SIZE * sizeof(uint64_t));
- if (!rdp_cookies)
- return ENOMEM;
- }
-
- dsp->direntries_cursor = rdp_direntries + RDP_DIRENTRIES_SIZE;
- dsp->stat_count = RDP_BATCH_SIZE;
- dsp->stat_cursor = RDP_BATCH_SIZE;
- dsp->resume_cookie = RDP_RESUME_KEY_START;
-
- return 0;
-}
-
-/**
- * Call into readdirplus() to refill our global dirent cache.
- *
- * This function also resets all cursors back to the beginning of the cache.
- * All stat buffers are retrieved by following symlinks.
- *
- * @return number of entries retrieved, -1 on error
- */
-static int
-rdp_fill_cache(struct rdp_dir_state *dsp)
-{
- int nread, dirfd;
-
- dirfd = dirfd(dsp->dirp);
- if (dirfd < 0) {
- DEBUG(1, ("Could not retrieve fd for DIR\n"));
- return -1;
- }
-
- /* Resize the stat_count to grab as many entries as possible */
- dsp->stat_count = RDP_BATCH_SIZE;
-
- DEBUG(9, ("Calling readdirplus() with DIR %p, dirfd: %d, "
- "resume_cookie %#llx, size_to_read: %zu, "
- "direntries_size: %zu, stat_count: %u\n",
- dsp->dirp, dirfd, dsp->resume_cookie, RDP_BATCH_SIZE,
- RDP_DIRENTRIES_SIZE, dsp->stat_count));
-
- nread = readdirplus(dirfd,
- RDP_FOLLOW,
- &dsp->resume_cookie,
- RDP_BATCH_SIZE,
- rdp_direntries,
- RDP_DIRENTRIES_SIZE,
- &dsp->stat_count,
- rdp_stats,
- rdp_cookies);
- if (nread < 0) {
- DEBUG(1, ("Error calling readdirplus(): %s\n",
- strerror(errno)));
- return -1;
- }
-
- DEBUG(9, ("readdirplus() returned %u entries from DIR %p\n",
- dsp->stat_count, dsp->dirp));
-
- dsp->direntries_cursor = rdp_direntries;
- dsp->stat_cursor = 0;
-
- return nread;
-}
-
-/**
- * Create a dir_state to track an open directory that we're enumerating.
- *
- * This utility function is globally accessible for use by other parts of the
- * onefs.so module to initialize a dir_state when a directory is opened through
- * a path other than the VFS layer.
- *
- * @return 0 on success and errno on failure
- *
- * @note: Callers of this function MUST cleanup the dir_state through a proper
- * call to VFS_CLOSEDIR().
- */
-int
-onefs_rdp_add_dir_state(connection_struct *conn, DIR *dirp)
-{
- int ret = 0;
- struct rdp_dir_state *dsp = NULL;
-
- /* No-op if readdirplus is disabled */
- if (!lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE,
- PARM_USE_READDIRPLUS, PARM_USE_READDIRPLUS_DEFAULT))
- {
- return 0;
- }
-
- /* Create a struct dir_state */
- dsp = SMB_MALLOC_P(struct rdp_dir_state);
- if (!dsp) {
- DEBUG(0, ("Error allocating struct rdp_dir_state.\n"));
- return ENOMEM;
- }
-
- /* Initialize the dir_state structure and add it to the list */
- ret = rdp_init(dsp);
- if (ret) {
- DEBUG(0, ("Error initializing readdirplus() buffers: %s\n",
- strerror(ret)));
- return ret;
- }
-
- /* Set the DIR in the dsp */
- dsp->dirp = dirp;
-
- DLIST_ADD(dirstatelist, dsp);
-
- return 0;
-}
-
-/**
- * Open a directory for enumeration.
- *
- * Create a state struct to track the state of this directory for the life
- * of this open.
- *
- * @param[in] handle vfs handle given in most VFS calls
- * @param[in] fname filename of the directory to open
- * @param[in] mask unused
- * @param[in] attr unused
- *
- * @return DIR pointer, NULL if directory does not exist, NULL on error
- */
-DIR *
-onefs_opendir(vfs_handle_struct *handle, const char *fname, const char *mask,
- uint32 attr)
-{
- int ret = 0;
- DIR *ret_dirp;
-
- /* Fallback to default system routines if readdirplus is disabled */
- if (!lp_parm_bool(SNUM(handle->conn), PARM_ONEFS_TYPE,
- PARM_USE_READDIRPLUS, PARM_USE_READDIRPLUS_DEFAULT))
- {
- return SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
- }
-
- /* Open the directory */
- ret_dirp = SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
- if (!ret_dirp) {
- DEBUG(3, ("Unable to open directory: %s\n", fname));
- return NULL;
- }
-
- /* Create the dir_state struct and add it to the list */
- ret = onefs_rdp_add_dir_state(handle->conn, ret_dirp);
- if (ret) {
- DEBUG(0, ("Error adding dir_state to the list\n"));
- return NULL;
- }
-
- DEBUG(9, ("Opened handle on directory: \"%s\", DIR %p\n",
- fname, ret_dirp));
-
- return ret_dirp;
-}
-
-/**
- * Retrieve one direntry and optional stat buffer from our readdir cache.
- *
- * Increment the internal resume cookie, and refresh the cache from the
- * kernel if necessary.
- *
- * The cache cursor tracks the last entry which was successfully returned
- * to a caller of onefs_readdir(). When a new entry is requested, this
- * function first increments the cursor, then returns that entry.
- *
- * @param[in] handle vfs handle given in most VFS calls
- * @param[in] dirp system DIR handle to retrieve direntries from
- * @param[in/out] sbuf optional stat buffer to fill, this can be NULL
- *
- * @return dirent structure, NULL if at the end of the directory, NULL on error
- */
-struct dirent *
-onefs_readdir(vfs_handle_struct *handle, DIR *dirp,
- SMB_STRUCT_STAT *sbuf)
-{
- struct rdp_dir_state *dsp = NULL;
- struct dirent *ret_direntp;
- bool same_as_last, filled_cache = false;
- int ret = -1;
-
- /* Set stat invalid in-case we error out */
- if (sbuf)
- SET_STAT_INVALID(*sbuf);
-
- /* Fallback to default system routines if readdirplus is disabled */
- if (!lp_parm_bool(SNUM(handle->conn), PARM_ONEFS_TYPE,
- PARM_USE_READDIRPLUS, PARM_USE_READDIRPLUS_DEFAULT))
- {
- return readdir(dirp);
- }
-
- /* Retrieve state based off DIR handle */
- ret = rdp_retrieve_dir_state(dirp, &dsp, &same_as_last);
- if (ret) {
- DEBUG(1, ("Could not retrieve dir_state struct for "
- "DIR pointer.\n"));
- ret_direntp = NULL;
- goto end;
- }
-
- /* DIR is the same, current buffer and cursors are valid.
- * Check if there are any entries left in our current cache. */
- if (same_as_last) {
- if (dsp->stat_cursor == dsp->stat_count - 1) {
- /* Cache is empty, refill from kernel */
- ret = rdp_fill_cache(dsp);
- if (ret <= 0) {
- ret_direntp = NULL;
- goto end;
- }
- filled_cache = true;
- }
- } else {
- /* DIR is different from last call, reset all buffers and
- * cursors, and refill the global cache from the new DIR */
- ret = rdp_fill_cache(dsp);
- if (ret <= 0) {
- ret_direntp = NULL;
- goto end;
- }
- filled_cache = true;
- DEBUG(8, ("Switched global rdp cache to new DIR entry.\n"));
- }
-
- /* If we just filled the cache we treat that action as the cursor
- * increment as the resume cookie used belonged to the previous
- * directory entry. If the cache has not changed we first increment
- * our cursor, then return the next entry */
- if (!filled_cache) {
- dsp->direntries_cursor +=
- ((struct dirent *)dsp->direntries_cursor)->d_reclen;
- dsp->stat_cursor++;
- }
-
- /* The resume_cookie stored here purposely differs based on whether we
- * just filled the cache. The resume cookie stored must always provide
- * the next direntry, in case the cache is reloaded on every
- * onefs_readdir() */
- dsp->resume_cookie = rdp_cookies[dsp->stat_cursor];
-
- /* Return an entry from cache */
- ret_direntp = ((struct dirent *)dsp->direntries_cursor);
- if (sbuf) {
- struct stat onefs_sbuf;
-
- onefs_sbuf = rdp_stats[dsp->stat_cursor];
- init_stat_ex_from_onefs_stat(sbuf, &onefs_sbuf);
-
- /* readdirplus() sets st_ino field to 0, if it was
- * unable to retrieve stat information for that
- * particular directory entry. */
- if (sbuf->st_ex_ino == 0)
- SET_STAT_INVALID(*sbuf);
- }
-
- DEBUG(9, ("Read from DIR %p, direntry: \"%s\", resume cookie: %#llx, "
- "cache cursor: %zu, cache count: %zu\n",
- dsp->dirp, ret_direntp->d_name, dsp->resume_cookie,
- dsp->stat_cursor, dsp->stat_count));
-
- /* FALLTHROUGH */
-end:
- /* Set rdp_last_dirp at the end of every VFS call where the cache was
- * reloaded */
- rdp_last_dirp = dirp;
- return ret_direntp;
-}
-
-/**
- * Set the location of the next direntry to be read via onefs_readdir().
- *
- * This function should only pass in locations retrieved from onefs_telldir().
- *
- * @param[in] handle vfs handle given in most VFS calls
- * @param[in] dirp system DIR handle to set offset on
- * @param[in] offset into the directory to resume reading from
- *
- * @return no return value
- */
-void
-onefs_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
-{
- struct rdp_dir_state *dsp = NULL;
- bool same_as_last;
- uint64_t resume_cookie = 0;
- int ret = -1;
-
- /* Fallback to default system routines if readdirplus is disabled */
- if (!lp_parm_bool(SNUM(handle->conn), PARM_ONEFS_TYPE,
- PARM_USE_READDIRPLUS, PARM_USE_READDIRPLUS_DEFAULT))
- {
- return seekdir(dirp, offset);
- }
-
- /* Validate inputs */
- if (offset < 0) {
- DEBUG(1, ("Invalid offset %ld passed.\n", offset));
- return;
- }
-
- /* Retrieve state based off DIR handle */
- ret = rdp_retrieve_dir_state(dirp, &dsp, &same_as_last);
- if (ret) {
- DEBUG(1, ("Could not retrieve dir_state struct for "
- "DIR pointer.\n"));
- /* XXX: we can't return an error, should we ABORT rather than
- * return without actually seeking? */
- return;
- }
-
- /* Convert offset to resume_cookie */
- resume_cookie = rdp_offset31_to_cookie63(offset);
-
- DEBUG(9, ("Seek DIR %p, offset: %ld, resume_cookie: %#llx\n",
- dsp->dirp, offset, resume_cookie));
-
- /* TODO: We could check if the resume_cookie is already in the cache
- * through a linear search. This would allow us to avoid the cost of
- * flushing the cache. Frequently, the seekdir offset will only be
- * one entry before the current cache cursor. However, usually
- * VFS_SEEKDIR() is only called at the end of a TRAND2_FIND read and
- * we'll flush the cache at the beginning of the next PDU anyway. Some
- * analysis should be done to see if this enhancement would provide
- * better performance. */
-
- /* Set the resume cookie and indicate that the cache should be reloaded
- * on next read */
- dsp->resume_cookie = resume_cookie;
- rdp_last_dirp = NULL;
-
- return;
-}
-
-/**
- * Returns the location of the next direntry to be read via onefs_readdir().
- *
- * This value can be passed into onefs_seekdir().
- *
- * @param[in] handle vfs handle given in most VFS calls
- * @param[in] dirp system DIR handle to set offset on
- *
- * @return offset into the directory to resume reading from
- */
-long
-onefs_telldir(vfs_handle_struct *handle, DIR *dirp)
-{
- struct rdp_dir_state *dsp = NULL;
- bool same_as_last;
- long offset;
- int ret = -1;
-
- /* Fallback to default system routines if readdirplus is disabled */
- if (!lp_parm_bool(SNUM(handle->conn), PARM_ONEFS_TYPE,
- PARM_USE_READDIRPLUS, PARM_USE_READDIRPLUS_DEFAULT))
- {
- return telldir(dirp);
- }
-
- /* Retrieve state based off DIR handle */
- ret = rdp_retrieve_dir_state(dirp, &dsp, &same_as_last);
- if (ret) {
- DEBUG(1, ("Could not retrieve dir_state struct for "
- "DIR pointer.\n"));
- return -1;
- }
-
- /* Convert resume_cookie to offset */
- offset = rdp_cookie63_to_offset31(dsp->resume_cookie);
- if (offset < 0) {
- DEBUG(1, ("Unable to convert resume_cookie: %#llx to a "
- "suitable 32-bit offset value. Error: %s\n",
- dsp->resume_cookie, strerror(errno)));
- return -1;
- }
-
- DEBUG(9, ("Seek DIR %p, offset: %ld, resume_cookie: %#llx\n",
- dsp->dirp, offset, dsp->resume_cookie));
-
- return offset;
-}
-
-/**
- * Set the next direntry to be read via onefs_readdir() to the beginning of the
- * directory.
- *
- * @param[in] handle vfs handle given in most VFS calls
- * @param[in] dirp system DIR handle to set offset on
- *
- * @return no return value
- */
-void
-onefs_rewinddir(vfs_handle_struct *handle, DIR *dirp)
-{
- struct rdp_dir_state *dsp = NULL;
- bool same_as_last;
- int ret = -1;
-
- /* Fallback to default system routines if readdirplus is disabled */
- if (!lp_parm_bool(SNUM(handle->conn), PARM_ONEFS_TYPE,
- PARM_USE_READDIRPLUS, PARM_USE_READDIRPLUS_DEFAULT))
- {
- return rewinddir(dirp);
- }
-
- /* Retrieve state based off DIR handle */
- ret = rdp_retrieve_dir_state(dirp, &dsp, &same_as_last);
- if (ret) {
- DEBUG(1, ("Could not retrieve dir_state struct for "
- "DIR pointer.\n"));
- return;
- }
-
- /* Reset location and resume key to beginning */
- ret = rdp_init(dsp);
- if (ret) {
- DEBUG(0, ("Error re-initializing rdp cursors: %s\n",
- strerror(ret)));
- return;
- }
-
- DEBUG(9, ("Rewind DIR: %p, to resume_cookie: %#llx\n", dsp->dirp,
- dsp->resume_cookie));
-
- return;
-}
-
-/**
- * Close DIR pointer and remove all state for that directory open.
- *
- * @param[in] handle vfs handle given in most VFS calls
- * @param[in] dirp system DIR handle to set offset on
- *
- * @return -1 on failure, setting errno
- */
-int
-onefs_closedir(vfs_handle_struct *handle, DIR *dirp)
-{
- struct rdp_dir_state *dsp = NULL;
- bool same_as_last;
- int ret_val = -1;
- int ret = -1;
-
- /* Fallback to default system routines if readdirplus is disabled */
- if (!lp_parm_bool(SNUM(handle->conn), PARM_ONEFS_TYPE,
- PARM_USE_READDIRPLUS, PARM_USE_READDIRPLUS_DEFAULT))
- {
- return SMB_VFS_NEXT_CLOSEDIR(handle, dirp);
- }
-
- /* Retrieve state based off DIR handle */
- ret = rdp_retrieve_dir_state(dirp, &dsp, &same_as_last);
- if (ret) {
- DEBUG(1, ("Could not retrieve dir_state struct for "
- "DIR pointer.\n"));
- errno = ENOENT;
- return -1;
- }
-
- /* Close DIR pointer */
- ret_val = SMB_VFS_NEXT_CLOSEDIR(handle, dsp->dirp);
-
- DEBUG(9, ("Closed handle on DIR %p\n", dsp->dirp));
-
- /* Tear down state struct */
- DLIST_REMOVE(dirstatelist, dsp);
- SAFE_FREE(dsp);
-
- /* Set lastp to NULL, as cache is no longer valid */
- rdp_last_dirp = NULL;
-
- return ret_val;
-}
-
-/**
- * Initialize cache data at the beginning of every SMB search operation
- *
- * Since filesystem operations, such as delete files or meta data
- * updates can occur to files in the directory we're searching
- * between FIND_FIRST and FIND_NEXT calls we must refresh the cache
- * from the kernel on every new search SMB.
- *
- * @param[in] handle vfs handle given in most VFS calls
- * @param[in] dirp system DIR handle for the current search
- *
- * @return nothing
- */
-void
-onefs_init_search_op(vfs_handle_struct *handle, DIR *dirp)
-{
- /* Setting the rdp_last_dirp to NULL will cause the next readdir
- * operation to refill the cache. */
- rdp_last_dirp = NULL;
-
- return;
-}
diff --git a/source3/modules/onefs_notify.c b/source3/modules/onefs_notify.c
deleted file mode 100644
index bbdade6015..0000000000
--- a/source3/modules/onefs_notify.c
+++ /dev/null
@@ -1,682 +0,0 @@
-/*
- * Unix SMB/CIFS implementation.
- *
- * Support for change notify using OneFS's file event notification system
- *
- * Copyright (C) Andrew Tridgell, 2006
- * Copyright (C) Steven Danneman, 2008
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/* Implement handling of change notify requests on files and directories using
- * Isilon OneFS's "ifs event" file notification system.
- *
- * The structure of this file is based off the implementation of change notify
- * using the inotify system calls in smbd/notify_inotify.c */
-
-/* TODO: We could reduce the number of file descriptors used by merging
- * multiple watch requests on the same directory into the same
- * onefs_notify_watch_context. To do this we'd need mux/demux routines that
- * when receiving an event on that watch context would check it against the
- * CompletionFilter and WatchTree of open SMB requests, and return notify
- * events back to the proper SMB requests */
-
-#include "includes.h"
-#include "smbd/smbd.h"
-#include "onefs.h"
-
-#include <ifs/ifs_types.h>
-#include <ifs/ifs_syscalls.h>
-#include <isi_util/syscalls.h>
-
-#include <sys/event.h>
-
-#define ONEFS_IFS_EVENT_MAX_NUM 8
-#define ONEFS_IFS_EVENT_MAX_BYTES (ONEFS_IFS_EVENT_MAX_NUM * \
- sizeof(struct ifs_event))
-
-struct onefs_notify_watch_context {
- struct sys_notify_context *ctx;
- int watch_fd;
- ino_t watch_lin;
- const char *path;
- int ifs_event_fd;
- uint32_t ifs_filter; /* the ifs event mask */
- uint32_t smb_filter; /* the windows completion filter */
- void (*callback)(struct sys_notify_context *ctx,
- void *private_data,
- struct notify_event *ev);
- void *private_data;
-};
-
-/**
- * Conversion map from a SMB completion filter to an IFS event mask.
- */
-static const struct {
- uint32_t smb_filter;
- uint32_t ifs_filter;
-} onefs_notify_conv[] = {
- {FILE_NOTIFY_CHANGE_FILE_NAME,
- NOTE_CREATE | NOTE_DELETE | NOTE_RENAME_FROM | NOTE_RENAME_TO},
- {FILE_NOTIFY_CHANGE_DIR_NAME,
- NOTE_CREATE | NOTE_DELETE | NOTE_RENAME_FROM | NOTE_RENAME_TO},
- {FILE_NOTIFY_CHANGE_ATTRIBUTES,
- NOTE_CREATE | NOTE_DELETE | NOTE_RENAME_FROM | NOTE_RENAME_TO |
- NOTE_ATTRIB},
- {FILE_NOTIFY_CHANGE_SIZE,
- NOTE_SIZE | NOTE_EXTEND},
- {FILE_NOTIFY_CHANGE_LAST_WRITE,
- NOTE_WRITE | NOTE_ATTRIB},
- /* OneFS doesn't set atime by default, but we can somewhat fake it by
- * notifying for other events that imply ACCESS */
- {FILE_NOTIFY_CHANGE_LAST_ACCESS,
- NOTE_WRITE | NOTE_ATTRIB},
- /* We don't have an ifs_event for the setting of create time, but we
- * can fake by notifying when a "new" file is created via rename */
- {FILE_NOTIFY_CHANGE_CREATION,
- NOTE_RENAME_TO},
- {FILE_NOTIFY_CHANGE_SECURITY,
- NOTE_SECURITY},
- /* Unsupported bits
- FILE_NOTIFY_CHANGE_EA (no EAs in OneFS)
- FILE_NOTIFY_CHANGE_STREAM_NAME (no ifs_event equivalent)
- FILE_NOTIFY_CHANGE_STREAM_SIZE (no ifs_event equivalent)
- FILE_NOTIFY_CHANGE_STREAM_WRITE (no ifs_event equivalent) */
-};
-
-#define ONEFS_NOTIFY_UNSUPPORTED (FILE_NOTIFY_CHANGE_LAST_ACCESS | \
- FILE_NOTIFY_CHANGE_CREATION | \
- FILE_NOTIFY_CHANGE_EA | \
- FILE_NOTIFY_CHANGE_STREAM_NAME | \
- FILE_NOTIFY_CHANGE_STREAM_SIZE | \
- FILE_NOTIFY_CHANGE_STREAM_WRITE)
-
-/**
- * Convert Windows/SMB filter/flags to IFS event filter.
- *
- * @param[in] smb_filter Windows Completion Filter sent in the SMB
- *
- * @return ifs event filter mask
- */
-static uint32_t
-onefs_notify_smb_filter_to_ifs_filter(uint32_t smb_filter)
-{
- int i;
- uint32_t ifs_filter = 0x0;
-
- for (i=0;i<ARRAY_SIZE(onefs_notify_conv);i++) {
- if (onefs_notify_conv[i].smb_filter & smb_filter) {
- ifs_filter |= onefs_notify_conv[i].ifs_filter;
- }
- }
-
- return ifs_filter;
-}
-
-/**
- * Convert IFS filter/flags to a Windows notify action.
- *
- * Returns Win notification actions, types (1-5).
- *
- * @param[in] smb_filter Windows Completion Filter sent in the SMB
- * @param[in] ifs_filter Returned from the kernel in the ifs_event
- *
- * @return 0 if there are no more relevant flags.
- */
-static int
-onefs_notify_ifs_filter_to_smb_action(uint32_t smb_filter, uint32_t ifs_filter)
-{
- /* Handle Windows special cases, before modifying events bitmask */
-
- /* Special case 1: win32api->MoveFile needs to send a modified
- * notification on the new file, if smb_filter == ATTRIBUTES.
- * Here we handle the case where two separate ATTR & NAME notifications
- * have been registered. We handle the case where both bits are set in
- * the same registration in onefs_notify_dispatch() */
- if ((smb_filter & FILE_NOTIFY_CHANGE_ATTRIBUTES) &&
- !(smb_filter & FILE_NOTIFY_CHANGE_FILE_NAME) &&
- (ifs_filter & NOTE_FILE) && (ifs_filter & NOTE_RENAME_TO))
- {
- return NOTIFY_ACTION_MODIFIED;
- }
-
- /* Special case 2: Writes need to send a modified
- * notification on the file, if smb_filter = ATTRIBUTES. */
- if ((smb_filter & FILE_NOTIFY_CHANGE_ATTRIBUTES) &&
- (ifs_filter & NOTE_FILE) && (ifs_filter & NOTE_WRITE))
- {
- return NOTIFY_ACTION_MODIFIED;
- }
-
- /* Loop because some events may be filtered out. Eventually all
- * relevant events will be taken care of and returned. */
- while (1) {
- if (ifs_filter & NOTE_CREATE) {
- ifs_filter &= ~NOTE_CREATE;
- if ((smb_filter & FILE_NOTIFY_CHANGE_FILE_NAME) &&
- (ifs_filter & NOTE_FILE))
- return NOTIFY_ACTION_ADDED;
- if ((smb_filter & FILE_NOTIFY_CHANGE_DIR_NAME) &&
- (ifs_filter & NOTE_DIRECTORY))
- return NOTIFY_ACTION_ADDED;
- }
- else if (ifs_filter & NOTE_DELETE) {
- ifs_filter &= ~NOTE_DELETE;
- if ((smb_filter & FILE_NOTIFY_CHANGE_FILE_NAME) &&
- (ifs_filter & NOTE_FILE))
- return NOTIFY_ACTION_REMOVED;
- if ((smb_filter & FILE_NOTIFY_CHANGE_DIR_NAME) &&
- (ifs_filter & NOTE_DIRECTORY))
- return NOTIFY_ACTION_REMOVED;
- }
- else if (ifs_filter & NOTE_WRITE) {
- ifs_filter &= ~NOTE_WRITE;
- if ((smb_filter & FILE_NOTIFY_CHANGE_LAST_WRITE) ||
- (smb_filter & FILE_NOTIFY_CHANGE_LAST_ACCESS))
- return NOTIFY_ACTION_MODIFIED;
- }
- else if ((ifs_filter & NOTE_SIZE) || (ifs_filter & NOTE_EXTEND)) {
- ifs_filter &= ~NOTE_SIZE;
- ifs_filter &= ~NOTE_EXTEND;
-
- /* TODO: Do something on NOTE_DIR? */
- if ((smb_filter & FILE_NOTIFY_CHANGE_SIZE) &&
- (ifs_filter & NOTE_FILE))
- return NOTIFY_ACTION_MODIFIED;
- }
- else if (ifs_filter & NOTE_ATTRIB) {
- ifs_filter &= ~NOTE_ATTRIB;
- /* NOTE_ATTRIB needs to be converted to a
- * LAST_WRITE as well, because we need to send
- * LAST_WRITE when the mtime changes. Looking into
- * better alternatives as this causes extra LAST_WRITE
- * notifications. We also return LAST_ACCESS as a
- * modification to attribs implies this. */
- if ((smb_filter & FILE_NOTIFY_CHANGE_ATTRIBUTES) ||
- (smb_filter & FILE_NOTIFY_CHANGE_LAST_WRITE) ||
- (smb_filter & FILE_NOTIFY_CHANGE_LAST_ACCESS))
- return NOTIFY_ACTION_MODIFIED;
- }
- else if (ifs_filter & NOTE_LINK) {
- ifs_filter &= ~NOTE_LINK;
- /* NOTE_LINK will send out NO notifications */
- }
- else if (ifs_filter & NOTE_REVOKE) {
- ifs_filter &= ~NOTE_REVOKE;
- /* NOTE_REVOKE will send out NO notifications */
- }
- else if (ifs_filter & NOTE_RENAME_FROM) {
- ifs_filter &= ~NOTE_RENAME_FROM;
-
- if (((smb_filter & FILE_NOTIFY_CHANGE_FILE_NAME) &&
- (ifs_filter & NOTE_FILE)) ||
- ((smb_filter & FILE_NOTIFY_CHANGE_DIR_NAME) &&
- (ifs_filter & NOTE_DIRECTORY))) {
- /* Check if this is a RENAME, not a MOVE */
- if (ifs_filter & NOTE_RENAME_SAMEDIR) {
- /* Remove the NOTE_RENAME_SAMEDIR, IFF
- * RENAME_TO is not in this event */
- if (!(ifs_filter & NOTE_RENAME_TO))
- ifs_filter &=
- ~NOTE_RENAME_SAMEDIR;
- return NOTIFY_ACTION_OLD_NAME;
- }
- return NOTIFY_ACTION_REMOVED;
- }
- }
- else if (ifs_filter & NOTE_RENAME_TO) {
- ifs_filter &= ~NOTE_RENAME_TO;
-
- if (((smb_filter & FILE_NOTIFY_CHANGE_FILE_NAME) &&
- (ifs_filter & NOTE_FILE)) ||
- ((smb_filter & FILE_NOTIFY_CHANGE_DIR_NAME) &&
- (ifs_filter & NOTE_DIRECTORY))) {
- /* Check if this is a RENAME, not a MOVE */
- if (ifs_filter & NOTE_RENAME_SAMEDIR) {
- /* Remove the NOTE_RENAME_SAMEDIR, IFF
- * RENAME_FROM is not in this event */
- if (!(ifs_filter & NOTE_RENAME_FROM))
- ifs_filter &=
- ~NOTE_RENAME_SAMEDIR;
- return NOTIFY_ACTION_NEW_NAME;
- }
- return NOTIFY_ACTION_ADDED;
- }
- /* RAW-NOTIFY shows us that a rename triggers a
- * creation time change */
- if ((smb_filter & FILE_NOTIFY_CHANGE_CREATION) &&
- (ifs_filter & NOTE_FILE))
- return NOTIFY_ACTION_MODIFIED;
- }
- else if (ifs_filter & NOTE_SECURITY) {
- ifs_filter &= ~NOTE_SECURITY;
-
- if (smb_filter & FILE_NOTIFY_CHANGE_SECURITY)
- return NOTIFY_ACTION_MODIFIED;
- } else {
- /* No relevant flags found */
- return 0;
- }
- }
-}
-
-/**
- * Retrieve a directory path of a changed file, relative to the watched dir
- *
- * @param[in] wc watch context for the returned event
- * @param[in] e ifs_event notification returned from the kernel
- * @param[out] path name relative to the watched dir. This is talloced
- * off of wc and needs to be freed by the caller.
- *
- * @return true on success
- *
- * TODO: This function currently doesn't handle path names with multiple
- * encodings. enc_get_lin_path() should be used in the future to convert
- * each path segment's encoding to UTF-8
- */
-static bool
-get_ifs_event_path(struct onefs_notify_watch_context *wc, struct ifs_event *e,
- char **path)
-{
- char *path_buf = NULL;
- size_t pathlen = 0;
- int error = 0;
-
- SMB_ASSERT(path);
-
- /* Lookup the path from watch_dir through our parent dir */
- if (e->namelen > 0) {
- error = lin_get_path(wc->watch_lin,
- e->parent_lin,
- HEAD_SNAPID,
- e->parent_parent_lin,
- e->parent_name_hash,
- &pathlen, &path_buf);
- if (!error) {
- /* Only add slash if a path exists in path_buf from
- * lin_get_path call. Windows does not expect a
- * leading '/' */
- if (pathlen > 0)
- *path = talloc_asprintf(wc, "%s/%s",
- path_buf, e->name);
- else
- *path = talloc_asprintf(wc, "%s", e->name);
- SAFE_FREE(path_buf);
- }
- }
-
- /* If ifs_event didn't return a name, or we errored out of our intial
- * path lookup, try again using the lin of the changed file */
- if (!(*path)) {
- error = lin_get_path(wc->watch_lin,
- e->lin,
- HEAD_SNAPID,
- e->parent_lin,
- e->name_hash,
- &pathlen, &path_buf);
- if (error) {
- /* It's possible that both the lin and the parent lin
- * are invalid (or not given) -- we will skip these
- * events. */
- DEBUG(3,("Path lookup failed. LINS are invalid: "
- "e->lin: 0x%llu, e->parent_lin: 0x%llu, "
- "e->parent_parent_lin: 0x%llu\n",
- e->lin, e->parent_lin, e->parent_parent_lin));
- SAFE_FREE(path_buf);
- return false;
- } else {
- *path = talloc_asprintf(wc, "%s", path_buf);
- DEBUG(5, ("Using path from event LIN = %s\n",
- path_buf));
- SAFE_FREE(path_buf);
- }
- }
-
- /* Replacement of UNIX slashes with WIN slashes is handled at a
- * higher layer. */
-
- return true;
-}
-
-/**
- * Dispatch one OneFS notify event to the general Samba code
- *
- * @param[in] wc watch context for the returned event
- * @param[in] e event returned from the kernel
- *
- * @return nothing
- */
-static void
-onefs_notify_dispatch(struct onefs_notify_watch_context *wc,
- struct ifs_event *e)
-{
- char *path = NULL;
- struct notify_event ne;
-
- DEBUG(5, ("Retrieved ifs event from kernel: lin=%#llx, ifs_events=%#x, "
- "parent_lin=%#llx, namelen=%d, name=\"%s\"\n",
- e->lin, e->events, e->parent_lin, e->namelen, e->name));
-
- /* Check validity of event returned from kernel */
- if (e->lin == 0) {
- /* The lin == 0 specifies 1 of 2 cases:
- * 1) We are out of events. The kernel has a limited
- * amount (somewhere near 90000)
- * 2) Split nodes have merged back and had data written
- * to them -- thus we've missed some of those events. */
- DEBUG(3, ("We've missed some kernel ifs events!\n"));
-
- /* Alert higher level to the problem so it returns catch-all
- * response to the client */
- ne.path = NULL;
- ne.action = 0;
- wc->callback(wc->ctx, wc->private_data, &ne);
- }
-
- if (e->lin == wc->watch_lin) {
- /* Windows doesn't report notifications on root
- * watched directory */
- /* TODO: This should be abstracted out to the general layer
- * instead of being handled in every notify provider */
- DEBUG(5, ("Skipping notification on root of the watched "
- "path.\n"));
- return;
- }
-
- /* Retrieve the full path for the ifs event name */
- if(!get_ifs_event_path(wc, e, &path)) {
- DEBUG(3, ("Failed to convert the ifs_event lins to a path. "
- "Skipping this event\n"));
- return;
- }
-
- if (!strncmp(path, ".ifsvar", 7)) {
- /* Skip notifications on file if its in ifs configuration
- * directory */
- goto clean;
- }
-
- ne.path = path;
-
- /* Convert ifs event mask to an smb action mask */
- ne.action = onefs_notify_ifs_filter_to_smb_action(wc->smb_filter,
- e->events);
-
- DEBUG(5, ("Converted smb_filter=%#x, ifs_events=%#x, to "
- "ne.action = %d, for ne.path = %s\n",
- wc->smb_filter, e->events, ne.action, ne.path));
-
- if (!ne.action)
- goto clean;
-
- /* Return notify_event to higher level */
- wc->callback(wc->ctx, wc->private_data, &ne);
-
- /* SMB expects a file rename/move to generate three actions, a
- * rename_from/delete on the from file, a rename_to/create on the to
- * file, and a modify for the rename_to file. If we have two separate
- * notifications registered for ATTRIBUTES and FILENAME, this case will
- * be handled by separate ifs_events in
- * onefs_notify_ifs_filter_to_smb_action(). If both bits are registered
- * in the same notification, we must send an extra MODIFIED action
- * here. */
- if ((wc->smb_filter & FILE_NOTIFY_CHANGE_ATTRIBUTES) &&
- (wc->smb_filter & FILE_NOTIFY_CHANGE_FILE_NAME) &&
- (e->events & NOTE_FILE) && (e->events & NOTE_RENAME_TO))
- {
- ne.action = NOTIFY_ACTION_MODIFIED;
- wc->callback(wc->ctx, wc->private_data, &ne);
- }
-
- /* FALLTHROUGH */
-clean:
- talloc_free(path);
- return;
-}
-
-/**
- * Callback when the kernel has some events for us
- *
- * Read events off ifs event fd and pass them to our dispatch function
- *
- * @param ev context of all tevents registered in the smbd
- * @param fde tevent struct specific to one ifs event channel
- * @param flags tevent flags passed when we added our ifs event channel fd to
- * the main loop
- * @param private_data onefs_notify_watch_context specific to this ifs event
- * channel
- *
- * @return nothing
- */
-static void
-onefs_notify_handler(struct event_context *ev,
- struct fd_event *fde,
- uint16_t flags,
- void *private_data)
-{
- struct onefs_notify_watch_context *wc = NULL;
- struct ifs_event ifs_events[ONEFS_IFS_EVENT_MAX_NUM];
- ssize_t nread = 0;
- int count = 0;
- int i = 0;
-
- wc = talloc_get_type(private_data, struct onefs_notify_watch_context);
-
- /* Read as many ifs events from the notify channel as we can */
- nread = sys_read(wc->ifs_event_fd, &ifs_events,
- ONEFS_IFS_EVENT_MAX_BYTES);
- if (nread == 0) {
- DEBUG(0,("No data found while reading ifs event fd?!\n"));
- return;
- }
- if (nread < 0) {
- DEBUG(0,("Failed to read ifs event data: %s\n",
- strerror(errno)));
- return;
- }
-
- count = nread / sizeof(struct ifs_event);
-
- DEBUG(5, ("Got %d notification events in %d bytes.\n", count, nread));
-
- /* Dispatch ifs_events one-at-a-time to higher level */
- for (i=0; i < count; i++) {
- onefs_notify_dispatch(wc, &ifs_events[i]);
- }
-}
-
-/**
- * Destroy the ifs event channel
- *
- * This is called from talloc_free() when the generic Samba notify layer frees
- * the onefs_notify_watch_context.
- *
- * @param[in] wc pointer to watch context which is being destroyed
- *
- * return 0 on success
-*/
-static int
-onefs_watch_destructor(struct onefs_notify_watch_context *wc)
-{
- /* The ifs_event_fd will re de-registered from the event loop by
- * another destructor triggered from the freeing of this wc */
- close(wc->ifs_event_fd);
- return 0;
-}
-
-/**
- * Register a single change notify watch request.
- *
- * Open an event listener on a directory to watch for modifications. This
- * channel is closed by a destructor when the caller calls talloc_free()
- * on *handle.
- *
- * @param[in] vfs_handle handle given to most VFS operations
- * @param[in] ctx context (conn and tevent) for this connection
- * @param[in] e filter and path of client's notify request
- * @param[in] callback function to call when file notification event is received
- * from the kernel, passing that event up to Samba's
- * generalized change notify layer
- * @param[in] private_data opaque data given to us by the general change notify
- * layer which must be returned in the callback function
- * @param[out] handle_p handle returned to generalized change notify layer used
- * to close the event channel when notification is
- * cancelled
- *
- * @return NT_STATUS_OK unless error
- */
-NTSTATUS
-onefs_notify_watch(vfs_handle_struct *vfs_handle,
- struct sys_notify_context *ctx,
- struct notify_entry *e,
- void (*callback)(struct sys_notify_context *ctx,
- void *private_data,
- struct notify_event *ev),
- void *private_data,
- void *handle_p)
-{
- int ifs_event_fd = -1;
- uint32_t ifs_filter = 0;
- uint32_t smb_filter = e->filter;
- bool watch_tree = !!e->subdir_filter;
- struct onefs_notify_watch_context *wc = NULL;
- void **handle = (void **)handle_p;
- SMB_STRUCT_STAT sbuf;
- NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
-
- /* Fallback to default Samba implementation if kernel CN is disabled */
- if (!lp_kernel_change_notify(vfs_handle->conn->params)) {
- (*handle) = NULL;
- return NT_STATUS_OK;
- }
-
- /* The OneFS open path should always give us a valid fd on a directory*/
- SMB_ASSERT(e->dir_fd >= 0);
-
- /* Always set e->filter to 0 so we don't fallback on the default change
- * notify backend. It's not cluster coherent or cross-protocol so we
- * can't guarantee correctness using it. */
- e->filter = 0;
- e->subdir_filter = 0;
-
- /* Snapshots do not currently allow event listeners. See Isilon
- * bug 33476 for an example of .snapshot debug spew that can occur. */
- if (e->dir_id.extid != HEAD_SNAPID)
- return NT_STATUS_INVALID_PARAMETER;
-
- /* Convert Completion Filter mask to IFS Event mask */
- ifs_filter = onefs_notify_smb_filter_to_ifs_filter(smb_filter);
-
- if (smb_filter & ONEFS_NOTIFY_UNSUPPORTED) {
- /* One or more of the filter bits could not be fully handled by
- * the ifs_event system. To be correct, if we cannot service a
- * bit in the completion filter we should return
- * NT_STATUS_NOT_IMPLEMENTED to let the client know that they
- * won't be receiving all the notify events that they asked for.
- * Unfortunately, WinXP clients cache this error message, stop
- * trying to send any notify requests at all, and instead return
- * NOT_IMPLEMENTED to all requesting apps without ever sending a
- * message to us. Thus we lie, and say we can service all bits,
- * but simply don't return actions for the filter bits we can't
- * detect or fully implement. */
- DEBUG(3,("One or more of the Windows completion filter bits "
- "for \"%s\" could not be fully handled by the "
- "ifs_event system. The failed bits are "
- "smb_filter=%#x\n",
- e->path, smb_filter & ONEFS_NOTIFY_UNSUPPORTED));
- }
-
- if (ifs_filter == 0) {
- /* None of the filter bits given are supported by the ifs_event
- * system. Don't create a kernel notify channel, but mock
- * up a fake handle for the caller. */
- DEBUG(3,("No bits in the Windows completion filter could be "
- "translated to ifs_event mask for \"%s\", "
- "smb_filter=%#x\n", e->path, smb_filter));
- (*handle) = NULL;
- return NT_STATUS_OK;
- }
-
- /* Register an ifs event channel for this watch request */
- ifs_event_fd = ifs_create_listener(watch_tree ?
- EVENT_RECURSIVE :
- EVENT_CHILDREN,
- ifs_filter,
- e->dir_fd);
- if (ifs_event_fd < 0) {
- DEBUG(0,("Failed to create listener for %s with \"%s\". "
- "smb_filter=0x%x, ifs_filter=0x%x, watch_tree=%u\n",
- strerror(errno), e->path, smb_filter, ifs_filter,
- watch_tree));
- return map_nt_error_from_unix(errno);
- }
-
- /* Create a watch context to track this change notify request */
- wc = talloc(ctx, struct onefs_notify_watch_context);
- if (wc == NULL) {
- status = NT_STATUS_NO_MEMORY;
- goto err;
- }
-
- /* Get LIN for directory */
- if (onefs_sys_fstat(e->dir_fd, &sbuf)) {
- DEBUG(0, ("stat on directory fd failed: %s\n",
- strerror(errno)));
- status = map_nt_error_from_unix(errno);
- goto err;
- }
-
- if (sbuf.st_ex_ino == 0) {
- DEBUG(0, ("0 LIN found!\n"));
- goto err;
- }
-
- wc->ctx = ctx;
- wc->watch_fd = e->dir_fd;
- wc->watch_lin = sbuf.st_ex_ino;
- wc->ifs_event_fd = ifs_event_fd;
- wc->ifs_filter = ifs_filter;
- wc->smb_filter = smb_filter;
- wc->callback = callback;
- wc->private_data = private_data;
- wc->path = talloc_strdup(wc, e->path);
- if (wc->path == NULL) {
- status = NT_STATUS_NO_MEMORY;
- goto err;
- }
-
- (*handle) = wc;
-
- /* The caller frees the handle to stop watching */
- talloc_set_destructor(wc, onefs_watch_destructor);
-
- /* Add a tevent waiting for the ifs event fd to be readable */
- event_add_fd(ctx->ev, wc, wc->ifs_event_fd, EVENT_FD_READ,
- onefs_notify_handler, wc);
-
- DEBUG(10, ("Watching for changes on \"%s\" smb_filter=0x%x, "
- "ifs_filter=0x%x, watch_tree=%d, ifs_event_fd=%d, "
- "dir_fd=%d, dir_lin=0x%llx\n",
- e->path, smb_filter, ifs_filter, watch_tree,
- ifs_event_fd, e->dir_fd, sbuf.st_ex_ino));
-
- return NT_STATUS_OK;
-
-err:
- talloc_free(wc);
- SMB_ASSERT(ifs_event_fd >= 0);
- close(ifs_event_fd);
- return status;
-}
diff --git a/source3/modules/onefs_open.c b/source3/modules/onefs_open.c
deleted file mode 100644
index a77d6f3e7e..0000000000
--- a/source3/modules/onefs_open.c
+++ /dev/null
@@ -1,2200 +0,0 @@
-/*
- * Unix SMB/CIFS implementation.
- *
- * This file began with some code from source3/smbd/open.c and has been
- * modified it work with ifs_createfile.
- *
- * ifs_createfile is a CIFS-specific syscall for opening/files and
- * directories. It adds support for:
- * - Full in-kernel access checks using a windows access_mask
- * - Cluster-coherent share mode locks
- * - Cluster-coherent oplocks
- * - Streams
- * - Setting security descriptors at create time
- * - Setting dos_attributes at create time
- *
- * Copyright (C) Andrew Tridgell 1992-1998
- * Copyright (C) Jeremy Allison 2001-2004
- * Copyright (C) Volker Lendecke 2005
- * Copyright (C) Tim Prouty, 2008
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "includes.h"
-#include "smbd/smbd.h"
-#include "onefs.h"
-#include "onefs_config.h"
-#include "oplock_onefs.h"
-#include "smbd/globals.h"
-
-extern const struct generic_mapping file_generic_mapping;
-
-struct onefs_fsp_data {
- uint64_t oplock_callback_id;
-};
-
-static NTSTATUS onefs_create_file_unixpath(connection_struct *conn,
- struct smb_request *req,
- struct smb_filename *smb_fname,
- uint32_t access_mask,
- uint32_t share_access,
- uint32_t create_disposition,
- uint32_t create_options,
- uint32_t file_attributes,
- uint32_t oplock_request,
- uint64_t allocation_size,
- uint32_t private_flags,
- struct security_descriptor *sd,
- struct ea_list *ea_list,
- files_struct **result,
- int *pinfo,
- struct onefs_fsp_data *fsp_data);
-
-/****************************************************************************
- Open a file.
-****************************************************************************/
-
-static NTSTATUS onefs_open_file(files_struct *fsp,
- connection_struct *conn,
- struct smb_request *req,
- const char *parent_dir,
- struct smb_filename *smb_fname,
- int flags,
- mode_t unx_mode,
- uint32 access_mask,
- uint32 open_access_mask,
- int oplock_request,
- uint64 id,
- uint32 share_access,
- uint32 create_options,
- uint32_t new_dos_attributes,
- struct security_descriptor *sd,
- int *granted_oplock)
-{
- struct smb_filename *smb_fname_onefs = NULL;
- NTSTATUS status = NT_STATUS_OK;
- int accmode = (flags & O_ACCMODE);
- int local_flags = flags;
- bool file_existed = VALID_STAT(smb_fname->st);
- const char *wild;
- int base_fd = -1;
-
- fsp->fh->fd = -1;
- errno = EPERM;
-
- /* Check permissions */
-
- /*
- * This code was changed after seeing a client open request
- * containing the open mode of (DENY_WRITE/read-only) with
- * the 'create if not exist' bit set. The previous code
- * would fail to open the file read only on a read-only share
- * as it was checking the flags parameter directly against O_RDONLY,
- * this was failing as the flags parameter was set to O_RDONLY|O_CREAT.
- * JRA.
- */
-
- if (!CAN_WRITE(conn)) {
- /* It's a read-only share - fail if we wanted to write. */
- if(accmode != O_RDONLY) {
- DEBUG(3, ("Permission denied opening %s\n",
- smb_fname_str_dbg(smb_fname)));
- return NT_STATUS_ACCESS_DENIED;
- } else if(flags & O_CREAT) {
- /* We don't want to write - but we must make sure that
- O_CREAT doesn't create the file if we have write
- access into the directory.
- */
- flags &= ~O_CREAT;
- local_flags &= ~O_CREAT;
- }
- }
-
- /*
- * This little piece of insanity is inspired by the
- * fact that an NT client can open a file for O_RDONLY,
- * but set the create disposition to FILE_EXISTS_TRUNCATE.
- * If the client *can* write to the file, then it expects to
- * truncate the file, even though it is opening for readonly.
- * Quicken uses this stupid trick in backup file creation...
- * Thanks *greatly* to "David W. Chapman Jr." <dwcjr@inethouston.net>
- * for helping track this one down. It didn't bite us in 2.0.x
- * as we always opened files read-write in that release. JRA.
- */
-
- if ((accmode == O_RDONLY) && ((flags & O_TRUNC) == O_TRUNC)) {
- DEBUG(10,("onefs_open_file: truncate requested on read-only "
- "open for file %s\n", smb_fname_str_dbg(smb_fname)));
- local_flags = (flags & ~O_ACCMODE)|O_RDWR;
- }
-
-#if defined(O_NONBLOCK) && defined(S_ISFIFO)
- /*
- * We would block on opening a FIFO with no one else on the
- * other end. Do what we used to do and add O_NONBLOCK to the
- * open flags. JRA.
- */
-
- if (file_existed && S_ISFIFO(smb_fname->st.st_ex_mode)) {
- local_flags |= O_NONBLOCK;
- }
-#endif
-
- /* Don't create files with Microsoft wildcard characters. */
- if (fsp->base_fsp) {
- /*
- * wildcard characters are allowed in stream names
- * only test the basefilename
- */
- wild = fsp->base_fsp->fsp_name->base_name;
- } else {
- wild = smb_fname->base_name;
- }
- if ((local_flags & O_CREAT) && !file_existed &&
- ms_has_wild(wild)) {
- /*
- * XXX: may need to remvoe this return...
- *
- * We dont think this check needs to exist. All it does is
- * block creating files with Microsoft wildcards, which is
- * fine if the creation originated from NFS or locally and
- * then was copied via Samba.
- */
- DEBUG(1, ("onefs_open_file: creating file with wildcard: %s\n",
- smb_fname_str_dbg(smb_fname)));
- return NT_STATUS_OBJECT_NAME_INVALID;
- }
-
- /* Actually do the open */
-
-#ifdef O_NOFOLLOW
- /*
- * Never follow symlinks on a POSIX client. The
- * client should be doing this.
- */
-
- if (fsp->posix_open || !lp_symlinks(SNUM(conn))) {
- flags |= O_NOFOLLOW;
- }
-#endif
- /* Setup a onefs-style smb_fname struct. */
- status = onefs_stream_prep_smb_fname(talloc_tos(), smb_fname,
- &smb_fname_onefs);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- /* If it's a stream pass in the base_fd */
- if ((conn->fs_capabilities & FILE_NAMED_STREAMS) &&
- is_ntfs_stream_smb_fname(smb_fname_onefs)) {
- SMB_ASSERT(fsp->base_fsp);
-
- DEBUG(10, ("Opening a stream: base=%s(%d), stream=%s\n",
- smb_fname_onefs->base_name, fsp->base_fsp->fh->fd,
- smb_fname_onefs->stream_name));
-
- base_fd = fsp->base_fsp->fh->fd;
- }
-
- fsp->fh->fd = onefs_sys_create_file(conn,
- base_fd,
- smb_fname_onefs->stream_name != NULL ?
- smb_fname_onefs->stream_name :
- smb_fname_onefs->base_name,
- access_mask,
- open_access_mask,
- share_access,
- create_options,
- flags,
- unx_mode,
- oplock_request,
- id,
- sd,
- new_dos_attributes,
- granted_oplock);
- TALLOC_FREE(smb_fname_onefs);
-
- if (fsp->fh->fd == -1) {
- if (errno == EMFILE) {
- static time_t last_warned = 0L;
-
- if (time((time_t *) NULL) > last_warned) {
- DEBUG(0, ("Too many open files, unable "
- "to open more! smbd's max "
- "open files = %d, also check "
- "sysctl kern.maxfiles and "
- "sysctl kern.maxfilesperproc\n",
- lp_max_open_files()));
- last_warned = time((time_t *) NULL);
- }
- }
-
- status = map_nt_error_from_unix(errno);
- DEBUG(3, ("Error opening file %s (%s) (local_flags=%d) "
- "(flags=%d)\n", smb_fname_str_dbg(smb_fname),
- strerror(errno), local_flags, flags));
- return status;
- }
-
- if ((local_flags & O_CREAT) && !file_existed) {
-
- /* Inherit the ACL if required */
- if (lp_inherit_perms(SNUM(conn))) {
- inherit_access_posix_acl(conn, parent_dir,
- smb_fname->base_name, unx_mode);
- }
-
- /* Change the owner if required. */
- if (lp_inherit_owner(SNUM(conn))) {
- change_file_owner_to_parent(conn, parent_dir,
- fsp);
- }
-
- notify_fname(conn, NOTIFY_ACTION_ADDED,
- FILE_NOTIFY_CHANGE_FILE_NAME, smb_fname->base_name);
- }
-
- if (!file_existed) {
- int ret;
-
- if (fsp->fh->fd == -1) {
- ret = SMB_VFS_STAT(conn, smb_fname);
- } else {
- ret = SMB_VFS_FSTAT(fsp, &smb_fname->st);
- /* If we have an fd, this stat should succeed. */
- if (ret == -1) {
- DEBUG(0, ("Error doing fstat on open file %s "
- "(%s)\n",
- smb_fname_str_dbg(smb_fname),
- strerror(errno) ));
- }
- }
-
- /* For a non-io open, this stat failing means file not found. JRA */
- if (ret == -1) {
- status = map_nt_error_from_unix(errno);
- fd_close(fsp);
- return status;
- }
- }
-
- /*
- * POSIX allows read-only opens of directories. We don't
- * want to do this (we use a different code path for this)
- * so catch a directory open and return an EISDIR. JRA.
- */
-
- if(S_ISDIR(smb_fname->st.st_ex_mode)) {
- fd_close(fsp);
- errno = EISDIR;
- return NT_STATUS_FILE_IS_A_DIRECTORY;
- }
-
- fsp->mode = smb_fname->st.st_ex_mode;
- fsp->file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
- fsp->vuid = req ? req->vuid : UID_FIELD_INVALID;
- fsp->file_pid = req ? req->smbpid : 0;
- fsp->can_lock = True;
- fsp->can_read = (access_mask & (FILE_READ_DATA)) ? True : False;
- if (!CAN_WRITE(conn)) {
- fsp->can_write = False;
- } else {
- fsp->can_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ?
- True : False;
- }
- fsp->print_file = NULL;
- fsp->modified = False;
- fsp->sent_oplock_break = NO_BREAK_SENT;
- fsp->is_directory = False;
- if (conn->aio_write_behind_list &&
- is_in_path(smb_fname->base_name, conn->aio_write_behind_list,
- conn->case_sensitive)) {
- fsp->aio_write_behind = True;
- }
-
- fsp->wcp = NULL; /* Write cache pointer. */
-
- DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n",
- conn->session_info->unix_info->unix_name,
- smb_fname_str_dbg(smb_fname),
- BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write),
- conn->num_files_open));
-
- errno = 0;
- return NT_STATUS_OK;
-}
-
-/****************************************************************************
- Handle the 1 second delay in returning a SHARING_VIOLATION error.
-****************************************************************************/
-
-static void defer_open(struct share_mode_lock *lck,
- struct timeval request_time,
- struct timeval timeout,
- struct smb_request *req,
- struct deferred_open_record *state)
-{
- int i;
-
- /* Paranoia check */
-
- for (i=0; i<lck->num_share_modes; i++) {
- struct share_mode_entry *e = &lck->share_modes[i];
-
- if (!is_deferred_open_entry(e)) {
- continue;
- }
-
- if (procid_is_me(&e->pid) && (e->op_mid == req->mid)) {
- DEBUG(0, ("Trying to defer an already deferred "
- "request: mid=%llu, exiting\n",
- (unsigned long long)req->mid));
- exit_server("attempt to defer a deferred request");
- }
- }
-
- /* End paranoia check */
-
- DEBUG(10,("defer_open_sharing_error: time [%u.%06u] adding deferred "
- "open entry for mid %llu\n",
- (unsigned int)request_time.tv_sec,
- (unsigned int)request_time.tv_usec,
- (unsigned long long)req->mid));
-
- if (!push_deferred_open_message_smb(req, request_time, timeout,
- state->id, (char *)state, sizeof(*state))) {
- exit_server("push_deferred_open_message_smb failed");
- }
- add_deferred_open(lck, req->mid, request_time, state->id);
-}
-
-static void schedule_defer_open(struct share_mode_lock *lck,
- struct timeval request_time,
- struct smb_request *req)
-{
- struct deferred_open_record state;
-
- /* This is a relative time, added to the absolute
- request_time value to get the absolute timeout time.
- Note that if this is the second or greater time we enter
- this codepath for this particular request mid then
- request_time is left as the absolute time of the *first*
- time this request mid was processed. This is what allows
- the request to eventually time out. */
-
- struct timeval timeout;
-
- /* Normally the smbd we asked should respond within
- * OPLOCK_BREAK_TIMEOUT seconds regardless of whether
- * the client did, give twice the timeout as a safety
- * measure here in case the other smbd is stuck
- * somewhere else. */
-
- /*
- * On OneFS, the kernel will always send an oplock_revoked message
- * before this timeout is hit.
- */
- timeout = timeval_set(OPLOCK_BREAK_TIMEOUT*10, 0);
-
- /* Nothing actually uses state.delayed_for_oplocks
- but it's handy to differentiate in debug messages
- between a 30 second delay due to oplock break, and
- a 1 second delay for share mode conflicts. */
-
- state.delayed_for_oplocks = True;
- state.failed = false;
- state.id = lck->id;
-
- if (!request_timed_out(request_time, timeout)) {
- defer_open(lck, request_time, timeout, req, &state);
- } else {
- /* A delayed-for-oplocks deferred open timing out should only
- * happen if there is a bug or extreme load, since we set the
- * timeout to 300 seconds. */
- DEBUG(0, ("Deferred open timeout! request_time=%d.%d, "
- "mid=%d\n", request_time.tv_sec, request_time.tv_usec,
- req->mid));
- }
-}
-
-/****************************************************************************
- Open a file with a share mode. Passed in an already created files_struct.
-****************************************************************************/
-NTSTATUS onefs_open_file_ntcreate(connection_struct *conn,
- struct smb_request *req,
- struct smb_filename *smb_fname,
- uint32 access_mask,
- uint32 share_access,
- uint32 create_disposition,
- uint32 create_options,
- uint32 new_dos_attributes,
- int oplock_request,
- uint32_t private_flags,
- struct security_descriptor *sd,
- files_struct *fsp,
- int *pinfo,
- struct onefs_fsp_data *fsp_data)
-{
- int flags=0;
- int flags2=0;
- bool file_existed = VALID_STAT(smb_fname->st);
- bool def_acl = False;
- bool posix_open = False;
- bool new_file_created = False;
- bool clear_ads = False;
- struct file_id id;
- mode_t new_unx_mode = (mode_t)0;
- mode_t unx_mode = (mode_t)0;
- int info;
- uint32 existing_dos_attributes = 0;
- struct timeval request_time = timeval_zero();
- struct share_mode_lock *lck = NULL;
- uint32 open_access_mask = access_mask;
- NTSTATUS status;
- int ret_flock;
- char *parent_dir;
- int granted_oplock;
- uint64_t oplock_callback_id = 0;
- uint32 createfile_attributes = 0;
-
- ZERO_STRUCT(id);
-
- if (conn->printer) {
- /*
- * Printers are handled completely differently.
- * Most of the passed parameters are ignored.
- */
-
- if (pinfo) {
- *pinfo = FILE_WAS_CREATED;
- }
-
- DEBUG(10, ("onefs_open_file_ntcreate: printer open fname=%s\n",
- smb_fname_str_dbg(smb_fname)));
-
- return print_spool_open(fsp, smb_fname->base_name,
- req->vuid);
- }
-
- if (!parent_dirname(talloc_tos(), smb_fname->base_name, &parent_dir,
- NULL)) {
- return NT_STATUS_NO_MEMORY;
- }
-
- if (new_dos_attributes & FILE_FLAG_POSIX_SEMANTICS) {
- posix_open = True;
- unx_mode = (mode_t)(new_dos_attributes & ~FILE_FLAG_POSIX_SEMANTICS);
- new_dos_attributes = 0;
- } else {
- /* We add FILE_ATTRIBUTE_ARCHIVE to this as this mode is only used if the file is
- * created new. */
- unx_mode = unix_mode(conn, new_dos_attributes | FILE_ATTRIBUTE_ARCHIVE,
- smb_fname, parent_dir);
- }
-
- DEBUG(10,("onefs_open_file_ntcreate: fname=%s, dos_attrs=0x%x "
- "access_mask=0x%x share_access=0x%x "
- "create_disposition = 0x%x create_options=0x%x "
- "unix mode=0%o oplock_request=0x%x\n",
- smb_fname_str_dbg(smb_fname), new_dos_attributes,
- access_mask, share_access, create_disposition,
- create_options, unx_mode, oplock_request));
-
- /*
- * Any non-stat-only open has the potential to contend oplocks, which
- * means to avoid blocking in the kernel (which is unacceptable), the
- * open must be deferred. In order to defer opens, req must not be
- * NULL. The known cases of calling with a NULL req:
- *
- * 1. Open the base file of a stream: Always done stat-only
- *
- * 2. open_file_fchmod(), which is called from 3 places:
- * A. try_chown: Posix acls only. Never called on onefs.
- * B. set_ea_dos_attributes: Can't be called from onefs, because
- * SMB_VFS_SETXATTR return ENOSYS.
- * C. file_set_dos_mode: This would only happen if the "dos
- * filemode" smb.conf parameter is set to yes. We ship with
- * it off, but if a customer were to turn it on it would be
- * bad.
- */
- if (req == NULL && !is_stat_open(access_mask) &&
- !is_ntfs_stream_smb_fname(smb_fname)) {
- smb_panic("NULL req on a non-stat-open!");
- }
-
- if ((req == NULL) && ((oplock_request & INTERNAL_OPEN_ONLY) == 0)) {
- DEBUG(0, ("No smb request but not an internal only open!\n"));
- return NT_STATUS_INTERNAL_ERROR;
- }
-
- /*
- * Only non-internal opens can be deferred at all
- */
-
- if (req) {
- void *ptr;
- if (get_deferred_open_message_state(req,
- &request_time,
- &ptr)) {
- struct deferred_open_record *state = (struct deferred_open_record *)ptr;
-
- /* Remember the absolute time of the original
- request with this mid. We'll use it later to
- see if this has timed out. */
-
- /* Remove the deferred open entry under lock. */
- remove_deferred_open_entry(state->id, req->mid);
-
- /* Ensure we don't reprocess this message. */
- remove_deferred_open_message_smb(req->mid);
-
- /*
- * When receiving a semlock_async_failure message, the
- * deferred open will be marked as "failed". Returning
- * INTERNAL_ERROR.
- */
- if (state->failed) {
- DEBUG(0, ("onefs_open_file_ntcreate: "
- "semlock_async_failure detected!\n"));
- return NT_STATUS_INTERNAL_ERROR;
- }
- }
- }
-
- status = check_name(conn, smb_fname->base_name);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- if (!posix_open) {
- new_dos_attributes &= SAMBA_ATTRIBUTES_MASK;
- if (file_existed) {
- existing_dos_attributes = dos_mode(conn, smb_fname);
- }
- }
-
- /* Setup dos_attributes to be set by ifs_createfile */
- if (lp_store_dos_attributes(SNUM(conn))) {
- createfile_attributes = (new_dos_attributes | FILE_ATTRIBUTE_ARCHIVE) &
- ~(FILE_ATTRIBUTE_NONINDEXED | FILE_ATTRIBUTE_COMPRESSED);
- }
-
- /* Ignore oplock requests if oplocks are disabled. */
- if (!lp_oplocks(SNUM(conn)) ||
- IS_VETO_OPLOCK_PATH(conn, smb_fname->base_name)) {
- /* Mask off everything except the private Samba bits. */
- oplock_request &= SAMBA_PRIVATE_OPLOCK_MASK;
- }
-
- /* this is for OS/2 long file names - say we don't support them */
- if (!lp_posix_pathnames() && strstr(smb_fname->base_name,".+,;=[].")) {
- /* OS/2 Workplace shell fix may be main code stream in a later
- * release. */
- DEBUG(5,("onefs_open_file_ntcreate: OS/2 long filenames are "
- "not supported.\n"));
- if (use_nt_status()) {
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
- }
- return NT_STATUS_DOS(ERRDOS, ERRcannotopen);
- }
-
- switch( create_disposition ) {
- /*
- * Currently we're using FILE_SUPERSEDE as the same as
- * FILE_OVERWRITE_IF but they really are
- * different. FILE_SUPERSEDE deletes an existing file
- * (requiring delete access) then recreates it.
- */
- case FILE_SUPERSEDE:
- /**
- * @todo: Clear all file attributes?
- * http://www.osronline.com/article.cfm?article=302
- * create if not exist, trunc if exist
- *
- * If file exists replace/overwrite. If file doesn't
- * exist create.
- */
- flags2 |= (O_CREAT | O_TRUNC);
- clear_ads = true;
- break;
-
- case FILE_OVERWRITE_IF:
- /* If file exists replace/overwrite. If file doesn't
- * exist create. */
- flags2 |= (O_CREAT | O_TRUNC);
- clear_ads = true;
- break;
-
- case FILE_OPEN:
- /* If file exists open. If file doesn't exist error. */
- if (!file_existed) {
- DEBUG(5,("onefs_open_file_ntcreate: FILE_OPEN "
- "requested for file %s and file "
- "doesn't exist.\n",
- smb_fname_str_dbg(smb_fname)));
- errno = ENOENT;
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
- }
- break;
-
- case FILE_OVERWRITE:
- /* If file exists overwrite. If file doesn't exist
- * error. */
- if (!file_existed) {
- DEBUG(5, ("onefs_open_file_ntcreate: "
- "FILE_OVERWRITE requested for file "
- "%s and file doesn't exist.\n",
- smb_fname_str_dbg(smb_fname)));
- errno = ENOENT;
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
- }
- flags2 |= O_TRUNC;
- clear_ads = true;
- break;
-
- case FILE_CREATE:
- /* If file exists error. If file doesn't exist
- * create. */
- if (file_existed) {
- DEBUG(5, ("onefs_open_file_ntcreate: "
- "FILE_CREATE requested for file %s "
- "and file already exists.\n",
- smb_fname_str_dbg(smb_fname)));
- if (S_ISDIR(smb_fname->st.st_ex_mode)) {
- errno = EISDIR;
- } else {
- errno = EEXIST;
- }
- return map_nt_error_from_unix(errno);
- }
- flags2 |= (O_CREAT|O_EXCL);
- break;
-
- case FILE_OPEN_IF:
- /* If file exists open. If file doesn't exist
- * create. */
- flags2 |= O_CREAT;
- break;
-
- default:
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- /* Match attributes on file exists and overwrite. */
- if (!posix_open && file_existed &&
- ((create_disposition == FILE_OVERWRITE) ||
- (create_disposition == FILE_OVERWRITE_IF))) {
- if (!open_match_attributes(conn, existing_dos_attributes,
- new_dos_attributes,
- smb_fname->st.st_ex_mode,
- unx_mode, &new_unx_mode)) {
- DEBUG(5, ("onefs_open_file_ntcreate: attributes "
- "missmatch for file %s (%x %x) (0%o, 0%o)\n",
- smb_fname_str_dbg(smb_fname),
- existing_dos_attributes,
- new_dos_attributes,
- (unsigned int)smb_fname->st.st_ex_mode,
- (unsigned int)unx_mode ));
- errno = EACCES;
- return NT_STATUS_ACCESS_DENIED;
- }
- }
-
- /*
- * OneFS understands MAXIMUM_ALLOWED_ACCESS, so only hack the
- * access_mask, but leave the MAA for the actual open in
- * open_access_mask.
- */
- open_access_mask = access_mask;
- if (open_access_mask & MAXIMUM_ALLOWED_ACCESS) {
- access_mask |= FILE_GENERIC_ALL;
- }
-
- /* Convert GENERIC bits to specific bits. */
- se_map_generic(&access_mask, &file_generic_mapping);
- se_map_generic(&open_access_mask, &file_generic_mapping);
-
- if ((flags2 & O_TRUNC) || (oplock_request & FORCE_OPLOCK_BREAK_TO_NONE)) {
- /* This will cause oplock breaks. */
- open_access_mask |= FILE_WRITE_DATA;
- }
-
- DEBUG(10, ("onefs_open_file_ntcreate: fname=%s, after mapping "
- "open_access_mask=%#x, access_mask=0x%x\n",
- smb_fname_str_dbg(smb_fname), open_access_mask,
- access_mask));
-
- /*
- * Note that we ignore the append flag as append does not
- * mean the same thing under DOS and Unix.
- */
-
- if ((access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ||
- (oplock_request & FORCE_OPLOCK_BREAK_TO_NONE)) {
-
- /*
- * DENY_DOS opens are always underlying read-write on the
- * file handle, no matter what the requested access mask
- * says. Stock samba just sets the flags, but since
- * ifs_createfile uses the access_mask, it must be updated as
- * well. This allows BASE-DENY* to pass.
- */
- if (create_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) {
-
- DEBUG(10,("onefs_open_file_ntcreate: deny_dos: "
- "Adding O_RDWR to flags "
- "(0x%x) and some READ bits to "
- "open_access_mask (0x%x)\n",
- flags, open_access_mask));
-
- flags = O_RDWR;
- open_access_mask |= (FILE_READ_ATTRIBUTES |
- FILE_READ_DATA | FILE_READ_EA | FILE_EXECUTE);
-
- } else if (access_mask & (FILE_READ_ATTRIBUTES |
- FILE_READ_DATA |
- FILE_READ_EA |
- FILE_EXECUTE)) {
- flags = O_RDWR;
- } else {
- flags = O_WRONLY;
- }
- } else {
- flags = O_RDONLY;
- }
-
- /* Currently we only look at FILE_WRITE_THROUGH for create options. */
-#if defined(O_SYNC)
- if ((create_options & FILE_WRITE_THROUGH) &&
- lp_strict_sync(SNUM(conn))) {
- flags2 |= O_SYNC;
- }
-#endif /* O_SYNC */
-
- if (posix_open && (access_mask & FILE_APPEND_DATA)) {
- flags2 |= O_APPEND;
- }
-
- if (!posix_open && !CAN_WRITE(conn)) {
- /*
- * We should really return a permission denied error if either
- * O_CREAT or O_TRUNC are set, but for compatibility with
- * older versions of Samba we just AND them out.
- */
- flags2 &= ~(O_CREAT|O_TRUNC);
-
- /* Deny DELETE_ACCESS explicitly if the share is read only. */
- if (access_mask & DELETE_ACCESS) {
- return map_nt_error_from_unix(EACCES);
- }
- }
-
- /* Ensure we can't write on a read-only share or file. */
- if (flags != O_RDONLY && file_existed &&
- (!CAN_WRITE(conn) || IS_DOS_READONLY(existing_dos_attributes))) {
- DEBUG(5, ("onefs_open_file_ntcreate: write access requested "
- "for file %s on read only %s\n",
- smb_fname_str_dbg(smb_fname),
- !CAN_WRITE(conn) ? "share" : "file" ));
- errno = EACCES;
- return NT_STATUS_ACCESS_DENIED;
- }
-
- DEBUG(10, ("fsp = %p\n", fsp));
-
- fsp->share_access = share_access;
- fsp->fh->private_options = private_flags;
- fsp->access_mask = open_access_mask; /* We change this to the
- * requested access_mask after
- * the open is done. */
- fsp->posix_open = posix_open;
-
- /* Ensure no SAMBA_PRIVATE bits can be set. */
- fsp->oplock_type = (oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK);
-
- if (timeval_is_zero(&request_time)) {
- request_time = fsp->open_time;
- }
-
- if (file_existed) {
- struct timespec old_write_time = smb_fname->st.st_ex_mtime;
- id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
-
- lck = get_share_mode_lock(talloc_tos(), id,
- conn->connectpath,
- smb_fname, &old_write_time);
-
- if (lck == NULL) {
- DEBUG(0, ("Could not get share mode lock\n"));
- return NT_STATUS_SHARING_VIOLATION;
- }
-
- if (lck->delete_on_close) {
- /* DELETE_PENDING is not deferred for a second */
- TALLOC_FREE(lck);
- return NT_STATUS_DELETE_PENDING;
- }
- }
-
- SMB_ASSERT(!file_existed || (lck != NULL));
-
- /*
- * Ensure we pay attention to default ACLs on directories. May be
- * neccessary depending on ACL policies.
- */
- if ((flags2 & O_CREAT) && lp_inherit_acls(SNUM(conn)) &&
- (def_acl = directory_has_default_acl(conn, parent_dir))) {
- unx_mode = 0777;
- }
-
- DEBUG(4,("calling onefs_open_file with flags=0x%X flags2=0x%X "
- "mode=0%o, access_mask = 0x%x, open_access_mask = 0x%x\n",
- (unsigned int)flags, (unsigned int)flags2,
- (unsigned int)unx_mode, (unsigned int)access_mask,
- (unsigned int)open_access_mask));
-
- /*
- * Since the open is guaranteed to be stat only if req == NULL, a
- * callback record is only needed if req != NULL.
- */
- if (req) {
- SMB_ASSERT(fsp_data);
- oplock_callback_id = onefs_oplock_wait_record(req->sconn,
- req->mid);
- if (oplock_callback_id == 0) {
- return NT_STATUS_NO_MEMORY;
- }
- } else {
- /*
- * It is also already asserted it's either a stream or a
- * stat-only open at this point.
- */
- SMB_ASSERT(fsp->oplock_type == NO_OPLOCK);
-
- /* The kernel and Samba's version of stat-only differs
- * slightly: The kernel doesn't think its stat-only if we're
- * truncating. We'd better have a req in order to defer the
- * open. */
- SMB_ASSERT(!((flags|flags2) & O_TRUNC));
- }
-
- /* Do the open. */
- status = onefs_open_file(fsp,
- conn,
- req,
- parent_dir,
- smb_fname,
- flags|flags2,
- unx_mode,
- access_mask,
- open_access_mask,
- fsp->oplock_type,
- oplock_callback_id,
- share_access,
- create_options,
- createfile_attributes,
- sd,
- &granted_oplock);
-
- if (!NT_STATUS_IS_OK(status)) {
-
- /* OneFS Oplock Handling */
- if (errno == EINPROGRESS) {
-
- /* If we get EINPROGRESS, the kernel will send us an
- * asynchronous semlock event back. Ensure we can defer
- * the open, by asserting req. */
- SMB_ASSERT(req);
-
- if (lck == NULL) {
- /*
- * We hit the race that when we did the stat
- * on the file it did not exist, and someone
- * has created it in between the stat and the
- * open_file() call. Defer our open waiting,
- * to break the oplock of the first opener.
- */
-
- struct timespec old_write_time;
-
- DEBUG(3, ("Someone created file %s with an "
- "oplock after we looked: Retrying\n",
- smb_fname_str_dbg(smb_fname)));
- /*
- * We hit the race that when we did the stat
- * on the file it did not exist, and someone
- * has created it in between the stat and the
- * open_file() call. Just retry immediately.
- */
- id = vfs_file_id_from_sbuf(conn,
- &smb_fname->st);
- if (!(lck = get_share_mode_lock(talloc_tos(),
- id, conn->connectpath, smb_fname,
- &old_write_time))) {
- /*
- * Emergency exit
- */
- DEBUG(0, ("onefs_open_file_ntcreate: "
- "Could not get share mode "
- "lock for %s\n",
- smb_fname_str_dbg(smb_fname)));
- status = NT_STATUS_SHARING_VIOLATION;
-
- /* XXXZLK: This will cause us to get a
- * semlock event when we aren't
- * expecting one. */
- goto cleanup_destroy;
- }
-
- schedule_defer_open(lck, request_time, req);
- goto cleanup;
- }
- /* Waiting for an oplock */
- DEBUG(5,("Async createfile because a client has an "
- "oplock on %s\n",
- smb_fname_str_dbg(smb_fname)));
-
- SMB_ASSERT(req);
- schedule_defer_open(lck, request_time, req);
- goto cleanup;
- }
-
- /* Check for a sharing violation */
- if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
- uint32 can_access_mask;
- bool can_access = True;
-
- /* If we raced on open we may not have a valid file_id
- * or stat buf. Get them again. */
- if (SMB_VFS_STAT(conn, fname, psbuf) == -1) {
- DEBUG(0,("Error doing stat on file %s "
- "(%s)\n", fname, strerror(errno)));
- status = NT_STATUS_SHARING_VIOLATION;
- goto cleanup_destroy;
- }
- id = vfs_file_id_from_sbuf(conn, psbuf);
-
- /* Check if this can be done with the deny_dos and fcb
- * calls. */
-
- /* Try to find dup fsp if possible. */
- if (private_flags &
- (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS|
- NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) {
-
- if (req == NULL) {
- DEBUG(0, ("DOS open without an SMB "
- "request!\n"));
- status = NT_STATUS_INTERNAL_ERROR;
- goto cleanup_destroy;
- }
-
- /* Use the client requested access mask here,
- * not the one we open with. */
- status = fcb_or_dos_open(req,
- conn,
- fsp,
- smb_fname,
- id,
- req->smbpid,
- req->vuid,
- access_mask,
- share_access,
- create_options);
-
- if (NT_STATUS_IS_OK(status)) {
- if (pinfo) {
- *pinfo = FILE_WAS_OPENED;
- }
- status = NT_STATUS_OK;
- goto cleanup;
- }
- }
-
- /*
- * This next line is a subtlety we need for
- * MS-Access. If a file open will fail due to share
- * permissions and also for security (access) reasons,
- * we need to return the access failed error, not the
- * share error. We can't open the file due to kernel
- * oplock deadlock (it's possible we failed above on
- * the open_mode_check()) so use a userspace check.
- */
-
- if (flags & O_RDWR) {
- can_access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
- } else if (flags & O_WRONLY) {
- can_access_mask = FILE_WRITE_DATA;
- } else {
- can_access_mask = FILE_READ_DATA;
- }
-
- if (((can_access_mask & FILE_WRITE_DATA) &&
- !CAN_WRITE(conn)) ||
- !NT_STATUS_IS_OK(smbd_check_access_rights(conn,
- smb_fname, can_access_mask))) {
- can_access = False;
- }
-
- /*
- * If we're returning a share violation, ensure we
- * cope with the braindead 1 second delay.
- */
- if (!(oplock_request & INTERNAL_OPEN_ONLY) &&
- lp_defer_sharing_violations()) {
- struct timeval timeout;
- struct deferred_open_record state;
- int timeout_usecs;
-
- /* this is a hack to speed up torture tests
- in 'make test' */
- timeout_usecs = lp_parm_int(SNUM(conn),
- "smbd","sharedelay",
- SHARING_VIOLATION_USEC_WAIT);
-
- /* This is a relative time, added to the
- absolute request_time value to get the
- absolute timeout time. Note that if this
- is the second or greater time we enter this
- codepath for this particular request mid
- then request_time is left as the absolute
- time of the *first* time this request mid
- was processed. This is what allows the
- request to eventually time out. */
-
- timeout = timeval_set(0, timeout_usecs);
-
- /* Nothing actually uses
- state.delayed_for_oplocks but it's handy to
- differentiate in debug messages between a
- 30 second delay due to oplock break, and a
- 1 second delay for share mode conflicts. */
-
- state.delayed_for_oplocks = False;
- state.id = id;
- state.failed = false;
-
- /*
- * We hit the race that when we did the stat
- * on the file it did not exist, and someone
- * has created it in between the stat and the
- * open_file() call. Retrieve the share_mode
- * lock on the newly opened file so we can
- * defer our request.
- */
- if (lck == NULL) {
- struct timespec old_write_time;
- old_write_time = get_mtimespec(psbuf);
-
- lck = get_share_mode_lock(talloc_tos(),
- id, conn->connectpath, fname,
- &old_write_time);
- if (lck == NULL) {
- DEBUG(0,
- ("onefs_open_file_ntcreate:"
- " Could not get share "
- "mode lock for %s\n",
- fname));
- /* This will cause us to return
- * immediately skipping the
- * the 1 second delay, which
- * isn't a big deal */
- status = NT_STATUS_SHARING_VIOLATION;
- goto cleanup_destroy;
- }
- }
-
- if ((req != NULL) &&
- !request_timed_out(request_time, timeout))
- {
- defer_open(lck, request_time, timeout,
- req, &state);
- }
- }
-
- if (can_access) {
- /*
- * We have detected a sharing violation here
- * so return the correct error code
- */
- status = NT_STATUS_SHARING_VIOLATION;
- } else {
- status = NT_STATUS_ACCESS_DENIED;
- }
-
- goto cleanup_destroy;
- }
-
- /*
- * Normal error, for example EACCES
- */
- cleanup_destroy:
- if (oplock_callback_id != 0) {
- destroy_onefs_callback_record(oplock_callback_id);
- }
- cleanup:
- TALLOC_FREE(lck);
- return status;
- }
-
- fsp->oplock_type = granted_oplock;
-
- if (oplock_callback_id != 0) {
- onefs_set_oplock_callback(oplock_callback_id, fsp);
- fsp_data->oplock_callback_id = oplock_callback_id;
- } else {
- SMB_ASSERT(fsp->oplock_type == NO_OPLOCK);
- }
-
- if (!file_existed) {
- struct timespec old_write_time = smb_fname->st.st_ex_mtime;
- /*
- * Deal with the race condition where two smbd's detect the
- * file doesn't exist and do the create at the same time. One
- * of them will win and set a share mode, the other (ie. this
- * one) should check if the requested share mode for this
- * create is allowed.
- */
-
- /*
- * Now the file exists and fsp is successfully opened,
- * fsp->file_id is valid and should replace the
- * dev=0, inode=0 from a non existent file. Spotted by
- * Nadav Danieli <nadavd@exanet.com>. JRA.
- */
-
- id = fsp->file_id;
-
- lck = get_share_mode_lock(talloc_tos(), id,
- conn->connectpath,
- smb_fname, &old_write_time);
-
- if (lck == NULL) {
- DEBUG(0, ("onefs_open_file_ntcreate: Could not get "
- "share mode lock for %s\n",
- smb_fname_str_dbg(smb_fname)));
- fd_close(fsp);
- return NT_STATUS_SHARING_VIOLATION;
- }
-
- if (lck->delete_on_close) {
- status = NT_STATUS_DELETE_PENDING;
- }
-
- if (!NT_STATUS_IS_OK(status)) {
- struct deferred_open_record state;
-
- fd_close(fsp);
-
- state.delayed_for_oplocks = False;
- state.id = id;
-
- /* Do it all over again immediately. In the second
- * round we will find that the file existed and handle
- * the DELETE_PENDING and FCB cases correctly. No need
- * to duplicate the code here. Essentially this is a
- * "goto top of this function", but don't tell
- * anybody... */
-
- if (req != NULL) {
- defer_open(lck, request_time, timeval_zero(),
- req, &state);
- }
- TALLOC_FREE(lck);
- return status;
- }
-
- /*
- * We exit this block with the share entry *locked*.....
- */
-
- }
-
- SMB_ASSERT(lck != NULL);
-
- /* Delete streams if create_disposition requires it */
- if (file_existed && clear_ads &&
- !is_ntfs_stream_smb_fname(smb_fname)) {
- status = delete_all_streams(conn, smb_fname->base_name);
- if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(lck);
- fd_close(fsp);
- return status;
- }
- }
-
- /* note that we ignore failure for the following. It is
- basically a hack for NFS, and NFS will never set one of
- these only read them. Nobody but Samba can ever set a deny
- mode and we have already checked our more authoritative
- locking database for permission to set this deny mode. If
- the kernel refuses the operations then the kernel is wrong.
- note that GPFS supports it as well - jmcd */
-
- if (fsp->fh->fd != -1) {
- ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, share_access, access_mask);
- if(ret_flock == -1 ){
-
- TALLOC_FREE(lck);
- fd_close(fsp);
- return NT_STATUS_SHARING_VIOLATION;
- }
- }
-
- /*
- * At this point onwards, we can guarentee that the share entry
- * is locked, whether we created the file or not, and that the
- * deny mode is compatible with all current opens.
- */
-
- /*
- * According to Samba4, SEC_FILE_READ_ATTRIBUTE is always granted,
- */
- fsp->access_mask = access_mask | FILE_READ_ATTRIBUTES;
-
- if (file_existed) {
- /* stat opens on existing files don't get oplocks. */
- if (is_stat_open(open_access_mask)) {
- fsp->oplock_type = NO_OPLOCK;
- }
-
- if (!(flags2 & O_TRUNC)) {
- info = FILE_WAS_OPENED;
- } else {
- info = FILE_WAS_OVERWRITTEN;
- }
- } else {
- info = FILE_WAS_CREATED;
- }
-
- if (pinfo) {
- *pinfo = info;
- }
-
- /*
- * Setup the oplock info in both the shared memory and
- * file structs.
- */
-
- if ((fsp->oplock_type != NO_OPLOCK) &&
- (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK)) {
- if (!set_file_oplock(fsp, fsp->oplock_type)) {
- /* Could not get the kernel oplock */
- fsp->oplock_type = NO_OPLOCK;
- }
- }
-
- if (fsp->oplock_type == LEVEL_II_OPLOCK &&
- (!lp_level2_oplocks(SNUM(conn)) ||
- !(global_client_caps & CAP_LEVEL_II_OPLOCKS))) {
-
- DEBUG(5, ("Downgrading level2 oplock on open "
- "because level2 oplocks = off\n"));
-
- release_file_oplock(fsp);
- }
-
- if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED ||
- info == FILE_WAS_SUPERSEDED) {
- new_file_created = True;
- }
-
- set_share_mode(lck, fsp, get_current_uid(conn),
- req ? req->mid : 0,
- fsp->oplock_type);
-
- /* Handle strange delete on close create semantics. */
- if (create_options & FILE_DELETE_ON_CLOSE) {
- status = can_set_delete_on_close(fsp, new_dos_attributes);
-
- if (!NT_STATUS_IS_OK(status)) {
- /* Remember to delete the mode we just added. */
- del_share_mode(lck, fsp);
- TALLOC_FREE(lck);
- fd_close(fsp);
- return status;
- }
- /* Note that here we set the *inital* delete on close flag,
- not the regular one. The magic gets handled in close. */
- fsp->initial_delete_on_close = True;
- }
-
- /*
- * Take care of inherited ACLs on created files - if default ACL not
- * selected.
- * May be necessary depending on acl policies.
- */
- if (!posix_open && !file_existed && !def_acl &&
- !(VALID_STAT(smb_fname->st) &&
- (smb_fname->st.st_ex_flags & SF_HASNTFSACL))) {
-
- int saved_errno = errno; /* We might get ENOSYS in the next
- * call.. */
-
- if (SMB_VFS_FCHMOD_ACL(fsp, unx_mode) == -1 &&
- errno == ENOSYS) {
- errno = saved_errno; /* Ignore ENOSYS */
- }
-
- } else if (new_unx_mode) {
-
- int ret = -1;
-
- /* Attributes need changing. File already existed. */
-
- {
- int saved_errno = errno; /* We might get ENOSYS in the
- * next call.. */
- ret = SMB_VFS_FCHMOD_ACL(fsp, new_unx_mode);
-
- if (ret == -1 && errno == ENOSYS) {
- errno = saved_errno; /* Ignore ENOSYS */
- } else {
- DEBUG(5, ("onefs_open_file_ntcreate: reset "
- "attributes of file %s to 0%o\n",
- smb_fname_str_dbg(smb_fname),
- (unsigned int)new_unx_mode));
- ret = 0; /* Don't do the fchmod below. */
- }
- }
-
- if ((ret == -1) &&
- (SMB_VFS_FCHMOD(fsp, new_unx_mode) == -1))
- DEBUG(5, ("onefs_open_file_ntcreate: failed to reset "
- "attributes of file %s to 0%o\n",
- smb_fname_str_dbg(smb_fname),
- (unsigned int)new_unx_mode));
- }
-
- /* If this is a successful open, we must remove any deferred open
- * records. */
- if (req != NULL) {
- del_deferred_open_entry(lck, req->mid);
- }
- TALLOC_FREE(lck);
-
- return NT_STATUS_OK;
-}
-
-
-/****************************************************************************
- Open a directory from an NT SMB call.
-****************************************************************************/
-static NTSTATUS onefs_open_directory(connection_struct *conn,
- struct smb_request *req,
- struct smb_filename *smb_dname,
- uint32 access_mask,
- uint32 share_access,
- uint32 create_disposition,
- uint32 create_options,
- uint32 file_attributes,
- struct security_descriptor *sd,
- files_struct **result,
- int *pinfo)
-{
- files_struct *fsp = NULL;
- struct share_mode_lock *lck = NULL;
- NTSTATUS status;
- struct timespec mtimespec;
- int info = 0;
- char *parent_dir;
- bool posix_open = false;
- uint32 create_flags = 0;
- uint32 mode = lp_dir_mask(SNUM(conn));
-
- DEBUG(5, ("onefs_open_directory: opening directory %s, "
- "access_mask = 0x%x, "
- "share_access = 0x%x create_options = 0x%x, "
- "create_disposition = 0x%x, file_attributes = 0x%x\n",
- smb_fname_str_dbg(smb_dname), (unsigned int)access_mask,
- (unsigned int)share_access, (unsigned int)create_options,
- (unsigned int)create_disposition,
- (unsigned int)file_attributes));
-
- if (!(file_attributes & FILE_FLAG_POSIX_SEMANTICS) &&
- (conn->fs_capabilities & FILE_NAMED_STREAMS) &&
- is_ntfs_stream_smb_fname(smb_dname)) {
- DEBUG(2, ("onefs_open_directory: %s is a stream name!\n",
- smb_fname_str_dbg(smb_dname)));
- return NT_STATUS_NOT_A_DIRECTORY;
- }
-
- switch (create_disposition) {
- case FILE_OPEN:
- /* If directory exists open. If directory doesn't
- * exist error. */
- create_flags = 0;
- info = FILE_WAS_OPENED;
- break;
- case FILE_CREATE:
- /* If directory exists error. If directory doesn't
- * exist create. */
- create_flags = O_CREAT | O_EXCL;
- info = FILE_WAS_CREATED;
- break;
- case FILE_OPEN_IF:
- /* If directory exists open. If directory doesn't
- * exist create. */
-
- /* Note: in order to return whether the directory was
- * opened or created, we first try to open and then try
- * to create. */
- create_flags = 0;
- info = FILE_WAS_OPENED;
- break;
- case FILE_SUPERSEDE:
- case FILE_OVERWRITE:
- case FILE_OVERWRITE_IF:
- default:
- DEBUG(5, ("onefs_open_directory: invalid "
- "create_disposition 0x%x for directory %s\n",
- (unsigned int)create_disposition,
- smb_fname_str_dbg(smb_dname)));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- /*
- * Check for write access to the share. Done in mkdir_internal() in
- * mainline samba.
- */
- if (!CAN_WRITE(conn) && (create_flags & O_CREAT)) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
- /* Get parent dirname */
- if (!parent_dirname(talloc_tos(), smb_dname->base_name, &parent_dir,
- NULL)) {
- return NT_STATUS_NO_MEMORY;
- }
-
- if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) {
- posix_open = true;
- mode = (mode_t)(file_attributes & ~FILE_FLAG_POSIX_SEMANTICS);
- file_attributes = 0;
- } else {
- mode = unix_mode(conn, FILE_ATTRIBUTE_DIRECTORY, smb_dname, parent_dir);
- }
-
- /*
- * The NONINDEXED and COMPRESSED bits seem to always be cleared on
- * directories, no matter if you specify that they should be set.
- */
- file_attributes &=
- ~(FILE_ATTRIBUTE_NONINDEXED | FILE_ATTRIBUTE_COMPRESSED);
-
- status = file_new(req, conn, &fsp);
- if(!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- /*
- * Actual open with retry magic to handle FILE_OPEN_IF which is
- * unique because the kernel won't tell us if the file was opened or
- * created.
- */
- retry_open:
- fsp->fh->fd = onefs_sys_create_file(conn,
- -1,
- smb_dname->base_name,
- access_mask,
- access_mask,
- share_access,
- create_options,
- create_flags | O_DIRECTORY,
- mode,
- 0,
- 0,
- sd,
- file_attributes,
- NULL);
-
- if (fsp->fh->fd == -1) {
- DEBUG(3, ("Error opening %s. Errno=%d (%s).\n",
- smb_fname_str_dbg(smb_dname), errno,
- strerror(errno)));
- SMB_ASSERT(errno != EINPROGRESS);
-
- if (create_disposition == FILE_OPEN_IF) {
- if (errno == ENOENT) {
- /* Try again, creating it this time. */
- create_flags = O_CREAT | O_EXCL;
- info = FILE_WAS_CREATED;
- goto retry_open;
- } else if (errno == EEXIST) {
- /* Uggh. Try again again. */
- create_flags = 0;
- info = FILE_WAS_OPENED;
- goto retry_open;
- }
- }
-
- /* Error cases below: */
- file_free(req, fsp);
-
- if ((errno == ENOENT) && (create_disposition == FILE_OPEN)) {
- DEBUG(5, ("onefs_open_directory: FILE_OPEN requested "
- "for directory %s and it doesn't "
- "exist.\n", smb_fname_str_dbg(smb_dname)));
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
- } else if ((errno == EEXIST) &&
- (create_disposition == FILE_CREATE)) {
- DEBUG(5, ("onefs_open_directory: FILE_CREATE "
- "requested for directory %s and it "
- "already exists.\n",
- smb_fname_str_dbg(smb_dname)));
- return NT_STATUS_OBJECT_NAME_COLLISION;
- } else if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
- /* Catch sharing violations. */
- return NT_STATUS_SHARING_VIOLATION;
- }
-
- return map_nt_error_from_unix(errno);
- }
-
- if (info == FILE_WAS_CREATED) {
-
- /* Pulled from mkdir_internal() */
- if (SMB_VFS_LSTAT(conn, smb_dname) == -1) {
- DEBUG(2, ("Could not stat directory '%s' just "
- "created: %s\n",
- smb_fname_str_dbg(smb_dname),
- strerror(errno)));
- return map_nt_error_from_unix(errno);
- }
-
- if (!S_ISDIR(smb_dname->st.st_ex_mode)) {
- DEBUG(0, ("Directory just '%s' created is not a "
- "directory\n",
- smb_fname_str_dbg(smb_dname)));
- return NT_STATUS_ACCESS_DENIED;
- }
-
- if (!posix_open) {
- /*
- * Check if high bits should have been set, then (if
- * bits are missing): add them. Consider bits
- * automagically set by UNIX, i.e. SGID bit from
- * parent dir.
- */
- if (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) &&
- (mode & ~smb_dname->st.st_ex_mode)) {
- SMB_VFS_CHMOD(conn, smb_dname->base_name,
- (smb_dname->st.st_ex_mode |
- (mode & ~smb_dname->st.st_ex_mode)));
- }
- }
-
- /* Change the owner if required. */
- if (lp_inherit_owner(SNUM(conn))) {
- change_dir_owner_to_parent(conn, parent_dir,
- smb_dname->base_name,
- &smb_dname->st);
- }
-
- notify_fname(conn, NOTIFY_ACTION_ADDED,
- FILE_NOTIFY_CHANGE_DIR_NAME,
- smb_dname->base_name);
- }
-
- /* Stat the fd for Samba bookkeeping. */
- if(SMB_VFS_FSTAT(fsp, &smb_dname->st) != 0) {
- fd_close(fsp);
- file_free(req, fsp);
- return map_nt_error_from_unix(errno);
- }
-
- /* Setup the files_struct for it. */
- fsp->mode = smb_dname->st.st_ex_mode;
- fsp->file_id = vfs_file_id_from_sbuf(conn, &smb_dname->st);
- fsp->vuid = req ? req->vuid : UID_FIELD_INVALID;
- fsp->file_pid = req ? req->smbpid : 0;
- fsp->can_lock = False;
- fsp->can_read = False;
- fsp->can_write = False;
-
- fsp->share_access = share_access;
- fsp->fh->private_options = 0;
- /*
- * According to Samba4, SEC_FILE_READ_ATTRIBUTE is always granted,
- */
- fsp->access_mask = access_mask | FILE_READ_ATTRIBUTES;
- fsp->print_file = NULL;
- fsp->modified = False;
- fsp->oplock_type = NO_OPLOCK;
- fsp->sent_oplock_break = NO_BREAK_SENT;
- fsp->is_directory = True;
- fsp->posix_open = posix_open;
-
- status = fsp_set_smb_fname(fsp, smb_dname);
- if (!NT_STATUS_IS_OK(status)) {
- fd_close(fsp);
- file_free(req, fsp);
- return status;
- }
-
- mtimespec = smb_dname->st.st_ex_mtime;
-
- /*
- * Still set the samba share mode lock for correct delete-on-close
- * semantics and to make smbstatus more useful.
- */
- lck = get_share_mode_lock(talloc_tos(), fsp->file_id,
- conn->connectpath, smb_dname, &mtimespec);
-
- if (lck == NULL) {
- DEBUG(0, ("onefs_open_directory: Could not get share mode "
- "lock for %s\n", smb_fname_str_dbg(smb_dname)));
- fd_close(fsp);
- file_free(req, fsp);
- return NT_STATUS_SHARING_VIOLATION;
- }
-
- if (lck->delete_on_close) {
- TALLOC_FREE(lck);
- fd_close(fsp);
- file_free(req, fsp);
- return NT_STATUS_DELETE_PENDING;
- }
-
- set_share_mode(lck, fsp, get_current_uid(conn),
- req ? req->mid : 0, NO_OPLOCK);
-
- /*
- * For directories the delete on close bit at open time seems
- * always to be honored on close... See test 19 in Samba4 BASE-DELETE.
- */
- if (create_options & FILE_DELETE_ON_CLOSE) {
- status = can_set_delete_on_close(fsp, 0);
- if (!NT_STATUS_IS_OK(status) &&
- !NT_STATUS_EQUAL(status, NT_STATUS_DIRECTORY_NOT_EMPTY)) {
- TALLOC_FREE(lck);
- fd_close(fsp);
- file_free(req, fsp);
- return status;
- }
-
- if (NT_STATUS_IS_OK(status)) {
- /* Note that here we set the *inital* delete on close flag,
- not the regular one. The magic gets handled in close. */
- fsp->initial_delete_on_close = True;
- }
- }
-
- TALLOC_FREE(lck);
-
- if (pinfo) {
- *pinfo = info;
- }
-
- *result = fsp;
- return NT_STATUS_OK;
-}
-
-/*
- * Wrapper around onefs_open_file_ntcreate and onefs_open_directory.
- */
-static NTSTATUS onefs_create_file_unixpath(connection_struct *conn,
- struct smb_request *req,
- struct smb_filename *smb_fname,
- uint32_t access_mask,
- uint32_t share_access,
- uint32_t create_disposition,
- uint32_t create_options,
- uint32_t file_attributes,
- uint32_t oplock_request,
- uint64_t allocation_size,
- uint32_t private_flags,
- struct security_descriptor *sd,
- struct ea_list *ea_list,
- files_struct **result,
- int *pinfo,
- struct onefs_fsp_data *fsp_data)
-{
- int info = FILE_WAS_OPENED;
- files_struct *base_fsp = NULL;
- files_struct *fsp = NULL;
- NTSTATUS status;
-
- DEBUG(10,("onefs_create_file_unixpath: access_mask = 0x%x "
- "file_attributes = 0x%x, share_access = 0x%x, "
- "create_disposition = 0x%x create_options = 0x%x "
- "oplock_request = 0x%x private_flags = 0x%x "
- "ea_list = 0x%p, sd = 0x%p, "
- "fname = %s\n",
- (unsigned int)access_mask,
- (unsigned int)file_attributes,
- (unsigned int)share_access,
- (unsigned int)create_disposition,
- (unsigned int)create_options,
- (unsigned int)oplock_request,
- (unsigned int)private_flags,
- ea_list, sd, smb_fname_str_dbg(smb_fname)));
-
- if (create_options & FILE_OPEN_BY_FILE_ID) {
- status = NT_STATUS_NOT_SUPPORTED;
- goto fail;
- }
-
- if (create_options & NTCREATEX_OPTIONS_INVALID_PARAM_MASK) {
- status = NT_STATUS_INVALID_PARAMETER;
- goto fail;
- }
-
- if (req == NULL) {
- SMB_ASSERT((oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK) ==
- NO_OPLOCK);
- oplock_request |= INTERNAL_OPEN_ONLY;
- }
-
- if (lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE,
- PARM_IGNORE_SACLS, PARM_IGNORE_SACLS_DEFAULT)) {
- access_mask &= ~SYSTEM_SECURITY_ACCESS;
- }
-
- if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
- && (access_mask & DELETE_ACCESS)
- && !is_ntfs_stream_smb_fname(smb_fname)) {
- /*
- * We can't open a file with DELETE access if any of the
- * streams is open without FILE_SHARE_DELETE
- */
- status = open_streams_for_delete(conn, smb_fname->base_name);
-
- if (!NT_STATUS_IS_OK(status)) {
- goto fail;
- }
- }
-
- if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
- && is_ntfs_stream_smb_fname(smb_fname)) {
- uint32 base_create_disposition;
- struct smb_filename *smb_fname_base = NULL;
-
- if (create_options & FILE_DIRECTORY_FILE) {
- status = NT_STATUS_NOT_A_DIRECTORY;
- goto fail;
- }
-
- switch (create_disposition) {
- case FILE_OPEN:
- base_create_disposition = FILE_OPEN;
- break;
- default:
- base_create_disposition = FILE_OPEN_IF;
- break;
- }
-
- /* Create an smb_filename with stream_name == NULL. */
- status = create_synthetic_smb_fname(talloc_tos(),
- smb_fname->base_name,
- NULL, NULL,
- &smb_fname_base);
- if (!NT_STATUS_IS_OK(status)) {
- goto fail;
- }
-
- if (SMB_VFS_STAT(conn, smb_fname_base) == -1) {
- DEBUG(10, ("Unable to stat stream: %s\n",
- smb_fname_str_dbg(smb_fname_base)));
- }
-
- status = onefs_create_file_unixpath(
- conn, /* conn */
- NULL, /* req */
- smb_fname_base, /* fname */
- SYNCHRONIZE_ACCESS, /* access_mask */
- (FILE_SHARE_READ |
- FILE_SHARE_WRITE |
- FILE_SHARE_DELETE), /* share_access */
- base_create_disposition, /* create_disposition*/
- 0, /* create_options */
- file_attributes, /* file_attributes */
- NO_OPLOCK, /* oplock_request */
- 0, /* allocation_size */
- 0, /* private_flags */
- NULL, /* sd */
- NULL, /* ea_list */
- &base_fsp, /* result */
- NULL, /* pinfo */
- NULL); /* fsp_data */
-
- TALLOC_FREE(smb_fname_base);
-
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10, ("onefs_create_file_unixpath for base %s "
- "failed: %s\n", smb_fname->base_name,
- nt_errstr(status)));
- goto fail;
- }
-
- /*
- * Testing against windows xp/2003/vista shows that oplocks
- * can actually be requested and granted on streams (see the
- * RAW-OPLOCK-STREAM1 smbtorture test).
- */
- if ((oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK) !=
- NO_OPLOCK) {
- DEBUG(5, ("Oplock(%d) being requested on a stream! "
- "Ignoring oplock request: fname=%s\n",
- oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK,
- smb_fname_str_dbg(smb_fname)));
- /* Request NO_OPLOCK instead. */
- oplock_request &= SAMBA_PRIVATE_OPLOCK_MASK;
- }
- }
-
- /* Covert generic bits in the security descriptor. */
- if (sd != NULL) {
- security_acl_map_generic(sd->dacl, &file_generic_mapping);
- security_acl_map_generic(sd->sacl, &file_generic_mapping);
- }
-
- /*
- * If it's a request for a directory open, deal with it separately.
- */
-
- if (create_options & FILE_DIRECTORY_FILE) {
-
- if (create_options & FILE_NON_DIRECTORY_FILE) {
- status = NT_STATUS_INVALID_PARAMETER;
- goto fail;
- }
-
- /* Can't open a temp directory. IFS kit test. */
- if (!(file_attributes & FILE_FLAG_POSIX_SEMANTICS) &&
- (file_attributes & FILE_ATTRIBUTE_TEMPORARY)) {
- status = NT_STATUS_INVALID_PARAMETER;
- goto fail;
- }
-
- /*
- * We will get a create directory here if the Win32
- * app specified a security descriptor in the
- * CreateDirectory() call.
- */
-
- status = onefs_open_directory(
- conn, /* conn */
- req, /* req */
- smb_fname, /* fname */
- access_mask, /* access_mask */
- share_access, /* share_access */
- create_disposition, /* create_disposition*/
- create_options, /* create_options */
- file_attributes, /* file_attributes */
- sd, /* sd */
- &fsp, /* result */
- &info); /* pinfo */
- } else {
-
- /*
- * Ordinary file case.
- */
-
- status = file_new(req, conn, &fsp);
- if(!NT_STATUS_IS_OK(status)) {
- goto fail;
- }
-
- /*
- * We're opening the stream element of a base_fsp
- * we already opened. Set up the base_fsp pointer.
- */
- if (base_fsp) {
- fsp->base_fsp = base_fsp;
- }
-
- status = onefs_open_file_ntcreate(
- conn, /* conn */
- req, /* req */
- smb_fname, /* fname */
- access_mask, /* access_mask */
- share_access, /* share_access */
- create_disposition, /* create_disposition*/
- create_options, /* create_options */
- file_attributes, /* file_attributes */
- oplock_request, /* oplock_request */
- sd, /* sd */
- fsp, /* result */
- &info, /* pinfo */
- fsp_data); /* fsp_data */
-
- if(!NT_STATUS_IS_OK(status)) {
- file_free(req, fsp);
- fsp = NULL;
- }
-
- if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) {
-
- /* A stream open never opens a directory */
-
- if (base_fsp) {
- status = NT_STATUS_FILE_IS_A_DIRECTORY;
- goto fail;
- }
-
- /*
- * Fail the open if it was explicitly a non-directory
- * file.
- */
-
- if (create_options & FILE_NON_DIRECTORY_FILE) {
- status = NT_STATUS_FILE_IS_A_DIRECTORY;
- goto fail;
- }
-
- create_options |= FILE_DIRECTORY_FILE;
-
- status = onefs_open_directory(
- conn, /* conn */
- req, /* req */
- smb_fname, /* fname */
- access_mask, /* access_mask */
- share_access, /* share_access */
- create_disposition, /* create_disposition*/
- create_options, /* create_options */
- file_attributes, /* file_attributes */
- sd, /* sd */
- &fsp, /* result */
- &info); /* pinfo */
- }
- }
-
- if (!NT_STATUS_IS_OK(status)) {
- goto fail;
- }
-
- fsp->base_fsp = base_fsp;
-
- SMB_ASSERT(fsp);
-
- if ((ea_list != NULL) && (info == FILE_WAS_CREATED)) {
- status = set_ea(conn, fsp, smb_fname, ea_list);
- if (!NT_STATUS_IS_OK(status)) {
- goto fail;
- }
- }
-
- if (!fsp->is_directory && S_ISDIR(smb_fname->st.st_ex_mode)) {
- status = NT_STATUS_ACCESS_DENIED;
- goto fail;
- }
-
- /* Save the requested allocation size. */
- if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) {
- if (allocation_size
- && (allocation_size > smb_fname->st.st_ex_size)) {
- fsp->initial_allocation_size = smb_roundup(
- fsp->conn, allocation_size);
- if (fsp->is_directory) {
- /* Can't set allocation size on a directory. */
- status = NT_STATUS_ACCESS_DENIED;
- goto fail;
- }
- if (vfs_allocate_file_space(
- fsp, fsp->initial_allocation_size) == -1) {
- status = NT_STATUS_DISK_FULL;
- goto fail;
- }
- } else {
- fsp->initial_allocation_size = smb_roundup(
- fsp->conn, (uint64_t)smb_fname->st.st_ex_size);
- }
- }
-
- DEBUG(10, ("onefs_create_file_unixpath: info=%d\n", info));
-
- *result = fsp;
- if (pinfo != NULL) {
- *pinfo = info;
- }
- if ((fsp->fh != NULL) && (fsp->fh->fd != -1)) {
- SMB_VFS_FSTAT(fsp, &smb_fname->st);
- }
- return NT_STATUS_OK;
-
- fail:
- DEBUG(10, ("onefs_create_file_unixpath: %s\n", nt_errstr(status)));
-
- if (fsp != NULL) {
- if (base_fsp && fsp->base_fsp == base_fsp) {
- /*
- * The close_file below will close
- * fsp->base_fsp.
- */
- base_fsp = NULL;
- }
- close_file(req, fsp, ERROR_CLOSE);
- fsp = NULL;
- }
- if (base_fsp != NULL) {
- close_file(req, base_fsp, ERROR_CLOSE);
- base_fsp = NULL;
- }
- return status;
-}
-
-static void destroy_onefs_fsp_data(void *p_data)
-{
- struct onefs_fsp_data *fsp_data = (struct onefs_fsp_data *)p_data;
-
- destroy_onefs_callback_record(fsp_data->oplock_callback_id);
-}
-
-/**
- * SMB_VFS_CREATE_FILE interface to onefs.
- */
-NTSTATUS onefs_create_file(vfs_handle_struct *handle,
- struct smb_request *req,
- uint16_t root_dir_fid,
- struct smb_filename *smb_fname,
- uint32_t access_mask,
- uint32_t share_access,
- uint32_t create_disposition,
- uint32_t create_options,
- uint32_t file_attributes,
- uint32_t oplock_request,
- uint64_t allocation_size,
- uint32_t private_flags,
- struct security_descriptor *sd,
- struct ea_list *ea_list,
- files_struct **result,
- int *pinfo)
-{
- connection_struct *conn = handle->conn;
- struct onefs_fsp_data fsp_data = {};
- int info = FILE_WAS_OPENED;
- files_struct *fsp = NULL;
- NTSTATUS status;
-
- DEBUG(10,("onefs_create_file: access_mask = 0x%x "
- "file_attributes = 0x%x, share_access = 0x%x, "
- "create_disposition = 0x%x create_options = 0x%x "
- "oplock_request = 0x%x private_flags = 0x%x"
- "root_dir_fid = 0x%x, ea_list = 0x%p, sd = 0x%p, "
- "fname = %s\n",
- (unsigned int)access_mask,
- (unsigned int)file_attributes,
- (unsigned int)share_access,
- (unsigned int)create_disposition,
- (unsigned int)create_options,
- (unsigned int)oplock_request,
- (unsigned int)private_flags,
- (unsigned int)root_dir_fid,
- ea_list, sd, smb_fname_str_dbg(smb_fname)));
-
- /* Get the file name if root_dir_fid was specified. */
- if (root_dir_fid != 0) {
- struct smb_filename *smb_fname_out = NULL;
- status = get_relative_fid_filename(conn, req, root_dir_fid,
- smb_fname, &smb_fname_out);
- if (!NT_STATUS_IS_OK(status)) {
- goto fail;
- }
- smb_fname = smb_fname_out;
- }
-
- /* All file access must go through check_name() */
- status = check_name(conn, smb_fname->base_name);
- if (!NT_STATUS_IS_OK(status)) {
- goto fail;
- }
-
- if (is_ntfs_stream_smb_fname(smb_fname)) {
- if (!(conn->fs_capabilities & FILE_NAMED_STREAMS)) {
- status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
- goto fail;
- }
-
- if (is_ntfs_default_stream_smb_fname(smb_fname)) {
- int ret;
- smb_fname->stream_name = NULL;
- /* We have to handle this error here. */
- if (create_options & FILE_DIRECTORY_FILE) {
- status = NT_STATUS_NOT_A_DIRECTORY;
- goto fail;
- }
- if (lp_posix_pathnames()) {
- ret = SMB_VFS_LSTAT(conn, smb_fname);
- } else {
- ret = SMB_VFS_STAT(conn, smb_fname);
- }
-
- if (ret == 0 && VALID_STAT_OF_DIR(smb_fname->st)) {
- status = NT_STATUS_FILE_IS_A_DIRECTORY;
- goto fail;
- }
- }
- }
-
- status = onefs_create_file_unixpath(
- conn, /* conn */
- req, /* req */
- smb_fname, /* fname */
- access_mask, /* access_mask */
- share_access, /* share_access */
- create_disposition, /* create_disposition*/
- create_options, /* create_options */
- file_attributes, /* file_attributes */
- oplock_request, /* oplock_request */
- allocation_size, /* allocation_size */
- private_flags,
- sd, /* sd */
- ea_list, /* ea_list */
- &fsp, /* result */
- &info, /* pinfo */
- &fsp_data); /* psbuf */
-
- if (!NT_STATUS_IS_OK(status)) {
- goto fail;
- }
-
- DEBUG(10, ("onefs_create_file: info=%d\n", info));
-
- /*
- * Setup private onefs_fsp_data. Currently the private data struct is
- * only used to store the oplock_callback_id so that when the file is
- * closed, the onefs_callback_record can be properly cleaned up in the
- * oplock_onefs sub-system.
- */
- if (fsp) {
- struct onefs_fsp_data *fsp_data_tmp = NULL;
- fsp_data_tmp = (struct onefs_fsp_data *)
- VFS_ADD_FSP_EXTENSION(handle, fsp, struct onefs_fsp_data,
- &destroy_onefs_fsp_data);
-
- if (fsp_data_tmp == NULL) {
- status = NT_STATUS_NO_MEMORY;
- goto fail;
- }
-
- *fsp_data_tmp = fsp_data;
- }
-
- *result = fsp;
- if (pinfo != NULL) {
- *pinfo = info;
- }
- return NT_STATUS_OK;
-
- fail:
- DEBUG(10, ("onefs_create_file: %s\n", nt_errstr(status)));
-
- if (fsp != NULL) {
- close_file(req, fsp, ERROR_CLOSE);
- fsp = NULL;
- }
- return status;
-}
diff --git a/source3/modules/onefs_shadow_copy.c b/source3/modules/onefs_shadow_copy.c
deleted file mode 100644
index 29ee9e1a22..0000000000
--- a/source3/modules/onefs_shadow_copy.c
+++ /dev/null
@@ -1,783 +0,0 @@
-/*
- * Unix SMB/CIFS implementation.
- *
- * OneFS shadow copy implementation that utilizes the file system's native
- * snapshot support. This file does all of the heavy lifting.
- *
- * Copyright (C) Dave Richards, 2007
- * Copyright (C) Tim Prouty, 2009
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "smbd/smbd.h"
-#include <ifs/ifs_syscalls.h>
-#include <sys/types.h>
-#include <sys/isi_enc.h>
-#include <sys/module.h>
-#include <sys/stat.h>
-#include <sys/syscall.h>
-#include <sys/time.h>
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <search.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "onefs_shadow_copy.h"
-
-/* Copied from ../include/proto.h */
-void become_root(void);
-void unbecome_root(void);
-
-#define SNAPSHOT_DIRECTORY ".snapshot"
-
-#define MAX_VERSIONS 64
-
-/**
- * A snapshot object.
- *
- * During snapshot enumeration, snapshots are represented by snapshot objects
- * and are stored in a snapshot set. The snapshot object represents one
- * snapshot within the set. An important thing to note about the set is that
- * the key of the snapshot object is the tv_sec component of the is_time
- * member. What this means is that we only store one snapshot for each
- * second. If multiple snapshots were created within the same second, we'll
- * keep the earliest one and ignore the rest. Thus, not all snapshots are
- * necessarily retained.
- */
-struct osc_snapshot {
- char * is_name;
- struct timespec is_time;
- struct osc_snapshot * is_next;
-};
-
-/**
- * A snapshot context object.
- *
- * Snapshot contexts are used to pass information throughout the snapshot
- * enumeration routines. As a result, snapshot contexts are stored on the
- * stack and are both created and destroyed within a single API function.
- */
-struct osc_snapshot_ctx {
- void * osc_set;
- struct timespec osc_mtime;
-};
-
-/**
- * A directory context.
- *
- * Directory contexts are the underlying data structured used to enumerate
- * snapshot versions. An opendir()-, readdir()- and closedir()-like interface
- * is provided that utilizes directory contexts. At the API level, directory
- * contexts are passed around as void pointers. Directory contexts are
- * allocated on the heap and their lifetime is dictated by the calling
- * routine.
- */
-struct osc_directory_ctx {
- size_t idc_pos;
- size_t idc_len;
- size_t idc_size;
- char ** idc_version;
-};
-
-/**
- * Return a file descriptor to the STF names directory.
- *
- * Opens the STF names directory and returns a file descriptor to it.
- * Subsequent calls return the same value (avoiding the need to re-open the
- * directory repeatedly). Caveat caller: don't close the file descriptor or
- * you will be shot!
- */
-static int
-osc_get_names_directory_fd(void)
-{
- static int fd = -1;
-
- if (fd == -1) {
- become_root();
- fd = pctl2_lin_open(STF_NAMES_LIN, HEAD_SNAPID, O_RDONLY);
- unbecome_root();
- }
-
- return fd;
-}
-
-/**
- * Compare two time values.
- *
- * Accepts two struct timespecs and compares the tv_sec components of these
- * values. It returns -1 if the first value preceeds the second, 0 if they
- * are equal and +1 if the first values succeeds the second.
- */
-static int
-osc_time_compare(const struct timespec *tsp1, const struct timespec *tsp2)
-{
- return (tsp1->tv_sec < tsp2->tv_sec) ? -1 :
- (tsp1->tv_sec > tsp2->tv_sec) ? +1 : 0;
-}
-
-/**
- * Compare two timespec values.
- *
- * Compares two timespec values. It returns -1 if the first value preceeds
- * the second, 0 if they are equal and +1 if the first values succeeds the
- * second.
- */
-static int
-osc_timespec_compare(const struct timespec *tsp1, const struct timespec *tsp2)
-{
- return (tsp1->tv_sec < tsp2->tv_sec) ? -1 :
- (tsp1->tv_sec > tsp2->tv_sec) ? +1 :
- (tsp1->tv_nsec < tsp2->tv_nsec) ? -1 :
- (tsp1->tv_nsec > tsp2->tv_nsec) ? +1 : 0;
-}
-
-/**
- * Determine whether a timespec value is zero.
- *
- * Return 1 if the struct timespec provided is zero and 0 otherwise.
- */
-static int
-osc_timespec_is_zero(const struct timespec *tsp)
-{
- return (tsp->tv_sec == 0) &&
- (tsp->tv_nsec == 0);
-}
-
-/**
- * Create a snapshot object.
- *
- * Allocates and initializes a new snapshot object. In addition to allocating
- * space for the snapshot object itself, space is allocated for the snapshot
- * name. Both the name and time are then copied to the new object.
- */
-static struct osc_snapshot *
-osc_snapshot_create(const char *name, const struct timespec *tsp)
-{
- struct osc_snapshot *isp;
-
- isp = malloc(sizeof *isp);
- if (isp == NULL)
- goto out;
-
- isp->is_name = malloc(strlen(name) + 1);
- if (isp->is_name == NULL) {
- free(isp);
- isp = NULL;
- goto out;
- }
-
- strcpy(isp->is_name, name);
- isp->is_time = *tsp;
- isp->is_next = NULL;
-
- out:
- return isp;
-}
-
-/**
- * Destroy a snapshot object.
- *
- * Frees both the name and the snapshot object itself. Appropriate NULL
- * checking is performed because counting on free to do so is immoral.
- */
-static void
-osc_snapshot_destroy(struct osc_snapshot *isp)
-{
- if (isp != NULL) {
- if (isp->is_name != NULL)
- free(isp->is_name);
- free(isp);
- }
-}
-
-/**
- * Destroy all snapshots in the snapshot list.
- *
- * Calls osc_snapshot_destroy() on each snapshot in the list.
- */
-static void
-osc_snapshot_destroy_list(struct osc_snapshot *isp)
-{
- struct osc_snapshot *tmp;
-
- while (isp != NULL) {
- tmp = isp;
- isp = isp->is_next;
- osc_snapshot_destroy(tmp);
- }
-}
-
-/**
- * Compare two snapshot objects.
- *
- * Compare two snapshot objects. It is really just a wrapper for
- * osc_time_compare(), which compare the time value of the two snapshots.
- * N.B. time value in this context refers only to the tv_sec component.
- */
-static int
-osc_snapshot_compare(const void *vp1, const void *vp2)
-{
- const struct osc_snapshot *isp1 = vp1;
- const struct osc_snapshot *isp2 = vp2;
-
- return -osc_time_compare(&isp1->is_time, &isp2->is_time);
-}
-
-/**
- * Insert a snapshot into the snapshot set.
- *
- * Inserts a new snapshot into the snapshot set. The key for snapshots is
- * their creation time (it's actually the seconds portion of the creation
- * time). If a duplicate snapshot is found in the set, the new snapshot is
- * added to a linked list of snapshots for that second.
- */
-static void
-osc_snapshot_insert(struct osc_snapshot_ctx *oscp, const char *name,
- const struct timespec *tsp, int *errorp)
-{
- struct osc_snapshot *isp1;
- struct osc_snapshot **ispp;
-
- isp1 = osc_snapshot_create(name, tsp);
- if (isp1 == NULL) {
- *errorp = 1;
- return;
- }
-
- ispp = tsearch(isp1, &oscp->osc_set, osc_snapshot_compare);
- if (ispp != NULL) {
- struct osc_snapshot *isp2 = *ispp;
-
- /* If this is the only snapshot for this second, we're done. */
- if (isp2 == isp1)
- return;
-
- /* Collision: add the new snapshot to the list. */
- isp1->is_next = isp2->is_next;
- isp2->is_next = isp1;
-
- } else
- *errorp = 1;
-
-}
-
-/**
- * Process the next snapshot.
- *
- * Called for (almost) every entry in a .snapshot directory, ("." and ".." are
- * ignored in osc_process_snapshot_directory()). All other entries are passed
- * to osc_process_snapshot(), however. These entries can fall into one of two
- * categories: snapshot names and snapshot aliases. We only care about
- * snapshot names (as aliases are just redundant entries). Once it verifies
- * that name represents a valid snapshot name, it calls fstat() to get the
- * creation time of the snapshot and then calls osc_snapshot_insert() to add
- * this entry to the snapshot set.
- */
-static void
-osc_process_snapshot(struct osc_snapshot_ctx *oscp, const char *name,
- int *errorp)
-{
- int fd;
- struct stf_stat stf_stat;
- struct stat stbuf;
-
- fd = osc_get_names_directory_fd();
- if (fd == -1)
- goto out;
-
- fd = enc_openat(fd, name, ENC_DEFAULT, O_RDONLY);
- if (fd == -1)
- goto out;
-
- memset(&stf_stat, 0, sizeof stf_stat);
- if (ifs_snap_stat(fd, &stf_stat) == -1)
- goto out;
-
- if (stf_stat.sf_type != SF_STF)
- goto out;
-
- if (fstat(fd, &stbuf) == -1)
- goto out;
-
- osc_snapshot_insert(oscp, name, &stbuf.st_birthtimespec, errorp);
-
- out:
- if (fd != -1)
- close(fd);
-}
-
-/**
- * Process a snapshot directory.
- *
- * Opens the snapshot directory and calls osc_process_snapshot() for each
- * entry. (Well ok, "." and ".." are ignored.) The goal here is to add all
- * snapshots in the directory to the snapshot set.
- */
-static void
-osc_process_snapshot_directory(struct osc_snapshot_ctx *oscp, int *errorp)
-{
- int fd;
- struct stat stbuf;
- DIR *dirp;
- struct dirent *dp;
-
- fd = osc_get_names_directory_fd();
- if (fd == -1)
- goto out;
-
- if (fstat(fd, &stbuf) == -1)
- goto out;
-
- dirp = opendir(SNAPSHOT_DIRECTORY);
- if (dirp == NULL)
- goto out;
-
- for (;;) {
- dp = readdir(dirp);
- if (dp == NULL)
- break;
-
- if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' ||
- (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
- continue;
-
- osc_process_snapshot(oscp, dp->d_name, errorp);
- if (*errorp)
- break;
- }
-
- closedir(dirp);
-
- if (!*errorp)
- oscp->osc_mtime = stbuf.st_mtimespec;
-
- out:
- return;
-}
-
-/**
- * Initialize a snapshot context object.
- *
- * Clears all members of the context object.
- */
-static void
-osc_snapshot_ctx_init(struct osc_snapshot_ctx *oscp)
-{
- memset(oscp, 0, sizeof *oscp);
-}
-
-/**
- * Desoy a snapshot context object.
- *
- * Frees all snapshots associated with the snapshot context and then calls
- * osc_snapshot_ctx_init() to re-initialize the context object.
- */
-static void
-osc_snapshot_ctx_clean(struct osc_snapshot_ctx *oscp)
-{
- struct osc_snapshot *tmp;
-
- while (oscp->osc_set != NULL) {
- tmp = *(void **)oscp->osc_set;
- tdelete(tmp, &oscp->osc_set, osc_snapshot_compare);
- osc_snapshot_destroy_list(tmp);
- }
-
- osc_snapshot_ctx_init(oscp);
-}
-
-/**
- * Return the "global" snapshot context.
- *
- * We maintain a single open snapshot context. Return a pointer to it.
- */
-static struct osc_snapshot_ctx *
-osc_get_snapshot_ctx(void)
-{
- static struct osc_snapshot_ctx osc = { 0, { 0, 0 } };
-
- return &osc;
-}
-
-/**
- * Determine whether a snapshot context is still valid.
- *
- * "Valid" in this context means "reusable". We can re-use a previous
- * snapshot context iff we successfully built a previous snapshot context
- * and no snapshots have been created or deleted since we did so.
- * A "names" directory exists within our snapshot
- * implementation in which all snapshot names are entered. Each time a
- * snapshot is created or deleted, an entry must be added or removed.
- * When this happens the modification time on the "names" directory
- * changes. Therefore, a snapshot context is valid iff the context
- * pointer is non-NULL, the cached modification time is non-zero
- * (zero means uninitialized), and the modification time of the "names"
- * directory matches the cached value.
- */
-static int
-osc_snapshot_ctx_is_valid(struct osc_snapshot_ctx *oscp)
-{
- int fd;
- struct stat stbuf;
-
- if (oscp == NULL)
- return 0;
-
- if (osc_timespec_is_zero(&oscp->osc_mtime))
- return 0;
-
- fd = osc_get_names_directory_fd();
- if (fd == -1)
- return 0;
-
- if (fstat(fd, &stbuf) == -1)
- return 0;
-
- if (osc_timespec_compare(&oscp->osc_mtime, &stbuf.st_mtimespec) != 0)
- return 0;
-
- return 1;
-}
-
-/**
- * Create and initialize a directory context.
- *
- * Allocates a directory context from the heap and initializes it.
- */
-static struct osc_directory_ctx *
-osc_directory_ctx_create(void)
-{
- struct osc_directory_ctx *idcp;
-
- idcp = malloc(sizeof *idcp);
- if (idcp != NULL)
- memset(idcp, 0, sizeof *idcp);
-
- return idcp;
-}
-
-/**
- * Destroy a directory context.
- *
- * Frees any versions associated with the directory context and then frees the
- * context itself.
- */
-static void
-osc_directory_ctx_destroy(struct osc_directory_ctx *idcp)
-{
- int i;
-
- if (idcp == NULL)
- return;
-
- for (i = 0; i < idcp->idc_len; i++)
- free(idcp->idc_version[i]);
-
- free(idcp);
-}
-
-/**
- * Expand the size of a directory context's version list.
- *
- * If osc_directory_ctx_append_version() detects that the version list is too
- * small to accomodate a new version string, it called
- * osc_directory_ctx_expand_version_list() to expand the version list.
- */
-static void
-osc_directory_ctx_expand_version_list(struct osc_snapshot_ctx *oscp,
- struct osc_directory_ctx *idcp, int *errorp)
-{
- size_t size;
- char **cpp;
-
- size = idcp->idc_size * 2 ?: 1;
-
- cpp = realloc(idcp->idc_version, size * sizeof (char *));
- if (cpp == NULL) {
- *errorp = 1;
- return;
- }
-
- idcp->idc_size = size;
- idcp->idc_version = cpp;
-}
-
-/**
- * Append a new version to a directory context.
- *
- * Appends a snapshot version to the
- * directory context's version list.
- */
-static void
-osc_directory_ctx_append_version(struct osc_snapshot_ctx *oscp,
- struct osc_directory_ctx *idcp, const struct timespec *tsp, int *errorp)
-{
- char *cp;
- struct tm *tmp;
- char text[64];
-
- if (idcp->idc_len >= MAX_VERSIONS)
- return;
-
- if (idcp->idc_len >= idcp->idc_size) {
- osc_directory_ctx_expand_version_list(oscp, idcp, errorp);
- if (*errorp)
- return;
- }
-
- tmp = gmtime(&tsp->tv_sec);
- if (tmp == NULL) {
- *errorp = 1;
- return;
- }
-
- snprintf(text, sizeof text,
- "@GMT-%04u.%02u.%02u-%02u.%02u.%02u",
- tmp->tm_year + 1900,
- tmp->tm_mon + 1,
- tmp->tm_mday,
- tmp->tm_hour,
- tmp->tm_min,
- tmp->tm_sec);
-
- cp = malloc(strlen(text) + 1);
- if (cp == NULL) {
- *errorp = 1;
- return;
- }
-
- strcpy(cp, text);
-
- idcp->idc_version[idcp->idc_len++] = cp;
-}
-
-/**
- * Make a directory context from a snapshot context.
- *
- * Once a snapshot context has been completely filled-in,
- * osc_make_directory_ctx() is used to build a directory context from it. The
- * idea here is to create version for each snapshot in the snapshot set.
- */
-static void
-osc_make_directory_ctx(struct osc_snapshot_ctx *oscp,
- struct osc_directory_ctx *idcp, int *errorp)
-{
- static void
- walk(const void *vp, VISIT v, int level)
- {
- const struct osc_snapshot *isp;
-
- if ((v != postorder && v != leaf) || *errorp)
- return;
-
- isp = *(const struct osc_snapshot **)(u_long)vp;
-
- osc_directory_ctx_append_version(oscp, idcp, &isp->is_time,
- errorp);
- }
-
- twalk(oscp->osc_set, walk);
-}
-
-/**
- * Open a version directory.
- *
- * Opens a version directory. What this really means is that
- * osc_version_opendir() returns a handle to a directory context, which can be
- * used to retrieve version strings.
- */
-void *
-osc_version_opendir(void)
-{
- int error = 0;
- struct osc_directory_ctx *idcp;
- struct osc_snapshot_ctx *oscp;
-
- idcp = osc_directory_ctx_create();
- if (idcp == NULL)
- goto error_out;
-
- oscp = osc_get_snapshot_ctx();
-
- if (!osc_snapshot_ctx_is_valid(oscp)) {
- osc_snapshot_ctx_clean(oscp);
- osc_process_snapshot_directory(oscp, &error);
- if (error)
- goto error_out;
- }
-
- osc_make_directory_ctx(oscp, idcp, &error);
- if (error)
- goto error_out;
-
- goto out;
-
- error_out:
- if (idcp != NULL) {
- osc_directory_ctx_destroy(idcp);
- idcp = NULL;
- }
-
- out:
- return (void *)idcp;
-}
-
-/**
- * Read the next version directory entry.
- *
- * Returns the name of the next version in the version directory, or NULL if
- * we're at the end of the directory. What this really does is return the
- * next version from the version list stored in the directory context.
- */
-char *
-osc_version_readdir(void *vp)
-{
- struct osc_directory_ctx *idcp = vp;
-
- if (idcp == NULL)
- return NULL;
-
- if (idcp->idc_pos >= idcp->idc_len)
- return NULL;
-
- return idcp->idc_version[idcp->idc_pos++];
-}
-
-/**
- * Close the version directory.
- *
- * Destroys the underlying directory context.
- */
-void
-osc_version_closedir(void *vp)
-{
- struct osc_directory_ctx *idcp = vp;
-
- if (idcp != NULL)
- osc_directory_ctx_destroy(idcp);
-}
-
-/**
- * Canonicalize a path.
- *
- * Converts paths of the form @GMT-.. to paths of the form ../.snapshot/..
- * It's not the prettiest routine I've ever written, but what the heck?
- */
-char *
-osc_canonicalize_path(const char *path, char *snap_component)
-{
- int error = 0;
- struct osc_snapshot_ctx *oscp;
- struct tm tm;
- int n;
- struct osc_snapshot is;
- struct osc_snapshot **ispp;
- struct osc_snapshot *isp;
- char *cpath = NULL;
- char *cpath2 = NULL;
- const char *snap_component_orig = snap_component;
- struct stat sb;
-
- oscp = osc_get_snapshot_ctx();
-
- if (!osc_snapshot_ctx_is_valid(oscp)) {
- osc_snapshot_ctx_clean(oscp);
- osc_process_snapshot_directory(oscp, &error);
- if (error)
- goto out;
- }
-
- memset(&tm, 0, sizeof tm);
- n = sscanf(snap_component,
- "@GMT-%4u.%2u.%2u-%2u.%2u.%2u",
- &tm.tm_year,
- &tm.tm_mon,
- &tm.tm_mday,
- &tm.tm_hour,
- &tm.tm_min,
- &tm.tm_sec);
- if (n != 6)
- goto out;
-
- tm.tm_year -= 1900;
- tm.tm_mon -= 1;
-
- is.is_name = NULL;
- is.is_time.tv_sec = timegm(&tm);
- is.is_time.tv_nsec = 0;
-
- ispp = tfind(&is, &oscp->osc_set, osc_snapshot_compare);
- if (ispp == NULL)
- goto out;
- isp = *ispp;
-
- /* Determine the path after "@GMT-..." */
- while (*snap_component != '/' && *snap_component != '\0')
- snap_component++;
-
- while (*snap_component == '/')
- snap_component++;
-
- cpath = malloc(strlen(SNAPSHOT_DIRECTORY) + strlen(isp->is_name) +
- strlen(path) + 3);
-
- if (cpath == NULL)
- goto out;
-
- /*
- * Use the first snapshot that has a successful stat for the requested
- * path.
- */
- while (true) {
-
- sprintf(cpath, "%s/%s", SNAPSHOT_DIRECTORY, isp->is_name);
-
- /* Append path before "@GMT-..." */
- if (snap_component_orig != path) {
- strcat(cpath, "/");
- strncat(cpath, path, snap_component_orig - path);
- }
-
- /* Append path after "@GMT-..." */
- if (*snap_component != '\0') {
- strcat(cpath, "/");
- strcat(cpath, snap_component);
- }
-
- /* If there is a valid snapshot for this file, we're done. */
- if (stat(cpath, &sb) == 0)
- break;
-
- /* Try the next snapshot. If this was the last one, give up. */
- isp = isp->is_next;
- if (isp == NULL)
- break;
-
- /* If the realloc fails, give up. */
- cpath2 = realloc(cpath, strlen(SNAPSHOT_DIRECTORY) +
- strlen(isp->is_name) + strlen(path) + 3);
- if (cpath2 == NULL)
- break;
- cpath = cpath2;
- }
-
- out:
- return cpath;
-}
diff --git a/source3/modules/onefs_shadow_copy.h b/source3/modules/onefs_shadow_copy.h
deleted file mode 100644
index 6415a4be1a..0000000000
--- a/source3/modules/onefs_shadow_copy.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Unix SMB/CIFS implementation.
- *
- * OneFS shadow copy implementation that utilizes the file system's native
- * snapshot support.
- *
- * Copyright (C) Dave Richards, 2007
- * Copyright (C) Tim Prouty, 2009
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef ONEFS_SHADOW_COPY_H
-#define ONEFS_SHADOW_COPY_H
-
-void *osc_version_opendir(void);
-char *osc_version_readdir(void *vp);
-void osc_version_closedir(void *vp);
-char *osc_canonicalize_path(const char *path, char *snap_component);
-
-#endif /* ONEFS_SHADOW_COPY_H */
diff --git a/source3/modules/onefs_streams.c b/source3/modules/onefs_streams.c
deleted file mode 100644
index 0a1d98c809..0000000000
--- a/source3/modules/onefs_streams.c
+++ /dev/null
@@ -1,771 +0,0 @@
-/*
- * Unix SMB/CIFS implementation.
- *
- * Support for OneFS Alternate Data Streams
- *
- * Copyright (C) Tim Prouty, 2008
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "includes.h"
-#include "smbd/smbd.h"
-#include "onefs.h"
-#include "onefs_config.h"
-
-#include <sys/isi_enc.h>
-
-NTSTATUS onefs_stream_prep_smb_fname(TALLOC_CTX *ctx,
- const struct smb_filename *smb_fname_in,
- struct smb_filename **smb_fname_out)
-{
- char *stream_name = NULL;
- NTSTATUS status;
-
- /*
- * Only attempt to strip off the trailing :$DATA if there is an actual
- * stream there. If it is the default stream, the smb_fname_out will
- * just have a NULL stream so the base file is opened.
- */
- if (smb_fname_in->stream_name &&
- !is_ntfs_default_stream_smb_fname(smb_fname_in)) {
- char *str_tmp = smb_fname_in->stream_name;
-
- /* First strip off the leading ':' */
- if (str_tmp[0] == ':') {
- str_tmp++;
- }
-
- /* Create a new copy of the stream_name. */
- stream_name = talloc_strdup(ctx, str_tmp);
- if (stream_name == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- /* Strip off the :$DATA if one exists. */
- str_tmp = strrchr_m(stream_name, ':');
- if (str_tmp) {
- if (strcasecmp_m(str_tmp, ":$DATA") != 0) {
- return NT_STATUS_INVALID_PARAMETER;
- }
- str_tmp[0] = '\0';
- }
- }
-
- /*
- * If there was a stream that wasn't the default stream the leading
- * colon and trailing :$DATA has now been stripped off. Create a new
- * smb_filename to pass back.
- */
- status = create_synthetic_smb_fname(ctx, smb_fname_in->base_name,
- stream_name, &smb_fname_in->st,
- smb_fname_out);
- TALLOC_FREE(stream_name);
-
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(5, ("Failed to prep stream name for %s: %s\n",
- *smb_fname_out ?
- smb_fname_str_dbg(*smb_fname_out) : "NULL",
- nt_errstr(status)));
- }
- return status;
-}
-
-int onefs_close(vfs_handle_struct *handle, struct files_struct *fsp)
-{
- int ret2, ret = 0;
-
- if (fsp->base_fsp) {
- ret = SMB_VFS_NEXT_CLOSE(handle, fsp->base_fsp);
- }
- ret2 = SMB_VFS_NEXT_CLOSE(handle, fsp);
-
- return ret ? ret : ret2;
-}
-
-/*
- * Get the ADS directory fd for a file.
- */
-static int get_stream_dir_fd(connection_struct *conn, const char *base,
- int *base_fdp)
-{
- int base_fd;
- int dir_fd;
- int saved_errno;
-
- DEBUG(10, ("Getting stream directory fd: %s (%d)\n", base,
- base_fdp ? *base_fdp : -1));
-
- /* If a valid base_fdp was given, use it. */
- if (base_fdp && *base_fdp >= 0) {
- base_fd = *base_fdp;
- } else {
- base_fd = onefs_sys_create_file(conn,
- -1,
- base,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- INTERNAL_OPEN_ONLY,
- 0,
- NULL,
- 0,
- NULL);
- if (base_fd < 0) {
- DEBUG(5, ("Failed getting base fd: %s\n",
- strerror(errno)));
- return -1;
- }
- }
-
- /* Open the ADS directory. */
- dir_fd = onefs_sys_create_file(conn,
- base_fd,
- ".",
- 0,
- FILE_READ_DATA,
- 0,
- 0,
- 0,
- 0,
- INTERNAL_OPEN_ONLY,
- 0,
- NULL,
- 0,
- NULL);
-
- /* Close base_fd if it's not need or on error. */
- if (!base_fdp || dir_fd < 0) {
- saved_errno = errno;
- close(base_fd);
- errno = saved_errno;
- }
-
- /* Set the out base_fdp if successful and it was requested. */
- if (base_fdp && dir_fd >= 0) {
- *base_fdp = base_fd;
- }
-
- if (dir_fd < 0) {
- DEBUG(5, ("Failed getting stream directory fd: %s\n",
- strerror(errno)));
- }
-
- return dir_fd;
-}
-
-int onefs_rename(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname_src,
- const struct smb_filename *smb_fname_dst)
-{
- struct smb_filename *smb_fname_src_onefs = NULL;
- struct smb_filename *smb_fname_dst_onefs = NULL;
- NTSTATUS status;
- int saved_errno;
- int dir_fd = -1;
- int ret = -1;
-
- START_PROFILE(syscall_rename_at);
-
- if (!is_ntfs_stream_smb_fname(smb_fname_src) &&
- !is_ntfs_stream_smb_fname(smb_fname_dst)) {
- ret = SMB_VFS_NEXT_RENAME(handle, smb_fname_src,
- smb_fname_dst);
- goto done;
- }
-
- /* For now don't allow renames from or to the default stream. */
- if (is_ntfs_default_stream_smb_fname(smb_fname_src) ||
- is_ntfs_default_stream_smb_fname(smb_fname_dst)) {
- DEBUG(3, ("Unable to rename to/from a default stream: %s -> "
- "%s\n", smb_fname_str_dbg(smb_fname_src),
- smb_fname_str_dbg(smb_fname_dst)));
- errno = ENOSYS;
- goto done;
- }
-
- /* prep stream smb_filename structs. */
- status = onefs_stream_prep_smb_fname(talloc_tos(), smb_fname_src,
- &smb_fname_src_onefs);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
- goto done;
- }
- status = onefs_stream_prep_smb_fname(talloc_tos(), smb_fname_dst,
- &smb_fname_dst_onefs);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
- goto done;
- }
-
- dir_fd = get_stream_dir_fd(handle->conn, smb_fname_src->base_name,
- NULL);
- if (dir_fd < -1) {
- goto done;
- }
-
- DEBUG(8, ("onefs_rename called for %s => %s\n",
- smb_fname_str_dbg(smb_fname_src_onefs),
- smb_fname_str_dbg(smb_fname_dst_onefs)));
-
- /* Handle rename of stream to default stream specially. */
- if (smb_fname_dst_onefs->stream_name == NULL) {
- ret = enc_renameat(dir_fd, smb_fname_src_onefs->stream_name,
- ENC_DEFAULT, AT_FDCWD,
- smb_fname_dst_onefs->base_name,
- ENC_DEFAULT);
- } else {
- ret = enc_renameat(dir_fd, smb_fname_src_onefs->stream_name,
- ENC_DEFAULT, dir_fd,
- smb_fname_dst_onefs->stream_name,
- ENC_DEFAULT);
- }
-
- done:
- END_PROFILE(syscall_rename_at);
- TALLOC_FREE(smb_fname_src_onefs);
- TALLOC_FREE(smb_fname_dst_onefs);
-
- saved_errno = errno;
- if (dir_fd >= 0) {
- close(dir_fd);
- }
- errno = saved_errno;
- return ret;
-}
-
-/*
- * Merge a base file's sbuf into the a streams's sbuf.
- */
-static void merge_stat(SMB_STRUCT_STAT *stream_sbuf,
- const SMB_STRUCT_STAT *base_sbuf)
-{
- int dos_flags = (UF_DOS_NOINDEX | UF_DOS_ARCHIVE |
- UF_DOS_HIDDEN | UF_DOS_RO | UF_DOS_SYSTEM);
- stream_sbuf->st_ex_mtime = base_sbuf->st_ex_mtime;
- stream_sbuf->st_ex_ctime = base_sbuf->st_ex_ctime;
- stream_sbuf->st_ex_atime = base_sbuf->st_ex_atime;
- stream_sbuf->st_ex_flags &= ~dos_flags;
- stream_sbuf->st_ex_flags |= base_sbuf->st_ex_flags & dos_flags;
-}
-
-/* fake timestamps */
-static void onefs_adjust_stat_time(struct connection_struct *conn,
- const char *fname, SMB_STRUCT_STAT *sbuf)
-{
- struct onefs_vfs_share_config cfg;
- struct timeval tv_now = {0, 0};
- bool static_mtime = False;
- bool static_atime = False;
-
- if (!onefs_get_config(SNUM(conn),
- ONEFS_VFS_CONFIG_FAKETIMESTAMPS, &cfg)) {
- return;
- }
-
- if (IS_MTIME_STATIC_PATH(conn, &cfg, fname)) {
- sbuf->st_ex_mtime = sbuf->st_ex_btime;
- static_mtime = True;
- }
- if (IS_ATIME_STATIC_PATH(conn, &cfg, fname)) {
- sbuf->st_ex_atime = sbuf->st_ex_btime;
- static_atime = True;
- }
-
- if (IS_CTIME_NOW_PATH(conn, &cfg, fname)) {
- if (cfg.ctime_slop < 0) {
- sbuf->st_ex_btime.tv_sec = INT_MAX - 1;
- } else {
- GetTimeOfDay(&tv_now);
- sbuf->st_ex_btime.tv_sec = tv_now.tv_sec +
- cfg.ctime_slop;
- }
- }
-
- if (!static_mtime && IS_MTIME_NOW_PATH(conn,&cfg,fname)) {
- if (cfg.mtime_slop < 0) {
- sbuf->st_ex_mtime.tv_sec = INT_MAX - 1;
- } else {
- if (tv_now.tv_sec == 0)
- GetTimeOfDay(&tv_now);
- sbuf->st_ex_mtime.tv_sec = tv_now.tv_sec +
- cfg.mtime_slop;
- }
- }
- if (!static_atime && IS_ATIME_NOW_PATH(conn,&cfg,fname)) {
- if (cfg.atime_slop < 0) {
- sbuf->st_ex_atime.tv_sec = INT_MAX - 1;
- } else {
- if (tv_now.tv_sec == 0)
- GetTimeOfDay(&tv_now);
- sbuf->st_ex_atime.tv_sec = tv_now.tv_sec +
- cfg.atime_slop;
- }
- }
-}
-
-static int stat_stream(struct connection_struct *conn, const char *base,
- const char *stream, SMB_STRUCT_STAT *sbuf, int flags)
-{
- SMB_STRUCT_STAT base_sbuf;
- int base_fd = -1, dir_fd, ret, saved_errno;
-
- dir_fd = get_stream_dir_fd(conn, base, &base_fd);
- if (dir_fd < 0) {
- return -1;
- }
-
- /* Stat the stream. */
- ret = onefs_sys_fstat_at(dir_fd, stream, sbuf, flags);
- if (ret != -1) {
- DEBUG(10, ("stat of stream '%s' failed: %s\n", stream,
- strerror(errno)));
- } else {
- /* Now stat the base file and merge the results. */
- ret = onefs_sys_fstat(base_fd, &base_sbuf);
- if (ret != -1) {
- merge_stat(sbuf, &base_sbuf);
- }
- }
-
- saved_errno = errno;
- close(dir_fd);
- close(base_fd);
- errno = saved_errno;
- return ret;
-}
-
-int onefs_stat(vfs_handle_struct *handle, struct smb_filename *smb_fname)
-{
- struct smb_filename *smb_fname_onefs = NULL;
- NTSTATUS status;
- int ret;
-
- status = onefs_stream_prep_smb_fname(talloc_tos(), smb_fname,
- &smb_fname_onefs);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
- return -1;
- }
-
- /*
- * If the smb_fname has no stream or is :$DATA, then just stat the
- * base stream. Otherwise stat the stream.
- */
- if (!is_ntfs_stream_smb_fname(smb_fname_onefs)) {
- ret = onefs_sys_stat(smb_fname_onefs->base_name,
- &smb_fname->st);
- } else {
- ret = stat_stream(handle->conn, smb_fname_onefs->base_name,
- smb_fname_onefs->stream_name, &smb_fname->st,
- 0);
- }
-
- onefs_adjust_stat_time(handle->conn, smb_fname->base_name,
- &smb_fname->st);
-
- TALLOC_FREE(smb_fname_onefs);
-
- return ret;
-}
-
-int onefs_fstat(vfs_handle_struct *handle, struct files_struct *fsp,
- SMB_STRUCT_STAT *sbuf)
-{
- SMB_STRUCT_STAT base_sbuf;
- int ret;
-
- /* Stat the stream, by calling next_fstat on the stream's fd. */
- ret = onefs_sys_fstat(fsp->fh->fd, sbuf);
- if (ret == -1) {
- return ret;
- }
-
- /* Stat the base file and merge the results. */
- if (fsp != NULL && fsp->base_fsp != NULL) {
- ret = onefs_sys_fstat(fsp->base_fsp->fh->fd, &base_sbuf);
- if (ret != -1) {
- merge_stat(sbuf, &base_sbuf);
- }
- }
-
- onefs_adjust_stat_time(handle->conn, fsp->fsp_name->base_name, sbuf);
- return ret;
-}
-
-int onefs_lstat(vfs_handle_struct *handle, struct smb_filename *smb_fname)
-{
- struct smb_filename *smb_fname_onefs = NULL;
- NTSTATUS status;
- int ret;
-
- status = onefs_stream_prep_smb_fname(talloc_tos(), smb_fname,
- &smb_fname_onefs);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
- return -1;
- }
-
- /*
- * If the smb_fname has no stream or is :$DATA, then just stat the
- * base stream. Otherwise stat the stream.
- */
- if (!is_ntfs_stream_smb_fname(smb_fname_onefs)) {
- ret = onefs_sys_lstat(smb_fname_onefs->base_name,
- &smb_fname->st);
- } else {
- ret = stat_stream(handle->conn, smb_fname_onefs->base_name,
- smb_fname_onefs->stream_name, &smb_fname->st,
- AT_SYMLINK_NOFOLLOW);
- }
-
- onefs_adjust_stat_time(handle->conn, smb_fname->base_name,
- &smb_fname->st);
-
- TALLOC_FREE(smb_fname_onefs);
-
- return ret;
-}
-
-int onefs_unlink(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname)
-{
- struct smb_filename *smb_fname_onefs = NULL;
- int ret;
- int dir_fd, saved_errno;
- NTSTATUS status;
-
- /* Not a stream. */
- if (!is_ntfs_stream_smb_fname(smb_fname)) {
- return SMB_VFS_NEXT_UNLINK(handle, smb_fname);
- }
-
- status = onefs_stream_prep_smb_fname(talloc_tos(), smb_fname,
- &smb_fname_onefs);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
- return -1;
- }
-
- /* Default stream (the ::$DATA was just stripped off). */
- if (!is_ntfs_stream_smb_fname(smb_fname_onefs)) {
- ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname_onefs);
- goto out;
- }
-
- dir_fd = get_stream_dir_fd(handle->conn, smb_fname_onefs->base_name,
- NULL);
- if (dir_fd < 0) {
- ret = -1;
- goto out;
- }
-
- ret = enc_unlinkat(dir_fd, smb_fname_onefs->stream_name, ENC_DEFAULT,
- 0);
-
- saved_errno = errno;
- close(dir_fd);
- errno = saved_errno;
- out:
- TALLOC_FREE(smb_fname_onefs);
- return ret;
-}
-
-int onefs_vtimes_streams(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- int flags, struct timespec times[3])
-{
- struct smb_filename *smb_fname_onefs = NULL;
- int ret;
- int dirfd;
- int saved_errno;
- NTSTATUS status;
-
- START_PROFILE(syscall_ntimes);
-
- if (!is_ntfs_stream_smb_fname(smb_fname)) {
- ret = vtimes(smb_fname->base_name, times, flags);
- return ret;
- }
-
- status = onefs_stream_prep_smb_fname(talloc_tos(), smb_fname,
- &smb_fname_onefs);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
- return -1;
- }
-
- /* Default stream (the ::$DATA was just stripped off). */
- if (!is_ntfs_stream_smb_fname(smb_fname_onefs)) {
- ret = vtimes(smb_fname_onefs->base_name, times, flags);
- goto out;
- }
-
- dirfd = get_stream_dir_fd(handle->conn, smb_fname->base_name, NULL);
- if (dirfd < -1) {
- ret = -1;
- goto out;
- }
-
- ret = enc_vtimesat(dirfd, smb_fname_onefs->stream_name, ENC_DEFAULT,
- times, flags);
-
- saved_errno = errno;
- close(dirfd);
- errno = saved_errno;
-
- out:
- END_PROFILE(syscall_ntimes);
- TALLOC_FREE(smb_fname_onefs);
- return ret;
-}
-
-/*
- * Streaminfo enumeration functionality
- */
-struct streaminfo_state {
- TALLOC_CTX *mem_ctx;
- vfs_handle_struct *handle;
- unsigned int num_streams;
- struct stream_struct *streams;
- NTSTATUS status;
-};
-
-static bool add_one_stream(TALLOC_CTX *mem_ctx, unsigned int *num_streams,
- struct stream_struct **streams,
- const char *name, off_t size,
- off_t alloc_size)
-{
- struct stream_struct *tmp;
-
- tmp = talloc_realloc(mem_ctx, *streams, struct stream_struct,
- (*num_streams)+1);
- if (tmp == NULL) {
- return false;
- }
-
- tmp[*num_streams].name = talloc_asprintf(mem_ctx, ":%s:%s", name,
- "$DATA");
- if (tmp[*num_streams].name == NULL) {
- return false;
- }
-
- tmp[*num_streams].size = size;
- tmp[*num_streams].alloc_size = alloc_size;
-
- *streams = tmp;
- *num_streams += 1;
- return true;
-}
-
-static NTSTATUS walk_onefs_streams(connection_struct *conn, files_struct *fsp,
- const char *fname,
- struct streaminfo_state *state,
- SMB_STRUCT_STAT *base_sbuf)
-{
- NTSTATUS status = NT_STATUS_OK;
- bool opened_base_fd = false;
- int base_fd = -1;
- int dir_fd = -1;
- int stream_fd = -1;
- int ret;
- DIR *dirp = NULL;
- struct dirent *dp = NULL;
- files_struct fake_fs;
- struct fd_handle fake_fh;
- SMB_STRUCT_STAT stream_sbuf;
-
- ZERO_STRUCT(fake_fh);
- ZERO_STRUCT(fake_fs);
-
- /* If the base file is already open, use its fd. */
- if ((fsp != NULL) && (fsp->fh->fd != -1)) {
- base_fd = fsp->fh->fd;
- } else {
- opened_base_fd = true;
- }
-
- dir_fd = get_stream_dir_fd(conn, fname, &base_fd);
- if (dir_fd < 0) {
- return map_nt_error_from_unix(errno);
- }
-
- /* Open the ADS directory. */
- if ((dirp = fdopendir(dir_fd)) == NULL) {
- DEBUG(0, ("Error on opendir %s. errno=%d (%s)\n",
- fname, errno, strerror(errno)));
- status = map_nt_error_from_unix(errno);
- goto out;
- }
-
- /* Initialize the dir state struct and add it to the list.
- * This is a layer violation, and really should be handled by a
- * VFS_FDOPENDIR() call which would properly setup the dir state.
- * But since this is all within the onefs.so module, we cheat for
- * now and call directly into the readdirplus code.
- * NOTE: This state MUST be freed by a proper VFS_CLOSEDIR() call. */
- ret = onefs_rdp_add_dir_state(conn, dirp);
- if (ret) {
- DEBUG(0, ("Error adding dir_state to the list\n"));
- status = map_nt_error_from_unix(errno);
- goto out;
- }
-
- fake_fs.conn = conn;
- fake_fs.fh = &fake_fh;
- status = create_synthetic_smb_fname(talloc_tos(), fname, NULL, NULL,
- &fake_fs.fsp_name);
- if (!NT_STATUS_IS_OK(status)) {
- goto out;
- }
-
- /* Iterate over the streams in the ADS directory. */
- while ((dp = SMB_VFS_READDIR(conn, dirp, NULL)) != NULL) {
- /* Skip the "." and ".." entries */
- if ((strcmp(dp->d_name, ".") == 0) ||
- (strcmp(dp->d_name, "..") == 0))
- continue;
-
- /* Open actual stream */
- if ((stream_fd = onefs_sys_create_file(conn,
- base_fd,
- dp->d_name,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- INTERNAL_OPEN_ONLY,
- 0,
- NULL,
- 0,
- NULL)) == -1) {
- DEBUG(0, ("Error opening stream %s:%s. "
- "errno=%d (%s)\n", fname, dp->d_name, errno,
- strerror(errno)));
- continue;
- }
-
- /* Figure out the stat info. */
- fake_fh.fd = stream_fd;
- ret = SMB_VFS_FSTAT(&fake_fs, &stream_sbuf);
- close(stream_fd);
-
- if (ret) {
- DEBUG(0, ("Error fstating stream %s:%s. "
- "errno=%d (%s)\n", fname, dp->d_name, errno,
- strerror(errno)));
- continue;
- }
-
- merge_stat(&stream_sbuf, base_sbuf);
-
- if (!add_one_stream(state->mem_ctx,
- &state->num_streams, &state->streams,
- dp->d_name, stream_sbuf.st_ex_size,
- SMB_VFS_GET_ALLOC_SIZE(conn, NULL,
- &stream_sbuf))) {
- state->status = NT_STATUS_NO_MEMORY;
- break;
- }
- }
-
-out:
- /* Cleanup everything that was opened. */
- if (dirp != NULL) {
- SMB_VFS_CLOSEDIR(conn, dirp);
- }
- if (dir_fd >= 0) {
- close(dir_fd);
- }
- if (opened_base_fd) {
- SMB_ASSERT(base_fd >= 0);
- close(base_fd);
- }
-
- TALLOC_FREE(fake_fs.fsp_name);
- return status;
-}
-
-NTSTATUS onefs_streaminfo(vfs_handle_struct *handle,
- struct files_struct *fsp,
- const char *fname,
- TALLOC_CTX *mem_ctx,
- unsigned int *num_streams,
- struct stream_struct **streams)
-{
- SMB_STRUCT_STAT sbuf;
- int ret;
- NTSTATUS status;
- struct streaminfo_state state;
-
- /* Get a valid stat. */
- if ((fsp != NULL) && (fsp->fh->fd != -1)) {
- ret = SMB_VFS_FSTAT(fsp, &sbuf);
- } else {
- struct smb_filename *smb_fname = NULL;
-
- status = create_synthetic_smb_fname(talloc_tos(), fname, NULL,
- NULL, &smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- ret = SMB_VFS_STAT(handle->conn, smb_fname);
-
- sbuf = smb_fname->st;
-
- TALLOC_FREE(smb_fname);
- }
-
- if (ret == -1) {
- return map_nt_error_from_unix(errno);
- }
-
- state.streams = *pstreams;
- state.num_streams = *pnum_streams;
-
- if (lp_parm_bool(SNUM(handle->conn), PARM_ONEFS_TYPE,
- PARM_IGNORE_STREAMS, PARM_IGNORE_STREAMS_DEFAULT)) {
- goto out;
- }
-
- state.mem_ctx = mem_ctx;
- state.handle = handle;
- state.status = NT_STATUS_OK;
-
- /* If there are more streams, add them too. */
- if (sbuf.st_ex_flags & UF_HASADS) {
-
- status = walk_onefs_streams(handle->conn, fsp, fname,
- &state, &sbuf);
-
- if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(state.streams);
- return status;
- }
-
- if (!NT_STATUS_IS_OK(state.status)) {
- TALLOC_FREE(state.streams);
- return state.status;
- }
- }
- out:
- *num_streams = state.num_streams;
- *streams = state.streams;
- return SMB_VFS_NEXT_STREAMINFO(handle, fsp, fname, mem_ctx, pnum_streams, pstreams);
-}
diff --git a/source3/modules/onefs_system.c b/source3/modules/onefs_system.c
deleted file mode 100644
index 07272cc86b..0000000000
--- a/source3/modules/onefs_system.c
+++ /dev/null
@@ -1,782 +0,0 @@
-/*
- * Unix SMB/CIFS implementation.
- * Support for OneFS system interfaces.
- *
- * Copyright (C) Tim Prouty, 2008
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "includes.h"
-#include "smbd/smbd.h"
-#include "onefs.h"
-#include "onefs_config.h"
-#include "oplock_onefs.h"
-
-#include <ifs/ifs_syscalls.h>
-#include <isi_acl/isi_acl_util.h>
-#include <sys/isi_acl.h>
-
-/*
- * Initialize the sm_lock struct before passing it to ifs_createfile.
- */
-static void smlock_init(connection_struct *conn, struct sm_lock *sml,
- bool isexe, uint32_t access_mask, uint32_t share_access,
- uint32_t create_options)
-{
- sml->sm_type.doc = false;
- sml->sm_type.isexe = isexe;
- sml->sm_type.statonly = is_stat_open(access_mask);
- sml->sm_type.access_mask = access_mask;
- sml->sm_type.share_access = share_access;
-
- /*
- * private_options was previously used for DENY_DOS/DENY_FCB checks in
- * the kernel, but are now properly handled by fcb_or_dos_open. In
- * these cases, ifs_createfile will return a sharing violation, which
- * gives fcb_or_dos_open the chance to open a duplicate file handle.
- */
- sml->sm_type.private_options = 0;
-
- /* 1 second delay is handled in onefs_open.c by deferring the open */
- sml->sm_timeout = timeval_set(0, 0);
-}
-
-static void smlock_dump(int debuglevel, const struct sm_lock *sml)
-{
- if (sml == NULL) {
- DEBUG(debuglevel, ("sml == NULL\n"));
- return;
- }
-
- DEBUG(debuglevel,
- ("smlock: doc=%s, isexec=%s, statonly=%s, access_mask=0x%x, "
- "share_access=0x%x, private_options=0x%x timeout=%d/%d\n",
- sml->sm_type.doc ? "True" : "False",
- sml->sm_type.isexe ? "True" : "False",
- sml->sm_type.statonly ? "True" : "False",
- sml->sm_type.access_mask,
- sml->sm_type.share_access,
- sml->sm_type.private_options,
- (int)sml->sm_timeout.tv_sec,
- (int)sml->sm_timeout.tv_usec));
-}
-
-/**
- * External interface to ifs_createfile
- */
-int onefs_sys_create_file(connection_struct *conn,
- int base_fd,
- const char *path,
- uint32_t access_mask,
- uint32_t open_access_mask,
- uint32_t share_access,
- uint32_t create_options,
- int flags,
- mode_t mode,
- int oplock_request,
- uint64_t id,
- struct security_descriptor *sd,
- uint32_t dos_flags,
- int *granted_oplock)
-{
- struct sm_lock sml, *psml = NULL;
- enum oplock_type onefs_oplock;
- enum oplock_type onefs_granted_oplock = OPLOCK_NONE;
- struct ifs_security_descriptor ifs_sd = {}, *pifs_sd = NULL;
- uint32_t sec_info_effective = 0;
- int ret_fd = -1;
- uint32_t onefs_dos_attributes;
- struct ifs_createfile_flags cf_flags = CF_FLAGS_NONE;
- char *mapped_name = NULL;
- NTSTATUS result;
-
- START_PROFILE(syscall_createfile);
-
- /* Translate the name to UNIX before calling ifs_createfile */
- mapped_name = talloc_strdup(talloc_tos(), path);
- if (mapped_name == NULL) {
- errno = ENOMEM;
- goto out;
- }
- result = SMB_VFS_TRANSLATE_NAME(conn, &mapped_name,
- vfs_translate_to_unix);
- if (!NT_STATUS_IS_OK(result)) {
- goto out;
- }
-
- /* Setup security descriptor and get secinfo. */
- if (sd != NULL) {
- NTSTATUS status;
- uint32_t sec_info_sent = 0;
-
- sec_info_sent = (get_sec_info(sd) & IFS_SEC_INFO_KNOWN_MASK);
-
- status = onefs_samba_sd_to_sd(sec_info_sent, sd, &ifs_sd,
- SNUM(conn), &sec_info_effective);
-
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("SD initialization failure: %s\n",
- nt_errstr(status)));
- errno = EINVAL;
- goto out;
- }
-
- pifs_sd = &ifs_sd;
- }
-
- /* Stripping off private bits will be done for us. */
- onefs_oplock = onefs_samba_oplock_to_oplock(oplock_request);
-
- if (!lp_oplocks(SNUM(conn))) {
- SMB_ASSERT(onefs_oplock == OPLOCK_NONE);
- }
-
- /* Convert samba dos flags to UF_DOS_* attributes. */
- onefs_dos_attributes = dos_attributes_to_stat_dos_flags(dos_flags);
-
- /**
- * Deal with kernel creating Default ACLs. (Isilon bug 47447.)
- *
- * 1) "nt acl support = no", default_acl = no
- * 2) "inherit permissions = yes", default_acl = no
- */
- if (lp_nt_acl_support(SNUM(conn)) && !lp_inherit_perms(SNUM(conn)))
- cf_flags = cf_flags_or(cf_flags, CF_FLAGS_DEFAULT_ACL);
-
- /*
- * Some customer workflows require the execute bit to be ignored.
- */
- if (lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE,
- PARM_ALLOW_EXECUTE_ALWAYS,
- PARM_ALLOW_EXECUTE_ALWAYS_DEFAULT) &&
- (open_access_mask & FILE_EXECUTE)) {
-
- DEBUG(3, ("Stripping execute bit from %s: (0x%x)\n", mapped_name,
- open_access_mask));
-
- /* Strip execute. */
- open_access_mask &= ~FILE_EXECUTE;
-
- /*
- * Add READ_DATA, so we're not left with desired_access=0. An
- * execute call should imply the client will read the data.
- */
- open_access_mask |= FILE_READ_DATA;
-
- DEBUGADD(3, ("New stripped access mask: 0x%x\n",
- open_access_mask));
- }
-
- DEBUG(10,("onefs_sys_create_file: base_fd = %d, fname = %s "
- "open_access_mask = 0x%x, flags = 0x%x, mode = 0%o, "
- "desired_oplock = %s, id = 0x%x, secinfo = 0x%x, sd = %p, "
- "dos_attributes = 0x%x, path = %s, "
- "default_acl=%s\n", base_fd, mapped_name,
- (unsigned int)open_access_mask,
- (unsigned int)flags,
- (unsigned int)mode,
- onefs_oplock_str(onefs_oplock),
- (unsigned int)id,
- sec_info_effective, sd,
- (unsigned int)onefs_dos_attributes, mapped_name,
- cf_flags_and_bool(cf_flags, CF_FLAGS_DEFAULT_ACL) ?
- "true" : "false"));
-
- /* Initialize smlock struct for files/dirs but not internal opens */
- if (!(oplock_request & INTERNAL_OPEN_ONLY)) {
- smlock_init(conn, &sml, is_executable(mapped_name), access_mask,
- share_access, create_options);
- psml = &sml;
- }
-
- smlock_dump(10, psml);
-
- ret_fd = ifs_createfile(base_fd, mapped_name,
- (enum ifs_ace_rights)open_access_mask, flags & ~O_ACCMODE, mode,
- onefs_oplock, id, psml, sec_info_effective, pifs_sd,
- onefs_dos_attributes, cf_flags, &onefs_granted_oplock);
-
- DEBUG(10,("onefs_sys_create_file(%s): ret_fd = %d, "
- "onefs_granted_oplock = %s\n",
- ret_fd < 0 ? strerror(errno) : "success", ret_fd,
- onefs_oplock_str(onefs_granted_oplock)));
-
- if (granted_oplock) {
- *granted_oplock =
- onefs_oplock_to_samba_oplock(onefs_granted_oplock);
- }
-
- out:
- END_PROFILE(syscall_createfile);
- aclu_free_sd(pifs_sd, false);
- TALLOC_FREE(mapped_name);
-
- return ret_fd;
-}
-
-/**
- * FreeBSD based sendfile implementation that allows for atomic semantics.
- */
-static ssize_t onefs_sys_do_sendfile(int tofd, int fromfd,
- const DATA_BLOB *header, off_t offset, size_t count, bool atomic)
-{
- size_t total=0;
- struct sf_hdtr hdr;
- struct iovec hdtrl;
- size_t hdr_len = 0;
- int flags = 0;
-
- if (atomic) {
- flags = SF_ATOMIC;
- }
-
- hdr.headers = &hdtrl;
- hdr.hdr_cnt = 1;
- hdr.trailers = NULL;
- hdr.trl_cnt = 0;
-
- /* Set up the header iovec. */
- if (header) {
- hdtrl.iov_base = (void *)header->data;
- hdtrl.iov_len = hdr_len = header->length;
- } else {
- hdtrl.iov_base = NULL;
- hdtrl.iov_len = 0;
- }
-
- total = count;
- while (total + hdtrl.iov_len) {
- off_t nwritten;
- int ret;
-
- /*
- * FreeBSD sendfile returns 0 on success, -1 on error.
- * Remember, the tofd and fromfd are reversed..... :-).
- * nwritten includes the header data sent.
- */
-
- do {
- ret = sendfile(fromfd, tofd, offset, total, &hdr,
- &nwritten, flags);
-#if defined(EWOULDBLOCK)
- } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
-#else
- } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
-#endif
-
- /* On error we're done. */
- if (ret == -1) {
- return -1;
- }
-
- /*
- * If this was an ATOMIC sendfile, nwritten doesn't
- * necessarily indicate an error. It could mean count > than
- * what sendfile can handle atomically (usually 64K) or that
- * there was a short read due to the file being truncated.
- */
- if (nwritten == 0) {
- return atomic ? 0 : -1;
- }
-
- /*
- * An atomic sendfile should never send partial data!
- */
- if (atomic && nwritten != total + hdtrl.iov_len) {
- DEBUG(0,("Atomic sendfile() sent partial data: "
- "%llu of %d\n", nwritten,
- total + hdtrl.iov_len));
- return -1;
- }
-
- /*
- * If this was a short (signal interrupted) write we may need
- * to subtract it from the header data, or null out the header
- * data altogether if we wrote more than hdtrl.iov_len bytes.
- * We change nwritten to be the number of file bytes written.
- */
-
- if (hdtrl.iov_base && hdtrl.iov_len) {
- if (nwritten >= hdtrl.iov_len) {
- nwritten -= hdtrl.iov_len;
- hdtrl.iov_base = NULL;
- hdtrl.iov_len = 0;
- } else {
- hdtrl.iov_base =
- (void *)((caddr_t)hdtrl.iov_base + nwritten);
- hdtrl.iov_len -= nwritten;
- nwritten = 0;
- }
- }
- total -= nwritten;
- offset += nwritten;
- }
- return count + hdr_len;
-}
-
-/**
- * Handles the subtleties of using sendfile with CIFS.
- */
-ssize_t onefs_sys_sendfile(connection_struct *conn, int tofd, int fromfd,
- const DATA_BLOB *header, off_t offset,
- size_t count)
-{
- bool atomic = false;
- ssize_t ret = 0;
-
- START_PROFILE_BYTES(syscall_sendfile, count);
-
- if (lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE,
- PARM_ATOMIC_SENDFILE,
- PARM_ATOMIC_SENDFILE_DEFAULT)) {
- atomic = true;
- }
-
- /* Try the sendfile */
- ret = onefs_sys_do_sendfile(tofd, fromfd, header, offset, count,
- atomic);
-
- /* If the sendfile wasn't atomic, we're done. */
- if (!atomic) {
- DEBUG(10, ("non-atomic sendfile read %ul bytes\n", ret));
- END_PROFILE(syscall_sendfile);
- return ret;
- }
-
- /*
- * Atomic sendfile takes care to not write anything to the socket
- * until all of the requested bytes have been read from the file.
- * There are two atomic cases that need to be handled.
- *
- * 1. The file was truncated causing less data to be read than was
- * requested. In this case, we return back to the caller to
- * indicate 0 bytes were written to the socket. This should
- * prompt the caller to fallback to the standard read path: read
- * the data, create a header that indicates how many bytes were
- * actually read, and send the header/data back to the client.
- *
- * This saves us from standard sendfile behavior of sending a
- * header promising more data then will actually be sent. The
- * only two options are to close the socket and kill the client
- * connection, or write a bunch of 0s. Closing the client
- * connection is bad because there could actually be multiple
- * sessions multiplexed from the same client that are all dropped
- * because of a truncate. Writing the remaining data as 0s also
- * isn't good, because the client will have an incorrect version
- * of the file. If the file is written back to the server, the 0s
- * will be written back. Fortunately, atomic sendfile allows us
- * to avoid making this choice in most cases.
- *
- * 2. One downside of atomic sendfile, is that there is a limit on
- * the number of bytes that can be sent atomically. The kernel
- * has a limited amount of mbuf space that it can read file data
- * into without exhausting the system's mbufs, so a buffer of
- * length xfsize is used. The xfsize at the time of writing this
- * is 64K. xfsize bytes are read from the file, and subsequently
- * written to the socket. This makes it impossible to do the
- * sendfile atomically for a byte count > xfsize.
- *
- * To cope with large requests, atomic sendfile returns -1 with
- * errno set to E2BIG. Since windows maxes out at 64K writes,
- * this is currently only a concern with non-windows clients.
- * Posix extensions allow the full 24bit bytecount field to be
- * used in ReadAndX, and clients such as smbclient and the linux
- * cifs client can request up to 16MB reads! There are a few
- * options for handling large sendfile requests.
- *
- * a. Fall back to the standard read path. This is unacceptable
- * because it would require prohibitively large mallocs.
- *
- * b. Fall back to using samba's fake_send_file which emulates
- * the kernel sendfile in userspace. This still has the same
- * problem of sending the header before all of the data has
- * been read, so it doesn't buy us anything, and has worse
- * performance than the kernel's zero-copy sendfile.
- *
- * c. Use non-atomic sendfile syscall to attempt a zero copy
- * read, and hope that there isn't a short read due to
- * truncation. In the case of a short read, there are two
- * options:
- *
- * 1. Kill the client connection
- *
- * 2. Write zeros to the socket for the remaining bytes
- * promised in the header.
- *
- * It is safer from a data corruption perspective to kill the
- * client connection, so this is our default behavior, but if
- * this causes problems this can be configured to write zeros
- * via smb.conf.
- */
-
- /* Handle case 1: short read -> truncated file. */
- if (ret == 0) {
- END_PROFILE(syscall_sendfile);
- return ret;
- }
-
- /* Handle case 2: large read. */
- if (ret == -1 && errno == E2BIG) {
-
- if (!lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE,
- PARM_SENDFILE_LARGE_READS,
- PARM_SENDFILE_LARGE_READS_DEFAULT)) {
- DEBUG(3, ("Not attempting non-atomic large sendfile: "
- "%lu bytes\n", count));
- END_PROFILE(syscall_sendfile);
- return 0;
- }
-
- if (count < 0x10000) {
- DEBUG(0, ("Count < 2^16 and E2BIG was returned! %lu\n",
- count));
- }
-
- DEBUG(10, ("attempting non-atomic large sendfile: %lu bytes\n",
- count));
-
- /* Try a non-atomic sendfile. */
- ret = onefs_sys_do_sendfile(tofd, fromfd, header, offset,
- count, false);
- /* Real error: kill the client connection. */
- if (ret == -1) {
- DEBUG(1, ("error on non-atomic large sendfile "
- "(%lu bytes): %s\n", count,
- strerror(errno)));
- END_PROFILE(syscall_sendfile);
- return ret;
- }
-
- /* Short read: kill the client connection. */
- if (ret != count + header->length) {
- DEBUG(1, ("short read on non-atomic large sendfile "
- "(%lu of %lu bytes): %s\n", ret, count,
- strerror(errno)));
-
- /*
- * Returning ret here would cause us to drop into the
- * codepath that calls sendfile_short_send, which
- * sends the client a bunch of zeros instead.
- * Returning -1 kills the connection.
- */
- if (lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE,
- PARM_SENDFILE_SAFE,
- PARM_SENDFILE_SAFE_DEFAULT)) {
- END_PROFILE(syscall_sendfile);
- return -1;
- }
-
- END_PROFILE(syscall_sendfile);
- return ret;
- }
-
- DEBUG(10, ("non-atomic large sendfile successful\n"));
- }
-
- /* There was error in the atomic sendfile. */
- if (ret == -1) {
- DEBUG(1, ("error on %s sendfile (%lu bytes): %s\n",
- atomic ? "atomic" : "non-atomic",
- count, strerror(errno)));
- }
-
- END_PROFILE(syscall_sendfile);
- return ret;
-}
-
-/**
- * Only talloc the spill buffer once (reallocing when necessary).
- */
-static char *get_spill_buffer(size_t new_count)
-{
- static int cur_count = 0;
- static char *spill_buffer = NULL;
-
- /* If a sufficiently sized buffer exists, just return. */
- if (new_count <= cur_count) {
- SMB_ASSERT(spill_buffer);
- return spill_buffer;
- }
-
- /* Allocate the first time. */
- if (cur_count == 0) {
- SMB_ASSERT(!spill_buffer);
- spill_buffer = talloc_array(NULL, char, new_count);
- if (spill_buffer) {
- cur_count = new_count;
- }
- return spill_buffer;
- }
-
- /* A buffer exists, but it's not big enough, so realloc. */
- SMB_ASSERT(spill_buffer);
- spill_buffer = talloc_realloc(NULL, spill_buffer, char, new_count);
- if (spill_buffer) {
- cur_count = new_count;
- }
- return spill_buffer;
-}
-
-/**
- * recvfile does zero-copy writes given an fd to write to, and a socket with
- * some data to write. If recvfile read more than it was able to write, it
- * spills the data into a buffer. After first reading any additional data
- * from the socket into the buffer, the spill buffer is then written with a
- * standard pwrite.
- */
-ssize_t onefs_sys_recvfile(int fromfd, int tofd, off_t offset,
- size_t count)
-{
- char *spill_buffer = NULL;
- bool socket_drained = false;
- int ret;
- off_t total_rbytes = 0;
- off_t total_wbytes = 0;
- off_t rbytes;
- off_t wbytes;
-
- START_PROFILE_BYTES(syscall_recvfile, count);
-
- DEBUG(10,("onefs_recvfile: from = %d, to = %d, offset=%llu, count = "
- "%lu\n", fromfd, tofd, offset, count));
-
- if (count == 0) {
- END_PROFILE(syscall_recvfile);
- return 0;
- }
-
- /*
- * Setup up a buffer for recvfile to spill data that has been read
- * from the socket but not written.
- */
- spill_buffer = get_spill_buffer(count);
- if (spill_buffer == NULL) {
- ret = -1;
- goto out;
- }
-
- /*
- * Keep trying recvfile until:
- * - There is no data left to read on the socket, or
- * - bytes read != bytes written, or
- * - An error is returned that isn't EINTR/EAGAIN
- */
- do {
- /* Keep track of bytes read/written for recvfile */
- rbytes = 0;
- wbytes = 0;
-
- DEBUG(10, ("calling recvfile loop, offset + total_wbytes = "
- "%llu, count - total_rbytes = %llu\n",
- offset + total_wbytes, count - total_rbytes));
-
- ret = recvfile(tofd, fromfd, offset + total_wbytes,
- count - total_wbytes, &rbytes, &wbytes, 0,
- spill_buffer);
-
- DEBUG(10, ("recvfile ret = %d, errno = %d, rbytes = %llu, "
- "wbytes = %llu\n", ret, ret >= 0 ? 0 : errno,
- rbytes, wbytes));
-
- /* Update our progress so far */
- total_rbytes += rbytes;
- total_wbytes += wbytes;
-
- } while ((count - total_rbytes) && (rbytes == wbytes) &&
- (ret == -1 && (errno == EINTR || errno == EAGAIN)));
-
- DEBUG(10, ("total_rbytes = %llu, total_wbytes = %llu\n",
- total_rbytes, total_wbytes));
-
- /* Log if recvfile didn't write everything it read. */
- if (total_rbytes != total_wbytes) {
- DEBUG(3, ("partial recvfile: total_rbytes=%llu but "
- "total_wbytes=%llu, diff = %llu\n", total_rbytes,
- total_wbytes, total_rbytes - total_wbytes));
- SMB_ASSERT(total_rbytes > total_wbytes);
- }
-
- /*
- * If there is still data on the socket, read it off.
- */
- while (total_rbytes < count) {
-
- DEBUG(3, ("shallow recvfile (%s), reading %llu\n",
- strerror(errno), count - total_rbytes));
-
- /*
- * Read the remaining data into the spill buffer. recvfile
- * may already have some data in the spill buffer, so start
- * filling the buffer at total_rbytes - total_wbytes.
- */
- ret = sys_read(fromfd,
- spill_buffer + (total_rbytes - total_wbytes),
- count - total_rbytes);
-
- if (ret <= 0) {
- if (ret == 0) {
- DEBUG(0, ("shallow recvfile read: EOF\n"));
- } else {
- DEBUG(0, ("shallow recvfile read failed: %s\n",
- strerror(errno)));
- }
- /* Socket is dead, so treat as if it were drained. */
- socket_drained = true;
- goto out;
- }
-
- /* Data was read so update the rbytes */
- total_rbytes += ret;
- }
-
- if (total_rbytes != count) {
- smb_panic("Unread recvfile data still on the socket!");
- }
-
- /*
- * Now write any spilled data + the extra data read off the socket.
- */
- while (total_wbytes < count) {
-
- DEBUG(3, ("partial recvfile, writing %llu\n", count - total_wbytes));
-
- ret = sys_pwrite(tofd, spill_buffer, count - total_wbytes,
- offset + total_wbytes);
-
- if (ret == -1) {
- DEBUG(0, ("partial recvfile write failed: %s\n",
- strerror(errno)));
- goto out;
- }
-
- /* Data was written so update the wbytes */
- total_wbytes += ret;
- }
-
- /* Success! */
- ret = total_wbytes;
-
-out:
-
- END_PROFILE(syscall_recvfile);
-
- /* Make sure we always try to drain the socket. */
- if (!socket_drained && count - total_rbytes) {
- int saved_errno = errno;
-
- if (drain_socket(fromfd, count - total_rbytes) !=
- count - total_rbytes) {
- /* Socket is dead! */
- DEBUG(0, ("drain socket failed: %d\n", errno));
- }
- errno = saved_errno;
- }
-
- return ret;
-}
-
-void init_stat_ex_from_onefs_stat(struct stat_ex *dst, const struct stat *src)
-{
- ZERO_STRUCT(*dst);
-
- dst->st_ex_dev = src->st_dev;
- dst->st_ex_ino = src->st_ino;
- dst->st_ex_mode = src->st_mode;
- dst->st_ex_nlink = src->st_nlink;
- dst->st_ex_uid = src->st_uid;
- dst->st_ex_gid = src->st_gid;
- dst->st_ex_rdev = src->st_rdev;
- dst->st_ex_size = src->st_size;
- dst->st_ex_atime = src->st_atimespec;
- dst->st_ex_mtime = src->st_mtimespec;
- dst->st_ex_ctime = src->st_ctimespec;
- dst->st_ex_btime = src->st_birthtimespec;
- dst->st_ex_blksize = src->st_blksize;
- dst->st_ex_blocks = src->st_blocks;
-
- dst->st_ex_flags = src->st_flags;
-
- dst->vfs_private = src->st_snapid;
-}
-
-int onefs_sys_stat(const char *fname, SMB_STRUCT_STAT *sbuf)
-{
- int ret;
- struct stat onefs_sbuf;
-
- ret = stat(fname, &onefs_sbuf);
-
- if (ret == 0) {
- /* we always want directories to appear zero size */
- if (S_ISDIR(onefs_sbuf.st_mode)) {
- onefs_sbuf.st_size = 0;
- }
- init_stat_ex_from_onefs_stat(sbuf, &onefs_sbuf);
- }
- return ret;
-}
-
-int onefs_sys_fstat(int fd, SMB_STRUCT_STAT *sbuf)
-{
- int ret;
- struct stat onefs_sbuf;
-
- ret = fstat(fd, &onefs_sbuf);
-
- if (ret == 0) {
- /* we always want directories to appear zero size */
- if (S_ISDIR(onefs_sbuf.st_mode)) {
- onefs_sbuf.st_size = 0;
- }
- init_stat_ex_from_onefs_stat(sbuf, &onefs_sbuf);
- }
- return ret;
-}
-
-int onefs_sys_fstat_at(int base_fd, const char *fname, SMB_STRUCT_STAT *sbuf,
- int flags)
-{
- int ret;
- struct stat onefs_sbuf;
-
- ret = enc_fstatat(base_fd, fname, ENC_DEFAULT, &onefs_sbuf, flags);
-
- if (ret == 0) {
- /* we always want directories to appear zero size */
- if (S_ISDIR(onefs_sbuf.st_mode)) {
- onefs_sbuf.st_size = 0;
- }
- init_stat_ex_from_onefs_stat(sbuf, &onefs_sbuf);
- }
- return ret;
-}
-
-int onefs_sys_lstat(const char *fname, SMB_STRUCT_STAT *sbuf)
-{
- int ret;
- struct stat onefs_sbuf;
-
- ret = lstat(fname, &onefs_sbuf);
-
- if (ret == 0) {
- /* we always want directories to appear zero size */
- if (S_ISDIR(onefs_sbuf.st_mode)) {
- onefs_sbuf.st_size = 0;
- }
- init_stat_ex_from_onefs_stat(sbuf, &onefs_sbuf);
- }
- return ret;
-}
-
diff --git a/source3/modules/perfcount_onefs.c b/source3/modules/perfcount_onefs.c
deleted file mode 100644
index fcc0620159..0000000000
--- a/source3/modules/perfcount_onefs.c
+++ /dev/null
@@ -1,481 +0,0 @@
-/*
- * Unix SMB/CIFS implementation.
- * Support for OneFS protocol statistics / perfcounters
- *
- * Copyright (C) Todd Stecher 2008
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "includes.h"
-#include "smbd/smbd.h"
-#include <sys/isi_stats_protocol.h>
-#include <sys/isi_stats_client.h>
-#include <sys/isi_stats_cifs.h>
-
-extern struct current_user current_user;
-
-struct onefs_op_counter {
- struct isp_op_delta iod;
- struct onefs_op_counter *next;
- struct onefs_op_counter *prev;
-};
-
-struct onefs_stats_context {
- bool alloced;
- struct isp_op_delta iod;
-
- /* ANDX commands stats stored here */
- struct onefs_op_counter *ops_chain;
-};
-
-const char *onefs_stat_debug(struct isp_op_delta *iod);
-
-struct onefs_stats_context g_context;
-
-static void onefs_smb_statistics_end(struct smb_perfcount_data *pcd);
-
-struct isp_op_delta *onefs_stats_get_op_delta(struct onefs_stats_context *ctxt)
-{
- /* operate on head of chain */
- if (ctxt->ops_chain) {
-#ifdef ONEFS_PERF_DEBUG
- DEBUG(0,("************* CHAINED *****\n"));
-#endif
- return &ctxt->ops_chain->iod;
- } else
- return &ctxt->iod;
-}
-
-/* statistics operations */
-static void onefs_smb_statistics_start(struct smb_perfcount_data *pcd)
-{
-
-#ifdef ONEFS_PERF_DEBUG
- if (g_context.iod.op) {
- DEBUG(0,("**************** OP Collision! %s(%d) \n",
- onefs_stat_debug(&g_context.iod), g_context.iod.op));
- }
-
-#endif
-
- ISP_OP_BEG(&g_context.iod, ISP_PROTO_CIFS, 0);
-
- if (g_context.iod.enabled)
- pcd->context = &g_context;
- else
- pcd->context = NULL;
-
-
-}
-
-static void onefs_smb_statistics_add(struct smb_perfcount_data *pcd)
-{
- struct onefs_op_counter *oc;
- struct onefs_stats_context *ctxt = pcd->context;
-
- /* not enabled */
- if (pcd->context == NULL)
- return;
-
- oc = SMB_MALLOC_P(struct onefs_op_counter);
-
- if (oc == NULL)
- return;
-
-#ifdef ONEFS_PERF_DEBUG
- DEBUG(0,("*********** add chained op \n"));
-#endif
-
- DLIST_ADD(ctxt->ops_chain, oc);
- ISP_OP_BEG(&oc->iod, ISP_PROTO_CIFS, 0);
-}
-
-static void onefs_smb_statistics_set_op(struct smb_perfcount_data *pcd, int op)
-{
- struct onefs_stats_context *ctxt = pcd->context;
- struct isp_op_delta *iod;
-
- /* not enabled */
- if (pcd->context == NULL)
- return;
-
- iod = onefs_stats_get_op_delta(ctxt);
- iod->op = isp_cifs_op_id(op);
-
-#ifdef ONEFS_PERF_DEBUG
- DEBUG(0,("***********SET op %s(%d)\n", onefs_stat_debug(iod), op));
-#endif
- /* no reply required */
- if (op == SMBntcancel)
- onefs_smb_statistics_end(pcd);
-
-}
-
-static void onefs_smb_statistics_set_subop(struct smb_perfcount_data *pcd,
- int subop)
-{
- struct onefs_stats_context *ctxt = pcd->context;
- struct isp_op_delta *iod;
-
- /* not enabled */
- if (pcd->context == NULL)
- return;
-
- iod = onefs_stats_get_op_delta(ctxt);
- iod->op = isp_cifs_sub_op_id(iod->op, subop);
-
-#ifdef ONEFS_PERF_DEBUG
- DEBUG(0,("******************** SET subop %s(%d)\n",
- onefs_stat_debug(iod), subop));
-#endif
-
- /*
- * finalize this one - we don't need to know when it
- * is set, but its useful as a counter
- */
- if (subop == NT_TRANSACT_NOTIFY_CHANGE)
- onefs_smb_statistics_end(pcd);
-}
-
-static void onefs_smb_statistics_set_ioctl(struct smb_perfcount_data *pcd,
- int io_ctl)
-{
- struct onefs_stats_context *ctxt = pcd->context;
- struct isp_op_delta *iod;
-
- /* not enabled */
- if (pcd->context == NULL)
- return;
-
- /* we only monitor shadow copy */
- if (io_ctl != FSCTL_GET_SHADOW_COPY_DATA)
- return;
-
- iod = onefs_stats_get_op_delta(ctxt);
- iod->op = isp_cifs_sub_op_id(iod->op, ISP_CIFS_NTRN_IOCTL_FGSCD);
-#ifdef ONEFS_PERF_DEBUG
- DEBUG(0,("******************** SET ioctl %s(%d)\n",
- onefs_stat_debug(iod), io_ctl));
-#endif
-}
-
-static void onefs_smb_statistics_set_msglen_in(struct smb_perfcount_data *pcd,
- uint64_t in_bytes)
-{
- struct onefs_stats_context *ctxt = pcd->context;
- struct isp_op_delta *iod;
-
- /* not enabled */
- if (pcd->context == NULL)
- return;
-
- iod = onefs_stats_get_op_delta(ctxt);
- iod->in_bytes = in_bytes;
-}
-
-static void onefs_smb_statistics_set_msglen_out(struct smb_perfcount_data *pcd,
- uint64_t out_bytes)
-{
- struct onefs_stats_context *ctxt = pcd->context;
-
- /* not enabled */
- if (pcd->context == NULL)
- return;
-
- if (ctxt->ops_chain)
- ctxt->ops_chain->iod.out_bytes = out_bytes;
-
- ctxt->iod.out_bytes = out_bytes;
-}
-
-static int onefs_copy_perfcount_context(struct onefs_stats_context *ctxt,
- struct onefs_stats_context **dest)
-{
- struct onefs_stats_context *new_ctxt;
-
- /* make an alloc'd copy of the data */
- new_ctxt = SMB_MALLOC_P(struct onefs_stats_context);
- if (!new_ctxt) {
- return -1;
- }
-
- memcpy(new_ctxt, ctxt, sizeof(struct onefs_stats_context));
- new_ctxt->alloced = True;
- *dest = new_ctxt;
- return 0;
-}
-
-static void onefs_smb_statistics_copy_context(struct smb_perfcount_data *pcd,
- struct smb_perfcount_data *dest)
-{
- struct onefs_stats_context *ctxt = pcd->context;
- struct onefs_stats_context *new_ctxt;
- int ret;
-
- /* not enabled */
- if (pcd->context == NULL)
- return;
-
-#ifdef ONEFS_PERF_DEBUG
- DEBUG(0,("******** COPYING op %s(%d)\n",
- onefs_stat_debug(&ctxt->iod), ctxt->iod.op));
-#endif
-
- ret = onefs_copy_perfcount_context(ctxt, &new_ctxt);
- if (ret)
- return;
-
- /* instrumentation */
- if (ctxt == &g_context)
- ZERO_STRUCT(g_context);
-
- dest->context = new_ctxt;
-}
-
-/*
- * For perf reasons, we usually use the global - sometimes, though,
- * when an operation is deferred, we need to alloc a copy.
- */
-static void onefs_smb_statistics_defer_op(struct smb_perfcount_data *pcd,
- struct smb_perfcount_data *def_pcd)
-{
- struct onefs_stats_context *ctxt = pcd->context;
- struct onefs_stats_context *deferred_ctxt;
- int ret;
-
- /* not enabled */
- if (pcd->context == NULL)
- return;
-
- /* already allocated ? */
- if (ctxt->alloced)
- {
- def_pcd->context = ctxt;
- pcd->context = NULL;
- return;
- }
-
-#ifdef ONEFS_PERF_DEBUG
- DEBUG(0,("******** DEFERRING op %s(%d)\n",
- onefs_stat_debug(&ctxt->iod), ctxt->iod.op));
-#endif
-
- ret = onefs_copy_perfcount_context(ctxt, &deferred_ctxt);
- if (ret)
- return;
-
- def_pcd->context = (void*) deferred_ctxt;
-
- /* instrumentation */
- if (ctxt == &g_context)
- ZERO_STRUCT(g_context);
-
- if (pcd != def_pcd)
- pcd->context = NULL;
-}
-
-static void onefs_smb_statistics_end(struct smb_perfcount_data *pcd)
-{
- struct onefs_stats_context *ctxt = pcd->context;
- struct onefs_op_counter *tmp;
- uint64_t uid;
-
- static in_addr_t rem_addr = 0;
- static in_addr_t loc_addr = 0;
-
- /* not enabled */
- if (pcd->context == NULL)
- return;
-
- uid = current_user.ut.uid ? current_user.ut.uid : ISC_UNKNOWN_CLIENT_ID;
-
- /* get address info once, doesn't change for process */
- if (rem_addr == 0) {
-
-#error Isilon, please remove this after testing the code below
-
- char *addr;
-
- addr = talloc_sub_basic(talloc_tos(), "", "", "%I");
- if (addr != NULL) {
- rem_addr = interpret_addr(addr);
- TALLOC_FREE(addr);
- } else {
- rem_addr = ISC_MASKED_ADDR;
- }
-
- addr = talloc_sub_basic(talloc_tos(), "", "", "%i");
- if (addr != NULL) {
- loc_addr = interpret_addr(addr);
- TALLOC_FREE(addr);
- } else {
- loc_addr = ISC_MASKED_ADDR;
- }
- }
-
- /*
- * bug here - we aren't getting the outlens right,
- * when dealing w/ chained requests.
- */
- for (tmp = ctxt->ops_chain; tmp; tmp = tmp->next) {
- tmp->iod.out_bytes = ctxt->iod.out_bytes;
- isc_cookie_init(&tmp->iod.cookie, rem_addr, loc_addr, uid);
- ISP_OP_END(&tmp->iod);
-#ifdef ONEFS_PERF_DEBUG
- DEBUG(0,("******** Finalized CHAIN op %s uid %llu in:%llu"
- ", out:%llu\n",
- onefs_stat_debug(&tmp->iod), uid,
- tmp->iod.in_bytes, tmp->iod.out_bytes));
-#endif
- SAFE_FREE(DLIST_PREV(tmp));
- }
-
- isc_cookie_init(&ctxt->iod.cookie, rem_addr, loc_addr, uid);
- ISP_OP_END(&ctxt->iod);
-#ifdef ONEFS_PERF_DEBUG
- DEBUG(0,("******** Finalized op %s uid %llu in:%llu, out:%llu\n",
- onefs_stat_debug(&ctxt->iod), uid,
- ctxt->iod.in_bytes, ctxt->iod.out_bytes));
-#endif
-
- if (ctxt->alloced)
- SAFE_FREE(ctxt);
- else
- ZERO_STRUCTP(ctxt);
-
- pcd->context = NULL;
-}
-
-
-static struct smb_perfcount_handlers onefs_pc_handlers = {
- onefs_smb_statistics_start,
- onefs_smb_statistics_add,
- onefs_smb_statistics_set_op,
- onefs_smb_statistics_set_subop,
- onefs_smb_statistics_set_ioctl,
- onefs_smb_statistics_set_msglen_in,
- onefs_smb_statistics_set_msglen_out,
- onefs_smb_statistics_copy_context,
- onefs_smb_statistics_defer_op,
- onefs_smb_statistics_end
-};
-
-NTSTATUS perfcount_onefs_init(void)
-{
- return smb_register_perfcounter(SMB_PERFCOUNTER_INTERFACE_VERSION,
- "pc_onefs", &onefs_pc_handlers);
-}
-
-#ifdef ONEFS_PERF_DEBUG
-/* debug helper */
-struct op_debug {
- int type;
- const char *name;
-};
-
-struct op_debug op_debug_table[] = {
- { 0x00, "mkdir"}, { 0x01, "rmdir"}, { 0x02, "open"}, { 0x03, "create"},
- { 0x04, "close"}, { 0x05, "flush"}, { 0x06, "unlink"}, { 0x07, "mv"},
- { 0x08, "getatr"}, { 0x09, "setatr"}, { 0x0a, "read"}, { 0x0b, "write"},
- { 0x0c, "lock"}, { 0x0d, "unlock"}, { 0x0e, "ctemp"}, { 0x0f, "mknew"},
- { 0x10, "chkpth"}, { 0x11, "exit"}, { 0x12, "lseek"}, { 0x13, "lockread"},
- { 0x14, "writeunlock"}, { 0x1a, "readbraw"}, { 0x1b, "readbmpx"},
- { 0x1c, "readbs"}, { 0x1d, "writebraw"}, { 0x1e, "writebmpx"},
- { 0x1f, "writebs"}, { 0x20, "writec"}, { 0x22, "setattre"},
- { 0x23, "getattre"}, { 0x24, "lockingx"}, { 0x25, "trans"},
- { 0x26, "transs"}, { 0x27, "ioctl"}, { 0x28, "ioctls"}, { 0x29, "copy"},
- { 0x2a, "move"}, { 0x2b, "echo"}, { 0x2c, "writeclose"}, { 0x2d, "openx"},
- { 0x2e, "readx"}, { 0x2f, "writex"}, { 0x34, "findclose"},
- { 0x35, "findnclose"}, { 0x70, "tcon"}, { 0x71, "tdis"},
- { 0x72, "negprot"}, { 0x73, "sesssetupx"}, { 0x74, "ulogoffx"},
- { 0x75, "tconx"}, { 0x80, "dskattr"}, { 0x81, "search"},
- { 0x82, "ffirst"}, { 0x83, "funique"}, { 0x84, "fclose"},
- { 0x400, "nttrans"},{ 0x500, "nttranss"},
- { 0xa2, "ntcreatex"}, { 0xa4, "ntcancel"}, { 0xa5, "ntrename"},
- { 0xc0, "splopen"}, { 0xc1, "splwr"}, { 0xc2, "splclose"},
- { 0xc3, "splretq"}, { 0xd0, "sends"}, { 0xd1, "sendb"},
- { 0xd2, "fwdname"}, { 0xd3, "cancelf"}, { 0xd4, "getmac"},
- { 0xd5, "sendstrt"}, { 0xd6, "sendend"}, { 0xd7, "sendtxt"},
- { ISP_CIFS_INVALID_OP, "unknown"},
- { ISP_CIFS_TRNS2 + 0x00, "trans2:open"},
- { ISP_CIFS_TRNS2 + 0x01, "trans2:findfirst"},
- { ISP_CIFS_TRNS2 + 0x02, "trans2:findnext"},
- { ISP_CIFS_TRNS2 + 0x03, "trans2:qfsinfo"},
- { ISP_CIFS_TRNS2 + 0x04, "trans2:setfsinfo"},
- { ISP_CIFS_TRNS2 + 0x05, "trans2:qpathinfo"},
- { ISP_CIFS_TRNS2 + 0x06, "trans2:setpathinfo"},
- { ISP_CIFS_TRNS2 + 0x07, "trans2:qfileinfo"},
- { ISP_CIFS_TRNS2 + 0x08, "trans2:setfileinfo"},
- { ISP_CIFS_TRNS2 + 0x0a, "trans2:ioctl"},
- { ISP_CIFS_TRNS2 + 0x0b, "trans2:findnotifyfirst"},
- { ISP_CIFS_TRNS2 + 0x0c, "trans2:findnotifynext"},
- { ISP_CIFS_TRNS2 + 0x0d, "trans2:mkdir"},
- { ISP_CIFS_TRNS2 + 0x10, "trans2:get_dfs_ref"},
- { ISP_CIFS_TRNS2 + ISP_CIFS_SUBOP_UNKNOWN, "trans2:unknown"},
- { ISP_CIFS_TRNSS2 +0x00, "transs2:open"},
- { ISP_CIFS_TRNSS2 +0x01, "transs2:findfirst"},
- { ISP_CIFS_TRNSS2 +0x02, "transs2:findnext"},
- { ISP_CIFS_TRNSS2 +0x03, "transs2:qfsinfo"},
- { ISP_CIFS_TRNSS2 +0x04, "transs2:setfsinfo"},
- { ISP_CIFS_TRNSS2 +0x05, "transs2:qpathinfo"},
- { ISP_CIFS_TRNSS2 +0x06, "transs2:setpathinfo"},
- { ISP_CIFS_TRNSS2 +0x07, "transs2:qfileinfo"},
- { ISP_CIFS_TRNSS2 +0x08, "transs2:setfileinfo"},
- { ISP_CIFS_TRNSS2 +0x0a, "transs2:ioctl"},
- { ISP_CIFS_TRNSS2 +0x0b, "transs2:findnotifyfirst"},
- { ISP_CIFS_TRNSS2 +0x0c, "transs2:findnotifynext"},
- { ISP_CIFS_TRNSS2 +0x0d, "transs2:mkdir"},
- { ISP_CIFS_TRNSS2 +0x10, "transs2:get_dfs_referral"},
- { ISP_CIFS_TRNSS2 + ISP_CIFS_SUBOP_UNKNOWN, "transs2:unknown"},
- { ISP_CIFS_NTRNS + 0x1, "nttrans:create"},
- { ISP_CIFS_NTRNS + 0x2, "nttrans:ioctl"},
- { ISP_CIFS_NTRNS + 0x3, "nttrans:set_security_desc"},
- { ISP_CIFS_NTRNS + 0x4, "nttrans:notify_change"},
- { ISP_CIFS_NTRNS + 0x5, "nttrans:rename"},
- { ISP_CIFS_NTRNS + 0x6, "nttrans:qry_security_desc"},
- { ISP_CIFS_NTRNS + 0x7, "nttrans:get_user_quota"},
- { ISP_CIFS_NTRNS + 0x8, "nttrans:set_user_quota"},
- { ISP_CIFS_NTRNS + ISP_CIFS_NTRN_IOCTL_FGSCD,
- "nttrans:ioctl:get_shadow_copy_data"},
- { ISP_CIFS_NTRNS + ISP_CIFS_SUBOP_UNKNOWN,
- "nttrans:unknown"},
- { ISP_CIFS_NTRNSS + 0x1, "nttranss:create"},
- { ISP_CIFS_NTRNSS + 0x2, "nttranss:ioctl"},
- { ISP_CIFS_NTRNSS + 0x3, "nttranss:set_security_desc"},
- { ISP_CIFS_NTRNSS + 0x4, "nttranss:notify_change"},
- { ISP_CIFS_NTRNSS + 0x5, "nttranss:rename"},
- { ISP_CIFS_NTRNSS + 0x6, "nttranss:qry_security_desc"},
- { ISP_CIFS_NTRNSS + 0x7, "nttranss:get_user_quota"},
- { ISP_CIFS_NTRNSS + 0x8, "nttranss:set_user_quota"},
- { ISP_CIFS_NTRNSS + ISP_CIFS_NTRN_IOCTL_FGSCD,
- "nttranss:ioctl:get_shadow_copy_data"},
- { ISP_CIFS_NTRNSS + ISP_CIFS_SUBOP_UNKNOWN,
- "nttranss:unknown"},
-};
-
-int op_debug_table_count = sizeof(op_debug_table) / sizeof(op_debug_table[0]);
-
-const char *onefs_stat_debug(struct isp_op_delta *iod)
-{
- int i;
- const char *unk = "unknown";
- for (i=0; i < op_debug_table_count;i++) {
- if (iod->op == op_debug_table[i].type)
- return op_debug_table[i].name;
- }
-
- return unk;
-}
-#endif
diff --git a/source3/modules/vfs_onefs.c b/source3/modules/vfs_onefs.c
deleted file mode 100644
index 619e3874a3..0000000000
--- a/source3/modules/vfs_onefs.c
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Unix SMB/CIFS implementation.
- * Support for OneFS
- *
- * Copyright (C) Tim Prouty, 2008
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "includes.h"
-#include "smbd/smbd.h"
-#include "onefs.h"
-#include "onefs_config.h"
-
-#undef DBGC_CLASS
-#define DBGC_CLASS DBGC_VFS
-
-static int onefs_connect(struct vfs_handle_struct *handle, const char *service,
- const char *user)
-{
- int ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
-
- if (ret < 0) {
- return ret;
- }
-
- ret = onefs_load_config(handle->conn);
- if (ret) {
- SMB_VFS_NEXT_DISCONNECT(handle);
- DEBUG(3, ("Load config failed: %s\n", strerror(errno)));
- return ret;
- }
-
- return 0;
-}
-
-static int onefs_mkdir(vfs_handle_struct *handle, const char *path,
- mode_t mode)
-{
- /* SMB_VFS_MKDIR should never be called in vfs_onefs */
- SMB_ASSERT(false);
- return SMB_VFS_NEXT_MKDIR(handle, path, mode);
-}
-
-static int onefs_open(vfs_handle_struct *handle,
- struct smb_filename *smb_fname,
- files_struct *fsp, int flags, mode_t mode)
-{
- /* SMB_VFS_OPEN should never be called in vfs_onefs */
- SMB_ASSERT(false);
- return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
-}
-
-static ssize_t onefs_sendfile(vfs_handle_struct *handle, int tofd,
- files_struct *fromfsp, const DATA_BLOB *header,
- off_t offset, size_t count)
-{
- ssize_t result;
-
- START_PROFILE_BYTES(syscall_sendfile, count);
- result = onefs_sys_sendfile(handle->conn, tofd, fromfsp->fh->fd,
- header, offset, count);
- END_PROFILE(syscall_sendfile);
- return result;
-}
-
-static ssize_t onefs_recvfile(vfs_handle_struct *handle, int fromfd,
- files_struct *tofsp, off_t offset,
- size_t count)
-{
- ssize_t result;
-
- START_PROFILE_BYTES(syscall_recvfile, count);
- result = onefs_sys_recvfile(fromfd, tofsp->fh->fd, offset, count);
- END_PROFILE(syscall_recvfile);
- return result;
-}
-
-static uint64_t onefs_get_alloc_size(struct vfs_handle_struct *handle,
- files_struct *fsp,
- const SMB_STRUCT_STAT *sbuf)
-{
- uint64_t result;
-
- START_PROFILE(syscall_get_alloc_size);
-
- if(S_ISDIR(sbuf->st_ex_mode)) {
- result = 0;
- goto out;
- }
-
- /* Just use the file size since st_blocks is unreliable on OneFS. */
- result = get_file_size_stat(sbuf);
-
- if (fsp && fsp->initial_allocation_size)
- result = MAX(result,fsp->initial_allocation_size);
-
- result = smb_roundup(handle->conn, result);
-
- out:
- END_PROFILE(syscall_get_alloc_size);
- return result;
-}
-
-static struct file_id onefs_file_id_create(struct vfs_handle_struct *handle,
- const SMB_STRUCT_STAT *sbuf)
-{
- struct file_id key;
-
- /* the ZERO_STRUCT ensures padding doesn't break using the key as a
- * blob */
- ZERO_STRUCT(key);
-
- key.devid = sbuf->st_ex_dev;
- key.inode = sbuf->st_ex_ino;
- key.extid = sbuf->vfs_private;
-
- return key;
-}
-
-static int onefs_statvfs(vfs_handle_struct *handle, const char *path,
- vfs_statvfs_struct *statbuf)
-{
- struct statvfs statvfs_buf;
- int result;
-
- DEBUG(5, ("Calling SMB_STAT_VFS \n"));
- result = statvfs(path, &statvfs_buf);
- ZERO_STRUCTP(statbuf);
-
- if (!result) {
- statbuf->OptimalTransferSize = statvfs_buf.f_iosize;
- statbuf->BlockSize = statvfs_buf.f_bsize;
- statbuf->TotalBlocks = statvfs_buf.f_blocks;
- statbuf->BlocksAvail = statvfs_buf.f_bfree;
- statbuf->UserBlocksAvail = statvfs_buf.f_bavail;
- statbuf->TotalFileNodes = statvfs_buf.f_files;
- statbuf->FreeFileNodes = statvfs_buf.f_ffree;
- statbuf->FsIdentifier =
- (((uint64_t)statvfs_buf.f_fsid.val[0]<<32) &
- 0xffffffff00000000LL) |
- (uint64_t)statvfs_buf.f_fsid.val[1];
- }
- return result;
-}
-
-static int onefs_get_real_filename(vfs_handle_struct *handle, const char *path,
- const char *name, TALLOC_CTX *mem_ctx,
- char **found_name)
-{
- struct stat sb;
- struct connection_struct *conn = handle->conn;
- struct stat_extra se;
- int result;
- char *unmangled_name = NULL;
- char *full_name = NULL;
-
- /* First demangle the name if necessary. */
- if (!conn->case_sensitive && mangle_is_mangled(name, conn->params) &&
- mangle_lookup_name_from_8_3(mem_ctx, name, &unmangled_name,
- conn->params)) {
- /* Name is now unmangled. */
- name = unmangled_name;
- }
-
- /* Do the case insensitive stat. */
- ZERO_STRUCT(se);
- se.se_version = ESTAT_CURRENT_VERSION;
- se.se_flags = ESTAT_CASE_INSENSITIVE | ESTAT_SYMLINK_NOFOLLOW;
-
- if (*path != '\0') {
- if (!(full_name = talloc_asprintf(mem_ctx, "%s/%s", path, name))) {
- errno = ENOMEM;
- DEBUG(2, ("talloc_asprintf failed\n"));
- result = -1;
- goto done;
- }
- }
-
- if ((result = estat(full_name ? full_name : name, &sb, &se)) != 0) {
- DEBUG(2, ("error calling estat: %s\n", strerror(errno)));
- goto done;
- }
-
- *found_name = talloc_strdup(mem_ctx, se.se_realname);
- if (*found_name == NULL) {
- errno = ENOMEM;
- result = -1;
- goto done;
- }
-
-done:
- TALLOC_FREE(full_name);
- TALLOC_FREE(unmangled_name);
- return result;
-}
-
-static int onefs_ntimes(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- struct smb_file_time *ft)
-{
- int flags = 0;
- struct timespec times[3];
-
- if (!null_timespec(ft->atime)) {
- flags |= VT_ATIME;
- times[0] = ft->atime;
- DEBUG(6,("**** onefs_ntimes: actime: %s.%d\n",
- time_to_asc(convert_timespec_to_time_t(ft->atime)),
- ft->atime.tv_nsec));
- }
-
- if (!null_timespec(ft->mtime)) {
- flags |= VT_MTIME;
- times[1] = ft->mtime;
- DEBUG(6,("**** onefs_ntimes: modtime: %s.%d\n",
- time_to_asc(convert_timespec_to_time_t(ft->mtime)),
- ft->mtime.tv_nsec));
- }
-
- if (!null_timespec(ft->create_time)) {
- flags |= VT_BTIME;
- times[2] = ft->create_time;
- DEBUG(6,("**** onefs_ntimes: createtime: %s.%d\n",
- time_to_asc(convert_timespec_to_time_t(ft->create_time)),
- ft->create_time.tv_nsec));
- }
-
- return onefs_vtimes_streams(handle, smb_fname, flags, times);
-}
-
-static uint32_t onefs_fs_capabilities(struct vfs_handle_struct *handle, enum timestamp_set_resolution *p_ts_res)
-{
- uint32_t result = 0;
-
- if (!lp_parm_bool(SNUM(handle->conn), PARM_ONEFS_TYPE,
- PARM_IGNORE_STREAMS, PARM_IGNORE_STREAMS_DEFAULT)) {
- result |= FILE_NAMED_STREAMS;
- }
-
- result |= SMB_VFS_NEXT_FS_CAPABILITIES(handle, p_ts_res);
- *p_ts_res = TIMESTAMP_SET_MSEC;
- return result;
-}
-
-static struct vfs_fn_pointers onefs_fns = {
- .connect_fn = onefs_connect,
- .fs_capabilities_fn = onefs_fs_capabilities,
- .opendir_fn = onefs_opendir,
- .readdir_fn = onefs_readdir,
- .seekdir_fn = onefs_seekdir,
- .telldir_fn = onefs_telldir,
- .rewind_dir_fn = onefs_rewinddir,
- .mkdir_fn = onefs_mkdir,
- .closedir_fn = onefs_closedir,
- .init_search_op_fn = onefs_init_search_op,
- .open_fn = onefs_open,
- .create_file_fn = onefs_create_file,
- .close_fn = onefs_close,
- .sendfile_fn = onefs_sendfile,
- .recvfile_fn = onefs_recvfile,
- .rename_fn = onefs_rename,
- .stat_fn = onefs_stat,
- .fstat_fn = onefs_fstat,
- .lstat_fn = onefs_lstat,
- .get_alloc_size_fn = onefs_get_alloc_size,
- .unlink_fn = onefs_unlink,
- .ntimes_fn = onefs_ntimes,
- .file_id_create_fn = onefs_file_id_create,
- .streaminfo_fn = onefs_streaminfo,
- .brl_lock_windows_fn = onefs_brl_lock_windows,
- .brl_unlock_windows_fn = onefs_brl_unlock_windows,
- .brl_cancel_windows_fn = onefs_brl_cancel_windows,
- .strict_lock_fn = onefs_strict_lock,
- .strict_unlock_fn = onefs_strict_unlock,
- .notify_watch_fn = onefs_notify_watch,
- .fget_nt_acl_fn = onefs_fget_nt_acl,
- .get_nt_acl_fn = onefs_get_nt_acl,
- .fset_nt_acl_fn = onefs_fset_nt_acl,
- .statvfs_fn = onefs_statvfs,
- .get_real_filename_fn = onefs_get_real_filename,
-};
-
-NTSTATUS vfs_onefs_init(void)
-{
- return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "onefs",
- &onefs_fns);
-}
diff --git a/source3/modules/vfs_onefs_shadow_copy.c b/source3/modules/vfs_onefs_shadow_copy.c
deleted file mode 100644
index ac61852d3d..0000000000
--- a/source3/modules/vfs_onefs_shadow_copy.c
+++ /dev/null
@@ -1,685 +0,0 @@
-/*
- * OneFS shadow copy implementation that utilizes the file system's native
- * snapshot support. This is based on the original shadow copy module from
- * 2004.
- *
- * Copyright (C) Stefan Metzmacher 2003-2004
- * Copyright (C) Tim Prouty 2009
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include "includes.h"
-#include "smbd/smbd.h"
-#include "onefs_shadow_copy.h"
-
-static int vfs_onefs_shadow_copy_debug_level = DBGC_VFS;
-
-#undef DBGC_CLASS
-#define DBGC_CLASS vfs_onefs_shadow_copy_debug_level
-
-#define SHADOW_COPY_PREFIX "@GMT-"
-#define SHADOW_COPY_SAMPLE "@GMT-2004.02.18-15.44.00"
-
-bool
-shadow_copy_match_name(const char *name, char **snap_component)
-{
- uint32 i = 0;
- char delim[] = SHADOW_COPY_PREFIX;
- char* start;
-
- start = strstr( name, delim );
-
- /*
- * The name could have SHADOW_COPY_PREFIX in it so we need to keep
- * trying until we get something that is the full length of the
- * SHADOW_COPY_SAMPLE.
- */
- while (start != NULL) {
-
- DEBUG(10,("Processing %s\n", name));
-
- /* size / correctness check */
- *snap_component = start;
- for ( i = sizeof(SHADOW_COPY_PREFIX);
- i < sizeof(SHADOW_COPY_SAMPLE); i++) {
- if (start[i] == '/') {
- if (i == sizeof(SHADOW_COPY_SAMPLE) - 1)
- return true;
- else
- break;
- } else if (start[i] == '\0')
- return (i == sizeof(SHADOW_COPY_SAMPLE) - 1);
- }
-
- start = strstr( start, delim );
- }
-
- return false;
-}
-
-static int
-onefs_shadow_copy_get_shadow_copy_data(vfs_handle_struct *handle,
- files_struct *fsp,
- SHADOW_COPY_DATA *shadow_copy_data,
- bool labels)
-{
- void *p = osc_version_opendir();
- char *snap_component = NULL;
- shadow_copy_data->num_volumes = 0;
- shadow_copy_data->labels = NULL;
-
- if (!p) {
- DEBUG(0, ("shadow_copy_get_shadow_copy_data: osc_opendir() "
- "failed for [%s]\n",fsp->conn->connectpath));
- return -1;
- }
-
- while (true) {
- SHADOW_COPY_LABEL *tlabels;
- char *d;
-
- d = osc_version_readdir(p);
- if (d == NULL)
- break;
-
- if (!shadow_copy_match_name(d, &snap_component)) {
- DEBUG(10,("shadow_copy_get_shadow_copy_data: ignore "
- "[%s]\n",d));
- continue;
- }
-
- DEBUG(7,("shadow_copy_get_shadow_copy_data: not ignore "
- "[%s]\n",d));
-
- if (!labels) {
- shadow_copy_data->num_volumes++;
- continue;
- }
-
- tlabels = (SHADOW_COPY_LABEL *)TALLOC_REALLOC(
- shadow_copy_data->mem_ctx,
- shadow_copy_data->labels,
- (shadow_copy_data->num_volumes+1) *
- sizeof(SHADOW_COPY_LABEL));
-
- if (tlabels == NULL) {
- DEBUG(0,("shadow_copy_get_shadow_copy_data: Out of "
- "memory\n"));
- osc_version_closedir(p);
- return -1;
- }
-
- snprintf(tlabels[shadow_copy_data->num_volumes++],
- sizeof(*tlabels), "%s",d);
-
- shadow_copy_data->labels = tlabels;
- }
-
- osc_version_closedir(p);
-
- return 0;
-}
-
-#define SHADOW_NEXT(op, args, rtype) do { \
- char *cpath = NULL; \
- char *snap_component = NULL; \
- rtype ret; \
- if (shadow_copy_match_name(path, &snap_component)) \
- cpath = osc_canonicalize_path(path, snap_component); \
- ret = SMB_VFS_NEXT_ ## op args; \
- SAFE_FREE(cpath); \
- return ret; \
- } while (0) \
-
-/*
- * XXX: Convert osc_canonicalize_path to use talloc instead of malloc.
- */
-#define SHADOW_NEXT_SMB_FNAME(op, args, rtype) do { \
- char *smb_base_name_tmp = NULL; \
- char *cpath = NULL; \
- char *snap_component = NULL; \
- rtype ret; \
- smb_base_name_tmp = smb_fname->base_name; \
- if (shadow_copy_match_name(smb_fname->base_name, \
- &snap_component)) { \
- cpath = osc_canonicalize_path(smb_fname->base_name, \
- snap_component); \
- smb_fname->base_name = cpath; \
- } \
- ret = SMB_VFS_NEXT_ ## op args; \
- smb_fname->base_name = smb_base_name_tmp; \
- SAFE_FREE(cpath); \
- return ret; \
- } while (0) \
-
-static uint64_t
-onefs_shadow_copy_disk_free(vfs_handle_struct *handle, const char *path,
- bool small_query, uint64_t *bsize, uint64_t *dfree,
- uint64_t *dsize)
-{
-
- SHADOW_NEXT(DISK_FREE,
- (handle, cpath ?: path, small_query, bsize, dfree, dsize),
- uint64_t);
-
-}
-
-static int
-onefs_shadow_copy_statvfs(struct vfs_handle_struct *handle, const char *path,
- struct vfs_statvfs_struct *statbuf)
-{
- SHADOW_NEXT(STATVFS,
- (handle, cpath ?: path, statbuf),
- int);
-}
-
-static DIR *
-onefs_shadow_copy_opendir(vfs_handle_struct *handle, const char *path,
- const char *mask, uint32_t attr)
-{
- SHADOW_NEXT(OPENDIR,
- (handle, cpath ?: path, mask, attr),
- DIR *);
-}
-
-static int
-onefs_shadow_copy_mkdir(vfs_handle_struct *handle, const char *path,
- mode_t mode)
-{
- SHADOW_NEXT(MKDIR,
- (handle, cpath ?: path, mode),
- int);
-}
-
-static int
-onefs_shadow_copy_rmdir(vfs_handle_struct *handle, const char *path)
-{
- SHADOW_NEXT(RMDIR,
- (handle, cpath ?: path),
- int);
-}
-
-static int
-onefs_shadow_copy_open(vfs_handle_struct *handle,
- struct smb_filename *smb_fname, files_struct *fsp,
- int flags, mode_t mode)
-{
- SHADOW_NEXT_SMB_FNAME(OPEN,
- (handle, smb_fname, fsp, flags, mode),
- int);
-}
-
-static NTSTATUS
-onefs_shadow_copy_create_file(vfs_handle_struct *handle,
- struct smb_request *req,
- uint16_t root_dir_fid,
- struct smb_filename *smb_fname,
- uint32_t access_mask,
- uint32_t share_access,
- uint32_t create_disposition,
- uint32_t create_options,
- uint32_t file_attributes,
- uint32_t oplock_request,
- uint64_t allocation_size,
- uint32_t private_flags,
- struct security_descriptor *sd,
- struct ea_list *ea_list,
- files_struct **result,
- int *pinfo)
-{
- SHADOW_NEXT_SMB_FNAME(CREATE_FILE,
- (handle, req, root_dir_fid, smb_fname,
- access_mask, share_access,
- create_disposition, create_options,
- file_attributes, oplock_request,
- allocation_size, private_flags,
- sd, ea_list, result, pinfo),
- NTSTATUS);
-}
-
-/**
- * XXX: macro-ize
- */
-static int
-onefs_shadow_copy_rename(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname_src,
- const struct smb_filename *smb_fname_dst)
-{
- char *old_cpath = NULL;
- char *old_snap_component = NULL;
- char *new_cpath = NULL;
- char *new_snap_component = NULL;
- struct smb_filename *smb_fname_src_tmp = NULL;
- struct smb_filename *smb_fname_dst_tmp = NULL;
- NTSTATUS status;
- int ret = -1;
-
- status = copy_smb_filename(talloc_tos(), smb_fname_src,
- &smb_fname_src_tmp);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
- goto out;
- }
- status = copy_smb_filename(talloc_tos(), smb_fname_dst,
- &smb_fname_dst_tmp);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
- goto out;
- }
-
- if (shadow_copy_match_name(smb_fname_src_tmp->base_name,
- &old_snap_component)) {
- old_cpath = osc_canonicalize_path(smb_fname_src_tmp->base_name,
- old_snap_component);
- smb_fname_src_tmp->base_name = old_cpath;
- }
-
- if (shadow_copy_match_name(smb_fname_dst_tmp->base_name,
- &new_snap_component)) {
- new_cpath = osc_canonicalize_path(smb_fname_dst_tmp->base_name,
- new_snap_component);
- smb_fname_dst_tmp->base_name = new_cpath;
- }
-
- ret = SMB_VFS_NEXT_RENAME(handle, smb_fname_src_tmp,
- smb_fname_dst_tmp);
-
- out:
- SAFE_FREE(old_cpath);
- SAFE_FREE(new_cpath);
- TALLOC_FREE(smb_fname_src_tmp);
- TALLOC_FREE(smb_fname_dst_tmp);
-
- return ret;
-}
-
-static int
-onefs_shadow_copy_stat(vfs_handle_struct *handle,
- struct smb_filename *smb_fname)
-{
- SHADOW_NEXT_SMB_FNAME(STAT,
- (handle, smb_fname),
- int);
-}
-
-static int
-onefs_shadow_copy_lstat(vfs_handle_struct *handle,
- struct smb_filename *smb_fname)
-{
- SHADOW_NEXT_SMB_FNAME(LSTAT,
- (handle, smb_fname),
- int);
-}
-
-static int
-onefs_shadow_copy_unlink(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname_in)
-{
- struct smb_filename *smb_fname = NULL;
- NTSTATUS status;
-
- status = copy_smb_filename(talloc_tos(), smb_fname_in, &smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
- return -1;
- }
-
- SHADOW_NEXT_SMB_FNAME(UNLINK,
- (handle, smb_fname),
- int);
-}
-
-static int
-onefs_shadow_copy_chmod(vfs_handle_struct *handle, const char *path,
- mode_t mode)
-{
- SHADOW_NEXT(CHMOD,
- (handle, cpath ?: path, mode),
- int);
-}
-
-static int
-onefs_shadow_copy_chown(vfs_handle_struct *handle, const char *path,
- uid_t uid, gid_t gid)
-{
- SHADOW_NEXT(CHOWN,
- (handle, cpath ?: path, uid, gid),
- int);
-}
-
-static int
-onefs_shadow_copy_lchown(vfs_handle_struct *handle, const char *path,
- uid_t uid, gid_t gid)
-{
- SHADOW_NEXT(LCHOWN,
- (handle, cpath ?: path, uid, gid),
- int);
-}
-
-static int
-onefs_shadow_copy_chdir(vfs_handle_struct *handle, const char *path)
-{
- SHADOW_NEXT(CHDIR,
- (handle, cpath ?: path),
- int);
-}
-
-static int
-onefs_shadow_copy_ntimes(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname_in,
- struct smb_file_time *ft)
-{
- struct smb_filename *smb_fname = NULL;
- NTSTATUS status;
-
- status = copy_smb_filename(talloc_tos(), smb_fname_in, &smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
- return -1;
- }
-
- SHADOW_NEXT_SMB_FNAME(NTIMES,
- (handle, smb_fname, ft),
- int);
-
-}
-
-/**
- * XXX: macro-ize
- */
-static int
-onefs_shadow_copy_symlink(vfs_handle_struct *handle,
- const char *oldpath, const char *newpath)
-{
- char *old_cpath = NULL;
- char *old_snap_component = NULL;
- char *new_cpath = NULL;
- char *new_snap_component = NULL;
- bool ret;
-
- if (shadow_copy_match_name(oldpath, &old_snap_component))
- old_cpath = osc_canonicalize_path(oldpath, old_snap_component);
-
- if (shadow_copy_match_name(newpath, &new_snap_component))
- new_cpath = osc_canonicalize_path(newpath, new_snap_component);
-
- ret = SMB_VFS_NEXT_SYMLINK(handle, old_cpath ?: oldpath,
- new_cpath ?: newpath);
-
- SAFE_FREE(old_cpath);
- SAFE_FREE(new_cpath);
-
- return ret;
-}
-
-static int
-onefs_shadow_copy_readlink(vfs_handle_struct *handle, const char *path,
- char *buf, size_t bufsiz)
-{
- SHADOW_NEXT(READLINK,
- (handle, cpath ?: path, buf, bufsiz),
- int);
-}
-
-/**
- * XXX: macro-ize
- */
-static int
-onefs_shadow_copy_link(vfs_handle_struct *handle, const char *oldpath,
- const char *newpath)
-{
- char *old_cpath = NULL;
- char *old_snap_component = NULL;
- char *new_cpath = NULL;
- char *new_snap_component = NULL;
- int ret;
-
- if (shadow_copy_match_name(oldpath, &old_snap_component))
- old_cpath = osc_canonicalize_path(oldpath, old_snap_component);
-
- if (shadow_copy_match_name(newpath, &new_snap_component))
- new_cpath = osc_canonicalize_path(newpath, new_snap_component);
-
- ret = SMB_VFS_NEXT_LINK(handle, old_cpath ?: oldpath,
- new_cpath ?: newpath);
-
- SAFE_FREE(old_cpath);
- SAFE_FREE(new_cpath);
-
- return ret;
-}
-
-static int
-onefs_shadow_copy_mknod(vfs_handle_struct *handle, const char *path,
- mode_t mode, SMB_DEV_T dev)
-{
- SHADOW_NEXT(MKNOD,
- (handle, cpath ?: path, mode, dev),
- int);
-}
-
-static char *
-onefs_shadow_copy_realpath(vfs_handle_struct *handle, const char *path)
-{
- SHADOW_NEXT(REALPATH,
- (handle, cpath ?: path),
- char *);
-}
-
-static int onefs_shadow_copy_chflags(struct vfs_handle_struct *handle,
- const char *path, unsigned int flags)
-{
- SHADOW_NEXT(CHFLAGS,
- (handle, cpath ?: path, flags),
- int);
-}
-
-static NTSTATUS
-onefs_shadow_copy_streaminfo(struct vfs_handle_struct *handle,
- struct files_struct *fsp,
- const char *path,
- TALLOC_CTX *mem_ctx,
- unsigned int *num_streams,
- struct stream_struct **streams)
-{
- SHADOW_NEXT(STREAMINFO,
- (handle, fsp, cpath ?: path, mem_ctx, num_streams,
- streams),
- NTSTATUS);
-}
-
-static int
-onefs_shadow_copy_get_real_filename(struct vfs_handle_struct *handle,
- const char *full_path,
- const char *path,
- TALLOC_CTX *mem_ctx,
- char **found_name)
-{
- SHADOW_NEXT(GET_REAL_FILENAME,
- (handle, full_path, cpath ?: path, mem_ctx, found_name),
- int);
-}
-
-static NTSTATUS
-onefs_shadow_copy_get_nt_acl(struct vfs_handle_struct *handle,
- const char *path, uint32 security_info,
- struct security_descriptor **ppdesc)
-{
- SHADOW_NEXT(GET_NT_ACL,
- (handle, cpath ?: path, security_info, ppdesc),
- NTSTATUS);
-}
-
-static int
-onefs_shadow_copy_chmod_acl(vfs_handle_struct *handle, const char *path,
- mode_t mode)
-{
- SHADOW_NEXT(CHMOD_ACL,
- (handle, cpath ?: path, mode),
- int);
-}
-
-static SMB_ACL_T
-onefs_shadow_copy_sys_acl_get_file(vfs_handle_struct *handle,
- const char *path, SMB_ACL_TYPE_T type)
-{
- SHADOW_NEXT(SYS_ACL_GET_FILE,
- (handle, cpath ?: path, type),
- SMB_ACL_T);
-}
-
-static int
-onefs_shadow_copy_sys_acl_set_file(vfs_handle_struct *handle, const char *path,
- SMB_ACL_TYPE_T type, SMB_ACL_T theacl)
-{
- SHADOW_NEXT(SYS_ACL_SET_FILE,
- (handle, cpath ?: path, type, theacl),
- int);
-}
-
-static int
-onefs_shadow_copy_sys_acl_delete_def_file(vfs_handle_struct *handle,
- const char *path)
-{
- SHADOW_NEXT(SYS_ACL_DELETE_DEF_FILE,
- (handle, cpath ?: path),
- int);
-}
-
-static ssize_t
-onefs_shadow_copy_getxattr(vfs_handle_struct *handle, const char *path,
- const char *name, void *value, size_t size)
-{
- SHADOW_NEXT(GETXATTR,
- (handle, cpath ?: path, name, value, size),
- ssize_t);
-}
-
-static ssize_t
-onefs_shadow_copy_listxattr(vfs_handle_struct *handle, const char *path,
- char *list, size_t size)
-{
- SHADOW_NEXT(LISTXATTR,
- (handle, cpath ?: path, list, size),
- ssize_t);
-}
-
-static int
-onefs_shadow_copy_removexattr(vfs_handle_struct *handle, const char *path,
- const char *name)
-{
- SHADOW_NEXT(REMOVEXATTR,
- (handle, cpath ?: path, name),
- int);
-}
-
-static int
-onefs_shadow_copy_setxattr(vfs_handle_struct *handle, const char *path,
- const char *name, const void *value, size_t size,
- int flags)
-{
- SHADOW_NEXT(SETXATTR,
- (handle, cpath ?: path, name, value, size, flags),
- int);
-}
-
-static bool
-onefs_shadow_copy_is_offline(struct vfs_handle_struct *handle,
- const struct smb_fname *fname,
- SMB_STRUCT_STAT *sbuf)
-{
-#error Isilon, please convert "char *path" to "struct smb_fname *fname"
- SHADOW_NEXT(IS_OFFLINE,
- (handle, cpath ?: path, sbuf),
- bool);
-}
-
-static int
-onefs_shadow_copy_set_offline(struct vfs_handle_struct *handle,
- const struct smb_filename *fname)
-{
-#error Isilon, please convert "char *path" to "struct smb_fname *fname"
- SHADOW_NEXT(SET_OFFLINE,
- (handle, cpath ?: path),
- int);
-}
-
-/* VFS operations structure */
-
-static struct vfs_fn_pointers onefs_shadow_copy_fns = {
- .disk_free_fn = onefs_shadow_copy_disk_free,
- .get_shadow_copy_data_fn = onefs_shadow_copy_get_shadow_copy_data,
- .statvfs_fn = onefs_shadow_copy_statvfs,
- .opendir_fn = onefs_shadow_copy_opendir,
- .mkdir_fn = onefs_shadow_copy_mkdir,
- .rmdir_fn = onefs_shadow_copy_rmdir,
- .open_fn = onefs_shadow_copy_open,
- .create_file_fn = onefs_shadow_copy_create_file,
- .rename_fn = onefs_shadow_copy_rename,
- .stat_fn = onefs_shadow_copy_stat,
- .stat_fn = onefs_shadow_copy_stat,
- .lstat_fn = onefs_shadow_copy_lstat,
- .unlink_fn = onefs_shadow_copy_unlink,
- .chmod_fn = onefs_shadow_copy_chmod,
- .chown_fn = onefs_shadow_copy_chown,
- .lchown_fn = onefs_shadow_copy_lchown,
- .chdir_fn = onefs_shadow_copy_chdir,
- .ntimes_fn = onefs_shadow_copy_ntimes,
- .symlink_fn = onefs_shadow_copy_symlink,
- .readlink_fn = onefs_shadow_copy_readlink,
- .link_fn = onefs_shadow_copy_link,
- .mknod_fn = onefs_shadow_copy_mknod,
- .realpath_fn = onefs_shadow_copy_realpath,
- .chflags_fn = onefs_shadow_copy_chflags,
- .streaminfo_fn = onefs_shadow_copy_streaminfo,
- .get_real_filename_fn = onefs_shadow_copy_get_real_filename,
- .get_nt_acl_fn = onefs_shadow_copy_get_nt_acl,
- .chmod_acl_fn = onefs_shadow_copy_chmod_acl,
- .sys_acl_get_file_fn = onefs_shadow_copy_sys_acl_get_file,
- .sys_acl_set_file_fn = onefs_shadow_copy_sys_acl_set_file,
- .sys_acl_delete_def_file_fn = onefs_shadow_copy_sys_acl_delete_def_file,
- .getxattr_fn = onefs_shadow_copy_getxattr,
- .listxattr_fn = onefs_shadow_copy_listxattr,
- .removexattr_fn = onefs_shadow_copy_removexattr,
- .setxattr_fn = onefs_shadow_copy_setxattr,
- .lsetxattr_fn = onefs_shadow_copy_lsetxattr,
- .is_offline_fn = onefs_shadow_copy_is_offline,
- .set_offline_fn = onefs_shadow_copy_set_offline,
-};
-
-NTSTATUS vfs_shadow_copy_init(void)
-{
- NTSTATUS ret;
-
- ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
- "onefs_shadow_copy",
- &onefs_shadow_copy_fns);
-
- if (!NT_STATUS_IS_OK(ret))
- return ret;
-
- vfs_onefs_shadow_copy_debug_level = debug_add_class("onefs_shadow_copy");
-
- if (vfs_onefs_shadow_copy_debug_level == -1) {
- vfs_onefs_shadow_copy_debug_level = DBGC_VFS;
- DEBUG(0, ("Couldn't register custom debugging class!\n"));
- } else {
- DEBUG(10, ("Debug class number of 'onefs_shadow_copy': %d\n",
- vfs_onefs_shadow_copy_debug_level));
- }
-
- return ret;
-}
diff --git a/source3/modules/wscript_build b/source3/modules/wscript_build
index 9607c34abe..3b257bcf66 100644
--- a/source3/modules/wscript_build
+++ b/source3/modules/wscript_build
@@ -43,10 +43,6 @@ VFS_SYNCOPS_SRC = 'vfs_syncops.c'
VFS_ACL_XATTR_SRC = 'vfs_acl_xattr.c'
VFS_ACL_TDB_SRC = 'vfs_acl_tdb.c'
VFS_SMB_TRAFFIC_ANALYZER_SRC = 'vfs_smb_traffic_analyzer.c'
-VFS_ONEFS_SRC = '''vfs_onefs.c onefs_acl.c onefs_system.c
- onefs_open.c onefs_streams.c onefs_dir.c
- onefs_cbrl.c onefs_notify.c onefs_config.c'''
-VFS_ONEFS_SHADOW_COPY_SRC = 'vfs_onefs_shadow_copy.c onefs_shadow_copy.c'
VFS_DIRSORT_SRC = 'vfs_dirsort.c'
VFS_SCANNEDONLY_SRC = 'vfs_scannedonly.c'
VFS_CROSSRENAME_SRC = 'vfs_crossrename.c'
@@ -416,22 +412,6 @@ bld.SAMBA3_MODULE('vfs_smb_traffic_analyzer',
internal_module=bld.SAMBA3_IS_STATIC_MODULE('vfs_smb_traffic_analyzer'),
enabled=bld.SAMBA3_IS_ENABLED_MODULE('vfs_smb_traffic_analyzer'))
-bld.SAMBA3_MODULE('vfs_onefs',
- subsystem='vfs',
- source=VFS_ONEFS_SRC,
- deps='samba-util',
- init_function='',
- internal_module=bld.SAMBA3_IS_STATIC_MODULE('vfs_onefs'),
- enabled=bld.SAMBA3_IS_ENABLED_MODULE('vfs_onefs'))
-
-bld.SAMBA3_MODULE('vfs_onefs_shadow_copy',
- subsystem='vfs',
- source=VFS_ONEFS_SHADOW_COPY_SRC,
- deps='samba-util',
- init_function='',
- internal_module=bld.SAMBA3_IS_STATIC_MODULE('vfs_onefs_shadow_copy'),
- enabled=bld.SAMBA3_IS_ENABLED_MODULE('vfs_onefs_shadow_copy'))
-
bld.SAMBA3_MODULE('vfs_dirsort',
subsystem='vfs',
source=VFS_DIRSORT_SRC,
@@ -480,20 +460,12 @@ bld.SAMBA3_MODULE('vfs_dfs_samba4',
internal_module=bld.SAMBA3_IS_STATIC_MODULE('vfs_dfs_samba4'),
enabled=bld.SAMBA3_IS_ENABLED_MODULE('vfs_dfs_samba4'))
-PERFCOUNT_ONEFS_SRC = 'perfcount_onefs.c'
PERFCOUNT_TEST_SRC = 'perfcount_test.c'
bld.SAMBA3_SUBSYSTEM('perfcount',
source='',
deps='smbd_base')
-bld.SAMBA3_MODULE('perfcount_onefs',
- subsystem='perfcount',
- source=PERFCOUNT_ONEFS_SRC,
- init_function='',
- internal_module=bld.SAMBA3_IS_STATIC_MODULE('perfcount_onefs'),
- enabled=bld.SAMBA3_IS_ENABLED_MODULE('perfcount_onefs'))
-
bld.SAMBA3_MODULE('perfcount_test',
subsystem='perfcount',
source=PERFCOUNT_TEST_SRC,