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/>.
22 #include "smbd/smbd.h"
24 #include "onefs_config.h"
27 #define DBGC_CLASS DBGC_VFS
29 static int onefs_connect(struct vfs_handle_struct
*handle
, const char *service
,
32 int ret
= SMB_VFS_NEXT_CONNECT(handle
, service
, user
);
38 ret
= onefs_load_config(handle
->conn
);
40 SMB_VFS_NEXT_DISCONNECT(handle
);
41 DEBUG(3, ("Load config failed: %s\n", strerror(errno
)));
48 static int onefs_mkdir(vfs_handle_struct
*handle
, const char *path
,
51 /* SMB_VFS_MKDIR should never be called in vfs_onefs */
53 return SMB_VFS_NEXT_MKDIR(handle
, path
, mode
);
56 static int onefs_open(vfs_handle_struct
*handle
,
57 struct smb_filename
*smb_fname
,
58 files_struct
*fsp
, int flags
, mode_t mode
)
60 /* SMB_VFS_OPEN should never be called in vfs_onefs */
62 return SMB_VFS_NEXT_OPEN(handle
, smb_fname
, fsp
, flags
, mode
);
65 static ssize_t
onefs_sendfile(vfs_handle_struct
*handle
, int tofd
,
66 files_struct
*fromfsp
, const DATA_BLOB
*header
,
67 SMB_OFF_T offset
, size_t count
)
71 START_PROFILE_BYTES(syscall_sendfile
, count
);
72 result
= onefs_sys_sendfile(handle
->conn
, tofd
, fromfsp
->fh
->fd
,
73 header
, offset
, count
);
74 END_PROFILE(syscall_sendfile
);
78 static ssize_t
onefs_recvfile(vfs_handle_struct
*handle
, int fromfd
,
79 files_struct
*tofsp
, SMB_OFF_T offset
,
84 START_PROFILE_BYTES(syscall_recvfile
, count
);
85 result
= onefs_sys_recvfile(fromfd
, tofsp
->fh
->fd
, offset
, count
);
86 END_PROFILE(syscall_recvfile
);
90 static uint64_t onefs_get_alloc_size(struct vfs_handle_struct
*handle
,
92 const SMB_STRUCT_STAT
*sbuf
)
96 START_PROFILE(syscall_get_alloc_size
);
98 if(S_ISDIR(sbuf
->st_ex_mode
)) {
103 /* Just use the file size since st_blocks is unreliable on OneFS. */
104 result
= get_file_size_stat(sbuf
);
106 if (fsp
&& fsp
->initial_allocation_size
)
107 result
= MAX(result
,fsp
->initial_allocation_size
);
109 result
= smb_roundup(handle
->conn
, result
);
112 END_PROFILE(syscall_get_alloc_size
);
116 static struct file_id
onefs_file_id_create(struct vfs_handle_struct
*handle
,
117 const SMB_STRUCT_STAT
*sbuf
)
121 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
125 key
.devid
= sbuf
->st_ex_dev
;
126 key
.inode
= sbuf
->st_ex_ino
;
127 key
.extid
= sbuf
->vfs_private
;
132 static int onefs_statvfs(vfs_handle_struct
*handle
, const char *path
,
133 vfs_statvfs_struct
*statbuf
)
135 struct statvfs statvfs_buf
;
138 DEBUG(5, ("Calling SMB_STAT_VFS \n"));
139 result
= statvfs(path
, &statvfs_buf
);
140 ZERO_STRUCTP(statbuf
);
143 statbuf
->OptimalTransferSize
= statvfs_buf
.f_iosize
;
144 statbuf
->BlockSize
= statvfs_buf
.f_bsize
;
145 statbuf
->TotalBlocks
= statvfs_buf
.f_blocks
;
146 statbuf
->BlocksAvail
= statvfs_buf
.f_bfree
;
147 statbuf
->UserBlocksAvail
= statvfs_buf
.f_bavail
;
148 statbuf
->TotalFileNodes
= statvfs_buf
.f_files
;
149 statbuf
->FreeFileNodes
= statvfs_buf
.f_ffree
;
150 statbuf
->FsIdentifier
=
151 (((uint64_t)statvfs_buf
.f_fsid
.val
[0]<<32) &
152 0xffffffff00000000LL
) |
153 (uint64_t)statvfs_buf
.f_fsid
.val
[1];
158 static int onefs_get_real_filename(vfs_handle_struct
*handle
, const char *path
,
159 const char *name
, TALLOC_CTX
*mem_ctx
,
163 struct connection_struct
*conn
= handle
->conn
;
164 struct stat_extra se
;
166 char *unmangled_name
= NULL
;
167 char *full_name
= NULL
;
169 /* First demangle the name if necessary. */
170 if (!conn
->case_sensitive
&& mangle_is_mangled(name
, conn
->params
) &&
171 mangle_lookup_name_from_8_3(mem_ctx
, name
, &unmangled_name
,
173 /* Name is now unmangled. */
174 name
= unmangled_name
;
177 /* Do the case insensitive stat. */
179 se
.se_version
= ESTAT_CURRENT_VERSION
;
180 se
.se_flags
= ESTAT_CASE_INSENSITIVE
| ESTAT_SYMLINK_NOFOLLOW
;
183 if (!(full_name
= talloc_asprintf(mem_ctx
, "%s/%s", path
, name
))) {
185 DEBUG(2, ("talloc_asprintf failed\n"));
191 if ((result
= estat(full_name
? full_name
: name
, &sb
, &se
)) != 0) {
192 DEBUG(2, ("error calling estat: %s\n", strerror(errno
)));
196 *found_name
= talloc_strdup(mem_ctx
, se
.se_realname
);
197 if (*found_name
== NULL
) {
204 TALLOC_FREE(full_name
);
205 TALLOC_FREE(unmangled_name
);
209 static int onefs_ntimes(vfs_handle_struct
*handle
,
210 const struct smb_filename
*smb_fname
,
211 struct smb_file_time
*ft
)
214 struct timespec times
[3];
216 if (!null_timespec(ft
->atime
)) {
218 times
[0] = ft
->atime
;
219 DEBUG(6,("**** onefs_ntimes: actime: %s.%d\n",
220 time_to_asc(convert_timespec_to_time_t(ft
->atime
)),
224 if (!null_timespec(ft
->mtime
)) {
226 times
[1] = ft
->mtime
;
227 DEBUG(6,("**** onefs_ntimes: modtime: %s.%d\n",
228 time_to_asc(convert_timespec_to_time_t(ft
->mtime
)),
232 if (!null_timespec(ft
->create_time
)) {
234 times
[2] = ft
->create_time
;
235 DEBUG(6,("**** onefs_ntimes: createtime: %s.%d\n",
236 time_to_asc(convert_timespec_to_time_t(ft
->create_time
)),
237 ft
->create_time
.tv_nsec
));
240 return onefs_vtimes_streams(handle
, smb_fname
, flags
, times
);
243 static uint32_t onefs_fs_capabilities(struct vfs_handle_struct
*handle
, enum timestamp_set_resolution
*p_ts_res
)
247 if (!lp_parm_bool(SNUM(handle
->conn
), PARM_ONEFS_TYPE
,
248 PARM_IGNORE_STREAMS
, PARM_IGNORE_STREAMS_DEFAULT
)) {
249 result
|= FILE_NAMED_STREAMS
;
252 result
|= SMB_VFS_NEXT_FS_CAPABILITIES(handle
, p_ts_res
);
253 *p_ts_res
= TIMESTAMP_SET_MSEC
;
257 static struct vfs_fn_pointers onefs_fns
= {
258 .connect_fn
= onefs_connect
,
259 .fs_capabilities
= onefs_fs_capabilities
,
260 .opendir
= onefs_opendir
,
261 .readdir
= onefs_readdir
,
262 .seekdir
= onefs_seekdir
,
263 .telldir
= onefs_telldir
,
264 .rewind_dir
= onefs_rewinddir
,
265 .mkdir
= onefs_mkdir
,
266 .closedir
= onefs_closedir
,
267 .init_search_op
= onefs_init_search_op
,
268 .open_fn
= onefs_open
,
269 .create_file
= onefs_create_file
,
270 .close_fn
= onefs_close
,
271 .sendfile
= onefs_sendfile
,
272 .recvfile
= onefs_recvfile
,
273 .rename
= onefs_rename
,
275 .fstat
= onefs_fstat
,
276 .lstat
= onefs_lstat
,
277 .get_alloc_size
= onefs_get_alloc_size
,
278 .unlink
= onefs_unlink
,
279 .ntimes
= onefs_ntimes
,
280 .file_id_create
= onefs_file_id_create
,
281 .streaminfo
= onefs_streaminfo
,
282 .brl_lock_windows
= onefs_brl_lock_windows
,
283 .brl_unlock_windows
= onefs_brl_unlock_windows
,
284 .brl_cancel_windows
= onefs_brl_cancel_windows
,
285 .strict_lock
= onefs_strict_lock
,
286 .strict_unlock
= onefs_strict_unlock
,
287 .notify_watch
= onefs_notify_watch
,
288 .fget_nt_acl
= onefs_fget_nt_acl
,
289 .get_nt_acl
= onefs_get_nt_acl
,
290 .fset_nt_acl
= onefs_fset_nt_acl
,
291 .statvfs
= onefs_statvfs
,
292 .get_real_filename
= onefs_get_real_filename
,
295 NTSTATUS
vfs_onefs_init(void)
297 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION
, "onefs",