2 * Unix SMB/CIFS implementation.
5 * Copyright (C) Tim Prouty, 2008
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
23 #include "onefs_config.h"
26 #define DBGC_CLASS DBGC_VFS
28 static int onefs_connect(struct vfs_handle_struct
*handle
, const char *service
,
33 ret
= onefs_load_config(handle
->conn
);
35 DEBUG(3, ("Load config failed: %s\n", strerror(errno
)));
39 return SMB_VFS_NEXT_CONNECT(handle
, service
, user
);
42 static int onefs_mkdir(vfs_handle_struct
*handle
, const char *path
,
45 /* SMB_VFS_MKDIR should never be called in vfs_onefs */
47 return SMB_VFS_NEXT_MKDIR(handle
, path
, mode
);
50 static int onefs_open(vfs_handle_struct
*handle
,
51 struct smb_filename
*smb_fname
,
52 files_struct
*fsp
, int flags
, mode_t mode
)
54 /* SMB_VFS_OPEN should never be called in vfs_onefs */
56 return SMB_VFS_NEXT_OPEN(handle
, smb_fname
, fsp
, flags
, mode
);
59 static ssize_t
onefs_sendfile(vfs_handle_struct
*handle
, int tofd
,
60 files_struct
*fromfsp
, const DATA_BLOB
*header
,
61 SMB_OFF_T offset
, size_t count
)
65 START_PROFILE_BYTES(syscall_sendfile
, count
);
66 result
= onefs_sys_sendfile(handle
->conn
, tofd
, fromfsp
->fh
->fd
,
67 header
, offset
, count
);
68 END_PROFILE(syscall_sendfile
);
72 static ssize_t
onefs_recvfile(vfs_handle_struct
*handle
, int fromfd
,
73 files_struct
*tofsp
, SMB_OFF_T offset
,
78 START_PROFILE_BYTES(syscall_recvfile
, count
);
79 result
= onefs_sys_recvfile(fromfd
, tofsp
->fh
->fd
, offset
, count
);
80 END_PROFILE(syscall_recvfile
);
84 static uint64_t onefs_get_alloc_size(struct vfs_handle_struct
*handle
,
86 const SMB_STRUCT_STAT
*sbuf
)
90 START_PROFILE(syscall_get_alloc_size
);
92 if(S_ISDIR(sbuf
->st_ex_mode
)) {
97 /* Just use the file size since st_blocks is unreliable on OneFS. */
98 result
= get_file_size_stat(sbuf
);
100 if (fsp
&& fsp
->initial_allocation_size
)
101 result
= MAX(result
,fsp
->initial_allocation_size
);
103 result
= smb_roundup(handle
->conn
, result
);
106 END_PROFILE(syscall_get_alloc_size
);
110 static struct file_id
onefs_file_id_create(struct vfs_handle_struct
*handle
,
111 const SMB_STRUCT_STAT
*sbuf
)
115 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
119 key
.devid
= sbuf
->st_ex_dev
;
120 key
.inode
= sbuf
->st_ex_ino
;
121 key
.extid
= sbuf
->vfs_private
;
126 static int onefs_statvfs(vfs_handle_struct
*handle
, const char *path
,
127 vfs_statvfs_struct
*statbuf
)
129 struct statvfs statvfs_buf
;
132 DEBUG(5, ("Calling SMB_STAT_VFS \n"));
133 result
= statvfs(path
, &statvfs_buf
);
134 ZERO_STRUCTP(statbuf
);
137 statbuf
->OptimalTransferSize
= statvfs_buf
.f_iosize
;
138 statbuf
->BlockSize
= statvfs_buf
.f_bsize
;
139 statbuf
->TotalBlocks
= statvfs_buf
.f_blocks
;
140 statbuf
->BlocksAvail
= statvfs_buf
.f_bfree
;
141 statbuf
->UserBlocksAvail
= statvfs_buf
.f_bavail
;
142 statbuf
->TotalFileNodes
= statvfs_buf
.f_files
;
143 statbuf
->FreeFileNodes
= statvfs_buf
.f_ffree
;
144 statbuf
->FsIdentifier
=
145 (((uint64_t)statvfs_buf
.f_fsid
.val
[0]<<32) &
146 0xffffffff00000000LL
) |
147 (uint64_t)statvfs_buf
.f_fsid
.val
[1];
152 static int onefs_get_real_filename(vfs_handle_struct
*handle
, const char *path
,
153 const char *name
, TALLOC_CTX
*mem_ctx
,
157 struct connection_struct
*conn
= handle
->conn
;
158 struct stat_extra se
;
160 char *unmangled_name
= NULL
;
161 char *full_name
= NULL
;
163 /* First demangle the name if necessary. */
164 if (!conn
->case_sensitive
&& mangle_is_mangled(name
, conn
->params
) &&
165 mangle_lookup_name_from_8_3(mem_ctx
, name
, &unmangled_name
,
167 /* Name is now unmangled. */
168 name
= unmangled_name
;
171 /* Do the case insensitive stat. */
173 se
.se_version
= ESTAT_CURRENT_VERSION
;
174 se
.se_flags
= ESTAT_CASE_INSENSITIVE
| ESTAT_SYMLINK_NOFOLLOW
;
177 if (!(full_name
= talloc_asprintf(mem_ctx
, "%s/%s", path
, name
))) {
179 DEBUG(2, ("talloc_asprintf failed\n"));
185 if ((result
= estat(full_name
? full_name
: name
, &sb
, &se
)) != 0) {
186 DEBUG(2, ("error calling estat: %s\n", strerror(errno
)));
190 *found_name
= talloc_strdup(mem_ctx
, se
.se_realname
);
191 if (*found_name
== NULL
) {
198 TALLOC_FREE(full_name
);
199 TALLOC_FREE(unmangled_name
);
203 static int onefs_ntimes(vfs_handle_struct
*handle
,
204 const struct smb_filename
*smb_fname
,
205 struct smb_file_time
*ft
)
208 struct timespec times
[3];
210 if (!null_timespec(ft
->atime
)) {
212 times
[0] = ft
->atime
;
213 DEBUG(6,("**** onefs_ntimes: actime: %s.%d\n",
214 time_to_asc(convert_timespec_to_time_t(ft
->atime
)),
218 if (!null_timespec(ft
->mtime
)) {
220 times
[1] = ft
->mtime
;
221 DEBUG(6,("**** onefs_ntimes: modtime: %s.%d\n",
222 time_to_asc(convert_timespec_to_time_t(ft
->mtime
)),
226 if (!null_timespec(ft
->create_time
)) {
228 times
[2] = ft
->create_time
;
229 DEBUG(6,("**** onefs_ntimes: createtime: %s.%d\n",
230 time_to_asc(convert_timespec_to_time_t(ft
->create_time
)),
231 ft
->create_time
.tv_nsec
));
234 return onefs_vtimes_streams(handle
, smb_fname
, flags
, times
);
237 static uint32_t onefs_fs_capabilities(struct vfs_handle_struct
*handle
, enum timestamp_set_resolution
*p_ts_res
)
241 if (!lp_parm_bool(SNUM(handle
->conn
), PARM_ONEFS_TYPE
,
242 PARM_IGNORE_STREAMS
, PARM_IGNORE_STREAMS_DEFAULT
)) {
243 result
|= FILE_NAMED_STREAMS
;
246 result
|= SMB_VFS_NEXT_FS_CAPABILITIES(handle
, p_ts_res
);
247 *p_ts_res
= TIMESTAMP_SET_MSEC
;
251 static struct vfs_fn_pointers onefs_fns
= {
252 .connect_fn
= onefs_connect
,
253 .fs_capabilities
= onefs_fs_capabilities
,
254 .opendir
= onefs_opendir
,
255 .readdir
= onefs_readdir
,
256 .seekdir
= onefs_seekdir
,
257 .telldir
= onefs_telldir
,
258 .rewind_dir
= onefs_rewinddir
,
259 .mkdir
= onefs_mkdir
,
260 .closedir
= onefs_closedir
,
261 .init_search_op
= onefs_init_search_op
,
263 .create_file
= onefs_create_file
,
264 .close_fn
= onefs_close
,
265 .sendfile
= onefs_sendfile
,
266 .recvfile
= onefs_recvfile
,
267 .rename
= onefs_rename
,
269 .fstat
= onefs_fstat
,
270 .lstat
= onefs_lstat
,
271 .get_alloc_size
= onefs_get_alloc_size
,
272 .unlink
= onefs_unlink
,
273 .ntimes
= onefs_ntimes
,
274 .file_id_create
= onefs_file_id_create
,
275 .streaminfo
= onefs_streaminfo
,
276 .brl_lock_windows
= onefs_brl_lock_windows
,
277 .brl_unlock_windows
= onefs_brl_unlock_windows
,
278 .brl_cancel_windows
= onefs_brl_cancel_windows
,
279 .strict_lock
= onefs_strict_lock
,
280 .strict_unlock
= onefs_strict_unlock
,
281 .notify_watch
= onefs_notify_watch
,
282 .fget_nt_acl
= onefs_fget_nt_acl
,
283 .get_nt_acl
= onefs_get_nt_acl
,
284 .fset_nt_acl
= onefs_fset_nt_acl
,
285 .statvfs
= onefs_statvfs
,
286 .get_real_filename
= onefs_get_real_filename
,
289 NTSTATUS
vfs_onefs_init(void)
291 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION
, "onefs",