return NT_STATUS_OK;
}
+int onefs_is_stream(const char *path, char **pbase, char **pstream,
+ bool *is_stream)
+{
+ (*is_stream) = is_ntfs_stream_name(path);
+
+ if (!(*is_stream)) {
+ return 0;
+ }
+
+ if (!NT_STATUS_IS_OK(onefs_split_ntfs_stream_name(talloc_tos(), path,
+ pbase, pstream))) {
+ DEBUG(10, ("onefs_split_ntfs_stream_name failed\n"));
+ errno = ENOMEM;
+ return -1;
+ }
+
+ return 0;
+}
+
int onefs_close(vfs_handle_struct *handle, struct files_struct *fsp)
{
int ret2, ret = 0;
char *nbase = NULL;
char *nsname = NULL;
- old_is_stream = is_ntfs_stream_name(oldname);
- new_is_stream = is_ntfs_stream_name(newname);
-
- if (!old_is_stream && !new_is_stream) {
- return SMB_VFS_NEXT_RENAME(handle, oldname, newname);
- }
-
frame = talloc_stackframe();
- if (!NT_STATUS_IS_OK(onefs_split_ntfs_stream_name(talloc_tos(),
- oldname, &obase,
- &osname))) {
- errno = ENOMEM;
- goto done;
- }
+ ret = onefs_is_stream(oldname, &obase, &osname, &old_is_stream);
+ if (ret)
+ return ret;
- if (!NT_STATUS_IS_OK(onefs_split_ntfs_stream_name(talloc_tos(),
- newname, &nbase,
- &nsname))) {
- errno = ENOMEM;
- goto done;
+ ret = onefs_is_stream(newname, &nbase, &nsname, &new_is_stream);
+ if (ret)
+ return ret;
+
+ if (!old_is_stream && !new_is_stream) {
+ return SMB_VFS_NEXT_RENAME(handle, oldname, newname);
}
dir_fd = get_stream_dir_fd(handle->conn, obase, NULL);
int onefs_stat(vfs_handle_struct *handle, const char *path,
SMB_STRUCT_STAT *sbuf)
{
+ int ret;
+ bool is_stream;
char *base = NULL;
char *stream = NULL;
- if (!is_ntfs_stream_name(path)) {
- return SMB_VFS_NEXT_STAT(handle, path, sbuf);
- }
+ ret = onefs_is_stream(path, &base, &stream, &is_stream);
+ if (ret)
+ return ret;
- if (!NT_STATUS_IS_OK(onefs_split_ntfs_stream_name(talloc_tos(), path,
- &base, &stream))) {
- DEBUG(10, ("onefs_split_ntfs_stream_name failed\n"));
- errno = ENOMEM;
- return -1;
+ if (!is_stream) {
+ return SMB_VFS_NEXT_STAT(handle, path, sbuf);
}
/* If it's the ::$DATA stream just stat the base file name. */
int onefs_lstat(vfs_handle_struct *handle, const char *path,
SMB_STRUCT_STAT *sbuf)
{
+ int ret;
+ bool is_stream;
char *base = NULL;
char *stream = NULL;
- if (!is_ntfs_stream_name(path)) {
- return SMB_VFS_NEXT_LSTAT(handle, path, sbuf);
- }
+ ret = onefs_is_stream(path, &base, &stream, &is_stream);
+ if (ret)
+ return ret;
- if (!NT_STATUS_IS_OK(onefs_split_ntfs_stream_name(talloc_tos(), path,
- &base, &stream))) {
- DEBUG(10, ("onefs_split_ntfs_stream_name failed\n"));
- errno = ENOMEM;
- return -1;
+ if (!is_stream) {
+ return SMB_VFS_NEXT_LSTAT(handle, path, sbuf);
}
/* If it's the ::$DATA stream just stat the base file name. */
int onefs_unlink(vfs_handle_struct *handle, const char *path)
{
+ int ret;
+ bool is_stream;
char *base = NULL;
char *stream = NULL;
- int dir_fd, ret, saved_errno;
+ int dir_fd, saved_errno;
- if (!is_ntfs_stream_name(path)) {
- return SMB_VFS_NEXT_UNLINK(handle, path);
+ ret = onefs_is_stream(path, &base, &stream, &is_stream);
+ if (ret) {
+ return ret;
}
- if (!NT_STATUS_IS_OK(onefs_split_ntfs_stream_name(talloc_tos(), path,
- &base, &stream))) {
- DEBUG(10, ("onefs_split_ntfs_stream_name failed\n"));
- errno = ENOMEM;
- return -1;
+ if (!is_stream) {
+ return SMB_VFS_NEXT_UNLINK(handle, path);
}
/* If it's the ::$DATA stream just unlink the base file name. */
return ret;
}
+int onefs_vtimes_streams(vfs_handle_struct *handle, const char *fname,
+ int flags, struct timespec times[3])
+{
+ int ret;
+ bool is_stream;
+ char *base;
+ char *stream;
+ int dirfd;
+ int saved_errno;
+
+ START_PROFILE(syscall_ntimes);
+
+ ret = onefs_is_stream(fname, &base, &stream, &is_stream);
+ if (ret)
+ return ret;
+
+ if (!is_stream) {
+ ret = vtimes(fname, times, flags);
+ return ret;
+ }
+
+ dirfd = get_stream_dir_fd(handle->conn, base, NULL);
+ if (dirfd < -1) {
+ return -1;
+ }
+
+ ret = enc_vtimesat(dirfd, stream, ENC_DEFAULT, times, flags);
+
+ END_PROFILE(syscall_ntimes);
+
+ saved_errno = errno;
+ close(dirfd);
+ errno = saved_errno;
+ return ret;
+}
+
int onefs_chflags(vfs_handle_struct *handle, const char *path,
unsigned int flags)
{
return result;
}
+static int onefs_ntimes(vfs_handle_struct *handle, const char *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, fname, flags, times);
+}
+
static uint32_t onefs_fs_capabilities(struct vfs_handle_struct *handle)
{
return SMB_VFS_NEXT_FS_CAPABILITIES(handle) | FILE_NAMED_STREAMS;
SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(onefs_unlink), SMB_VFS_OP_UNLINK,
SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(onefs_ntimes), SMB_VFS_OP_NTIMES,
+ SMB_VFS_LAYER_OPAQUE},
{SMB_VFS_OP(onefs_chflags), SMB_VFS_OP_CHFLAGS,
SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(onefs_streaminfo), SMB_VFS_OP_STREAMINFO,