vfs:ceph: Fix mkdir_fn to take struct smb_filename * insted of char *
[nivanova/samba-autobuild/.git] / source3 / modules / vfs_ceph.c
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>
8
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.
13
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.
18
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/>.
21 */
22
23 /*
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.
26  *
27  * Add the following smb.conf parameter to each share that will be hosted on
28  * Ceph:
29  *
30  *   vfs objects = ceph [any others you need go here]
31  */
32
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"
39
40 #undef DBGC_CLASS
41 #define DBGC_CLASS DBGC_VFS
42
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
47
48 /*
49  * Use %llu whenever we have a 64bit unsigned int, and cast to (long long unsigned)
50  */
51 #define llu(_var) ((long long unsigned)_var)
52
53 /*
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
56  */
57 #define WRAP_RETURN(_res) \
58         errno = 0; \
59         if (_res < 0) { \
60                 errno = -_res; \
61                 return -1; \
62         } \
63         return _res \
64
65 /*
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.
69  *
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
73  */
74 static struct ceph_mount_info * cmount = NULL;
75 static uint32_t cmount_cnt = 0;
76
77 /* Check for NULL pointer parameters in cephwrap_* functions */
78
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. */
82
83 static int cephwrap_connect(struct vfs_handle_struct *handle,  const char *service, const char *user)
84 {
85         int ret;
86         char buf[256];
87
88         const char * conf_file;
89
90         if (cmount) {
91                 handle->data = cmount; /* We have been here before */
92                 cmount_cnt++;
93                 return 0;
94         }
95
96         conf_file = lp_parm_const_string(SNUM(handle->conn), "ceph", "config_file", NULL);
97
98         DEBUG(2, ( "[CEPH] calling: ceph_create\n" ));
99         ret = ceph_create(&cmount, NULL);
100         if (ret)
101                 goto err_out;
102
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 {
108
109                 DEBUG(2, ( "[CEPH] calling: ceph_conf_read_file with %s\n", conf_file));
110                 ret = ceph_conf_read_file(cmount, NULL);
111         }
112
113         if (ret)
114                 goto err_out;
115
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;
120
121         DEBUG(2, ("[CEPH] calling: ceph_mount\n"));
122         ret = ceph_mount(cmount, NULL);
123         if (ret < 0)
124                 goto err_out;
125
126
127         /*
128          * encode mount context/state into our vfs/connection holding structure
129          * cmount is a ceph_mount_t*
130          */
131         handle->data = cmount;
132         cmount_cnt++;
133
134         return 0;
135
136 err_out:
137         /*
138          * Handle the error correctly. Ceph returns -errno.
139          */
140         DEBUG(2, ("[CEPH] Error return: %s\n", strerror(-ret)));
141         WRAP_RETURN(ret);
142 }
143
144 static void cephwrap_disconnect(struct vfs_handle_struct *handle)
145 {
146         if (!cmount) {
147                 DEBUG(0, ("[CEPH] Error, ceph not mounted\n"));
148                 return;
149         }
150
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;
155         }
156
157         ceph_shutdown(cmount);
158
159         cmount = NULL;  /* Make it safe */
160 }
161
162 /* Disk operations */
163
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)
167 {
168         struct statvfs statvfs_buf;
169         int ret;
170
171         if (!(ret = ceph_statfs(handle->data, path, &statvfs_buf))) {
172                 /*
173                  * Provide all the correct values.
174                  */
175                 *bsize = statvfs_buf.f_bsize;
176                 *dfree = statvfs_buf.f_bavail;
177                 *dsize = statvfs_buf.f_blocks;
178                 DEBUG(10, ("[CEPH] bsize: %llu, dfree: %llu, dsize: %llu\n",
179                         llu(*bsize), llu(*dfree), llu(*dsize)));
180                 return *dfree;
181         } else {
182                 DEBUG(10, ("[CEPH] ceph_statfs returned %d\n", ret));
183                 WRAP_RETURN(ret);
184         }
185 }
186
187 static int cephwrap_get_quota(struct vfs_handle_struct *handle,
188                               const char *path, enum SMB_QUOTA_TYPE qtype,
189                               unid_t id, SMB_DISK_QUOTA *qt)
190 {
191         /* libceph: Ceph does not implement this */
192 #if 0
193 /* was ifdef HAVE_SYS_QUOTAS */
194         int ret;
195
196         ret = ceph_get_quota(handle->conn->connectpath, qtype, id, qt);
197
198         if (ret) {
199                 errno = -ret;
200                 ret = -1;
201         }
202
203         return ret;
204 #else
205         errno = ENOSYS;
206         return -1;
207 #endif
208 }
209
210 static int cephwrap_set_quota(struct vfs_handle_struct *handle,  enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
211 {
212         /* libceph: Ceph does not implement this */
213 #if 0
214 /* was ifdef HAVE_SYS_QUOTAS */
215         int ret;
216
217         ret = ceph_set_quota(handle->conn->connectpath, qtype, id, qt);
218         if (ret) {
219                 errno = -ret;
220                 ret = -1;
221         }
222
223         return ret;
224 #else
225         WRAP_RETURN(-ENOSYS);
226 #endif
227 }
228
229 static int cephwrap_statvfs(struct vfs_handle_struct *handle,  const char *path, vfs_statvfs_struct *statbuf)
230 {
231         struct statvfs statvfs_buf;
232         int ret;
233
234         ret = ceph_statfs(handle->data, path, &statvfs_buf);
235         if (ret < 0) {
236                 WRAP_RETURN(ret);
237         } else {
238                 statbuf->OptimalTransferSize = statvfs_buf.f_frsize;
239                 statbuf->BlockSize = statvfs_buf.f_bsize;
240                 statbuf->TotalBlocks = statvfs_buf.f_blocks;
241                 statbuf->BlocksAvail = statvfs_buf.f_bfree;
242                 statbuf->UserBlocksAvail = statvfs_buf.f_bavail;
243                 statbuf->TotalFileNodes = statvfs_buf.f_files;
244                 statbuf->FreeFileNodes = statvfs_buf.f_ffree;
245                 statbuf->FsIdentifier = statvfs_buf.f_fsid;
246                 DEBUG(10, ("[CEPH] f_bsize: %ld, f_blocks: %ld, f_bfree: %ld, f_bavail: %ld\n",
247                         (long int)statvfs_buf.f_bsize, (long int)statvfs_buf.f_blocks,
248                         (long int)statvfs_buf.f_bfree, (long int)statvfs_buf.f_bavail));
249         }
250         return ret;
251 }
252
253 /* Directory operations */
254
255 static DIR *cephwrap_opendir(struct vfs_handle_struct *handle,  const char *fname, const char *mask, uint32_t attr)
256 {
257         int ret = 0;
258         struct ceph_dir_result *result;
259         DEBUG(10, ("[CEPH] opendir(%p, %s)\n", handle, fname));
260
261         /* Returns NULL if it does not exist or there are problems ? */
262         ret = ceph_opendir(handle->data, fname, &result);
263         if (ret < 0) {
264                 result = NULL;
265                 errno = -ret; /* We return result which is NULL in this case */
266         }
267
268         DEBUG(10, ("[CEPH] opendir(...) = %d\n", ret));
269         return (DIR *) result;
270 }
271
272 static DIR *cephwrap_fdopendir(struct vfs_handle_struct *handle,
273                                struct files_struct *fsp,
274                                const char *mask,
275                                uint32_t attributes)
276 {
277         int ret = 0;
278         struct ceph_dir_result *result;
279         DEBUG(10, ("[CEPH] fdopendir(%p, %p)\n", handle, fsp));
280
281         ret = ceph_opendir(handle->data, fsp->fsp_name->base_name, &result);
282         if (ret < 0) {
283                 result = NULL;
284                 errno = -ret; /* We return result which is NULL in this case */
285         }
286
287         DEBUG(10, ("[CEPH] fdopendir(...) = %d\n", ret));
288         return (DIR *) result;
289 }
290
291 static struct dirent *cephwrap_readdir(struct vfs_handle_struct *handle,
292                                        DIR *dirp,
293                                        SMB_STRUCT_STAT *sbuf)
294 {
295         struct dirent *result;
296
297         DEBUG(10, ("[CEPH] readdir(%p, %p)\n", handle, dirp));
298         result = ceph_readdir(handle->data, (struct ceph_dir_result *) dirp);
299         DEBUG(10, ("[CEPH] readdir(...) = %p\n", result));
300
301         /* Default Posix readdir() does not give us stat info.
302          * Set to invalid to indicate we didn't return this info. */
303         if (sbuf)
304                 SET_STAT_INVALID(*sbuf);
305         return result;
306 }
307
308 static void cephwrap_seekdir(struct vfs_handle_struct *handle, DIR *dirp, long offset)
309 {
310         DEBUG(10, ("[CEPH] seekdir(%p, %p, %ld)\n", handle, dirp, offset));
311         ceph_seekdir(handle->data, (struct ceph_dir_result *) dirp, offset);
312 }
313
314 static long cephwrap_telldir(struct vfs_handle_struct *handle, DIR *dirp)
315 {
316         long ret;
317         DEBUG(10, ("[CEPH] telldir(%p, %p)\n", handle, dirp));
318         ret = ceph_telldir(handle->data, (struct ceph_dir_result *) dirp);
319         DEBUG(10, ("[CEPH] telldir(...) = %ld\n", ret));
320         WRAP_RETURN(ret);
321 }
322
323 static void cephwrap_rewinddir(struct vfs_handle_struct *handle, DIR *dirp)
324 {
325         DEBUG(10, ("[CEPH] rewinddir(%p, %p)\n", handle, dirp));
326         ceph_rewinddir(handle->data, (struct ceph_dir_result *) dirp);
327 }
328
329 static int cephwrap_mkdir(struct vfs_handle_struct *handle,
330                           const struct smb_filename *smb_fname,
331                           mode_t mode)
332 {
333         int result;
334         bool has_dacl = False;
335         char *parent = NULL;
336         const char *path = smb_fname->base_name;
337
338         DEBUG(10, ("[CEPH] mkdir(%p, %s)\n", handle, path));
339
340         if (lp_inherit_acls(SNUM(handle->conn))
341             && parent_dirname(talloc_tos(), path, &parent, NULL)
342             && (has_dacl = directory_has_default_acl(handle->conn, parent)))
343                 mode = 0777;
344
345         TALLOC_FREE(parent);
346
347         result = ceph_mkdir(handle->data, path, mode);
348
349         /*
350          * Note. This order is important
351          */
352         if (result) {
353                 WRAP_RETURN(result);
354         } else if (result == 0 && !has_dacl) {
355                 /*
356                  * We need to do this as the default behavior of POSIX ACLs
357                  * is to set the mask to be the requested group permission
358                  * bits, not the group permission bits to be the requested
359                  * group permission bits. This is not what we want, as it will
360                  * mess up any inherited ACL bits that were set. JRA.
361                  */
362                 int saved_errno = errno; /* We may get ENOSYS */
363                 if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
364                         errno = saved_errno;
365         }
366
367         return result;
368 }
369
370 static int cephwrap_rmdir(struct vfs_handle_struct *handle,  const char *path)
371 {
372         int result;
373
374         DEBUG(10, ("[CEPH] rmdir(%p, %s)\n", handle, path));
375         result = ceph_rmdir(handle->data, path);
376         DEBUG(10, ("[CEPH] rmdir(...) = %d\n", result));
377         WRAP_RETURN(result);
378 }
379
380 static int cephwrap_closedir(struct vfs_handle_struct *handle, DIR *dirp)
381 {
382         int result;
383
384         DEBUG(10, ("[CEPH] closedir(%p, %p)\n", handle, dirp));
385         result = ceph_closedir(handle->data, (struct ceph_dir_result *) dirp);
386         DEBUG(10, ("[CEPH] closedir(...) = %d\n", result));
387         WRAP_RETURN(result);
388 }
389
390 /* File operations */
391
392 static int cephwrap_open(struct vfs_handle_struct *handle,
393                         struct smb_filename *smb_fname,
394                         files_struct *fsp, int flags, mode_t mode)
395 {
396         int result = -ENOENT;
397         DEBUG(10, ("[CEPH] open(%p, %s, %p, %d, %d)\n", handle, smb_fname_str_dbg(smb_fname), fsp, flags, mode));
398
399         if (smb_fname->stream_name) {
400                 goto out;
401         }
402
403         result = ceph_open(handle->data, smb_fname->base_name, flags, mode);
404 out:
405         DEBUG(10, ("[CEPH] open(...) = %d\n", result));
406         WRAP_RETURN(result);
407 }
408
409 static int cephwrap_close(struct vfs_handle_struct *handle, files_struct *fsp)
410 {
411         int result;
412
413         DEBUG(10, ("[CEPH] close(%p, %p)\n", handle, fsp));
414         result = ceph_close(handle->data, fsp->fh->fd);
415         DEBUG(10, ("[CEPH] close(...) = %d\n", result));
416
417         WRAP_RETURN(result);
418 }
419
420 static ssize_t cephwrap_read(struct vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
421 {
422         ssize_t result;
423
424         DEBUG(10, ("[CEPH] read(%p, %p, %p, %llu)\n", handle, fsp, data, llu(n)));
425
426         /* Using -1 for the offset means read/write rather than pread/pwrite */
427         result = ceph_read(handle->data, fsp->fh->fd, data, n, -1);
428         DEBUG(10, ("[CEPH] read(...) = %llu\n", llu(result)));
429         WRAP_RETURN(result);
430 }
431
432 static ssize_t cephwrap_pread(struct vfs_handle_struct *handle, files_struct *fsp, void *data,
433                         size_t n, off_t offset)
434 {
435         ssize_t result;
436
437         DEBUG(10, ("[CEPH] pread(%p, %p, %p, %llu, %llu)\n", handle, fsp, data, llu(n), llu(offset)));
438
439         result = ceph_read(handle->data, fsp->fh->fd, data, n, offset);
440         DEBUG(10, ("[CEPH] pread(...) = %llu\n", llu(result)));
441         WRAP_RETURN(result);
442 }
443
444
445 static ssize_t cephwrap_write(struct vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
446 {
447         ssize_t result;
448
449         DEBUG(10, ("[CEPH] write(%p, %p, %p, %llu)\n", handle, fsp, data, llu(n)));
450
451         result = ceph_write(handle->data, fsp->fh->fd, data, n, -1);
452
453         DEBUG(10, ("[CEPH] write(...) = %llu\n", llu(result)));
454         if (result < 0) {
455                 WRAP_RETURN(result);
456         }
457         fsp->fh->pos += result;
458         return result;
459 }
460
461 static ssize_t cephwrap_pwrite(struct vfs_handle_struct *handle, files_struct *fsp, const void *data,
462                         size_t n, off_t offset)
463 {
464         ssize_t result;
465
466         DEBUG(10, ("[CEPH] pwrite(%p, %p, %p, %llu, %llu)\n", handle, fsp, data, llu(n), llu(offset)));
467         result = ceph_write(handle->data, fsp->fh->fd, data, n, offset);
468         DEBUG(10, ("[CEPH] pwrite(...) = %llu\n", llu(result)));
469         WRAP_RETURN(result);
470 }
471
472 static off_t cephwrap_lseek(struct vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
473 {
474         off_t result = 0;
475
476         DEBUG(10, ("[CEPH] cephwrap_lseek\n"));
477         /* Cope with 'stat' file opens. */
478         if (fsp->fh->fd != -1) {
479                 result = ceph_lseek(handle->data, fsp->fh->fd, offset, whence);
480         }
481         WRAP_RETURN(result);
482 }
483
484 static ssize_t cephwrap_sendfile(struct vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
485                         off_t offset, size_t n)
486 {
487         /*
488          * We cannot support sendfile because libceph is in user space.
489          */
490         DEBUG(10, ("[CEPH] cephwrap_sendfile\n"));
491         errno = ENOTSUP;
492         return -1;
493 }
494
495 static ssize_t cephwrap_recvfile(struct vfs_handle_struct *handle,
496                         int fromfd,
497                         files_struct *tofsp,
498                         off_t offset,
499                         size_t n)
500 {
501         /*
502          * We cannot support recvfile because libceph is in user space.
503          */
504         DEBUG(10, ("[CEPH] cephwrap_recvfile\n"));
505         errno=ENOTSUP;
506         return -1;
507 }
508
509 static int cephwrap_rename(struct vfs_handle_struct *handle,
510                           const struct smb_filename *smb_fname_src,
511                           const struct smb_filename *smb_fname_dst)
512 {
513         int result = -1;
514         DEBUG(10, ("[CEPH] cephwrap_rename\n"));
515         if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
516                 errno = ENOENT;
517                 return result;
518         }
519
520         result = ceph_rename(handle->data, smb_fname_src->base_name, smb_fname_dst->base_name);
521         WRAP_RETURN(result);
522 }
523
524 static int cephwrap_fsync(struct vfs_handle_struct *handle, files_struct *fsp)
525 {
526         int result;
527         DEBUG(10, ("[CEPH] cephwrap_fsync\n"));
528         result = ceph_fsync(handle->data, fsp->fh->fd, false);
529         WRAP_RETURN(result);
530 }
531
532 static int cephwrap_stat(struct vfs_handle_struct *handle,
533                         struct smb_filename *smb_fname)
534 {
535         int result = -1;
536         struct stat stbuf;
537
538         DEBUG(10, ("[CEPH] stat(%p, %s)\n", handle, smb_fname_str_dbg(smb_fname)));
539
540         if (smb_fname->stream_name) {
541                 errno = ENOENT;
542                 return result;
543         }
544
545         result = ceph_stat(handle->data, smb_fname->base_name, (struct stat *) &stbuf);
546         DEBUG(10, ("[CEPH] stat(...) = %d\n", result));
547         if (result < 0) {
548                 WRAP_RETURN(result);
549         } else {
550                 DEBUG(10, ("[CEPH]\tstbuf = {dev = %llu, ino = %llu, mode = 0x%x, nlink = %llu, "
551                            "uid = %d, gid = %d, rdev = %llu, size = %llu, blksize = %llu, "
552                            "blocks = %llu, atime = %llu, mtime = %llu, ctime = %llu}\n",
553                            llu(stbuf.st_dev), llu(stbuf.st_ino), stbuf.st_mode, llu(stbuf.st_nlink),
554                            stbuf.st_uid, stbuf.st_gid, llu(stbuf.st_rdev), llu(stbuf.st_size), llu(stbuf.st_blksize),
555                            llu(stbuf.st_blocks), llu(stbuf.st_atime), llu(stbuf.st_mtime), llu(stbuf.st_ctime)));
556         }
557         init_stat_ex_from_stat(
558                         &smb_fname->st, &stbuf,
559                         lp_fake_directory_create_times(SNUM(handle->conn)));
560         DEBUG(10, ("[CEPH] mode = 0x%x\n", smb_fname->st.st_ex_mode));
561         return result;
562 }
563
564 static int cephwrap_fstat(struct vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
565 {
566         int result = -1;
567         struct stat stbuf;
568
569         DEBUG(10, ("[CEPH] fstat(%p, %d)\n", handle, fsp->fh->fd));
570         result = ceph_fstat(handle->data, fsp->fh->fd, (struct stat *) &stbuf);
571         DEBUG(10, ("[CEPH] fstat(...) = %d\n", result));
572         if (result < 0) {
573                 WRAP_RETURN(result);
574         } else {
575                 DEBUG(10, ("[CEPH]\tstbuf = {dev = %llu, ino = %llu, mode = 0x%x, nlink = %llu, "
576                            "uid = %d, gid = %d, rdev = %llu, size = %llu, blksize = %llu, "
577                            "blocks = %llu, atime = %llu, mtime = %llu, ctime = %llu}\n",
578                            llu(stbuf.st_dev), llu(stbuf.st_ino), stbuf.st_mode, llu(stbuf.st_nlink),
579                            stbuf.st_uid, stbuf.st_gid, llu(stbuf.st_rdev), llu(stbuf.st_size), llu(stbuf.st_blksize),
580                            llu(stbuf.st_blocks), llu(stbuf.st_atime), llu(stbuf.st_mtime), llu(stbuf.st_ctime)));
581         }
582
583         init_stat_ex_from_stat(
584                         sbuf, &stbuf,
585                         lp_fake_directory_create_times(SNUM(handle->conn)));
586         DEBUG(10, ("[CEPH] mode = 0x%x\n", sbuf->st_ex_mode));
587         return result;
588 }
589
590 static int cephwrap_lstat(struct vfs_handle_struct *handle,
591                          struct smb_filename *smb_fname)
592 {
593         int result = -1;
594         struct stat stbuf;
595
596         DEBUG(10, ("[CEPH] lstat(%p, %s)\n", handle, smb_fname_str_dbg(smb_fname)));
597
598         if (smb_fname->stream_name) {
599                 errno = ENOENT;
600                 return result;
601         }
602
603         result = ceph_lstat(handle->data, smb_fname->base_name, &stbuf);
604         DEBUG(10, ("[CEPH] lstat(...) = %d\n", result));
605         if (result < 0) {
606                 WRAP_RETURN(result);
607         }
608         init_stat_ex_from_stat(
609                         &smb_fname->st, &stbuf,
610                         lp_fake_directory_create_times(SNUM(handle->conn)));
611         return result;
612 }
613
614 static int cephwrap_unlink(struct vfs_handle_struct *handle,
615                           const struct smb_filename *smb_fname)
616 {
617         int result = -1;
618
619         DEBUG(10, ("[CEPH] unlink(%p, %s)\n", handle, smb_fname_str_dbg(smb_fname)));
620         if (smb_fname->stream_name) {
621                 errno = ENOENT;
622                 return result;
623         }
624         result = ceph_unlink(handle->data, smb_fname->base_name);
625         DEBUG(10, ("[CEPH] unlink(...) = %d\n", result));
626         WRAP_RETURN(result);
627 }
628
629 static int cephwrap_chmod(struct vfs_handle_struct *handle,  const char *path, mode_t mode)
630 {
631         int result;
632
633         DEBUG(10, ("[CEPH] chmod(%p, %s, %d)\n", handle, path, mode));
634
635         /*
636          * We need to do this due to the fact that the default POSIX ACL
637          * chmod modifies the ACL *mask* for the group owner, not the
638          * group owner bits directly. JRA.
639          */
640
641
642         {
643                 int saved_errno = errno; /* We might get ENOSYS */
644                 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
645                         return result;
646                 }
647                 /* Error - return the old errno. */
648                 errno = saved_errno;
649         }
650
651         result = ceph_chmod(handle->data, path, mode);
652         DEBUG(10, ("[CEPH] chmod(...) = %d\n", result));
653         WRAP_RETURN(result);
654 }
655
656 static int cephwrap_fchmod(struct vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
657 {
658         int result;
659
660         DEBUG(10, ("[CEPH] fchmod(%p, %p, %d)\n", handle, fsp, mode));
661
662         /*
663          * We need to do this due to the fact that the default POSIX ACL
664          * chmod modifies the ACL *mask* for the group owner, not the
665          * group owner bits directly. JRA.
666          */
667
668         {
669                 int saved_errno = errno; /* We might get ENOSYS */
670                 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
671                         return result;
672                 }
673                 /* Error - return the old errno. */
674                 errno = saved_errno;
675         }
676
677 #if defined(HAVE_FCHMOD)
678         result = ceph_fchmod(handle->data, fsp->fh->fd, mode);
679         DEBUG(10, ("[CEPH] fchmod(...) = %d\n", result));
680         WRAP_RETURN(result);
681 #else
682         errno = ENOSYS;
683 #endif
684         return -1;
685 }
686
687 static int cephwrap_chown(struct vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
688 {
689         int result;
690         DEBUG(10, ("[CEPH] chown(%p, %s, %d, %d)\n", handle, path, uid, gid));
691         result = ceph_chown(handle->data, path, uid, gid);
692         DEBUG(10, ("[CEPH] chown(...) = %d\n", result));
693         WRAP_RETURN(result);
694 }
695
696 static int cephwrap_fchown(struct vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
697 {
698         int result;
699 #ifdef HAVE_FCHOWN
700
701         DEBUG(10, ("[CEPH] fchown(%p, %p, %d, %d)\n", handle, fsp, uid, gid));
702         result = ceph_fchown(handle->data, fsp->fh->fd, uid, gid);
703         DEBUG(10, ("[CEPH] fchown(...) = %d\n", result));
704         WRAP_RETURN(result);
705 #else
706         errno = ENOSYS;
707         result = -1;
708 #endif
709         return result;
710 }
711
712 static int cephwrap_lchown(struct vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
713 {
714         int result;
715
716         DEBUG(10, ("[CEPH] lchown(%p, %s, %d, %d)\n", handle, path, uid, gid));
717         result = ceph_lchown(handle->data, path, uid, gid);
718         DEBUG(10, ("[CEPH] lchown(...) = %d\n", result));
719         WRAP_RETURN(result);
720 }
721
722 static int cephwrap_chdir(struct vfs_handle_struct *handle,  const char *path)
723 {
724         int result = -1;
725         DEBUG(10, ("[CEPH] chdir(%p, %s)\n", handle, path));
726         /*
727          * If the path is just / use chdir because Ceph is below / and
728          * cannot deal with changing directory above its mount point
729          */
730         if (path && !strcmp(path, "/"))
731                 return chdir(path);
732
733         result = ceph_chdir(handle->data, path);
734         DEBUG(10, ("[CEPH] chdir(...) = %d\n", result));
735         WRAP_RETURN(result);
736 }
737
738 static char *cephwrap_getwd(struct vfs_handle_struct *handle)
739 {
740         const char *cwd = ceph_getcwd(handle->data);
741         DEBUG(10, ("[CEPH] getwd(%p) = %s\n", handle, cwd));
742         return SMB_STRDUP(cwd);
743 }
744
745 static int cephwrap_ntimes(struct vfs_handle_struct *handle,
746                          const struct smb_filename *smb_fname,
747                          struct smb_file_time *ft)
748 {
749         struct utimbuf buf;
750         int result;
751
752         if (null_timespec(ft->atime)) {
753                 buf.actime = smb_fname->st.st_ex_atime.tv_sec;
754         } else {
755                 buf.actime = ft->atime.tv_sec;
756         }
757         if (null_timespec(ft->mtime)) {
758                 buf.modtime = smb_fname->st.st_ex_mtime.tv_sec;
759         } else {
760                 buf.modtime = ft->mtime.tv_sec;
761         }
762         if (!null_timespec(ft->create_time)) {
763                 set_create_timespec_ea(handle->conn, smb_fname,
764                                        ft->create_time);
765         }
766         if (buf.actime == smb_fname->st.st_ex_atime.tv_sec &&
767             buf.modtime == smb_fname->st.st_ex_mtime.tv_sec) {
768                 return 0;
769         }
770
771         result = ceph_utime(handle->data, smb_fname->base_name, &buf);
772         DEBUG(10, ("[CEPH] ntimes(%p, %s, {%ld, %ld, %ld, %ld}) = %d\n", handle, smb_fname_str_dbg(smb_fname),
773                                 ft->mtime.tv_sec, ft->atime.tv_sec, ft->ctime.tv_sec,
774                                 ft->create_time.tv_sec, result));
775         return result;
776 }
777
778 static int strict_allocate_ftruncate(struct vfs_handle_struct *handle, files_struct *fsp, off_t len)
779 {
780         off_t space_to_write;
781         uint64_t space_avail;
782         uint64_t bsize,dfree,dsize;
783         int ret;
784         NTSTATUS status;
785         SMB_STRUCT_STAT *pst;
786
787         status = vfs_stat_fsp(fsp);
788         if (!NT_STATUS_IS_OK(status)) {
789                 return -1;
790         }
791         pst = &fsp->fsp_name->st;
792
793 #ifdef S_ISFIFO
794         if (S_ISFIFO(pst->st_ex_mode))
795                 return 0;
796 #endif
797
798         if (pst->st_ex_size == len)
799                 return 0;
800
801         /* Shrink - just ftruncate. */
802         if (pst->st_ex_size > len)
803                 return ftruncate(fsp->fh->fd, len);
804
805         space_to_write = len - pst->st_ex_size;
806
807         /* for allocation try fallocate first. This can fail on some
808            platforms e.g. when the filesystem doesn't support it and no
809            emulation is being done by the libc (like on AIX with JFS1). In that
810            case we do our own emulation. fallocate implementations can
811            return ENOTSUP or EINVAL in cases like that. */
812         ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
813         if (ret == -1 && errno == ENOSPC) {
814                 return -1;
815         }
816         if (ret == 0) {
817                 return 0;
818         }
819         DEBUG(10,("[CEPH] strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
820                 "error %d. Falling back to slow manual allocation\n", errno));
821
822         /* available disk space is enough or not? */
823         space_avail = get_dfree_info(fsp->conn,
824                                      fsp->fsp_name->base_name,
825                                      &bsize, &dfree, &dsize);
826         /* space_avail is 1k blocks */
827         if (space_avail == (uint64_t)-1 ||
828                         ((uint64_t)space_to_write/1024 > space_avail) ) {
829                 errno = ENOSPC;
830                 return -1;
831         }
832
833         /* Write out the real space on disk. */
834         return vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
835 }
836
837 static int cephwrap_ftruncate(struct vfs_handle_struct *handle, files_struct *fsp, off_t len)
838 {
839         int result = -1;
840         SMB_STRUCT_STAT st;
841         char c = 0;
842         off_t currpos;
843
844         DEBUG(10, ("[CEPH] ftruncate(%p, %p, %llu\n", handle, fsp, llu(len)));
845
846         if (lp_strict_allocate(SNUM(fsp->conn))) {
847                 result = strict_allocate_ftruncate(handle, fsp, len);
848                 return result;
849         }
850
851         /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
852            sys_ftruncate if the system supports it. Then I discovered that
853            you can have some filesystems that support ftruncate
854            expansion and some that don't! On Linux fat can't do
855            ftruncate extend but ext2 can. */
856
857         result = ceph_ftruncate(handle->data, fsp->fh->fd, len);
858         if (result == 0)
859                 goto done;
860
861         /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
862            extend a file with ftruncate. Provide alternate implementation
863            for this */
864         currpos = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
865         if (currpos == -1) {
866                 goto done;
867         }
868
869         /* Do an fstat to see if the file is longer than the requested
870            size in which case the ftruncate above should have
871            succeeded or shorter, in which case seek to len - 1 and
872            write 1 byte of zero */
873         if (SMB_VFS_FSTAT(fsp, &st) == -1) {
874                 goto done;
875         }
876
877 #ifdef S_ISFIFO
878         if (S_ISFIFO(st.st_ex_mode)) {
879                 result = 0;
880                 goto done;
881         }
882 #endif
883
884         if (st.st_ex_size == len) {
885                 result = 0;
886                 goto done;
887         }
888
889         if (st.st_ex_size > len) {
890                 /* the sys_ftruncate should have worked */
891                 goto done;
892         }
893
894         if (SMB_VFS_LSEEK(fsp, len-1, SEEK_SET) != len -1)
895                 goto done;
896
897         if (SMB_VFS_WRITE(fsp, &c, 1)!=1)
898                 goto done;
899
900         /* Seek to where we were */
901         if (SMB_VFS_LSEEK(fsp, currpos, SEEK_SET) != currpos)
902                 goto done;
903         result = 0;
904
905   done:
906
907         return result;
908 }
909
910 static bool cephwrap_lock(struct vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
911 {
912         DEBUG(10, ("[CEPH] lock\n"));
913         return true;
914 }
915
916 static int cephwrap_kernel_flock(struct vfs_handle_struct *handle, files_struct *fsp,
917                                 uint32_t share_mode, uint32_t access_mask)
918 {
919         DEBUG(10, ("[CEPH] kernel_flock\n"));
920         /*
921          * We must return zero here and pretend all is good.
922          * One day we might have this in CEPH.
923          */
924         return 0;
925 }
926
927 static bool cephwrap_getlock(struct vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
928 {
929         DEBUG(10, ("[CEPH] getlock returning false and errno=0\n"));
930
931         errno = 0;
932         return false;
933 }
934
935 /*
936  * We cannot let this fall through to the default, because the file might only
937  * be accessible from libceph (which is a user-space client) but the fd might
938  * be for some file the kernel knows about.
939  */
940 static int cephwrap_linux_setlease(struct vfs_handle_struct *handle, files_struct *fsp,
941                                 int leasetype)
942 {
943         int result = -1;
944
945         DEBUG(10, ("[CEPH] linux_setlease\n"));
946         errno = ENOSYS;
947         return result;
948 }
949
950 static int cephwrap_symlink(struct vfs_handle_struct *handle,  const char *oldpath, const char *newpath)
951 {
952         int result = -1;
953         DEBUG(10, ("[CEPH] symlink(%p, %s, %s)\n", handle, oldpath, newpath));
954         result = ceph_symlink(handle->data, oldpath, newpath);
955         DEBUG(10, ("[CEPH] symlink(...) = %d\n", result));
956         WRAP_RETURN(result);
957 }
958
959 static int cephwrap_readlink(struct vfs_handle_struct *handle,  const char *path, char *buf, size_t bufsiz)
960 {
961         int result = -1;
962         DEBUG(10, ("[CEPH] readlink(%p, %s, %p, %llu)\n", handle, path, buf, llu(bufsiz)));
963         result = ceph_readlink(handle->data, path, buf, bufsiz);
964         DEBUG(10, ("[CEPH] readlink(...) = %d\n", result));
965         WRAP_RETURN(result);
966 }
967
968 static int cephwrap_link(struct vfs_handle_struct *handle,  const char *oldpath, const char *newpath)
969 {
970         int result = -1;
971         DEBUG(10, ("[CEPH] link(%p, %s, %s)\n", handle, oldpath, newpath));
972         result = ceph_link(handle->data, oldpath, newpath);
973         DEBUG(10, ("[CEPH] link(...) = %d\n", result));
974         WRAP_RETURN(result);
975 }
976
977 static int cephwrap_mknod(struct vfs_handle_struct *handle,  const char *pathname, mode_t mode, SMB_DEV_T dev)
978 {
979         int result = -1;
980         DEBUG(10, ("[CEPH] mknod(%p, %s)\n", handle, pathname));
981         result = ceph_mknod(handle->data, pathname, mode, dev);
982         DEBUG(10, ("[CEPH] mknod(...) = %d\n", result));
983         WRAP_RETURN(result);
984 }
985
986 /*
987  * This is a simple version of real-path ... a better version is needed to
988  * ask libceph about symbolic links.
989  */
990 static char *cephwrap_realpath(struct vfs_handle_struct *handle,  const char *path)
991 {
992         char *result;
993         size_t len = strlen(path);
994
995         result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
996         if (len && (path[0] == '/')) {
997                 int r = asprintf(&result, "%s", path);
998                 if (r < 0) return NULL;
999         } else if ((len >= 2) && (path[0] == '.') && (path[1] == '/')) {
1000                 if (len == 2) {
1001                         int r = asprintf(&result, "%s",
1002                                         handle->conn->connectpath);
1003                         if (r < 0) return NULL;
1004                 } else {
1005                         int r = asprintf(&result, "%s/%s",
1006                                         handle->conn->connectpath, &path[2]);
1007                         if (r < 0) return NULL;
1008                 }
1009         } else {
1010                 int r = asprintf(&result, "%s/%s",
1011                                 handle->conn->connectpath, path);
1012                 if (r < 0) return NULL;
1013         }
1014         DEBUG(10, ("[CEPH] realpath(%p, %s) = %s\n", handle, path, result));
1015         return result;
1016 }
1017
1018 static int cephwrap_chflags(struct vfs_handle_struct *handle, const char *path,
1019                            unsigned int flags)
1020 {
1021         errno = ENOSYS;
1022         return -1;
1023 }
1024
1025 static int cephwrap_get_real_filename(struct vfs_handle_struct *handle,
1026                                      const char *path,
1027                                      const char *name,
1028                                      TALLOC_CTX *mem_ctx,
1029                                      char **found_name)
1030 {
1031         /*
1032          * Don't fall back to get_real_filename so callers can differentiate
1033          * between a full directory scan and an actual case-insensitive stat.
1034          */
1035         errno = EOPNOTSUPP;
1036         return -1;
1037 }
1038
1039 static const char *cephwrap_connectpath(struct vfs_handle_struct *handle,
1040                                        const char *fname)
1041 {
1042         return handle->conn->connectpath;
1043 }
1044
1045 /****************************************************************
1046  Extended attribute operations.
1047 *****************************************************************/
1048
1049 static ssize_t cephwrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
1050 {
1051         int ret;
1052         DEBUG(10, ("[CEPH] getxattr(%p, %s, %s, %p, %llu)\n", handle, path, name, value, llu(size)));
1053         ret = ceph_getxattr(handle->data, path, name, value, size);
1054         DEBUG(10, ("[CEPH] getxattr(...) = %d\n", ret));
1055         if (ret < 0) {
1056                 WRAP_RETURN(ret);
1057         } else {
1058                 return (ssize_t)ret;
1059         }
1060 }
1061
1062 static ssize_t cephwrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
1063 {
1064         int ret;
1065         DEBUG(10, ("[CEPH] fgetxattr(%p, %p, %s, %p, %llu)\n", handle, fsp, name, value, llu(size)));
1066 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1067         ret = ceph_fgetxattr(handle->data, fsp->fh->fd, name, value, size);
1068 #else
1069         ret = ceph_getxattr(handle->data, fsp->fsp_name->base_name, name, value, size);
1070 #endif
1071         DEBUG(10, ("[CEPH] fgetxattr(...) = %d\n", ret));
1072         if (ret < 0) {
1073                 WRAP_RETURN(ret);
1074         } else {
1075                 return (ssize_t)ret;
1076         }
1077 }
1078
1079 static ssize_t cephwrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
1080 {
1081         int ret;
1082         DEBUG(10, ("[CEPH] listxattr(%p, %s, %p, %llu)\n", handle, path, list, llu(size)));
1083         ret = ceph_listxattr(handle->data, path, list, size);
1084         DEBUG(10, ("[CEPH] listxattr(...) = %d\n", ret));
1085         if (ret < 0) {
1086                 WRAP_RETURN(ret);
1087         } else {
1088                 return (ssize_t)ret;
1089         }
1090 }
1091
1092 #if 0
1093 static ssize_t cephwrap_llistxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
1094 {
1095         int ret;
1096         DEBUG(10, ("[CEPH] llistxattr(%p, %s, %p, %llu)\n", handle, path, list, llu(size)));
1097         ret = ceph_llistxattr(handle->data, path, list, size);
1098         DEBUG(10, ("[CEPH] listxattr(...) = %d\n", ret));
1099         if (ret < 0) {
1100                 WRAP_RETURN(ret);
1101         } else {
1102                 return (ssize_t)ret;
1103         }
1104 }
1105 #endif
1106
1107 static ssize_t cephwrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
1108 {
1109         int ret;
1110         DEBUG(10, ("[CEPH] flistxattr(%p, %p, %s, %llu)\n", handle, fsp, list, llu(size)));
1111 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1112         ret = ceph_flistxattr(handle->data, fsp->fh->fd, list, size);
1113 #else
1114         ret = ceph_listxattr(handle->data, fsp->fsp_name->base_name, list, size);
1115 #endif
1116         DEBUG(10, ("[CEPH] flistxattr(...) = %d\n", ret));
1117         if (ret < 0) {
1118                 WRAP_RETURN(ret);
1119         } else {
1120                 return (ssize_t)ret;
1121         }
1122 }
1123
1124 static int cephwrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
1125 {
1126         int ret;
1127         DEBUG(10, ("[CEPH] removexattr(%p, %s, %s)\n", handle, path, name));
1128         ret = ceph_removexattr(handle->data, path, name);
1129         DEBUG(10, ("[CEPH] removexattr(...) = %d\n", ret));
1130         WRAP_RETURN(ret);
1131 }
1132
1133 static int cephwrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
1134 {
1135         int ret;
1136         DEBUG(10, ("[CEPH] fremovexattr(%p, %p, %s)\n", handle, fsp, name));
1137 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1138         ret = ceph_fremovexattr(handle->data, fsp->fh->fd, name);
1139 #else
1140         ret = ceph_removexattr(handle->data, fsp->fsp_name->base_name, name);
1141 #endif
1142         DEBUG(10, ("[CEPH] fremovexattr(...) = %d\n", ret));
1143         WRAP_RETURN(ret);
1144 }
1145
1146 static int cephwrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
1147 {
1148         int ret;
1149         DEBUG(10, ("[CEPH] setxattr(%p, %s, %s, %p, %llu, %d)\n", handle, path, name, value, llu(size), flags));
1150         ret = ceph_setxattr(handle->data, path, name, value, size, flags);
1151         DEBUG(10, ("[CEPH] setxattr(...) = %d\n", ret));
1152         WRAP_RETURN(ret);
1153 }
1154
1155 static int cephwrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
1156 {
1157         int ret;
1158         DEBUG(10, ("[CEPH] fsetxattr(%p, %p, %s, %p, %llu, %d)\n", handle, fsp, name, value, llu(size), flags));
1159 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1160         ret = ceph_fsetxattr(handle->data, fsp->fh->fd,
1161                              name, value, size, flags);
1162 #else
1163         ret = ceph_setxattr(handle->data, fsp->fsp_name->base_name, name, value, size, flags);
1164 #endif
1165         DEBUG(10, ("[CEPH] fsetxattr(...) = %d\n", ret));
1166         WRAP_RETURN(ret);
1167 }
1168
1169 static bool cephwrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
1170 {
1171
1172         /*
1173          * We do not support AIO yet.
1174          */
1175
1176         DEBUG(10, ("[CEPH] cephwrap_aio_force(%p, %p) = false (errno = ENOTSUP)\n", handle, fsp));
1177         errno = ENOTSUP;
1178         return false;
1179 }
1180
1181 static bool cephwrap_is_offline(struct vfs_handle_struct *handle,
1182                                 const struct smb_filename *fname,
1183                                 SMB_STRUCT_STAT *sbuf)
1184 {
1185         return false;
1186 }
1187
1188 static int cephwrap_set_offline(struct vfs_handle_struct *handle,
1189                                 const struct smb_filename *fname)
1190 {
1191         errno = ENOTSUP;
1192         return -1;
1193 }
1194
1195 static SMB_ACL_T cephwrap_sys_acl_get_file(struct vfs_handle_struct *handle,
1196                                            const char *path_p,
1197                                            SMB_ACL_TYPE_T type,
1198                                            TALLOC_CTX *mem_ctx)
1199 {
1200         errno = ENOTSUP;
1201         return NULL;
1202 }
1203
1204 static SMB_ACL_T cephwrap_sys_acl_get_fd(struct vfs_handle_struct *handle,
1205                                          struct files_struct *fsp,
1206                                          TALLOC_CTX *mem_ctx)
1207 {
1208         errno = ENOTSUP;
1209         return NULL;
1210 }
1211
1212 static int cephwrap_sys_acl_set_file(struct vfs_handle_struct *handle,
1213                                      const char *name,
1214                                      SMB_ACL_TYPE_T acltype,
1215                                      SMB_ACL_T theacl)
1216 {
1217         errno = ENOTSUP;
1218         return -1;
1219 }
1220
1221 static int cephwrap_sys_acl_set_fd(struct vfs_handle_struct *handle,
1222                                    struct files_struct *fsp,
1223                                    SMB_ACL_T theacl)
1224 {
1225         errno = ENOTSUP;
1226         return -1;
1227 }
1228
1229 static int cephwrap_sys_acl_delete_def_file(struct vfs_handle_struct *handle,
1230                                             const char *path)
1231 {
1232         errno = ENOTSUP;
1233         return -1;
1234 }
1235
1236 static struct vfs_fn_pointers ceph_fns = {
1237         /* Disk operations */
1238
1239         .connect_fn = cephwrap_connect,
1240         .disconnect_fn = cephwrap_disconnect,
1241         .disk_free_fn = cephwrap_disk_free,
1242         .get_quota_fn = cephwrap_get_quota,
1243         .set_quota_fn = cephwrap_set_quota,
1244         .statvfs_fn = cephwrap_statvfs,
1245
1246         /* Directory operations */
1247
1248         .opendir_fn = cephwrap_opendir,
1249         .fdopendir_fn = cephwrap_fdopendir,
1250         .readdir_fn = cephwrap_readdir,
1251         .seekdir_fn = cephwrap_seekdir,
1252         .telldir_fn = cephwrap_telldir,
1253         .rewind_dir_fn = cephwrap_rewinddir,
1254         .mkdir_fn = cephwrap_mkdir,
1255         .rmdir_fn = cephwrap_rmdir,
1256         .closedir_fn = cephwrap_closedir,
1257
1258         /* File operations */
1259
1260         .open_fn = cephwrap_open,
1261         .close_fn = cephwrap_close,
1262         .read_fn = cephwrap_read,
1263         .pread_fn = cephwrap_pread,
1264         .write_fn = cephwrap_write,
1265         .pwrite_fn = cephwrap_pwrite,
1266         .lseek_fn = cephwrap_lseek,
1267         .sendfile_fn = cephwrap_sendfile,
1268         .recvfile_fn = cephwrap_recvfile,
1269         .rename_fn = cephwrap_rename,
1270         .fsync_fn = cephwrap_fsync,
1271         .stat_fn = cephwrap_stat,
1272         .fstat_fn = cephwrap_fstat,
1273         .lstat_fn = cephwrap_lstat,
1274         .unlink_fn = cephwrap_unlink,
1275         .chmod_fn = cephwrap_chmod,
1276         .fchmod_fn = cephwrap_fchmod,
1277         .chown_fn = cephwrap_chown,
1278         .fchown_fn = cephwrap_fchown,
1279         .lchown_fn = cephwrap_lchown,
1280         .chdir_fn = cephwrap_chdir,
1281         .getwd_fn = cephwrap_getwd,
1282         .ntimes_fn = cephwrap_ntimes,
1283         .ftruncate_fn = cephwrap_ftruncate,
1284         .lock_fn = cephwrap_lock,
1285         .kernel_flock_fn = cephwrap_kernel_flock,
1286         .linux_setlease_fn = cephwrap_linux_setlease,
1287         .getlock_fn = cephwrap_getlock,
1288         .symlink_fn = cephwrap_symlink,
1289         .readlink_fn = cephwrap_readlink,
1290         .link_fn = cephwrap_link,
1291         .mknod_fn = cephwrap_mknod,
1292         .realpath_fn = cephwrap_realpath,
1293         .chflags_fn = cephwrap_chflags,
1294         .get_real_filename_fn = cephwrap_get_real_filename,
1295         .connectpath_fn = cephwrap_connectpath,
1296
1297         /* EA operations. */
1298         .getxattr_fn = cephwrap_getxattr,
1299         .fgetxattr_fn = cephwrap_fgetxattr,
1300         .listxattr_fn = cephwrap_listxattr,
1301         .flistxattr_fn = cephwrap_flistxattr,
1302         .removexattr_fn = cephwrap_removexattr,
1303         .fremovexattr_fn = cephwrap_fremovexattr,
1304         .setxattr_fn = cephwrap_setxattr,
1305         .fsetxattr_fn = cephwrap_fsetxattr,
1306
1307         /* Posix ACL Operations */
1308         .sys_acl_get_file_fn = cephwrap_sys_acl_get_file,
1309         .sys_acl_get_fd_fn = cephwrap_sys_acl_get_fd,
1310         .sys_acl_set_file_fn = cephwrap_sys_acl_set_file,
1311         .sys_acl_set_fd_fn = cephwrap_sys_acl_set_fd,
1312         .sys_acl_delete_def_file_fn = cephwrap_sys_acl_delete_def_file,
1313
1314         /* aio operations */
1315         .aio_force_fn = cephwrap_aio_force,
1316
1317         /* offline operations */
1318         .is_offline_fn = cephwrap_is_offline,
1319         .set_offline_fn = cephwrap_set_offline
1320 };
1321
1322 NTSTATUS vfs_ceph_init(void);
1323 NTSTATUS vfs_ceph_init(void)
1324 {
1325         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
1326                                 "ceph", &ceph_fns);
1327 }