smbcacls: Use defines for security flags
[Samba.git] / source3 / modules / vfs_ceph.c
blob409189b0bee9906c322a2aeade2529899ae09492
1 /*
2 Unix SMB/CIFS implementation.
3 Wrap disk only vfs functions to sidestep dodgy compilers.
4 Copyright (C) Tim Potter 1998
5 Copyright (C) Jeremy Allison 2007
6 Copyright (C) Brian Chrisman 2011 <bchrisman@gmail.com>
7 Copyright (C) Richard Sharpe 2011 <realrichardsharpe@gmail.com>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 * This VFS only works with the libceph.so user-space client. It is not needed
25 * if you are using the kernel client or the FUSE client.
27 * Add the following smb.conf parameter to each share that will be hosted on
28 * Ceph:
30 * vfs objects = ceph [any others you need go here]
33 #include "includes.h"
34 #include "smbd/smbd.h"
35 #include <dirent.h>
36 #include <sys/statvfs.h>
37 #include "cephfs/libcephfs.h"
38 #include "smbprofile.h"
40 #undef DBGC_CLASS
41 #define DBGC_CLASS DBGC_VFS
43 #ifndef LIBCEPHFS_VERSION
44 #define LIBCEPHFS_VERSION(maj, min, extra) ((maj << 16) + (min << 8) + extra)
45 #define LIBCEPHFS_VERSION_CODE LIBCEPHFS_VERSION(0, 0, 0)
46 #endif
49 * Use %llu whenever we have a 64bit unsigned int, and cast to (long long unsigned)
51 #define llu(_var) ((long long unsigned)_var)
54 * Note, libceph's return code model is to return -errno! So we have to convert
55 * to what Samba expects, with is set errno to -return and return -1
57 #define WRAP_RETURN(_res) \
58 errno = 0; \
59 if (_res < 0) { \
60 errno = -_res; \
61 return -1; \
62 } \
63 return _res \
66 * We mount only one file system and then all shares are assumed to be in that.
67 * FIXME: If we want to support more than one FS, then we have to deal with
68 * this differently.
70 * So, cmount tells us if we have been this way before and whether
71 * we need to mount ceph and cmount_cnt tells us how many times we have
72 * connected
74 static struct ceph_mount_info * cmount = NULL;
75 static uint32_t cmount_cnt = 0;
77 /* Check for NULL pointer parameters in cephwrap_* functions */
79 /* We don't want to have NULL function pointers lying around. Someone
80 is sure to try and execute them. These stubs are used to prevent
81 this possibility. */
83 static int cephwrap_connect(struct vfs_handle_struct *handle, const char *service, const char *user)
85 int ret;
86 char buf[256];
88 const char * conf_file;
90 if (cmount) {
91 handle->data = cmount; /* We have been here before */
92 cmount_cnt++;
93 return 0;
96 conf_file = lp_parm_const_string(SNUM(handle->conn), "ceph", "config_file", NULL);
98 DEBUG(2, ( "[CEPH] calling: ceph_create\n" ));
99 ret = ceph_create(&cmount, NULL);
100 if (ret)
101 goto err_out;
103 if (conf_file) {
104 /* Override the config file */
105 DEBUG(2, ( "[CEPH] calling: ceph_conf_read_file\n" ));
106 ret = ceph_conf_read_file(cmount, conf_file);
107 } else {
109 DEBUG(2, ( "[CEPH] calling: ceph_conf_read_file with %s\n", conf_file));
110 ret = ceph_conf_read_file(cmount, NULL);
113 if (ret)
114 goto err_out;
116 DEBUG(2, ( "[CEPH] calling: ceph_conf_get\n" ));
117 ret = ceph_conf_get(cmount, "log file", buf, sizeof(buf));
118 if (ret < 0)
119 goto err_out;
121 DEBUG(2, ("[CEPH] calling: ceph_mount\n"));
122 ret = ceph_mount(cmount, NULL);
123 if (ret < 0)
124 goto err_out;
128 * encode mount context/state into our vfs/connection holding structure
129 * cmount is a ceph_mount_t*
131 handle->data = cmount;
132 cmount_cnt++;
134 return 0;
136 err_out:
138 * Handle the error correctly. Ceph returns -errno.
140 DEBUG(2, ("[CEPH] Error return: %s\n", strerror(-ret)));
141 WRAP_RETURN(ret);
144 static void cephwrap_disconnect(struct vfs_handle_struct *handle)
146 if (!cmount) {
147 DEBUG(0, ("[CEPH] Error, ceph not mounted\n"));
148 return;
151 /* Should we unmount/shutdown? Only if the last disconnect? */
152 if (--cmount_cnt) {
153 DEBUG(10, ("[CEPH] Not shuting down CEPH because still more connections\n"));
154 return;
157 ceph_shutdown(cmount);
159 cmount = NULL; /* Make it safe */
162 /* Disk operations */
164 static uint64_t cephwrap_disk_free(struct vfs_handle_struct *handle,
165 const char *path, uint64_t *bsize,
166 uint64_t *dfree, uint64_t *dsize)
168 struct statvfs statvfs_buf;
169 int ret;
171 if (!(ret = ceph_statfs(handle->data, path, &statvfs_buf))) {
173 * Provide all the correct values.
175 *bsize = statvfs_buf.f_bsize;
176 *dfree = statvfs_buf.f_bavail;
177 *dsize = statvfs_buf.f_blocks;
178 disk_norm(bsize, dfree, dsize);
179 DEBUG(10, ("[CEPH] bsize: %llu, dfree: %llu, dsize: %llu\n",
180 llu(*bsize), llu(*dfree), llu(*dsize)));
181 return *dfree;
182 } else {
183 DEBUG(10, ("[CEPH] ceph_statfs returned %d\n", ret));
184 WRAP_RETURN(ret);
188 static int cephwrap_get_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
190 /* libceph: Ceph does not implement this */
191 #if 0
192 /* was ifdef HAVE_SYS_QUOTAS */
193 int ret;
195 ret = ceph_get_quota(handle->conn->connectpath, qtype, id, qt);
197 if (ret) {
198 errno = -ret;
199 ret = -1;
202 return ret;
203 #else
204 errno = ENOSYS;
205 return -1;
206 #endif
209 static int cephwrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
211 /* libceph: Ceph does not implement this */
212 #if 0
213 /* was ifdef HAVE_SYS_QUOTAS */
214 int ret;
216 ret = ceph_set_quota(handle->conn->connectpath, qtype, id, qt);
217 if (ret) {
218 errno = -ret;
219 ret = -1;
222 return ret;
223 #else
224 WRAP_RETURN(-ENOSYS);
225 #endif
228 static int cephwrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
230 struct statvfs statvfs_buf;
231 int ret;
233 ret = ceph_statfs(handle->data, path, &statvfs_buf);
234 if (ret < 0) {
235 WRAP_RETURN(ret);
236 } else {
237 statbuf->OptimalTransferSize = statvfs_buf.f_frsize;
238 statbuf->BlockSize = statvfs_buf.f_bsize;
239 statbuf->TotalBlocks = statvfs_buf.f_blocks;
240 statbuf->BlocksAvail = statvfs_buf.f_bfree;
241 statbuf->UserBlocksAvail = statvfs_buf.f_bavail;
242 statbuf->TotalFileNodes = statvfs_buf.f_files;
243 statbuf->FreeFileNodes = statvfs_buf.f_ffree;
244 statbuf->FsIdentifier = statvfs_buf.f_fsid;
245 DEBUG(10, ("[CEPH] f_bsize: %ld, f_blocks: %ld, f_bfree: %ld, f_bavail: %ld\n",
246 (long int)statvfs_buf.f_bsize, (long int)statvfs_buf.f_blocks,
247 (long int)statvfs_buf.f_bfree, (long int)statvfs_buf.f_bavail));
249 return ret;
252 /* Directory operations */
254 static DIR *cephwrap_opendir(struct vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
256 int ret = 0;
257 struct ceph_dir_result *result;
258 DEBUG(10, ("[CEPH] opendir(%p, %s)\n", handle, fname));
260 /* Returns NULL if it does not exist or there are problems ? */
261 ret = ceph_opendir(handle->data, fname, &result);
262 if (ret < 0) {
263 result = NULL;
264 errno = -ret; /* We return result which is NULL in this case */
267 DEBUG(10, ("[CEPH] opendir(...) = %d\n", ret));
268 return (DIR *) result;
271 static DIR *cephwrap_fdopendir(struct vfs_handle_struct *handle,
272 struct files_struct *fsp,
273 const char *mask,
274 uint32 attributes)
276 int ret = 0;
277 struct ceph_dir_result *result;
278 DEBUG(10, ("[CEPH] fdopendir(%p, %p)\n", handle, fsp));
280 ret = ceph_opendir(handle->data, fsp->fsp_name->base_name, &result);
281 if (ret < 0) {
282 result = NULL;
283 errno = -ret; /* We return result which is NULL in this case */
286 DEBUG(10, ("[CEPH] fdopendir(...) = %d\n", ret));
287 return (DIR *) result;
290 static struct dirent *cephwrap_readdir(struct vfs_handle_struct *handle,
291 DIR *dirp,
292 SMB_STRUCT_STAT *sbuf)
294 struct dirent *result;
296 DEBUG(10, ("[CEPH] readdir(%p, %p)\n", handle, dirp));
297 result = ceph_readdir(handle->data, (struct ceph_dir_result *) dirp);
298 DEBUG(10, ("[CEPH] readdir(...) = %p\n", result));
300 /* Default Posix readdir() does not give us stat info.
301 * Set to invalid to indicate we didn't return this info. */
302 if (sbuf)
303 SET_STAT_INVALID(*sbuf);
304 return result;
307 static void cephwrap_seekdir(struct vfs_handle_struct *handle, DIR *dirp, long offset)
309 DEBUG(10, ("[CEPH] seekdir(%p, %p, %ld)\n", handle, dirp, offset));
310 ceph_seekdir(handle->data, (struct ceph_dir_result *) dirp, offset);
313 static long cephwrap_telldir(struct vfs_handle_struct *handle, DIR *dirp)
315 long ret;
316 DEBUG(10, ("[CEPH] telldir(%p, %p)\n", handle, dirp));
317 ret = ceph_telldir(handle->data, (struct ceph_dir_result *) dirp);
318 DEBUG(10, ("[CEPH] telldir(...) = %ld\n", ret));
319 WRAP_RETURN(ret);
322 static void cephwrap_rewinddir(struct vfs_handle_struct *handle, DIR *dirp)
324 DEBUG(10, ("[CEPH] rewinddir(%p, %p)\n", handle, dirp));
325 ceph_rewinddir(handle->data, (struct ceph_dir_result *) dirp);
328 static int cephwrap_mkdir(struct vfs_handle_struct *handle, const char *path, mode_t mode)
330 int result;
331 bool has_dacl = False;
332 char *parent = NULL;
334 DEBUG(10, ("[CEPH] mkdir(%p, %s)\n", handle, path));
336 if (lp_inherit_acls(SNUM(handle->conn))
337 && parent_dirname(talloc_tos(), path, &parent, NULL)
338 && (has_dacl = directory_has_default_acl(handle->conn, parent)))
339 mode = 0777;
341 TALLOC_FREE(parent);
343 result = ceph_mkdir(handle->data, path, mode);
346 * Note. This order is important
348 if (result) {
349 WRAP_RETURN(result);
350 } else if (result == 0 && !has_dacl) {
352 * We need to do this as the default behavior of POSIX ACLs
353 * is to set the mask to be the requested group permission
354 * bits, not the group permission bits to be the requested
355 * group permission bits. This is not what we want, as it will
356 * mess up any inherited ACL bits that were set. JRA.
358 int saved_errno = errno; /* We may get ENOSYS */
359 if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
360 errno = saved_errno;
363 return result;
366 static int cephwrap_rmdir(struct vfs_handle_struct *handle, const char *path)
368 int result;
370 DEBUG(10, ("[CEPH] rmdir(%p, %s)\n", handle, path));
371 result = ceph_rmdir(handle->data, path);
372 DEBUG(10, ("[CEPH] rmdir(...) = %d\n", result));
373 WRAP_RETURN(result);
376 static int cephwrap_closedir(struct vfs_handle_struct *handle, DIR *dirp)
378 int result;
380 DEBUG(10, ("[CEPH] closedir(%p, %p)\n", handle, dirp));
381 result = ceph_closedir(handle->data, (struct ceph_dir_result *) dirp);
382 DEBUG(10, ("[CEPH] closedir(...) = %d\n", result));
383 WRAP_RETURN(result);
386 /* File operations */
388 static int cephwrap_open(struct vfs_handle_struct *handle,
389 struct smb_filename *smb_fname,
390 files_struct *fsp, int flags, mode_t mode)
392 int result = -ENOENT;
393 DEBUG(10, ("[CEPH] open(%p, %s, %p, %d, %d)\n", handle, smb_fname_str_dbg(smb_fname), fsp, flags, mode));
395 if (smb_fname->stream_name) {
396 goto out;
399 result = ceph_open(handle->data, smb_fname->base_name, flags, mode);
400 out:
401 DEBUG(10, ("[CEPH] open(...) = %d\n", result));
402 WRAP_RETURN(result);
405 static int cephwrap_close(struct vfs_handle_struct *handle, files_struct *fsp)
407 int result;
409 DEBUG(10, ("[CEPH] close(%p, %p)\n", handle, fsp));
410 result = ceph_close(handle->data, fsp->fh->fd);
411 DEBUG(10, ("[CEPH] close(...) = %d\n", result));
413 WRAP_RETURN(result);
416 static ssize_t cephwrap_read(struct vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
418 ssize_t result;
420 DEBUG(10, ("[CEPH] read(%p, %p, %p, %llu)\n", handle, fsp, data, llu(n)));
422 /* Using -1 for the offset means read/write rather than pread/pwrite */
423 result = ceph_read(handle->data, fsp->fh->fd, data, n, -1);
424 DEBUG(10, ("[CEPH] read(...) = %llu\n", llu(result)));
425 WRAP_RETURN(result);
428 static ssize_t cephwrap_pread(struct vfs_handle_struct *handle, files_struct *fsp, void *data,
429 size_t n, off_t offset)
431 ssize_t result;
433 DEBUG(10, ("[CEPH] pread(%p, %p, %p, %llu, %llu)\n", handle, fsp, data, llu(n), llu(offset)));
435 result = ceph_read(handle->data, fsp->fh->fd, data, n, offset);
436 DEBUG(10, ("[CEPH] pread(...) = %llu\n", llu(result)));
437 WRAP_RETURN(result);
441 static ssize_t cephwrap_write(struct vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
443 ssize_t result;
445 DEBUG(10, ("[CEPH] write(%p, %p, %p, %llu)\n", handle, fsp, data, llu(n)));
447 result = ceph_write(handle->data, fsp->fh->fd, data, n, -1);
449 DEBUG(10, ("[CEPH] write(...) = %llu\n", llu(result)));
450 if (result < 0) {
451 WRAP_RETURN(result);
453 fsp->fh->pos += result;
454 return result;
457 static ssize_t cephwrap_pwrite(struct vfs_handle_struct *handle, files_struct *fsp, const void *data,
458 size_t n, off_t offset)
460 ssize_t result;
462 DEBUG(10, ("[CEPH] pwrite(%p, %p, %p, %llu, %llu)\n", handle, fsp, data, llu(n), llu(offset)));
463 result = ceph_write(handle->data, fsp->fh->fd, data, n, offset);
464 DEBUG(10, ("[CEPH] pwrite(...) = %llu\n", llu(result)));
465 WRAP_RETURN(result);
468 static off_t cephwrap_lseek(struct vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
470 off_t result = 0;
472 DEBUG(10, ("[CEPH] cephwrap_lseek\n"));
473 /* Cope with 'stat' file opens. */
474 if (fsp->fh->fd != -1) {
475 result = ceph_lseek(handle->data, fsp->fh->fd, offset, whence);
477 WRAP_RETURN(result);
480 static ssize_t cephwrap_sendfile(struct vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
481 off_t offset, size_t n)
484 * We cannot support sendfile because libceph is in user space.
486 DEBUG(10, ("[CEPH] cephwrap_sendfile\n"));
487 errno = ENOTSUP;
488 return -1;
491 static ssize_t cephwrap_recvfile(struct vfs_handle_struct *handle,
492 int fromfd,
493 files_struct *tofsp,
494 off_t offset,
495 size_t n)
498 * We cannot support recvfile because libceph is in user space.
500 DEBUG(10, ("[CEPH] cephwrap_recvfile\n"));
501 errno=ENOTSUP;
502 return -1;
505 static int cephwrap_rename(struct vfs_handle_struct *handle,
506 const struct smb_filename *smb_fname_src,
507 const struct smb_filename *smb_fname_dst)
509 int result = -1;
510 DEBUG(10, ("[CEPH] cephwrap_rename\n"));
511 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
512 errno = ENOENT;
513 return result;
516 result = ceph_rename(handle->data, smb_fname_src->base_name, smb_fname_dst->base_name);
517 WRAP_RETURN(result);
520 static int cephwrap_fsync(struct vfs_handle_struct *handle, files_struct *fsp)
522 int result;
523 DEBUG(10, ("[CEPH] cephwrap_fsync\n"));
524 result = ceph_fsync(handle->data, fsp->fh->fd, false);
525 WRAP_RETURN(result);
528 static int cephwrap_stat(struct vfs_handle_struct *handle,
529 struct smb_filename *smb_fname)
531 int result = -1;
532 struct stat stbuf;
534 DEBUG(10, ("[CEPH] stat(%p, %s)\n", handle, smb_fname_str_dbg(smb_fname)));
536 if (smb_fname->stream_name) {
537 errno = ENOENT;
538 return result;
541 result = ceph_stat(handle->data, smb_fname->base_name, (struct stat *) &stbuf);
542 DEBUG(10, ("[CEPH] stat(...) = %d\n", result));
543 if (result < 0) {
544 WRAP_RETURN(result);
545 } else {
546 DEBUG(10, ("[CEPH]\tstbuf = {dev = %llu, ino = %llu, mode = 0x%x, nlink = %llu, "
547 "uid = %d, gid = %d, rdev = %llu, size = %llu, blksize = %llu, "
548 "blocks = %llu, atime = %llu, mtime = %llu, ctime = %llu}\n",
549 llu(stbuf.st_dev), llu(stbuf.st_ino), stbuf.st_mode, llu(stbuf.st_nlink),
550 stbuf.st_uid, stbuf.st_gid, llu(stbuf.st_rdev), llu(stbuf.st_size), llu(stbuf.st_blksize),
551 llu(stbuf.st_blocks), llu(stbuf.st_atime), llu(stbuf.st_mtime), llu(stbuf.st_ctime)));
553 init_stat_ex_from_stat(
554 &smb_fname->st, &stbuf,
555 lp_fake_directory_create_times(SNUM(handle->conn)));
556 DEBUG(10, ("[CEPH] mode = 0x%x\n", smb_fname->st.st_ex_mode));
557 return result;
560 static int cephwrap_fstat(struct vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
562 int result = -1;
563 struct stat stbuf;
565 DEBUG(10, ("[CEPH] fstat(%p, %d)\n", handle, fsp->fh->fd));
566 result = ceph_fstat(handle->data, fsp->fh->fd, (struct stat *) &stbuf);
567 DEBUG(10, ("[CEPH] fstat(...) = %d\n", result));
568 if (result < 0) {
569 WRAP_RETURN(result);
570 } else {
571 DEBUG(10, ("[CEPH]\tstbuf = {dev = %llu, ino = %llu, mode = 0x%x, nlink = %llu, "
572 "uid = %d, gid = %d, rdev = %llu, size = %llu, blksize = %llu, "
573 "blocks = %llu, atime = %llu, mtime = %llu, ctime = %llu}\n",
574 llu(stbuf.st_dev), llu(stbuf.st_ino), stbuf.st_mode, llu(stbuf.st_nlink),
575 stbuf.st_uid, stbuf.st_gid, llu(stbuf.st_rdev), llu(stbuf.st_size), llu(stbuf.st_blksize),
576 llu(stbuf.st_blocks), llu(stbuf.st_atime), llu(stbuf.st_mtime), llu(stbuf.st_ctime)));
579 init_stat_ex_from_stat(
580 sbuf, &stbuf,
581 lp_fake_directory_create_times(SNUM(handle->conn)));
582 DEBUG(10, ("[CEPH] mode = 0x%x\n", sbuf->st_ex_mode));
583 return result;
586 static int cephwrap_lstat(struct vfs_handle_struct *handle,
587 struct smb_filename *smb_fname)
589 int result = -1;
590 struct stat stbuf;
592 DEBUG(10, ("[CEPH] lstat(%p, %s)\n", handle, smb_fname_str_dbg(smb_fname)));
594 if (smb_fname->stream_name) {
595 errno = ENOENT;
596 return result;
599 result = ceph_lstat(handle->data, smb_fname->base_name, &stbuf);
600 DEBUG(10, ("[CEPH] lstat(...) = %d\n", result));
601 if (result < 0) {
602 WRAP_RETURN(result);
604 init_stat_ex_from_stat(
605 &smb_fname->st, &stbuf,
606 lp_fake_directory_create_times(SNUM(handle->conn)));
607 return result;
610 static int cephwrap_unlink(struct vfs_handle_struct *handle,
611 const struct smb_filename *smb_fname)
613 int result = -1;
615 DEBUG(10, ("[CEPH] unlink(%p, %s)\n", handle, smb_fname_str_dbg(smb_fname)));
616 if (smb_fname->stream_name) {
617 errno = ENOENT;
618 return result;
620 result = ceph_unlink(handle->data, smb_fname->base_name);
621 DEBUG(10, ("[CEPH] unlink(...) = %d\n", result));
622 WRAP_RETURN(result);
625 static int cephwrap_chmod(struct vfs_handle_struct *handle, const char *path, mode_t mode)
627 int result;
629 DEBUG(10, ("[CEPH] chmod(%p, %s, %d)\n", handle, path, mode));
632 * We need to do this due to the fact that the default POSIX ACL
633 * chmod modifies the ACL *mask* for the group owner, not the
634 * group owner bits directly. JRA.
639 int saved_errno = errno; /* We might get ENOSYS */
640 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
641 return result;
643 /* Error - return the old errno. */
644 errno = saved_errno;
647 result = ceph_chmod(handle->data, path, mode);
648 DEBUG(10, ("[CEPH] chmod(...) = %d\n", result));
649 WRAP_RETURN(result);
652 static int cephwrap_fchmod(struct vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
654 int result;
656 DEBUG(10, ("[CEPH] fchmod(%p, %p, %d)\n", handle, fsp, mode));
659 * We need to do this due to the fact that the default POSIX ACL
660 * chmod modifies the ACL *mask* for the group owner, not the
661 * group owner bits directly. JRA.
665 int saved_errno = errno; /* We might get ENOSYS */
666 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
667 return result;
669 /* Error - return the old errno. */
670 errno = saved_errno;
673 #if defined(HAVE_FCHMOD)
674 result = ceph_fchmod(handle->data, fsp->fh->fd, mode);
675 DEBUG(10, ("[CEPH] fchmod(...) = %d\n", result));
676 WRAP_RETURN(result);
677 #else
678 errno = ENOSYS;
679 #endif
680 return -1;
683 static int cephwrap_chown(struct vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
685 int result;
686 DEBUG(10, ("[CEPH] chown(%p, %s, %d, %d)\n", handle, path, uid, gid));
687 result = ceph_chown(handle->data, path, uid, gid);
688 DEBUG(10, ("[CEPH] chown(...) = %d\n", result));
689 WRAP_RETURN(result);
692 static int cephwrap_fchown(struct vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
694 int result;
695 #ifdef HAVE_FCHOWN
697 DEBUG(10, ("[CEPH] fchown(%p, %p, %d, %d)\n", handle, fsp, uid, gid));
698 result = ceph_fchown(handle->data, fsp->fh->fd, uid, gid);
699 DEBUG(10, ("[CEPH] fchown(...) = %d\n", result));
700 WRAP_RETURN(result);
701 #else
702 errno = ENOSYS;
703 result = -1;
704 #endif
705 return result;
708 static int cephwrap_lchown(struct vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
710 int result;
712 DEBUG(10, ("[CEPH] lchown(%p, %s, %d, %d)\n", handle, path, uid, gid));
713 result = ceph_lchown(handle->data, path, uid, gid);
714 DEBUG(10, ("[CEPH] lchown(...) = %d\n", result));
715 WRAP_RETURN(result);
718 static int cephwrap_chdir(struct vfs_handle_struct *handle, const char *path)
720 int result = -1;
721 DEBUG(10, ("[CEPH] chdir(%p, %s)\n", handle, path));
723 * If the path is just / use chdir because Ceph is below / and
724 * cannot deal with changing directory above its mount point
726 if (path && !strcmp(path, "/"))
727 return chdir(path);
729 result = ceph_chdir(handle->data, path);
730 DEBUG(10, ("[CEPH] chdir(...) = %d\n", result));
731 WRAP_RETURN(result);
734 static char *cephwrap_getwd(struct vfs_handle_struct *handle)
736 const char *cwd = ceph_getcwd(handle->data);
737 DEBUG(10, ("[CEPH] getwd(%p) = %s\n", handle, cwd));
738 return SMB_STRDUP(cwd);
741 static int cephwrap_ntimes(struct vfs_handle_struct *handle,
742 const struct smb_filename *smb_fname,
743 struct smb_file_time *ft)
745 struct utimbuf buf;
746 int result;
748 if (null_timespec(ft->atime)) {
749 buf.actime = smb_fname->st.st_ex_atime.tv_sec;
750 } else {
751 buf.actime = ft->atime.tv_sec;
753 if (null_timespec(ft->mtime)) {
754 buf.modtime = smb_fname->st.st_ex_mtime.tv_sec;
755 } else {
756 buf.modtime = ft->mtime.tv_sec;
758 if (!null_timespec(ft->create_time)) {
759 set_create_timespec_ea(handle->conn, smb_fname,
760 ft->create_time);
762 if (buf.actime == smb_fname->st.st_ex_atime.tv_sec &&
763 buf.modtime == smb_fname->st.st_ex_mtime.tv_sec) {
764 return 0;
767 result = ceph_utime(handle->data, smb_fname->base_name, &buf);
768 DEBUG(10, ("[CEPH] ntimes(%p, %s, {%ld, %ld, %ld, %ld}) = %d\n", handle, smb_fname_str_dbg(smb_fname),
769 ft->mtime.tv_sec, ft->atime.tv_sec, ft->ctime.tv_sec,
770 ft->create_time.tv_sec, result));
771 return result;
774 static int strict_allocate_ftruncate(struct vfs_handle_struct *handle, files_struct *fsp, off_t len)
776 off_t space_to_write;
777 uint64_t space_avail;
778 uint64_t bsize,dfree,dsize;
779 int ret;
780 NTSTATUS status;
781 SMB_STRUCT_STAT *pst;
783 status = vfs_stat_fsp(fsp);
784 if (!NT_STATUS_IS_OK(status)) {
785 return -1;
787 pst = &fsp->fsp_name->st;
789 #ifdef S_ISFIFO
790 if (S_ISFIFO(pst->st_ex_mode))
791 return 0;
792 #endif
794 if (pst->st_ex_size == len)
795 return 0;
797 /* Shrink - just ftruncate. */
798 if (pst->st_ex_size > len)
799 return ftruncate(fsp->fh->fd, len);
801 space_to_write = len - pst->st_ex_size;
803 /* for allocation try fallocate first. This can fail on some
804 platforms e.g. when the filesystem doesn't support it and no
805 emulation is being done by the libc (like on AIX with JFS1). In that
806 case we do our own emulation. fallocate implementations can
807 return ENOTSUP or EINVAL in cases like that. */
808 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
809 if (ret == -1 && errno == ENOSPC) {
810 return -1;
812 if (ret == 0) {
813 return 0;
815 DEBUG(10,("[CEPH] strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
816 "error %d. Falling back to slow manual allocation\n", errno));
818 /* available disk space is enough or not? */
819 space_avail = get_dfree_info(fsp->conn,
820 fsp->fsp_name->base_name,
821 &bsize, &dfree, &dsize);
822 /* space_avail is 1k blocks */
823 if (space_avail == (uint64_t)-1 ||
824 ((uint64_t)space_to_write/1024 > space_avail) ) {
825 errno = ENOSPC;
826 return -1;
829 /* Write out the real space on disk. */
830 return vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
833 static int cephwrap_ftruncate(struct vfs_handle_struct *handle, files_struct *fsp, off_t len)
835 int result = -1;
836 SMB_STRUCT_STAT st;
837 char c = 0;
838 off_t currpos;
840 DEBUG(10, ("[CEPH] ftruncate(%p, %p, %llu\n", handle, fsp, llu(len)));
842 if (lp_strict_allocate(SNUM(fsp->conn))) {
843 result = strict_allocate_ftruncate(handle, fsp, len);
844 return result;
847 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
848 sys_ftruncate if the system supports it. Then I discovered that
849 you can have some filesystems that support ftruncate
850 expansion and some that don't! On Linux fat can't do
851 ftruncate extend but ext2 can. */
853 result = ceph_ftruncate(handle->data, fsp->fh->fd, len);
854 if (result == 0)
855 goto done;
857 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
858 extend a file with ftruncate. Provide alternate implementation
859 for this */
860 currpos = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
861 if (currpos == -1) {
862 goto done;
865 /* Do an fstat to see if the file is longer than the requested
866 size in which case the ftruncate above should have
867 succeeded or shorter, in which case seek to len - 1 and
868 write 1 byte of zero */
869 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
870 goto done;
873 #ifdef S_ISFIFO
874 if (S_ISFIFO(st.st_ex_mode)) {
875 result = 0;
876 goto done;
878 #endif
880 if (st.st_ex_size == len) {
881 result = 0;
882 goto done;
885 if (st.st_ex_size > len) {
886 /* the sys_ftruncate should have worked */
887 goto done;
890 if (SMB_VFS_LSEEK(fsp, len-1, SEEK_SET) != len -1)
891 goto done;
893 if (SMB_VFS_WRITE(fsp, &c, 1)!=1)
894 goto done;
896 /* Seek to where we were */
897 if (SMB_VFS_LSEEK(fsp, currpos, SEEK_SET) != currpos)
898 goto done;
899 result = 0;
901 done:
903 return result;
906 static bool cephwrap_lock(struct vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
908 DEBUG(10, ("[CEPH] lock\n"));
909 return true;
912 static int cephwrap_kernel_flock(struct vfs_handle_struct *handle, files_struct *fsp,
913 uint32 share_mode, uint32 access_mask)
915 DEBUG(10, ("[CEPH] kernel_flock\n"));
917 * We must return zero here and pretend all is good.
918 * One day we might have this in CEPH.
920 return 0;
923 static bool cephwrap_getlock(struct vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
925 DEBUG(10, ("[CEPH] getlock returning false and errno=0\n"));
927 errno = 0;
928 return false;
932 * We cannot let this fall through to the default, because the file might only
933 * be accessible from libceph (which is a user-space client) but the fd might
934 * be for some file the kernel knows about.
936 static int cephwrap_linux_setlease(struct vfs_handle_struct *handle, files_struct *fsp,
937 int leasetype)
939 int result = -1;
941 DEBUG(10, ("[CEPH] linux_setlease\n"));
942 errno = ENOSYS;
943 return result;
946 static int cephwrap_symlink(struct vfs_handle_struct *handle, const char *oldpath, const char *newpath)
948 int result = -1;
949 DEBUG(10, ("[CEPH] symlink(%p, %s, %s)\n", handle, oldpath, newpath));
950 result = ceph_symlink(handle->data, oldpath, newpath);
951 DEBUG(10, ("[CEPH] symlink(...) = %d\n", result));
952 WRAP_RETURN(result);
955 static int cephwrap_readlink(struct vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
957 int result = -1;
958 DEBUG(10, ("[CEPH] readlink(%p, %s, %p, %llu)\n", handle, path, buf, llu(bufsiz)));
959 result = ceph_readlink(handle->data, path, buf, bufsiz);
960 DEBUG(10, ("[CEPH] readlink(...) = %d\n", result));
961 WRAP_RETURN(result);
964 static int cephwrap_link(struct vfs_handle_struct *handle, const char *oldpath, const char *newpath)
966 int result = -1;
967 DEBUG(10, ("[CEPH] link(%p, %s, %s)\n", handle, oldpath, newpath));
968 result = ceph_link(handle->data, oldpath, newpath);
969 DEBUG(10, ("[CEPH] link(...) = %d\n", result));
970 WRAP_RETURN(result);
973 static int cephwrap_mknod(struct vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
975 int result = -1;
976 DEBUG(10, ("[CEPH] mknod(%p, %s)\n", handle, pathname));
977 result = ceph_mknod(handle->data, pathname, mode, dev);
978 DEBUG(10, ("[CEPH] mknod(...) = %d\n", result));
979 WRAP_RETURN(result);
983 * This is a simple version of real-path ... a better version is needed to
984 * ask libceph about symbolic links.
986 static char *cephwrap_realpath(struct vfs_handle_struct *handle, const char *path)
988 char *result;
989 size_t len = strlen(path);
991 result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
992 if (len && (path[0] == '/')) {
993 int r = asprintf(&result, "%s", path);
994 if (r < 0) return NULL;
995 } else if ((len >= 2) && (path[0] == '.') && (path[1] == '/')) {
996 if (len == 2) {
997 int r = asprintf(&result, "%s",
998 handle->conn->connectpath);
999 if (r < 0) return NULL;
1000 } else {
1001 int r = asprintf(&result, "%s/%s",
1002 handle->conn->connectpath, &path[2]);
1003 if (r < 0) return NULL;
1005 } else {
1006 int r = asprintf(&result, "%s/%s",
1007 handle->conn->connectpath, path);
1008 if (r < 0) return NULL;
1010 DEBUG(10, ("[CEPH] realpath(%p, %s) = %s\n", handle, path, result));
1011 return result;
1014 static NTSTATUS cephwrap_notify_watch(struct vfs_handle_struct *vfs_handle,
1015 struct sys_notify_context *ctx,
1016 const char *path,
1017 uint32_t *filter,
1018 uint32_t *subdir_filter,
1019 void (*callback)(struct sys_notify_context *ctx,
1020 void *private_data,
1021 struct notify_event *ev),
1022 void *private_data,
1023 void *handle_p)
1026 * We cannot call inotify on files the kernel does not know about
1028 return NT_STATUS_OK;
1031 static int cephwrap_chflags(struct vfs_handle_struct *handle, const char *path,
1032 unsigned int flags)
1034 errno = ENOSYS;
1035 return -1;
1038 static int cephwrap_get_real_filename(struct vfs_handle_struct *handle,
1039 const char *path,
1040 const char *name,
1041 TALLOC_CTX *mem_ctx,
1042 char **found_name)
1045 * Don't fall back to get_real_filename so callers can differentiate
1046 * between a full directory scan and an actual case-insensitive stat.
1048 errno = EOPNOTSUPP;
1049 return -1;
1052 static const char *cephwrap_connectpath(struct vfs_handle_struct *handle,
1053 const char *fname)
1055 return handle->conn->connectpath;
1058 /****************************************************************
1059 Extended attribute operations.
1060 *****************************************************************/
1062 static ssize_t cephwrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
1064 int ret;
1065 DEBUG(10, ("[CEPH] getxattr(%p, %s, %s, %p, %llu)\n", handle, path, name, value, llu(size)));
1066 ret = ceph_getxattr(handle->data, path, name, value, size);
1067 DEBUG(10, ("[CEPH] getxattr(...) = %d\n", ret));
1068 if (ret < 0) {
1069 WRAP_RETURN(ret);
1070 } else {
1071 return (ssize_t)ret;
1075 static ssize_t cephwrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
1077 int ret;
1078 DEBUG(10, ("[CEPH] fgetxattr(%p, %p, %s, %p, %llu)\n", handle, fsp, name, value, llu(size)));
1079 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1080 ret = ceph_fgetxattr(handle->data, fsp->fh->fd, name, value, size);
1081 #else
1082 ret = ceph_getxattr(handle->data, fsp->fsp_name->base_name, name, value, size);
1083 #endif
1084 DEBUG(10, ("[CEPH] fgetxattr(...) = %d\n", ret));
1085 if (ret < 0) {
1086 WRAP_RETURN(ret);
1087 } else {
1088 return (ssize_t)ret;
1092 static ssize_t cephwrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
1094 int ret;
1095 DEBUG(10, ("[CEPH] listxattr(%p, %s, %p, %llu)\n", handle, path, list, llu(size)));
1096 ret = ceph_listxattr(handle->data, path, list, size);
1097 DEBUG(10, ("[CEPH] listxattr(...) = %d\n", ret));
1098 if (ret < 0) {
1099 WRAP_RETURN(ret);
1100 } else {
1101 return (ssize_t)ret;
1105 #if 0
1106 static ssize_t cephwrap_llistxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
1108 int ret;
1109 DEBUG(10, ("[CEPH] llistxattr(%p, %s, %p, %llu)\n", handle, path, list, llu(size)));
1110 ret = ceph_llistxattr(handle->data, path, list, size);
1111 DEBUG(10, ("[CEPH] listxattr(...) = %d\n", ret));
1112 if (ret < 0) {
1113 WRAP_RETURN(ret);
1114 } else {
1115 return (ssize_t)ret;
1118 #endif
1120 static ssize_t cephwrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
1122 int ret;
1123 DEBUG(10, ("[CEPH] flistxattr(%p, %p, %s, %llu)\n", handle, fsp, list, llu(size)));
1124 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1125 ret = ceph_flistxattr(handle->data, fsp->fh->fd, list, size);
1126 #else
1127 ret = ceph_listxattr(handle->data, fsp->fsp_name->base_name, list, size);
1128 #endif
1129 DEBUG(10, ("[CEPH] flistxattr(...) = %d\n", ret));
1130 if (ret < 0) {
1131 WRAP_RETURN(ret);
1132 } else {
1133 return (ssize_t)ret;
1137 static int cephwrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
1139 int ret;
1140 DEBUG(10, ("[CEPH] removexattr(%p, %s, %s)\n", handle, path, name));
1141 ret = ceph_removexattr(handle->data, path, name);
1142 DEBUG(10, ("[CEPH] removexattr(...) = %d\n", ret));
1143 WRAP_RETURN(ret);
1146 static int cephwrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
1148 int ret;
1149 DEBUG(10, ("[CEPH] fremovexattr(%p, %p, %s)\n", handle, fsp, name));
1150 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1151 ret = ceph_fremovexattr(handle->data, fsp->fh->fd, name);
1152 #else
1153 ret = ceph_removexattr(handle->data, fsp->fsp_name->base_name, name);
1154 #endif
1155 DEBUG(10, ("[CEPH] fremovexattr(...) = %d\n", ret));
1156 WRAP_RETURN(ret);
1159 static int cephwrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
1161 int ret;
1162 DEBUG(10, ("[CEPH] setxattr(%p, %s, %s, %p, %llu, %d)\n", handle, path, name, value, llu(size), flags));
1163 ret = ceph_setxattr(handle->data, path, name, value, size, flags);
1164 DEBUG(10, ("[CEPH] setxattr(...) = %d\n", ret));
1165 WRAP_RETURN(ret);
1168 static int cephwrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
1170 int ret;
1171 DEBUG(10, ("[CEPH] fsetxattr(%p, %p, %s, %p, %llu, %d)\n", handle, fsp, name, value, llu(size), flags));
1172 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1173 ret = ceph_fsetxattr(handle->data, fsp->fh->fd,
1174 name, value, size, flags);
1175 #else
1176 ret = ceph_setxattr(handle->data, fsp->fsp_name->base_name, name, value, size, flags);
1177 #endif
1178 DEBUG(10, ("[CEPH] fsetxattr(...) = %d\n", ret));
1179 WRAP_RETURN(ret);
1182 static bool cephwrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
1186 * We do not support AIO yet.
1189 DEBUG(10, ("[CEPH] cephwrap_aio_force(%p, %p) = false (errno = ENOTSUP)\n", handle, fsp));
1190 errno = ENOTSUP;
1191 return false;
1194 static bool cephwrap_is_offline(struct vfs_handle_struct *handle,
1195 const struct smb_filename *fname,
1196 SMB_STRUCT_STAT *sbuf)
1198 return false;
1201 static int cephwrap_set_offline(struct vfs_handle_struct *handle,
1202 const struct smb_filename *fname)
1204 errno = ENOTSUP;
1205 return -1;
1208 static SMB_ACL_T cephwrap_sys_acl_get_file(struct vfs_handle_struct *handle,
1209 const char *path_p,
1210 SMB_ACL_TYPE_T type,
1211 TALLOC_CTX *mem_ctx)
1213 errno = ENOTSUP;
1214 return NULL;
1217 static SMB_ACL_T cephwrap_sys_acl_get_fd(struct vfs_handle_struct *handle,
1218 struct files_struct *fsp,
1219 TALLOC_CTX *mem_ctx)
1221 errno = ENOTSUP;
1222 return NULL;
1225 static int cephwrap_sys_acl_set_file(struct vfs_handle_struct *handle,
1226 const char *name,
1227 SMB_ACL_TYPE_T acltype,
1228 SMB_ACL_T theacl)
1230 errno = ENOTSUP;
1231 return -1;
1234 static int cephwrap_sys_acl_set_fd(struct vfs_handle_struct *handle,
1235 struct files_struct *fsp,
1236 SMB_ACL_T theacl)
1238 errno = ENOTSUP;
1239 return -1;
1242 static int cephwrap_sys_acl_delete_def_file(struct vfs_handle_struct *handle,
1243 const char *path)
1245 errno = ENOTSUP;
1246 return -1;
1249 static struct vfs_fn_pointers ceph_fns = {
1250 /* Disk operations */
1252 .connect_fn = cephwrap_connect,
1253 .disconnect_fn = cephwrap_disconnect,
1254 .disk_free_fn = cephwrap_disk_free,
1255 .get_quota_fn = cephwrap_get_quota,
1256 .set_quota_fn = cephwrap_set_quota,
1257 .statvfs_fn = cephwrap_statvfs,
1259 /* Directory operations */
1261 .opendir_fn = cephwrap_opendir,
1262 .fdopendir_fn = cephwrap_fdopendir,
1263 .readdir_fn = cephwrap_readdir,
1264 .seekdir_fn = cephwrap_seekdir,
1265 .telldir_fn = cephwrap_telldir,
1266 .rewind_dir_fn = cephwrap_rewinddir,
1267 .mkdir_fn = cephwrap_mkdir,
1268 .rmdir_fn = cephwrap_rmdir,
1269 .closedir_fn = cephwrap_closedir,
1271 /* File operations */
1273 .open_fn = cephwrap_open,
1274 .close_fn = cephwrap_close,
1275 .read_fn = cephwrap_read,
1276 .pread_fn = cephwrap_pread,
1277 .write_fn = cephwrap_write,
1278 .pwrite_fn = cephwrap_pwrite,
1279 .lseek_fn = cephwrap_lseek,
1280 .sendfile_fn = cephwrap_sendfile,
1281 .recvfile_fn = cephwrap_recvfile,
1282 .rename_fn = cephwrap_rename,
1283 .fsync_fn = cephwrap_fsync,
1284 .stat_fn = cephwrap_stat,
1285 .fstat_fn = cephwrap_fstat,
1286 .lstat_fn = cephwrap_lstat,
1287 .unlink_fn = cephwrap_unlink,
1288 .chmod_fn = cephwrap_chmod,
1289 .fchmod_fn = cephwrap_fchmod,
1290 .chown_fn = cephwrap_chown,
1291 .fchown_fn = cephwrap_fchown,
1292 .lchown_fn = cephwrap_lchown,
1293 .chdir_fn = cephwrap_chdir,
1294 .getwd_fn = cephwrap_getwd,
1295 .ntimes_fn = cephwrap_ntimes,
1296 .ftruncate_fn = cephwrap_ftruncate,
1297 .lock_fn = cephwrap_lock,
1298 .kernel_flock_fn = cephwrap_kernel_flock,
1299 .linux_setlease_fn = cephwrap_linux_setlease,
1300 .getlock_fn = cephwrap_getlock,
1301 .symlink_fn = cephwrap_symlink,
1302 .readlink_fn = cephwrap_readlink,
1303 .link_fn = cephwrap_link,
1304 .mknod_fn = cephwrap_mknod,
1305 .realpath_fn = cephwrap_realpath,
1306 .notify_watch_fn = cephwrap_notify_watch,
1307 .chflags_fn = cephwrap_chflags,
1308 .get_real_filename_fn = cephwrap_get_real_filename,
1309 .connectpath_fn = cephwrap_connectpath,
1311 /* EA operations. */
1312 .getxattr_fn = cephwrap_getxattr,
1313 .fgetxattr_fn = cephwrap_fgetxattr,
1314 .listxattr_fn = cephwrap_listxattr,
1315 .flistxattr_fn = cephwrap_flistxattr,
1316 .removexattr_fn = cephwrap_removexattr,
1317 .fremovexattr_fn = cephwrap_fremovexattr,
1318 .setxattr_fn = cephwrap_setxattr,
1319 .fsetxattr_fn = cephwrap_fsetxattr,
1321 /* Posix ACL Operations */
1322 .sys_acl_get_file_fn = cephwrap_sys_acl_get_file,
1323 .sys_acl_get_fd_fn = cephwrap_sys_acl_get_fd,
1324 .sys_acl_set_file_fn = cephwrap_sys_acl_set_file,
1325 .sys_acl_set_fd_fn = cephwrap_sys_acl_set_fd,
1326 .sys_acl_delete_def_file_fn = cephwrap_sys_acl_delete_def_file,
1328 /* aio operations */
1329 .aio_force_fn = cephwrap_aio_force,
1331 /* offline operations */
1332 .is_offline_fn = cephwrap_is_offline,
1333 .set_offline_fn = cephwrap_set_offline
1336 NTSTATUS vfs_ceph_init(void);
1337 NTSTATUS vfs_ceph_init(void)
1339 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
1340 "ceph", &ceph_fns);