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
,
31 int ret
= SMB_VFS_NEXT_CONNECT(handle
, service
, user
);
37 ret
= onefs_load_config(handle
->conn
);
39 SMB_VFS_NEXT_DISCONNECT(handle
);
40 DEBUG(3, ("Load config failed: %s\n", strerror(errno
)));
47 static int onefs_mkdir(vfs_handle_struct
*handle
, const char *path
,
50 /* SMB_VFS_MKDIR should never be called in vfs_onefs */
52 return SMB_VFS_NEXT_MKDIR(handle
, path
, mode
);
55 static int onefs_open(vfs_handle_struct
*handle
,
56 struct smb_filename
*smb_fname
,
57 files_struct
*fsp
, int flags
, mode_t mode
)
59 /* SMB_VFS_OPEN should never be called in vfs_onefs */
61 return SMB_VFS_NEXT_OPEN(handle
, smb_fname
, fsp
, flags
, mode
);
64 static ssize_t
onefs_sendfile(vfs_handle_struct
*handle
, int tofd
,
65 files_struct
*fromfsp
, const DATA_BLOB
*header
,
66 SMB_OFF_T offset
, size_t count
)
70 START_PROFILE_BYTES(syscall_sendfile
, count
);
71 result
= onefs_sys_sendfile(handle
->conn
, tofd
, fromfsp
->fh
->fd
,
72 header
, offset
, count
);
73 END_PROFILE(syscall_sendfile
);
77 static ssize_t
onefs_recvfile(vfs_handle_struct
*handle
, int fromfd
,
78 files_struct
*tofsp
, SMB_OFF_T offset
,
83 START_PROFILE_BYTES(syscall_recvfile
, count
);
84 result
= onefs_sys_recvfile(fromfd
, tofsp
->fh
->fd
, offset
, count
);
85 END_PROFILE(syscall_recvfile
);
89 static uint64_t onefs_get_alloc_size(struct vfs_handle_struct
*handle
,
91 const SMB_STRUCT_STAT
*sbuf
)
95 START_PROFILE(syscall_get_alloc_size
);
97 if(S_ISDIR(sbuf
->st_ex_mode
)) {
102 /* Just use the file size since st_blocks is unreliable on OneFS. */
103 result
= get_file_size_stat(sbuf
);
105 if (fsp
&& fsp
->initial_allocation_size
)
106 result
= MAX(result
,fsp
->initial_allocation_size
);
108 result
= smb_roundup(handle
->conn
, result
);
111 END_PROFILE(syscall_get_alloc_size
);
115 static struct file_id
onefs_file_id_create(struct vfs_handle_struct
*handle
,
116 const SMB_STRUCT_STAT
*sbuf
)
120 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
124 key
.devid
= sbuf
->st_ex_dev
;
125 key
.inode
= sbuf
->st_ex_ino
;
126 key
.extid
= sbuf
->vfs_private
;
131 static int onefs_statvfs(vfs_handle_struct
*handle
, const char *path
,
132 vfs_statvfs_struct
*statbuf
)
134 struct statvfs statvfs_buf
;
137 DEBUG(5, ("Calling SMB_STAT_VFS \n"));
138 result
= statvfs(path
, &statvfs_buf
);
139 ZERO_STRUCTP(statbuf
);
142 statbuf
->OptimalTransferSize
= statvfs_buf
.f_iosize
;
143 statbuf
->BlockSize
= statvfs_buf
.f_bsize
;
144 statbuf
->TotalBlocks
= statvfs_buf
.f_blocks
;
145 statbuf
->BlocksAvail
= statvfs_buf
.f_bfree
;
146 statbuf
->UserBlocksAvail
= statvfs_buf
.f_bavail
;
147 statbuf
->TotalFileNodes
= statvfs_buf
.f_files
;
148 statbuf
->FreeFileNodes
= statvfs_buf
.f_ffree
;
149 statbuf
->FsIdentifier
=
150 (((uint64_t)statvfs_buf
.f_fsid
.val
[0]<<32) &
151 0xffffffff00000000LL
) |
152 (uint64_t)statvfs_buf
.f_fsid
.val
[1];
157 static int onefs_get_real_filename(vfs_handle_struct
*handle
, const char *path
,
158 const char *name
, TALLOC_CTX
*mem_ctx
,
162 struct connection_struct
*conn
= handle
->conn
;
163 struct stat_extra se
;
165 char *unmangled_name
= NULL
;
166 char *full_name
= NULL
;
168 /* First demangle the name if necessary. */
169 if (!conn
->case_sensitive
&& mangle_is_mangled(name
, conn
->params
) &&
170 mangle_lookup_name_from_8_3(mem_ctx
, name
, &unmangled_name
,
172 /* Name is now unmangled. */
173 name
= unmangled_name
;
176 /* Do the case insensitive stat. */
178 se
.se_version
= ESTAT_CURRENT_VERSION
;
179 se
.se_flags
= ESTAT_CASE_INSENSITIVE
| ESTAT_SYMLINK_NOFOLLOW
;
182 if (!(full_name
= talloc_asprintf(mem_ctx
, "%s/%s", path
, name
))) {
184 DEBUG(2, ("talloc_asprintf failed\n"));
190 if ((result
= estat(full_name
? full_name
: name
, &sb
, &se
)) != 0) {
191 DEBUG(2, ("error calling estat: %s\n", strerror(errno
)));
195 *found_name
= talloc_strdup(mem_ctx
, se
.se_realname
);
196 if (*found_name
== NULL
) {
203 TALLOC_FREE(full_name
);
204 TALLOC_FREE(unmangled_name
);
208 static int onefs_ntimes(vfs_handle_struct
*handle
,
209 const struct smb_filename
*smb_fname
,
210 struct smb_file_time
*ft
)
213 struct timespec times
[3];
215 if (!null_timespec(ft
->atime
)) {
217 times
[0] = ft
->atime
;
218 DEBUG(6,("**** onefs_ntimes: actime: %s.%d\n",
219 time_to_asc(convert_timespec_to_time_t(ft
->atime
)),
223 if (!null_timespec(ft
->mtime
)) {
225 times
[1] = ft
->mtime
;
226 DEBUG(6,("**** onefs_ntimes: modtime: %s.%d\n",
227 time_to_asc(convert_timespec_to_time_t(ft
->mtime
)),
231 if (!null_timespec(ft
->create_time
)) {
233 times
[2] = ft
->create_time
;
234 DEBUG(6,("**** onefs_ntimes: createtime: %s.%d\n",
235 time_to_asc(convert_timespec_to_time_t(ft
->create_time
)),
236 ft
->create_time
.tv_nsec
));
239 return onefs_vtimes_streams(handle
, smb_fname
, flags
, times
);
242 static uint32_t onefs_fs_capabilities(struct vfs_handle_struct
*handle
, enum timestamp_set_resolution
*p_ts_res
)
246 if (!lp_parm_bool(SNUM(handle
->conn
), PARM_ONEFS_TYPE
,
247 PARM_IGNORE_STREAMS
, PARM_IGNORE_STREAMS_DEFAULT
)) {
248 result
|= FILE_NAMED_STREAMS
;
251 result
|= SMB_VFS_NEXT_FS_CAPABILITIES(handle
, p_ts_res
);
252 *p_ts_res
= TIMESTAMP_SET_MSEC
;
256 static struct vfs_fn_pointers onefs_fns
= {
257 .connect_fn
= onefs_connect
,
258 .fs_capabilities
= onefs_fs_capabilities
,
259 .opendir
= onefs_opendir
,
260 .readdir
= onefs_readdir
,
261 .seekdir
= onefs_seekdir
,
262 .telldir
= onefs_telldir
,
263 .rewind_dir
= onefs_rewinddir
,
264 .mkdir
= onefs_mkdir
,
265 .closedir
= onefs_closedir
,
266 .init_search_op
= onefs_init_search_op
,
268 .create_file
= onefs_create_file
,
269 .close_fn
= onefs_close
,
270 .sendfile
= onefs_sendfile
,
271 .recvfile
= onefs_recvfile
,
272 .rename
= onefs_rename
,
274 .fstat
= onefs_fstat
,
275 .lstat
= onefs_lstat
,
276 .get_alloc_size
= onefs_get_alloc_size
,
277 .unlink
= onefs_unlink
,
278 .ntimes
= onefs_ntimes
,
279 .file_id_create
= onefs_file_id_create
,
280 .streaminfo
= onefs_streaminfo
,
281 .brl_lock_windows
= onefs_brl_lock_windows
,
282 .brl_unlock_windows
= onefs_brl_unlock_windows
,
283 .brl_cancel_windows
= onefs_brl_cancel_windows
,
284 .strict_lock
= onefs_strict_lock
,
285 .strict_unlock
= onefs_strict_unlock
,
286 .notify_watch
= onefs_notify_watch
,
287 .fget_nt_acl
= onefs_fget_nt_acl
,
288 .get_nt_acl
= onefs_get_nt_acl
,
289 .fset_nt_acl
= onefs_fset_nt_acl
,
290 .statvfs
= onefs_statvfs
,
291 .get_real_filename
= onefs_get_real_filename
,
294 NTSTATUS
vfs_onefs_init(void)
296 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION
, "onefs",