87b4cd2a791cdc8afe00f7197b9c1fd7fbfca76b
[samba.git] / source3 / modules / vfs_shadow_copy2.c
1 /*
2  * shadow_copy2: a shadow copy module (second implementation)
3  *
4  * Copyright (C) Andrew Tridgell   2007 (portions taken from shadow_copy2)
5  * Copyright (C) Ed Plese          2009
6  * Copyright (C) Volker Lendecke   2011
7  * Copyright (C) Christian Ambach  2011
8  * Copyright (C) Michael Adam      2013
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24
25 /*
26  * This is a second implemetation of a shadow copy module for exposing
27  * file system snapshots to windows clients as shadow copies.
28  *
29  * See the manual page for documentation.
30  */
31
32 #include "includes.h"
33 #include "smbd/smbd.h"
34 #include "system/filesys.h"
35 #include "include/ntioctl.h"
36 #include "util_tdb.h"
37
38 struct shadow_copy2_config {
39         char *gmt_format;
40         bool use_sscanf;
41         bool use_localtime;
42         char *snapdir;
43         bool snapdirseverywhere;
44         bool crossmountpoints;
45         bool fixinodes;
46         char *sort_order;
47         bool snapdir_absolute;
48         char *mount_point;
49         char *rel_connectpath; /* share root, relative to a snapshot root */
50         char *snapshot_basepath; /* the absolute version of snapdir */
51 };
52
53 static bool shadow_copy2_find_slashes(TALLOC_CTX *mem_ctx, const char *str,
54                                       size_t **poffsets,
55                                       unsigned *pnum_offsets)
56 {
57         unsigned num_offsets;
58         size_t *offsets;
59         const char *p;
60
61         num_offsets = 0;
62
63         p = str;
64         while ((p = strchr(p, '/')) != NULL) {
65                 num_offsets += 1;
66                 p += 1;
67         }
68
69         offsets = talloc_array(mem_ctx, size_t, num_offsets);
70         if (offsets == NULL) {
71                 return false;
72         }
73
74         p = str;
75         num_offsets = 0;
76         while ((p = strchr(p, '/')) != NULL) {
77                 offsets[num_offsets] = p-str;
78                 num_offsets += 1;
79                 p += 1;
80         }
81
82         *poffsets = offsets;
83         *pnum_offsets = num_offsets;
84         return true;
85 }
86
87 /**
88  * Given a timestamp, build the posix level GMT-tag string
89  * based on the configurable format.
90  */
91 static size_t shadow_copy2_posix_gmt_string(struct vfs_handle_struct *handle,
92                                             time_t snapshot,
93                                             char *snaptime_string,
94                                             size_t len)
95 {
96         struct tm snap_tm;
97         size_t snaptime_len;
98         struct shadow_copy2_config *config;
99
100         SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config,
101                                 return 0);
102
103         if (config->use_sscanf) {
104                 snaptime_len = snprintf(snaptime_string,
105                                         len,
106                                         config->gmt_format,
107                                         (unsigned long)snapshot);
108                 if (snaptime_len <= 0) {
109                         DEBUG(10, ("snprintf failed\n"));
110                         return snaptime_len;
111                 }
112         } else {
113                 if (config->use_localtime) {
114                         if (localtime_r(&snapshot, &snap_tm) == 0) {
115                                 DEBUG(10, ("gmtime_r failed\n"));
116                                 return -1;
117                         }
118                 } else {
119                         if (gmtime_r(&snapshot, &snap_tm) == 0) {
120                                 DEBUG(10, ("gmtime_r failed\n"));
121                                 return -1;
122                         }
123                 }
124                 snaptime_len = strftime(snaptime_string,
125                                         len,
126                                         config->gmt_format,
127                                         &snap_tm);
128                 if (snaptime_len == 0) {
129                         DEBUG(10, ("strftime failed\n"));
130                         return 0;
131                 }
132         }
133
134         return snaptime_len;
135 }
136
137 /**
138  * Given a timestamp, build the string to insert into a path
139  * as a path component for creating the local path to the
140  * snapshot at the given timestamp of the input path.
141  *
142  * In the case of a parallel snapdir (specified with an
143  * absolute path), this is the inital portion of the
144  * local path of any snapshot file. The complete path is
145  * obtained by appending the portion of the file's path
146  * below the share root's mountpoint.
147  */
148 static char *shadow_copy2_insert_string(TALLOC_CTX *mem_ctx,
149                                         struct vfs_handle_struct *handle,
150                                         time_t snapshot)
151 {
152         fstring snaptime_string;
153         size_t snaptime_len = 0;
154         char *result = NULL;
155         struct shadow_copy2_config *config;
156
157         SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config,
158                                 return NULL);
159
160         snaptime_len = shadow_copy2_posix_gmt_string(handle,
161                                                      snapshot,
162                                                      snaptime_string,
163                                                      sizeof(snaptime_string));
164         if (snaptime_len <= 0) {
165                 return NULL;
166         }
167
168         if (config->snapdir_absolute) {
169                 result = talloc_asprintf(mem_ctx, "%s/%s",
170                                          config->snapdir, snaptime_string);
171         } else {
172                 result = talloc_asprintf(mem_ctx, "/%s/%s",
173                                          config->snapdir, snaptime_string);
174         }
175         if (result == NULL) {
176                 DEBUG(1, (__location__ " talloc_asprintf failed\n"));
177         }
178
179         return result;
180 }
181
182 /**
183  * Build the posix snapshot path for the connection
184  * at the given timestamp, i.e. the absolute posix path
185  * that contains the snapshot for this file system.
186  *
187  * This only applies to classical case, i.e. not
188  * to the "snapdirseverywhere" mode.
189  */
190 static char *shadow_copy2_snapshot_path(TALLOC_CTX *mem_ctx,
191                                         struct vfs_handle_struct *handle,
192                                         time_t snapshot)
193 {
194         fstring snaptime_string;
195         size_t snaptime_len = 0;
196         char *result = NULL;
197         struct shadow_copy2_config *config;
198
199         SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config,
200                                 return NULL);
201
202         snaptime_len = shadow_copy2_posix_gmt_string(handle,
203                                                      snapshot,
204                                                      snaptime_string,
205                                                      sizeof(snaptime_string));
206         if (snaptime_len <= 0) {
207                 return NULL;
208         }
209
210         result = talloc_asprintf(mem_ctx, "%s/%s",
211                                  config->snapshot_basepath, snaptime_string);
212         if (result == NULL) {
213                 DEBUG(1, (__location__ " talloc_asprintf failed\n"));
214         }
215
216         return result;
217 }
218
219 /**
220  * Strip a snapshot component from a filename as
221  * handed in via the smb layer.
222  * Returns the parsed timestamp and the stripped filename.
223  */
224 static bool shadow_copy2_strip_snapshot(TALLOC_CTX *mem_ctx,
225                                         struct vfs_handle_struct *handle,
226                                         const char *name,
227                                         time_t *ptimestamp,
228                                         char **pstripped)
229 {
230         struct tm tm;
231         time_t timestamp;
232         const char *p;
233         char *q;
234         char *stripped;
235         size_t rest_len, dst_len;
236         struct shadow_copy2_config *config;
237         const char *snapdir;
238         ssize_t snapdirlen;
239         ptrdiff_t len_before_gmt;
240
241         SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config,
242                                 return false);
243
244         DEBUG(10, (__location__ ": enter path '%s'\n", name));
245
246         p = strstr_m(name, "@GMT-");
247         if (p == NULL) {
248                 DEBUG(11, ("@GMT not found\n"));
249                 goto no_snapshot;
250         }
251         if ((p > name) && (p[-1] != '/')) {
252                 /* the GMT-token does not start a path-component */
253                 DEBUG(10, ("not at start, p=%p, name=%p, p[-1]=%d\n",
254                            p, name, (int)p[-1]));
255                 goto no_snapshot;
256         }
257
258         /*
259          * Figure out whether we got an already converted string. One
260          * case where this happens is in a smb2 create call with the
261          * mxac create blob set. We do the get_acl call on
262          * fsp->fsp_name, which is already converted. We are converted
263          * if we got a file name of the form ".snapshots/@GMT-",
264          * i.e. ".snapshots/" precedes "p".
265          */
266
267         snapdir = lp_parm_const_string(SNUM(handle->conn), "shadow", "snapdir",
268                                        ".snapshots");
269         snapdirlen = strlen(snapdir);
270         len_before_gmt = p - name;
271
272         if ((len_before_gmt >= (snapdirlen + 1)) && (p[-1] == '/')) {
273                 const char *parent_snapdir = p - (snapdirlen+1);
274
275                 DEBUG(10, ("parent_snapdir = %s\n", parent_snapdir));
276
277                 if (strncmp(parent_snapdir, snapdir, snapdirlen) == 0) {
278                         DEBUG(10, ("name=%s is already converted\n", name));
279                         goto no_snapshot;
280                 }
281         }
282         q = strptime(p, GMT_FORMAT, &tm);
283         if (q == NULL) {
284                 DEBUG(10, ("strptime failed\n"));
285                 goto no_snapshot;
286         }
287         tm.tm_isdst = -1;
288         timestamp = timegm(&tm);
289         if (timestamp == (time_t)-1) {
290                 DEBUG(10, ("timestamp==-1\n"));
291                 goto no_snapshot;
292         }
293         if (q[0] == '\0') {
294                 /*
295                  * The name consists of only the GMT token or the GMT
296                  * token is at the end of the path. XP seems to send
297                  * @GMT- at the end under certain circumstances even
298                  * with a path prefix.
299                  */
300                 if (pstripped != NULL) {
301                         stripped = talloc_strndup(mem_ctx, name, p - name);
302                         if (stripped == NULL) {
303                                 return false;
304                         }
305                         *pstripped = stripped;
306                 }
307                 *ptimestamp = timestamp;
308                 return true;
309         }
310         if (q[0] != '/') {
311                 /*
312                  * It is not a complete path component, i.e. the path
313                  * component continues after the gmt-token.
314                  */
315                 DEBUG(10, ("q[0] = %d\n", (int)q[0]));
316                 goto no_snapshot;
317         }
318         q += 1;
319
320         rest_len = strlen(q);
321         dst_len = (p-name) + rest_len;
322
323         if (config->snapdirseverywhere) {
324                 char *insert;
325                 bool have_insert;
326                 insert = shadow_copy2_insert_string(talloc_tos(), handle,
327                                                     timestamp);
328                 if (insert == NULL) {
329                         errno = ENOMEM;
330                         return false;
331                 }
332
333                 DEBUG(10, (__location__ ": snapdirseverywhere mode.\n"
334                            "path '%s'.\n"
335                            "insert string '%s'\n", name, insert));
336
337                 have_insert = (strstr(name, insert+1) != NULL);
338                 DEBUG(10, ("have_insert=%d, name=%s, insert+1=%s\n",
339                            (int)have_insert, name, insert+1));
340                 if (have_insert) {
341                         DEBUG(10, (__location__ ": insert string '%s' found in "
342                                    "path '%s' found in snapdirseverywhere mode "
343                                    "==> already converted\n", insert, name));
344                         TALLOC_FREE(insert);
345                         goto no_snapshot;
346                 }
347                 TALLOC_FREE(insert);
348         } else {
349                 char *snapshot_path;
350                 char *s;
351
352                 snapshot_path = shadow_copy2_snapshot_path(talloc_tos(),
353                                                            handle,
354                                                            timestamp);
355                 if (snapshot_path == NULL) {
356                         errno = ENOMEM;
357                         return false;
358                 }
359
360                 DEBUG(10, (__location__ " path: '%s'.\n"
361                            "snapshot path: '%s'\n", name, snapshot_path));
362
363                 s = strstr(name, snapshot_path);
364                 if (s == name) {
365                         /*
366                          * this starts with "snapshot_basepath/GMT-Token"
367                          * so it is already a converted absolute
368                          * path. Don't process further.
369                          */
370                         DEBUG(10, (__location__ ": path '%s' starts with "
371                                    "snapshot path '%s' (not in "
372                                    "snapdirseverywhere mode) ==> "
373                                    "already converted\n", name, snapshot_path));
374                         talloc_free(snapshot_path);
375                         goto no_snapshot;
376                 }
377                 talloc_free(snapshot_path);
378         }
379
380         if (pstripped != NULL) {
381                 stripped = talloc_array(mem_ctx, char, dst_len+1);
382                 if (stripped == NULL) {
383                         errno = ENOMEM;
384                         return false;
385                 }
386                 if (p > name) {
387                         memcpy(stripped, name, p-name);
388                 }
389                 if (rest_len > 0) {
390                         memcpy(stripped + (p-name), q, rest_len);
391                 }
392                 stripped[dst_len] = '\0';
393                 *pstripped = stripped;
394         }
395         *ptimestamp = timestamp;
396         return true;
397 no_snapshot:
398         *ptimestamp = 0;
399         return true;
400 }
401
402 static char *shadow_copy2_find_mount_point(TALLOC_CTX *mem_ctx,
403                                            vfs_handle_struct *handle)
404 {
405         char *path = talloc_strdup(mem_ctx, handle->conn->connectpath);
406         dev_t dev;
407         struct stat st;
408         char *p;
409
410         if (stat(path, &st) != 0) {
411                 talloc_free(path);
412                 return NULL;
413         }
414
415         dev = st.st_dev;
416
417         while ((p = strrchr(path, '/')) && p > path) {
418                 *p = 0;
419                 if (stat(path, &st) != 0) {
420                         talloc_free(path);
421                         return NULL;
422                 }
423                 if (st.st_dev != dev) {
424                         *p = '/';
425                         break;
426                 }
427         }
428
429         return path;
430 }
431
432 /**
433  * Convert from a name as handed in via the SMB layer
434  * and a timestamp into the local path of the snapshot
435  * of the provided file at the provided time.
436  * Also return the path in the snapshot corresponding
437  * to the file's share root.
438  */
439 static char *shadow_copy2_do_convert(TALLOC_CTX *mem_ctx,
440                                      struct vfs_handle_struct *handle,
441                                      const char *name, time_t timestamp,
442                                      size_t *snaproot_len)
443 {
444         struct smb_filename converted_fname;
445         char *result = NULL;
446         size_t *slashes = NULL;
447         unsigned num_slashes;
448         char *path = NULL;
449         size_t pathlen;
450         char *insert = NULL;
451         char *converted = NULL;
452         size_t insertlen, connectlen = 0;
453         int i, saved_errno;
454         size_t min_offset;
455         struct shadow_copy2_config *config;
456         size_t in_share_offset = 0;
457
458         SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config,
459                                 return NULL);
460
461         DEBUG(10, ("converting '%s'\n", name));
462
463         if (!config->snapdirseverywhere) {
464                 int ret;
465                 char *snapshot_path;
466
467                 snapshot_path = shadow_copy2_snapshot_path(talloc_tos(),
468                                                            handle,
469                                                            timestamp);
470                 if (snapshot_path == NULL) {
471                         goto fail;
472                 }
473
474                 if (config->rel_connectpath == NULL) {
475                         converted = talloc_asprintf(mem_ctx, "%s/%s",
476                                                     snapshot_path, name);
477                 } else {
478                         converted = talloc_asprintf(mem_ctx, "%s/%s/%s",
479                                                     snapshot_path,
480                                                     config->rel_connectpath,
481                                                     name);
482                 }
483                 if (converted == NULL) {
484                         goto fail;
485                 }
486
487                 ZERO_STRUCT(converted_fname);
488                 converted_fname.base_name = converted;
489
490                 ret = SMB_VFS_NEXT_LSTAT(handle, &converted_fname);
491                 DEBUG(10, ("Trying[not snapdirseverywhere] %s: %d (%s)\n",
492                            converted,
493                            ret, ret == 0 ? "ok" : strerror(errno)));
494                 if (ret == 0) {
495                         DEBUG(10, ("Found %s\n", converted));
496                         result = converted;
497                         converted = NULL;
498                         if (snaproot_len != NULL) {
499                                 *snaproot_len = strlen(snapshot_path);
500                                 if (config->rel_connectpath != NULL) {
501                                         *snaproot_len +=
502                                             strlen(config->rel_connectpath) + 1;
503                                 }
504                         }
505                         goto fail;
506                 } else {
507                         errno = ENOENT;
508                         goto fail;
509                 }
510                 /* never reached ... */
511         }
512
513         connectlen = strlen(handle->conn->connectpath);
514         if (name[0] == 0) {
515                 path = talloc_strdup(mem_ctx, handle->conn->connectpath);
516         } else {
517                 path = talloc_asprintf(
518                         mem_ctx, "%s/%s", handle->conn->connectpath, name);
519         }
520         if (path == NULL) {
521                 errno = ENOMEM;
522                 goto fail;
523         }
524         pathlen = talloc_get_size(path)-1;
525
526         if (!shadow_copy2_find_slashes(talloc_tos(), path,
527                                        &slashes, &num_slashes)) {
528                 goto fail;
529         }
530
531         insert = shadow_copy2_insert_string(talloc_tos(), handle, timestamp);
532         if (insert == NULL) {
533                 goto fail;
534         }
535         insertlen = talloc_get_size(insert)-1;
536
537         /*
538          * Note: We deliberatly don't expensively initialize the
539          * array with talloc_zero here: Putting zero into
540          * converted[pathlen+insertlen] below is sufficient, because
541          * in the following for loop, the insert string is inserted
542          * at various slash places. So the memory up to position
543          * pathlen+insertlen will always be initialized when the
544          * converted string is used.
545          */
546         converted = talloc_array(mem_ctx, char, pathlen + insertlen + 1);
547         if (converted == NULL) {
548                 goto fail;
549         }
550
551         if (path[pathlen-1] != '/') {
552                 /*
553                  * Append a fake slash to find the snapshot root
554                  */
555                 size_t *tmp;
556                 tmp = talloc_realloc(talloc_tos(), slashes,
557                                      size_t, num_slashes+1);
558                 if (tmp == NULL) {
559                         goto fail;
560                 }
561                 slashes = tmp;
562                 slashes[num_slashes] = pathlen;
563                 num_slashes += 1;
564         }
565
566         min_offset = 0;
567
568         if (!config->crossmountpoints) {
569                 min_offset = strlen(config->mount_point);
570         }
571
572         memcpy(converted, path, pathlen+1);
573         converted[pathlen+insertlen] = '\0';
574
575         ZERO_STRUCT(converted_fname);
576         converted_fname.base_name = converted;
577
578         for (i = num_slashes-1; i>=0; i--) {
579                 int ret;
580                 size_t offset;
581
582                 offset = slashes[i];
583
584                 if (offset < min_offset) {
585                         errno = ENOENT;
586                         goto fail;
587                 }
588
589                 if (offset >= connectlen) {
590                         in_share_offset = offset;
591                 }
592
593                 memcpy(converted+offset, insert, insertlen);
594
595                 offset += insertlen;
596                 memcpy(converted+offset, path + slashes[i],
597                        pathlen - slashes[i]);
598
599                 ret = SMB_VFS_NEXT_LSTAT(handle, &converted_fname);
600
601                 DEBUG(10, ("Trying[snapdirseverywhere] %s: %d (%s)\n",
602                            converted,
603                            ret, ret == 0 ? "ok" : strerror(errno)));
604                 if (ret == 0) {
605                         /* success */
606                         if (snaproot_len != NULL) {
607                                 *snaproot_len = in_share_offset + insertlen;
608                         }
609                         break;
610                 }
611                 if (errno == ENOTDIR) {
612                         /*
613                          * This is a valid condition: We appended the
614                          * .snaphots/@GMT.. to a file name. Just try
615                          * with the upper levels.
616                          */
617                         continue;
618                 }
619                 if (errno != ENOENT) {
620                         /* Other problem than "not found" */
621                         goto fail;
622                 }
623         }
624
625         if (i >= 0) {
626                 /*
627                  * Found something
628                  */
629                 DEBUG(10, ("Found %s\n", converted));
630                 result = converted;
631                 converted = NULL;
632         } else {
633                 errno = ENOENT;
634         }
635 fail:
636         saved_errno = errno;
637         TALLOC_FREE(converted);
638         TALLOC_FREE(insert);
639         TALLOC_FREE(slashes);
640         TALLOC_FREE(path);
641         errno = saved_errno;
642         return result;
643 }
644
645 /**
646  * Convert from a name as handed in via the SMB layer
647  * and a timestamp into the local path of the snapshot
648  * of the provided file at the provided time.
649  */
650 static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
651                                   struct vfs_handle_struct *handle,
652                                   const char *name, time_t timestamp)
653 {
654         return shadow_copy2_do_convert(mem_ctx, handle, name, timestamp, NULL);
655 }
656
657 /*
658   modify a sbuf return to ensure that inodes in the shadow directory
659   are different from those in the main directory
660  */
661 static void convert_sbuf(vfs_handle_struct *handle, const char *fname,
662                          SMB_STRUCT_STAT *sbuf)
663 {
664         struct shadow_copy2_config *config;
665
666         SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config,
667                                 return);
668
669         if (config->fixinodes) {
670                 /* some snapshot systems, like GPFS, return the name
671                    device:inode for the snapshot files as the current
672                    files. That breaks the 'restore' button in the shadow copy
673                    GUI, as the client gets a sharing violation.
674
675                    This is a crude way of allowing both files to be
676                    open at once. It has a slight chance of inode
677                    number collision, but I can't see a better approach
678                    without significant VFS changes
679                 */
680                 TDB_DATA key = { .dptr = discard_const_p(uint8_t, fname),
681                                  .dsize = strlen(fname) };
682                 uint32_t shash;
683
684                 shash = tdb_jenkins_hash(&key) & 0xFF000000;
685                 if (shash == 0) {
686                         shash = 1;
687                 }
688                 sbuf->st_ex_ino ^= shash;
689         }
690 }
691
692 static DIR *shadow_copy2_opendir(vfs_handle_struct *handle,
693                                             const char *fname,
694                                             const char *mask,
695                                             uint32_t attr)
696 {
697         time_t timestamp;
698         char *stripped;
699         DIR *ret;
700         int saved_errno;
701         char *conv;
702
703         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
704                                          &timestamp, &stripped)) {
705                 return NULL;
706         }
707         if (timestamp == 0) {
708                 return SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
709         }
710         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
711         TALLOC_FREE(stripped);
712         if (conv == NULL) {
713                 return NULL;
714         }
715         ret = SMB_VFS_NEXT_OPENDIR(handle, conv, mask, attr);
716         saved_errno = errno;
717         TALLOC_FREE(conv);
718         errno = saved_errno;
719         return ret;
720 }
721
722 static int shadow_copy2_rename(vfs_handle_struct *handle,
723                                const struct smb_filename *smb_fname_src,
724                                const struct smb_filename *smb_fname_dst)
725 {
726         time_t timestamp_src, timestamp_dst;
727
728         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
729                                          smb_fname_src->base_name,
730                                          &timestamp_src, NULL)) {
731                 return -1;
732         }
733         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
734                                          smb_fname_dst->base_name,
735                                          &timestamp_dst, NULL)) {
736                 return -1;
737         }
738         if (timestamp_src != 0) {
739                 errno = EXDEV;
740                 return -1;
741         }
742         if (timestamp_dst != 0) {
743                 errno = EROFS;
744                 return -1;
745         }
746         return SMB_VFS_NEXT_RENAME(handle, smb_fname_src, smb_fname_dst);
747 }
748
749 static int shadow_copy2_symlink(vfs_handle_struct *handle,
750                                 const char *oldname, const char *newname)
751 {
752         time_t timestamp_old, timestamp_new;
753
754         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, oldname,
755                                          &timestamp_old, NULL)) {
756                 return -1;
757         }
758         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, newname,
759                                          &timestamp_new, NULL)) {
760                 return -1;
761         }
762         if ((timestamp_old != 0) || (timestamp_new != 0)) {
763                 errno = EROFS;
764                 return -1;
765         }
766         return SMB_VFS_NEXT_SYMLINK(handle, oldname, newname);
767 }
768
769 static int shadow_copy2_link(vfs_handle_struct *handle,
770                              const char *oldname, const char *newname)
771 {
772         time_t timestamp_old, timestamp_new;
773
774         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, oldname,
775                                          &timestamp_old, NULL)) {
776                 return -1;
777         }
778         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, newname,
779                                          &timestamp_new, NULL)) {
780                 return -1;
781         }
782         if ((timestamp_old != 0) || (timestamp_new != 0)) {
783                 errno = EROFS;
784                 return -1;
785         }
786         return SMB_VFS_NEXT_LINK(handle, oldname, newname);
787 }
788
789 static int shadow_copy2_stat(vfs_handle_struct *handle,
790                              struct smb_filename *smb_fname)
791 {
792         time_t timestamp;
793         char *stripped, *tmp;
794         int ret, saved_errno;
795
796         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
797                                          smb_fname->base_name,
798                                          &timestamp, &stripped)) {
799                 return -1;
800         }
801         if (timestamp == 0) {
802                 return SMB_VFS_NEXT_STAT(handle, smb_fname);
803         }
804
805         tmp = smb_fname->base_name;
806         smb_fname->base_name = shadow_copy2_convert(
807                 talloc_tos(), handle, stripped, timestamp);
808         TALLOC_FREE(stripped);
809
810         if (smb_fname->base_name == NULL) {
811                 smb_fname->base_name = tmp;
812                 return -1;
813         }
814
815         ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
816         saved_errno = errno;
817
818         TALLOC_FREE(smb_fname->base_name);
819         smb_fname->base_name = tmp;
820
821         if (ret == 0) {
822                 convert_sbuf(handle, smb_fname->base_name, &smb_fname->st);
823         }
824         errno = saved_errno;
825         return ret;
826 }
827
828 static int shadow_copy2_lstat(vfs_handle_struct *handle,
829                               struct smb_filename *smb_fname)
830 {
831         time_t timestamp;
832         char *stripped, *tmp;
833         int ret, saved_errno;
834
835         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
836                                          smb_fname->base_name,
837                                          &timestamp, &stripped)) {
838                 return -1;
839         }
840         if (timestamp == 0) {
841                 return SMB_VFS_NEXT_LSTAT(handle, smb_fname);
842         }
843
844         tmp = smb_fname->base_name;
845         smb_fname->base_name = shadow_copy2_convert(
846                 talloc_tos(), handle, stripped, timestamp);
847         TALLOC_FREE(stripped);
848
849         if (smb_fname->base_name == NULL) {
850                 smb_fname->base_name = tmp;
851                 return -1;
852         }
853
854         ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
855         saved_errno = errno;
856
857         TALLOC_FREE(smb_fname->base_name);
858         smb_fname->base_name = tmp;
859
860         if (ret == 0) {
861                 convert_sbuf(handle, smb_fname->base_name, &smb_fname->st);
862         }
863         errno = saved_errno;
864         return ret;
865 }
866
867 static int shadow_copy2_fstat(vfs_handle_struct *handle, files_struct *fsp,
868                               SMB_STRUCT_STAT *sbuf)
869 {
870         time_t timestamp;
871         int ret;
872
873         ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
874         if (ret == -1) {
875                 return ret;
876         }
877         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
878                                          fsp->fsp_name->base_name,
879                                          &timestamp, NULL)) {
880                 return 0;
881         }
882         if (timestamp != 0) {
883                 convert_sbuf(handle, fsp->fsp_name->base_name, sbuf);
884         }
885         return 0;
886 }
887
888 static int shadow_copy2_open(vfs_handle_struct *handle,
889                              struct smb_filename *smb_fname, files_struct *fsp,
890                              int flags, mode_t mode)
891 {
892         time_t timestamp;
893         char *stripped, *tmp;
894         int ret, saved_errno;
895
896         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
897                                          smb_fname->base_name,
898                                          &timestamp, &stripped)) {
899                 return -1;
900         }
901         if (timestamp == 0) {
902                 return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
903         }
904
905         tmp = smb_fname->base_name;
906         smb_fname->base_name = shadow_copy2_convert(
907                 talloc_tos(), handle, stripped, timestamp);
908         TALLOC_FREE(stripped);
909
910         if (smb_fname->base_name == NULL) {
911                 smb_fname->base_name = tmp;
912                 return -1;
913         }
914
915         ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
916         saved_errno = errno;
917
918         TALLOC_FREE(smb_fname->base_name);
919         smb_fname->base_name = tmp;
920
921         errno = saved_errno;
922         return ret;
923 }
924
925 static int shadow_copy2_unlink(vfs_handle_struct *handle,
926                                const struct smb_filename *smb_fname)
927 {
928         time_t timestamp;
929         char *stripped;
930         int ret, saved_errno;
931         struct smb_filename *conv;
932
933         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
934                                          smb_fname->base_name,
935                                          &timestamp, &stripped)) {
936                 return -1;
937         }
938         if (timestamp == 0) {
939                 return SMB_VFS_NEXT_UNLINK(handle, smb_fname);
940         }
941         conv = cp_smb_filename(talloc_tos(), smb_fname);
942         if (conv == NULL) {
943                 errno = ENOMEM;
944                 return -1;
945         }
946         conv->base_name = shadow_copy2_convert(
947                 conv, handle, stripped, timestamp);
948         TALLOC_FREE(stripped);
949         if (conv->base_name == NULL) {
950                 return -1;
951         }
952         ret = SMB_VFS_NEXT_UNLINK(handle, conv);
953         saved_errno = errno;
954         TALLOC_FREE(conv);
955         errno = saved_errno;
956         return ret;
957 }
958
959 static int shadow_copy2_chmod(vfs_handle_struct *handle, const char *fname,
960                               mode_t mode)
961 {
962         time_t timestamp;
963         char *stripped;
964         int ret, saved_errno;
965         char *conv;
966
967         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
968                                          &timestamp, &stripped)) {
969                 return -1;
970         }
971         if (timestamp == 0) {
972                 return SMB_VFS_NEXT_CHMOD(handle, fname, mode);
973         }
974         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
975         TALLOC_FREE(stripped);
976         if (conv == NULL) {
977                 return -1;
978         }
979         ret = SMB_VFS_NEXT_CHMOD(handle, conv, mode);
980         saved_errno = errno;
981         TALLOC_FREE(conv);
982         errno = saved_errno;
983         return ret;
984 }
985
986 static int shadow_copy2_chown(vfs_handle_struct *handle, const char *fname,
987                               uid_t uid, gid_t gid)
988 {
989         time_t timestamp;
990         char *stripped;
991         int ret, saved_errno;
992         char *conv;
993
994         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
995                                          &timestamp, &stripped)) {
996                 return -1;
997         }
998         if (timestamp == 0) {
999                 return SMB_VFS_NEXT_CHOWN(handle, fname, uid, gid);
1000         }
1001         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1002         TALLOC_FREE(stripped);
1003         if (conv == NULL) {
1004                 return -1;
1005         }
1006         ret = SMB_VFS_NEXT_CHOWN(handle, conv, uid, gid);
1007         saved_errno = errno;
1008         TALLOC_FREE(conv);
1009         errno = saved_errno;
1010         return ret;
1011 }
1012
1013 static int shadow_copy2_chdir(vfs_handle_struct *handle,
1014                               const char *fname)
1015 {
1016         time_t timestamp;
1017         char *stripped;
1018         int ret, saved_errno;
1019         char *conv;
1020
1021         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
1022                                          &timestamp, &stripped)) {
1023                 return -1;
1024         }
1025         if (timestamp == 0) {
1026                 return SMB_VFS_NEXT_CHDIR(handle, fname);
1027         }
1028         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1029         TALLOC_FREE(stripped);
1030         if (conv == NULL) {
1031                 return -1;
1032         }
1033         ret = SMB_VFS_NEXT_CHDIR(handle, conv);
1034         saved_errno = errno;
1035         TALLOC_FREE(conv);
1036         errno = saved_errno;
1037         return ret;
1038 }
1039
1040 static int shadow_copy2_ntimes(vfs_handle_struct *handle,
1041                                const struct smb_filename *smb_fname,
1042                                struct smb_file_time *ft)
1043 {
1044         time_t timestamp;
1045         char *stripped;
1046         int ret, saved_errno;
1047         struct smb_filename *conv;
1048
1049         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
1050                                          smb_fname->base_name,
1051                                          &timestamp, &stripped)) {
1052                 return -1;
1053         }
1054         if (timestamp == 0) {
1055                 return SMB_VFS_NEXT_NTIMES(handle, smb_fname, ft);
1056         }
1057         conv = cp_smb_filename(talloc_tos(), smb_fname);
1058         if (conv == NULL) {
1059                 errno = ENOMEM;
1060                 return -1;
1061         }
1062         conv->base_name = shadow_copy2_convert(
1063                 conv, handle, stripped, timestamp);
1064         TALLOC_FREE(stripped);
1065         if (conv->base_name == NULL) {
1066                 return -1;
1067         }
1068         ret = SMB_VFS_NEXT_NTIMES(handle, conv, ft);
1069         saved_errno = errno;
1070         TALLOC_FREE(conv);
1071         errno = saved_errno;
1072         return ret;
1073 }
1074
1075 static int shadow_copy2_readlink(vfs_handle_struct *handle,
1076                                  const char *fname, char *buf, size_t bufsiz)
1077 {
1078         time_t timestamp;
1079         char *stripped;
1080         int ret, saved_errno;
1081         char *conv;
1082
1083         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
1084                                          &timestamp, &stripped)) {
1085                 return -1;
1086         }
1087         if (timestamp == 0) {
1088                 return SMB_VFS_NEXT_READLINK(handle, fname, buf, bufsiz);
1089         }
1090         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1091         TALLOC_FREE(stripped);
1092         if (conv == NULL) {
1093                 return -1;
1094         }
1095         ret = SMB_VFS_NEXT_READLINK(handle, conv, buf, bufsiz);
1096         saved_errno = errno;
1097         TALLOC_FREE(conv);
1098         errno = saved_errno;
1099         return ret;
1100 }
1101
1102 static int shadow_copy2_mknod(vfs_handle_struct *handle,
1103                               const char *fname, mode_t mode, SMB_DEV_T dev)
1104 {
1105         time_t timestamp;
1106         char *stripped;
1107         int ret, saved_errno;
1108         char *conv;
1109
1110         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
1111                                          &timestamp, &stripped)) {
1112                 return -1;
1113         }
1114         if (timestamp == 0) {
1115                 return SMB_VFS_NEXT_MKNOD(handle, fname, mode, dev);
1116         }
1117         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1118         TALLOC_FREE(stripped);
1119         if (conv == NULL) {
1120                 return -1;
1121         }
1122         ret = SMB_VFS_NEXT_MKNOD(handle, conv, mode, dev);
1123         saved_errno = errno;
1124         TALLOC_FREE(conv);
1125         errno = saved_errno;
1126         return ret;
1127 }
1128
1129 static char *shadow_copy2_realpath(vfs_handle_struct *handle,
1130                                    const char *fname)
1131 {
1132         time_t timestamp;
1133         char *stripped = NULL;
1134         char *tmp = NULL;
1135         char *result = NULL;
1136         int saved_errno;
1137
1138         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
1139                                          &timestamp, &stripped)) {
1140                 goto done;
1141         }
1142         if (timestamp == 0) {
1143                 return SMB_VFS_NEXT_REALPATH(handle, fname);
1144         }
1145
1146         tmp = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1147         if (tmp == NULL) {
1148                 goto done;
1149         }
1150
1151         result = SMB_VFS_NEXT_REALPATH(handle, tmp);
1152
1153 done:
1154         saved_errno = errno;
1155         TALLOC_FREE(tmp);
1156         TALLOC_FREE(stripped);
1157         errno = saved_errno;
1158         return result;
1159 }
1160
1161 /**
1162  * Check whether a given directory contains a
1163  * snapshot directory as direct subdirectory.
1164  * If yes, return the path of the snapshot-subdir,
1165  * otherwise return NULL.
1166  */
1167 static char *have_snapdir(struct vfs_handle_struct *handle,
1168                           const char *path)
1169 {
1170         struct smb_filename smb_fname;
1171         int ret;
1172         struct shadow_copy2_config *config;
1173
1174         SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config,
1175                                 return NULL);
1176
1177         ZERO_STRUCT(smb_fname);
1178         smb_fname.base_name = talloc_asprintf(talloc_tos(), "%s/%s",
1179                                               path, config->snapdir);
1180         if (smb_fname.base_name == NULL) {
1181                 return NULL;
1182         }
1183
1184         ret = SMB_VFS_NEXT_STAT(handle, &smb_fname);
1185         if ((ret == 0) && (S_ISDIR(smb_fname.st.st_ex_mode))) {
1186                 return smb_fname.base_name;
1187         }
1188         TALLOC_FREE(smb_fname.base_name);
1189         return NULL;
1190 }
1191
1192 static bool check_access_snapdir(struct vfs_handle_struct *handle,
1193                                 const char *path)
1194 {
1195         struct smb_filename smb_fname;
1196         int ret;
1197         NTSTATUS status;
1198
1199         ZERO_STRUCT(smb_fname);
1200         smb_fname.base_name = talloc_asprintf(talloc_tos(),
1201                                                 "%s",
1202                                                 path);
1203         if (smb_fname.base_name == NULL) {
1204                 return false;
1205         }
1206
1207         ret = SMB_VFS_NEXT_STAT(handle, &smb_fname);
1208         if (ret != 0 || !S_ISDIR(smb_fname.st.st_ex_mode)) {
1209                 TALLOC_FREE(smb_fname.base_name);
1210                 return false;
1211         }
1212
1213         status = smbd_check_access_rights(handle->conn,
1214                                         &smb_fname,
1215                                         false,
1216                                         SEC_DIR_LIST);
1217         if (!NT_STATUS_IS_OK(status)) {
1218                 DEBUG(0,("user does not have list permission "
1219                         "on snapdir %s\n",
1220                         smb_fname.base_name));
1221                 TALLOC_FREE(smb_fname.base_name);
1222                 return false;
1223         }
1224         TALLOC_FREE(smb_fname.base_name);
1225         return true;
1226 }
1227
1228 /**
1229  * Find the snapshot directory (if any) for the given
1230  * filename (which is relative to the share).
1231  */
1232 static const char *shadow_copy2_find_snapdir(TALLOC_CTX *mem_ctx,
1233                                              struct vfs_handle_struct *handle,
1234                                              struct smb_filename *smb_fname)
1235 {
1236         char *path, *p;
1237         const char *snapdir;
1238         struct shadow_copy2_config *config;
1239
1240         SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config,
1241                                 return NULL);
1242
1243         /*
1244          * If the non-snapdisrseverywhere mode, we should not search!
1245          */
1246         if (!config->snapdirseverywhere) {
1247                 return config->snapshot_basepath;
1248         }
1249
1250         path = talloc_asprintf(mem_ctx, "%s/%s",
1251                                handle->conn->connectpath,
1252                                smb_fname->base_name);
1253         if (path == NULL) {
1254                 return NULL;
1255         }
1256
1257         snapdir = have_snapdir(handle, path);
1258         if (snapdir != NULL) {
1259                 TALLOC_FREE(path);
1260                 return snapdir;
1261         }
1262
1263         while ((p = strrchr(path, '/')) && (p > path)) {
1264
1265                 p[0] = '\0';
1266
1267                 snapdir = have_snapdir(handle, path);
1268                 if (snapdir != NULL) {
1269                         TALLOC_FREE(path);
1270                         return snapdir;
1271                 }
1272         }
1273         TALLOC_FREE(path);
1274         return NULL;
1275 }
1276
1277 static bool shadow_copy2_snapshot_to_gmt(vfs_handle_struct *handle,
1278                                          const char *name,
1279                                          char *gmt, size_t gmt_len)
1280 {
1281         struct tm timestamp;
1282         time_t timestamp_t;
1283         unsigned long int timestamp_long;
1284         const char *fmt;
1285         struct shadow_copy2_config *config;
1286
1287         SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config,
1288                                 return NULL);
1289
1290         fmt = config->gmt_format;
1291
1292         ZERO_STRUCT(timestamp);
1293         if (config->use_sscanf) {
1294                 if (sscanf(name, fmt, &timestamp_long) != 1) {
1295                         DEBUG(10, ("shadow_copy2_snapshot_to_gmt: "
1296                                    "no sscanf match %s: %s\n",
1297                                    fmt, name));
1298                         return false;
1299                 }
1300                 timestamp_t = timestamp_long;
1301                 gmtime_r(&timestamp_t, &timestamp);
1302         } else {
1303                 if (strptime(name, fmt, &timestamp) == NULL) {
1304                         DEBUG(10, ("shadow_copy2_snapshot_to_gmt: "
1305                                    "no match %s: %s\n",
1306                                    fmt, name));
1307                         return false;
1308                 }
1309                 DEBUG(10, ("shadow_copy2_snapshot_to_gmt: match %s: %s\n",
1310                            fmt, name));
1311                 
1312                 if (config->use_localtime) {
1313                         timestamp.tm_isdst = -1;
1314                         timestamp_t = mktime(&timestamp);
1315                         gmtime_r(&timestamp_t, &timestamp);
1316                 }
1317         }
1318
1319         strftime(gmt, gmt_len, GMT_FORMAT, &timestamp);
1320         return true;
1321 }
1322
1323 static int shadow_copy2_label_cmp_asc(const void *x, const void *y)
1324 {
1325         return strncmp((const char *)x, (const char *)y, sizeof(SHADOW_COPY_LABEL));
1326 }
1327
1328 static int shadow_copy2_label_cmp_desc(const void *x, const void *y)
1329 {
1330         return -strncmp((const char *)x, (const char *)y, sizeof(SHADOW_COPY_LABEL));
1331 }
1332
1333 /*
1334   sort the shadow copy data in ascending or descending order
1335  */
1336 static void shadow_copy2_sort_data(vfs_handle_struct *handle,
1337                                    struct shadow_copy_data *shadow_copy2_data)
1338 {
1339         int (*cmpfunc)(const void *, const void *);
1340         const char *sort;
1341         struct shadow_copy2_config *config;
1342
1343         SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config,
1344                                 return);
1345
1346         sort = config->sort_order;
1347         if (sort == NULL) {
1348                 return;
1349         }
1350
1351         if (strcmp(sort, "asc") == 0) {
1352                 cmpfunc = shadow_copy2_label_cmp_asc;
1353         } else if (strcmp(sort, "desc") == 0) {
1354                 cmpfunc = shadow_copy2_label_cmp_desc;
1355         } else {
1356                 return;
1357         }
1358
1359         if (shadow_copy2_data && shadow_copy2_data->num_volumes > 0 &&
1360             shadow_copy2_data->labels)
1361         {
1362                 TYPESAFE_QSORT(shadow_copy2_data->labels,
1363                                shadow_copy2_data->num_volumes,
1364                                cmpfunc);
1365         }
1366 }
1367
1368 static int shadow_copy2_get_shadow_copy_data(
1369         vfs_handle_struct *handle, files_struct *fsp,
1370         struct shadow_copy_data *shadow_copy2_data,
1371         bool labels)
1372 {
1373         DIR *p;
1374         const char *snapdir;
1375         struct dirent *d;
1376         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1377         bool ret;
1378
1379         snapdir = shadow_copy2_find_snapdir(tmp_ctx, handle, fsp->fsp_name);
1380         if (snapdir == NULL) {
1381                 DEBUG(0,("shadow:snapdir not found for %s in get_shadow_copy_data\n",
1382                          handle->conn->connectpath));
1383                 errno = EINVAL;
1384                 talloc_free(tmp_ctx);
1385                 return -1;
1386         }
1387         ret = check_access_snapdir(handle, snapdir);
1388         if (!ret) {
1389                 DEBUG(0,("access denied on listing snapdir %s\n", snapdir));
1390                 errno = EACCES;
1391                 talloc_free(tmp_ctx);
1392                 return -1;
1393         }
1394
1395         p = SMB_VFS_NEXT_OPENDIR(handle, snapdir, NULL, 0);
1396
1397         if (!p) {
1398                 DEBUG(2,("shadow_copy2: SMB_VFS_NEXT_OPENDIR() failed for '%s'"
1399                          " - %s\n", snapdir, strerror(errno)));
1400                 talloc_free(tmp_ctx);
1401                 errno = ENOSYS;
1402                 return -1;
1403         }
1404
1405         shadow_copy2_data->num_volumes = 0;
1406         shadow_copy2_data->labels      = NULL;
1407
1408         while ((d = SMB_VFS_NEXT_READDIR(handle, p, NULL))) {
1409                 char snapshot[GMT_NAME_LEN+1];
1410                 SHADOW_COPY_LABEL *tlabels;
1411
1412                 /*
1413                  * ignore names not of the right form in the snapshot
1414                  * directory
1415                  */
1416                 if (!shadow_copy2_snapshot_to_gmt(
1417                             handle, d->d_name,
1418                             snapshot, sizeof(snapshot))) {
1419
1420                         DEBUG(6, ("shadow_copy2_get_shadow_copy_data: "
1421                                   "ignoring %s\n", d->d_name));
1422                         continue;
1423                 }
1424                 DEBUG(6,("shadow_copy2_get_shadow_copy_data: %s -> %s\n",
1425                          d->d_name, snapshot));
1426
1427                 if (!labels) {
1428                         /* the caller doesn't want the labels */
1429                         shadow_copy2_data->num_volumes++;
1430                         continue;
1431                 }
1432
1433                 tlabels = talloc_realloc(shadow_copy2_data,
1434                                          shadow_copy2_data->labels,
1435                                          SHADOW_COPY_LABEL,
1436                                          shadow_copy2_data->num_volumes+1);
1437                 if (tlabels == NULL) {
1438                         DEBUG(0,("shadow_copy2: out of memory\n"));
1439                         SMB_VFS_NEXT_CLOSEDIR(handle, p);
1440                         talloc_free(tmp_ctx);
1441                         return -1;
1442                 }
1443
1444                 strlcpy(tlabels[shadow_copy2_data->num_volumes], snapshot,
1445                         sizeof(*tlabels));
1446
1447                 shadow_copy2_data->num_volumes++;
1448                 shadow_copy2_data->labels = tlabels;
1449         }
1450
1451         SMB_VFS_NEXT_CLOSEDIR(handle,p);
1452
1453         shadow_copy2_sort_data(handle, shadow_copy2_data);
1454
1455         talloc_free(tmp_ctx);
1456         return 0;
1457 }
1458
1459 static NTSTATUS shadow_copy2_fget_nt_acl(vfs_handle_struct *handle,
1460                                         struct files_struct *fsp,
1461                                         uint32_t security_info,
1462                                          TALLOC_CTX *mem_ctx,
1463                                         struct security_descriptor **ppdesc)
1464 {
1465         time_t timestamp;
1466         char *stripped;
1467         NTSTATUS status;
1468         char *conv;
1469         struct smb_filename *smb_fname = NULL;
1470
1471         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
1472                                          fsp->fsp_name->base_name,
1473                                          &timestamp, &stripped)) {
1474                 return map_nt_error_from_unix(errno);
1475         }
1476         if (timestamp == 0) {
1477                 return SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info,
1478                                                 mem_ctx,
1479                                                 ppdesc);
1480         }
1481         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1482         TALLOC_FREE(stripped);
1483         if (conv == NULL) {
1484                 return map_nt_error_from_unix(errno);
1485         }
1486         smb_fname = synthetic_smb_fname(talloc_tos(),
1487                                         conv,
1488                                         NULL,
1489                                         NULL);
1490         if (smb_fname == NULL) {
1491                 TALLOC_FREE(conv);
1492                 return NT_STATUS_NO_MEMORY;
1493         }
1494
1495         status = SMB_VFS_NEXT_GET_NT_ACL(handle, smb_fname, security_info,
1496                                          mem_ctx, ppdesc);
1497         TALLOC_FREE(conv);
1498         TALLOC_FREE(smb_fname);
1499         return status;
1500 }
1501
1502 static NTSTATUS shadow_copy2_get_nt_acl(vfs_handle_struct *handle,
1503                                         const struct smb_filename *smb_fname,
1504                                         uint32_t security_info,
1505                                         TALLOC_CTX *mem_ctx,
1506                                         struct security_descriptor **ppdesc)
1507 {
1508         time_t timestamp;
1509         char *stripped;
1510         NTSTATUS status;
1511         char *conv;
1512         struct smb_filename *conv_smb_fname = NULL;
1513
1514         if (!shadow_copy2_strip_snapshot(talloc_tos(),
1515                                         handle,
1516                                         smb_fname->base_name,
1517                                         &timestamp,
1518                                         &stripped)) {
1519                 return map_nt_error_from_unix(errno);
1520         }
1521         if (timestamp == 0) {
1522                 return SMB_VFS_NEXT_GET_NT_ACL(handle, smb_fname, security_info,
1523                                                mem_ctx, ppdesc);
1524         }
1525         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1526         TALLOC_FREE(stripped);
1527         if (conv == NULL) {
1528                 return map_nt_error_from_unix(errno);
1529         }
1530         conv_smb_fname = synthetic_smb_fname(talloc_tos(),
1531                                         conv,
1532                                         NULL,
1533                                         NULL);
1534         if (conv_smb_fname == NULL) {
1535                 TALLOC_FREE(conv);
1536                 return NT_STATUS_NO_MEMORY;
1537         }
1538         status = SMB_VFS_NEXT_GET_NT_ACL(handle, conv_smb_fname, security_info,
1539                                          mem_ctx, ppdesc);
1540         TALLOC_FREE(conv);
1541         TALLOC_FREE(conv_smb_fname);
1542         return status;
1543 }
1544
1545 static int shadow_copy2_mkdir(vfs_handle_struct *handle,
1546                               const char *fname, mode_t mode)
1547 {
1548         time_t timestamp;
1549         char *stripped;
1550         int ret, saved_errno;
1551         char *conv;
1552
1553         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
1554                                          &timestamp, &stripped)) {
1555                 return -1;
1556         }
1557         if (timestamp == 0) {
1558                 return SMB_VFS_NEXT_MKDIR(handle, fname, mode);
1559         }
1560         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1561         TALLOC_FREE(stripped);
1562         if (conv == NULL) {
1563                 return -1;
1564         }
1565         ret = SMB_VFS_NEXT_MKDIR(handle, conv, mode);
1566         saved_errno = errno;
1567         TALLOC_FREE(conv);
1568         errno = saved_errno;
1569         return ret;
1570 }
1571
1572 static int shadow_copy2_rmdir(vfs_handle_struct *handle, const char *fname)
1573 {
1574         time_t timestamp;
1575         char *stripped;
1576         int ret, saved_errno;
1577         char *conv;
1578
1579         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
1580                                          &timestamp, &stripped)) {
1581                 return -1;
1582         }
1583         if (timestamp == 0) {
1584                 return SMB_VFS_NEXT_RMDIR(handle, fname);
1585         }
1586         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1587         TALLOC_FREE(stripped);
1588         if (conv == NULL) {
1589                 return -1;
1590         }
1591         ret = SMB_VFS_NEXT_RMDIR(handle, conv);
1592         saved_errno = errno;
1593         TALLOC_FREE(conv);
1594         errno = saved_errno;
1595         return ret;
1596 }
1597
1598 static int shadow_copy2_chflags(vfs_handle_struct *handle, const char *fname,
1599                                 unsigned int flags)
1600 {
1601         time_t timestamp;
1602         char *stripped;
1603         int ret, saved_errno;
1604         char *conv;
1605
1606         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
1607                                          &timestamp, &stripped)) {
1608                 return -1;
1609         }
1610         if (timestamp == 0) {
1611                 return SMB_VFS_NEXT_CHFLAGS(handle, fname, flags);
1612         }
1613         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1614         TALLOC_FREE(stripped);
1615         if (conv == NULL) {
1616                 return -1;
1617         }
1618         ret = SMB_VFS_NEXT_CHFLAGS(handle, conv, flags);
1619         saved_errno = errno;
1620         TALLOC_FREE(conv);
1621         errno = saved_errno;
1622         return ret;
1623 }
1624
1625 static ssize_t shadow_copy2_getxattr(vfs_handle_struct *handle,
1626                                      const char *fname, const char *aname,
1627                                      void *value, size_t size)
1628 {
1629         time_t timestamp;
1630         char *stripped;
1631         ssize_t ret;
1632         int saved_errno;
1633         char *conv;
1634
1635         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
1636                                          &timestamp, &stripped)) {
1637                 return -1;
1638         }
1639         if (timestamp == 0) {
1640                 return SMB_VFS_NEXT_GETXATTR(handle, fname, aname, value,
1641                                              size);
1642         }
1643         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1644         TALLOC_FREE(stripped);
1645         if (conv == NULL) {
1646                 return -1;
1647         }
1648         ret = SMB_VFS_NEXT_GETXATTR(handle, conv, aname, value, size);
1649         saved_errno = errno;
1650         TALLOC_FREE(conv);
1651         errno = saved_errno;
1652         return ret;
1653 }
1654
1655 static ssize_t shadow_copy2_listxattr(struct vfs_handle_struct *handle,
1656                                       const char *fname,
1657                                       char *list, size_t size)
1658 {
1659         time_t timestamp;
1660         char *stripped;
1661         ssize_t ret;
1662         int saved_errno;
1663         char *conv;
1664
1665         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
1666                                          &timestamp, &stripped)) {
1667                 return -1;
1668         }
1669         if (timestamp == 0) {
1670                 return SMB_VFS_NEXT_LISTXATTR(handle, fname, list, size);
1671         }
1672         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1673         TALLOC_FREE(stripped);
1674         if (conv == NULL) {
1675                 return -1;
1676         }
1677         ret = SMB_VFS_NEXT_LISTXATTR(handle, conv, list, size);
1678         saved_errno = errno;
1679         TALLOC_FREE(conv);
1680         errno = saved_errno;
1681         return ret;
1682 }
1683
1684 static int shadow_copy2_removexattr(vfs_handle_struct *handle,
1685                                     const char *fname, const char *aname)
1686 {
1687         time_t timestamp;
1688         char *stripped;
1689         int ret, saved_errno;
1690         char *conv;
1691
1692         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
1693                                          &timestamp, &stripped)) {
1694                 return -1;
1695         }
1696         if (timestamp == 0) {
1697                 return SMB_VFS_NEXT_REMOVEXATTR(handle, fname, aname);
1698         }
1699         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1700         TALLOC_FREE(stripped);
1701         if (conv == NULL) {
1702                 return -1;
1703         }
1704         ret = SMB_VFS_NEXT_REMOVEXATTR(handle, conv, aname);
1705         saved_errno = errno;
1706         TALLOC_FREE(conv);
1707         errno = saved_errno;
1708         return ret;
1709 }
1710
1711 static int shadow_copy2_setxattr(struct vfs_handle_struct *handle,
1712                                  const char *fname,
1713                                  const char *aname, const void *value,
1714                                  size_t size, int flags)
1715 {
1716         time_t timestamp;
1717         char *stripped;
1718         ssize_t ret;
1719         int saved_errno;
1720         char *conv;
1721
1722         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
1723                                          &timestamp, &stripped)) {
1724                 return -1;
1725         }
1726         if (timestamp == 0) {
1727                 return SMB_VFS_NEXT_SETXATTR(handle, fname, aname, value, size,
1728                                              flags);
1729         }
1730         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1731         TALLOC_FREE(stripped);
1732         if (conv == NULL) {
1733                 return -1;
1734         }
1735         ret = SMB_VFS_NEXT_SETXATTR(handle, conv, aname, value, size, flags);
1736         saved_errno = errno;
1737         TALLOC_FREE(conv);
1738         errno = saved_errno;
1739         return ret;
1740 }
1741
1742 static int shadow_copy2_chmod_acl(vfs_handle_struct *handle,
1743                                   const char *fname, mode_t mode)
1744 {
1745         time_t timestamp;
1746         char *stripped;
1747         ssize_t ret;
1748         int saved_errno;
1749         char *conv;
1750
1751         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
1752                                          &timestamp, &stripped)) {
1753                 return -1;
1754         }
1755         if (timestamp == 0) {
1756                 return SMB_VFS_NEXT_CHMOD_ACL(handle, fname, mode);
1757         }
1758         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1759         TALLOC_FREE(stripped);
1760         if (conv == NULL) {
1761                 return -1;
1762         }
1763         ret = SMB_VFS_NEXT_CHMOD_ACL(handle, conv, mode);
1764         saved_errno = errno;
1765         TALLOC_FREE(conv);
1766         errno = saved_errno;
1767         return ret;
1768 }
1769
1770 static int shadow_copy2_get_real_filename(struct vfs_handle_struct *handle,
1771                                           const char *path,
1772                                           const char *name,
1773                                           TALLOC_CTX *mem_ctx,
1774                                           char **found_name)
1775 {
1776         time_t timestamp;
1777         char *stripped;
1778         ssize_t ret;
1779         int saved_errno;
1780         char *conv;
1781
1782         DEBUG(10, ("shadow_copy2_get_real_filename called for path=[%s], "
1783                    "name=[%s]\n", path, name));
1784
1785         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, path,
1786                                          &timestamp, &stripped)) {
1787                 DEBUG(10, ("shadow_copy2_strip_snapshot failed\n"));
1788                 return -1;
1789         }
1790         if (timestamp == 0) {
1791                 DEBUG(10, ("timestamp == 0\n"));
1792                 return SMB_VFS_NEXT_GET_REAL_FILENAME(handle, path, name,
1793                                                       mem_ctx, found_name);
1794         }
1795         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1796         TALLOC_FREE(stripped);
1797         if (conv == NULL) {
1798                 DEBUG(10, ("shadow_copy2_convert failed\n"));
1799                 return -1;
1800         }
1801         DEBUG(10, ("Calling NEXT_GET_REAL_FILE_NAME for conv=[%s], "
1802                    "name=[%s]\n", conv, name));
1803         ret = SMB_VFS_NEXT_GET_REAL_FILENAME(handle, conv, name,
1804                                              mem_ctx, found_name);
1805         DEBUG(10, ("NEXT_REAL_FILE_NAME returned %d\n", (int)ret));
1806         saved_errno = errno;
1807         TALLOC_FREE(conv);
1808         errno = saved_errno;
1809         return ret;
1810 }
1811
1812 static const char *shadow_copy2_connectpath(struct vfs_handle_struct *handle,
1813                                             const char *fname)
1814 {
1815         time_t timestamp;
1816         char *stripped = NULL;
1817         char *tmp = NULL;
1818         char *result = NULL;
1819         int saved_errno;
1820         size_t rootpath_len = 0;
1821
1822         DBG_DEBUG("Calc connect path for [%s]\n", fname);
1823
1824         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
1825                                          &timestamp, &stripped)) {
1826                 goto done;
1827         }
1828         if (timestamp == 0) {
1829                 return SMB_VFS_NEXT_CONNECTPATH(handle, fname);
1830         }
1831
1832         tmp = shadow_copy2_do_convert(talloc_tos(), handle, stripped, timestamp,
1833                                       &rootpath_len);
1834         if (tmp == NULL) {
1835                 goto done;
1836         }
1837
1838         DBG_DEBUG("converted path is [%s] root path is [%.*s]\n", tmp,
1839                   (int)rootpath_len, tmp);
1840
1841         tmp[rootpath_len] = '\0';
1842         result = SMB_VFS_NEXT_REALPATH(handle, tmp);
1843         if (result == NULL) {
1844                 goto done;
1845         }
1846
1847         DBG_DEBUG("connect path is [%s]\n", result);
1848
1849 done:
1850         saved_errno = errno;
1851         TALLOC_FREE(tmp);
1852         TALLOC_FREE(stripped);
1853         errno = saved_errno;
1854         return result;
1855 }
1856
1857 static uint64_t shadow_copy2_disk_free(vfs_handle_struct *handle,
1858                                        const char *path, uint64_t *bsize,
1859                                        uint64_t *dfree, uint64_t *dsize)
1860 {
1861         time_t timestamp;
1862         char *stripped;
1863         ssize_t ret;
1864         int saved_errno;
1865         char *conv;
1866
1867         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, path,
1868                                          &timestamp, &stripped)) {
1869                 return -1;
1870         }
1871         if (timestamp == 0) {
1872                 return SMB_VFS_NEXT_DISK_FREE(handle, path,
1873                                               bsize, dfree, dsize);
1874         }
1875
1876         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1877         TALLOC_FREE(stripped);
1878         if (conv == NULL) {
1879                 return -1;
1880         }
1881
1882         ret = SMB_VFS_NEXT_DISK_FREE(handle, conv, bsize, dfree, dsize);
1883
1884         saved_errno = errno;
1885         TALLOC_FREE(conv);
1886         errno = saved_errno;
1887
1888         return ret;
1889 }
1890
1891 static int shadow_copy2_get_quota(vfs_handle_struct *handle, const char *path,
1892                                   enum SMB_QUOTA_TYPE qtype, unid_t id,
1893                                   SMB_DISK_QUOTA *dq)
1894 {
1895         time_t timestamp;
1896         char *stripped;
1897         int ret;
1898         int saved_errno;
1899         char *conv;
1900
1901         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, path, &timestamp,
1902                                          &stripped)) {
1903                 return -1;
1904         }
1905         if (timestamp == 0) {
1906                 return SMB_VFS_NEXT_GET_QUOTA(handle, path, qtype, id, dq);
1907         }
1908
1909         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1910         TALLOC_FREE(stripped);
1911         if (conv == NULL) {
1912                 return -1;
1913         }
1914
1915         ret = SMB_VFS_NEXT_GET_QUOTA(handle, conv, qtype, id, dq);
1916
1917         saved_errno = errno;
1918         TALLOC_FREE(conv);
1919         errno = saved_errno;
1920
1921         return ret;
1922 }
1923
1924 static int shadow_copy2_connect(struct vfs_handle_struct *handle,
1925                                 const char *service, const char *user)
1926 {
1927         struct shadow_copy2_config *config;
1928         int ret;
1929         const char *snapdir;
1930         const char *gmt_format;
1931         const char *sort_order;
1932         const char *basedir = NULL;
1933         const char *snapsharepath = NULL;
1934         const char *mount_point;
1935
1936         DEBUG(10, (__location__ ": cnum[%u], connectpath[%s]\n",
1937                    (unsigned)handle->conn->cnum,
1938                    handle->conn->connectpath));
1939
1940         ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
1941         if (ret < 0) {
1942                 return ret;
1943         }
1944
1945         config = talloc_zero(handle->conn, struct shadow_copy2_config);
1946         if (config == NULL) {
1947                 DEBUG(0, ("talloc_zero() failed\n"));
1948                 errno = ENOMEM;
1949                 return -1;
1950         }
1951
1952         gmt_format = lp_parm_const_string(SNUM(handle->conn),
1953                                           "shadow", "format",
1954                                           GMT_FORMAT);
1955         config->gmt_format = talloc_strdup(config, gmt_format);
1956         if (config->gmt_format == NULL) {
1957                 DEBUG(0, ("talloc_strdup() failed\n"));
1958                 errno = ENOMEM;
1959                 return -1;
1960         }
1961
1962         config->use_sscanf = lp_parm_bool(SNUM(handle->conn),
1963                                           "shadow", "sscanf", false);
1964
1965         config->use_localtime = lp_parm_bool(SNUM(handle->conn),
1966                                              "shadow", "localtime",
1967                                              false);
1968
1969         snapdir = lp_parm_const_string(SNUM(handle->conn),
1970                                        "shadow", "snapdir",
1971                                        ".snapshots");
1972         config->snapdir = talloc_strdup(config, snapdir);
1973         if (config->snapdir == NULL) {
1974                 DEBUG(0, ("talloc_strdup() failed\n"));
1975                 errno = ENOMEM;
1976                 return -1;
1977         }
1978
1979         config->snapdirseverywhere = lp_parm_bool(SNUM(handle->conn),
1980                                                   "shadow",
1981                                                   "snapdirseverywhere",
1982                                                   false);
1983
1984         config->crossmountpoints = lp_parm_bool(SNUM(handle->conn),
1985                                                 "shadow", "crossmountpoints",
1986                                                 false);
1987
1988         if (config->crossmountpoints && !config->snapdirseverywhere) {
1989                 DBG_WARNING("Warning: 'crossmountpoints' depends on "
1990                             "'snapdirseverywhere'. Disabling crossmountpoints.\n");
1991         }
1992
1993         config->fixinodes = lp_parm_bool(SNUM(handle->conn),
1994                                          "shadow", "fixinodes",
1995                                          false);
1996
1997         sort_order = lp_parm_const_string(SNUM(handle->conn),
1998                                           "shadow", "sort", "desc");
1999         config->sort_order = talloc_strdup(config, sort_order);
2000         if (config->sort_order == NULL) {
2001                 DEBUG(0, ("talloc_strdup() failed\n"));
2002                 errno = ENOMEM;
2003                 return -1;
2004         }
2005
2006         mount_point = lp_parm_const_string(SNUM(handle->conn),
2007                                            "shadow", "mountpoint", NULL);
2008         if (mount_point != NULL) {
2009                 if (mount_point[0] != '/') {
2010                         DEBUG(1, (__location__ " Warning: 'mountpoint' is "
2011                                   "relative ('%s'), but it has to be an "
2012                                   "absolute path. Ignoring provided value.\n",
2013                                   mount_point));
2014                         mount_point = NULL;
2015                 } else {
2016                         char *p;
2017                         p = strstr(handle->conn->connectpath, mount_point);
2018                         if (p != handle->conn->connectpath) {
2019                                 DBG_WARNING("Warning: the share root (%s) is "
2020                                             "not a subdirectory of the "
2021                                             "specified mountpoint (%s). "
2022                                             "Ignoring provided value.\n",
2023                                             handle->conn->connectpath,
2024                                             mount_point);
2025                                 mount_point = NULL;
2026                         }
2027                 }
2028         }
2029
2030         if (mount_point != NULL) {
2031                 config->mount_point = talloc_strdup(config, mount_point);
2032                 if (config->mount_point == NULL) {
2033                         DEBUG(0, (__location__ " talloc_strdup() failed\n"));
2034                         return -1;
2035                 }
2036         } else {
2037                 config->mount_point = shadow_copy2_find_mount_point(config,
2038                                                                     handle);
2039                 if (config->mount_point == NULL) {
2040                         DBG_WARNING("shadow_copy2_find_mount_point "
2041                                     "of the share root '%s' failed: %s\n",
2042                                     handle->conn->connectpath, strerror(errno));
2043                         return -1;
2044                 }
2045         }
2046
2047         basedir = lp_parm_const_string(SNUM(handle->conn),
2048                                        "shadow", "basedir", NULL);
2049
2050         if (basedir != NULL) {
2051                 if (basedir[0] != '/') {
2052                         DEBUG(1, (__location__ " Warning: 'basedir' is "
2053                                   "relative ('%s'), but it has to be an "
2054                                   "absolute path. Disabling basedir.\n",
2055                                   basedir));
2056                         basedir = NULL;
2057                 } else {
2058                         char *p;
2059                         p = strstr(basedir, config->mount_point);
2060                         if (p != basedir) {
2061                                 DEBUG(1, ("Warning: basedir (%s) is not a "
2062                                           "subdirectory of the share root's "
2063                                           "mount point (%s). "
2064                                           "Disabling basedir\n",
2065                                           basedir, config->mount_point));
2066                                 basedir = NULL;
2067                         }
2068                 }
2069         }
2070
2071         if (config->snapdirseverywhere && basedir != NULL) {
2072                 DEBUG(1, (__location__ " Warning: 'basedir' is incompatible "
2073                           "with 'snapdirseverywhere'. Disabling basedir.\n"));
2074                 basedir = NULL;
2075         }
2076
2077         snapsharepath = lp_parm_const_string(SNUM(handle->conn), "shadow",
2078                                              "snapsharepath", NULL);
2079         if (snapsharepath != NULL) {
2080                 if (snapsharepath[0] == '/') {
2081                         DBG_WARNING("Warning: 'snapsharepath' is "
2082                                     "absolute ('%s'), but it has to be a "
2083                                     "relative path. Disabling snapsharepath.\n",
2084                                     snapsharepath);
2085                         snapsharepath = NULL;
2086                 }
2087                 if (config->snapdirseverywhere && snapsharepath != NULL) {
2088                         DBG_WARNING("Warning: 'snapsharepath' is incompatible "
2089                                     "with 'snapdirseverywhere'. Disabling "
2090                                     "snapsharepath.\n");
2091                         snapsharepath = NULL;
2092                 }
2093         }
2094
2095         if (basedir != NULL && snapsharepath != NULL) {
2096                 DBG_WARNING("Warning: 'snapsharepath' is incompatible with "
2097                             "'basedir'. Disabling snapsharepath\n");
2098                 snapsharepath = NULL;
2099         }
2100
2101         if (snapsharepath != NULL) {
2102                 config->rel_connectpath = talloc_strdup(config, snapsharepath);
2103                 if (config->rel_connectpath == NULL) {
2104                         DBG_ERR("talloc_strdup() failed\n");
2105                         errno = ENOMEM;
2106                         return -1;
2107                 }
2108         }
2109
2110         if (basedir == NULL) {
2111                 basedir = config->mount_point;
2112         }
2113
2114         if (config->rel_connectpath == NULL &&
2115             strlen(basedir) != strlen(handle->conn->connectpath)) {
2116                 config->rel_connectpath = talloc_strdup(config,
2117                         handle->conn->connectpath + strlen(basedir));
2118                 if (config->rel_connectpath == NULL) {
2119                         DEBUG(0, ("talloc_strdup() failed\n"));
2120                         errno = ENOMEM;
2121                         return -1;
2122                 }
2123         }
2124
2125         if (config->snapdir[0] == '/') {
2126                 config->snapdir_absolute = true;
2127
2128                 if (config->snapdirseverywhere == true) {
2129                         DEBUG(1, (__location__ " Warning: An absolute snapdir "
2130                                   "is incompatible with 'snapdirseverywhere', "
2131                                   "setting 'snapdirseverywhere' to false.\n"));
2132                         config->snapdirseverywhere = false;
2133                 }
2134
2135                 if (config->crossmountpoints == true) {
2136                         DEBUG(1, (__location__ " Warning: 'crossmountpoints' "
2137                                   "is not supported with an absolute snapdir. "
2138                                   "Disabling it.\n"));
2139                         config->crossmountpoints = false;
2140                 }
2141
2142                 config->snapshot_basepath = config->snapdir;
2143         } else {
2144                 config->snapshot_basepath = talloc_asprintf(config, "%s/%s",
2145                                 config->mount_point, config->snapdir);
2146                 if (config->snapshot_basepath == NULL) {
2147                         DEBUG(0, ("talloc_asprintf() failed\n"));
2148                         errno = ENOMEM;
2149                         return -1;
2150                 }
2151         }
2152
2153         DEBUG(10, ("shadow_copy2_connect: configuration:\n"
2154                    "  share root: '%s'\n"
2155                    "  mountpoint: '%s'\n"
2156                    "  rel share root: '%s'\n"
2157                    "  snapdir: '%s'\n"
2158                    "  snapshot base path: '%s'\n"
2159                    "  format: '%s'\n"
2160                    "  use sscanf: %s\n"
2161                    "  snapdirs everywhere: %s\n"
2162                    "  cross mountpoints: %s\n"
2163                    "  fix inodes: %s\n"
2164                    "  sort order: %s\n"
2165                    "",
2166                    handle->conn->connectpath,
2167                    config->mount_point,
2168                    config->rel_connectpath,
2169                    config->snapdir,
2170                    config->snapshot_basepath,
2171                    config->gmt_format,
2172                    config->use_sscanf ? "yes" : "no",
2173                    config->snapdirseverywhere ? "yes" : "no",
2174                    config->crossmountpoints ? "yes" : "no",
2175                    config->fixinodes ? "yes" : "no",
2176                    config->sort_order
2177                    ));
2178
2179
2180         SMB_VFS_HANDLE_SET_DATA(handle, config,
2181                                 NULL, struct shadow_copy2_config,
2182                                 return -1);
2183
2184         return 0;
2185 }
2186
2187 static struct vfs_fn_pointers vfs_shadow_copy2_fns = {
2188         .connect_fn = shadow_copy2_connect,
2189         .opendir_fn = shadow_copy2_opendir,
2190         .disk_free_fn = shadow_copy2_disk_free,
2191         .get_quota_fn = shadow_copy2_get_quota,
2192         .rename_fn = shadow_copy2_rename,
2193         .link_fn = shadow_copy2_link,
2194         .symlink_fn = shadow_copy2_symlink,
2195         .stat_fn = shadow_copy2_stat,
2196         .lstat_fn = shadow_copy2_lstat,
2197         .fstat_fn = shadow_copy2_fstat,
2198         .open_fn = shadow_copy2_open,
2199         .unlink_fn = shadow_copy2_unlink,
2200         .chmod_fn = shadow_copy2_chmod,
2201         .chown_fn = shadow_copy2_chown,
2202         .chdir_fn = shadow_copy2_chdir,
2203         .ntimes_fn = shadow_copy2_ntimes,
2204         .readlink_fn = shadow_copy2_readlink,
2205         .mknod_fn = shadow_copy2_mknod,
2206         .realpath_fn = shadow_copy2_realpath,
2207         .get_nt_acl_fn = shadow_copy2_get_nt_acl,
2208         .fget_nt_acl_fn = shadow_copy2_fget_nt_acl,
2209         .get_shadow_copy_data_fn = shadow_copy2_get_shadow_copy_data,
2210         .mkdir_fn = shadow_copy2_mkdir,
2211         .rmdir_fn = shadow_copy2_rmdir,
2212         .getxattr_fn = shadow_copy2_getxattr,
2213         .listxattr_fn = shadow_copy2_listxattr,
2214         .removexattr_fn = shadow_copy2_removexattr,
2215         .setxattr_fn = shadow_copy2_setxattr,
2216         .chmod_acl_fn = shadow_copy2_chmod_acl,
2217         .chflags_fn = shadow_copy2_chflags,
2218         .get_real_filename_fn = shadow_copy2_get_real_filename,
2219         .connectpath_fn = shadow_copy2_connectpath,
2220 };
2221
2222 NTSTATUS vfs_shadow_copy2_init(void);
2223 NTSTATUS vfs_shadow_copy2_init(void)
2224 {
2225         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2226                                 "shadow_copy2", &vfs_shadow_copy2_fns);
2227 }