2d1b1e67fdb847f983bb709a1e1824c8d50ee891
[kai/samba-autobuild/.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  * Copyright (C) Rajesh Joseph     2016
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25
26 /*
27  * This is a second implemetation of a shadow copy module for exposing
28  * file system snapshots to windows clients as shadow copies.
29  *
30  * See the manual page for documentation.
31  */
32
33 #include "includes.h"
34 #include "smbd/smbd.h"
35 #include "system/filesys.h"
36 #include "include/ntioctl.h"
37 #include "util_tdb.h"
38 #include "lib/util_path.h"
39
40 struct shadow_copy2_config {
41         char *gmt_format;
42         bool use_sscanf;
43         bool use_localtime;
44         char *snapdir;
45         char *delimiter;
46         bool snapdirseverywhere;
47         bool crossmountpoints;
48         bool fixinodes;
49         char *sort_order;
50         bool snapdir_absolute;
51         char *mount_point;
52         char *rel_connectpath; /* share root, relative to a snapshot root */
53         char *snapshot_basepath; /* the absolute version of snapdir */
54 };
55
56 /* Data-structure to hold the list of snap entries */
57 struct shadow_copy2_snapentry {
58         char *snapname;
59         char *time_fmt;
60         struct shadow_copy2_snapentry *next;
61         struct shadow_copy2_snapentry *prev;
62 };
63
64 struct shadow_copy2_snaplist_info {
65         struct shadow_copy2_snapentry *snaplist; /* snapshot list */
66         regex_t *regex; /* Regex to filter snaps */
67         time_t fetch_time; /* snaplist update time */
68 };
69
70
71 /*
72  * shadow_copy2 private structure. This structure will be
73  * used to keep module specific information
74  */
75 struct shadow_copy2_private {
76         struct shadow_copy2_config *config;
77         struct shadow_copy2_snaplist_info *snaps;
78         char *shadow_cwd; /* Absolute $cwd path. */
79         /* Absolute connectpath - can vary depending on $cwd. */
80         char *shadow_connectpath;
81 };
82
83 static int shadow_copy2_get_shadow_copy_data(
84         vfs_handle_struct *handle, files_struct *fsp,
85         struct shadow_copy_data *shadow_copy2_data,
86         bool labels);
87
88 /**
89  *This function will create a new snapshot list entry and
90  * return to the caller. This entry will also be added to
91  * the global snapshot list.
92  *
93  * @param[in]   priv    shadow_copy2 specific data structure
94  * @return      Newly   created snapshot entry or NULL on failure
95  */
96 static struct shadow_copy2_snapentry *shadow_copy2_create_snapentry(
97                                         struct shadow_copy2_private *priv)
98 {
99         struct shadow_copy2_snapentry *tmpentry = NULL;
100
101         tmpentry = talloc_zero(priv->snaps, struct shadow_copy2_snapentry);
102         if (tmpentry == NULL) {
103                 DBG_ERR("talloc_zero() failed\n");
104                 errno = ENOMEM;
105                 return NULL;
106         }
107
108         DLIST_ADD(priv->snaps->snaplist, tmpentry);
109
110         return tmpentry;
111 }
112
113 /**
114  *This function will delete the entire snaplist and reset
115  * priv->snaps->snaplist to NULL.
116  *
117  * @param[in] priv shadow_copye specific data structure
118  */
119 static void shadow_copy2_delete_snaplist(struct shadow_copy2_private *priv)
120 {
121         struct shadow_copy2_snapentry *tmp = NULL;
122
123         while ((tmp = priv->snaps->snaplist) != NULL) {
124                 DLIST_REMOVE(priv->snaps->snaplist, tmp);
125                 talloc_free(tmp);
126         }
127 }
128
129 /**
130  * Given a timestamp this function searches the global snapshot list
131  * and returns the complete snapshot directory name saved in the entry.
132  *
133  * @param[in]   priv            shadow_copy2 specific structure
134  * @param[in]   timestamp       timestamp corresponding to one of the snapshot
135  * @param[out]  snap_str        buffer to copy the actual snapshot name
136  * @param[in]   len             length of snap_str buffer
137  *
138  * @return      Length of actual snapshot name, and -1 on failure
139  */
140 static ssize_t shadow_copy2_saved_snapname(struct shadow_copy2_private *priv,
141                                           struct tm *timestamp,
142                                           char *snap_str, size_t len)
143 {
144         ssize_t snaptime_len = -1;
145         struct shadow_copy2_snapentry *entry = NULL;
146
147         snaptime_len = strftime(snap_str, len, GMT_FORMAT, timestamp);
148         if (snaptime_len == 0) {
149                 DBG_ERR("strftime failed\n");
150                 return -1;
151         }
152
153         snaptime_len = -1;
154
155         for (entry = priv->snaps->snaplist; entry; entry = entry->next) {
156                 if (strcmp(entry->time_fmt, snap_str) == 0) {
157                         snaptime_len = snprintf(snap_str, len, "%s",
158                                                 entry->snapname);
159                         return snaptime_len;
160                 }
161         }
162
163         snap_str[0] = 0;
164         return snaptime_len;
165 }
166
167
168 /**
169  * This function will check if snaplist is updated or not. If snaplist
170  * is empty then it will create a new list. Each time snaplist is updated
171  * the time is recorded. If the snapshot time is greater than the snaplist
172  * update time then chances are we are working on an older list. Then discard
173  * the old list and fetch a new snaplist.
174  *
175  * @param[in]   handle          VFS handle struct
176  * @param[in]   snap_time       time of snapshot
177  *
178  * @return      true if the list is updated else false
179  */
180 static bool shadow_copy2_update_snaplist(struct vfs_handle_struct *handle,
181                 time_t snap_time)
182 {
183         int ret = -1;
184         bool snaplist_updated = false;
185         struct files_struct fsp = {0};
186         struct smb_filename smb_fname = {0};
187         double seconds = 0.0;
188         struct shadow_copy2_private *priv = NULL;
189
190         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
191                                 return false);
192
193         seconds = difftime(snap_time, priv->snaps->fetch_time);
194
195         /*
196          * Fetch the snapshot list if either the snaplist is empty or the
197          * required snapshot time is greater than the last fetched snaplist
198          * time.
199          */
200         if (seconds > 0 || (priv->snaps->snaplist == NULL)) {
201                 smb_fname.base_name = discard_const_p(char, ".");
202                 fsp.fsp_name = &smb_fname;
203
204                 ret = shadow_copy2_get_shadow_copy_data(handle, &fsp,
205                                                         NULL, false);
206                 if (ret == 0) {
207                         snaplist_updated = true;
208                 } else {
209                         DBG_ERR("Failed to get shadow copy data\n");
210                 }
211
212         }
213
214         return snaplist_updated;
215 }
216
217 static bool shadow_copy2_find_slashes(TALLOC_CTX *mem_ctx, const char *str,
218                                       size_t **poffsets,
219                                       unsigned *pnum_offsets)
220 {
221         unsigned num_offsets;
222         size_t *offsets;
223         const char *p;
224
225         num_offsets = 0;
226
227         p = str;
228         while ((p = strchr(p, '/')) != NULL) {
229                 num_offsets += 1;
230                 p += 1;
231         }
232
233         offsets = talloc_array(mem_ctx, size_t, num_offsets);
234         if (offsets == NULL) {
235                 return false;
236         }
237
238         p = str;
239         num_offsets = 0;
240         while ((p = strchr(p, '/')) != NULL) {
241                 offsets[num_offsets] = p-str;
242                 num_offsets += 1;
243                 p += 1;
244         }
245
246         *poffsets = offsets;
247         *pnum_offsets = num_offsets;
248         return true;
249 }
250
251 /**
252  * Given a timestamp, build the posix level GMT-tag string
253  * based on the configurable format.
254  */
255 static ssize_t shadow_copy2_posix_gmt_string(struct vfs_handle_struct *handle,
256                                             time_t snapshot,
257                                             char *snaptime_string,
258                                             size_t len)
259 {
260         struct tm snap_tm;
261         ssize_t snaptime_len;
262         struct shadow_copy2_config *config;
263         struct shadow_copy2_private *priv;
264
265         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
266                                 return 0);
267
268         config = priv->config;
269
270         if (config->use_sscanf) {
271                 snaptime_len = snprintf(snaptime_string,
272                                         len,
273                                         config->gmt_format,
274                                         (unsigned long)snapshot);
275                 if (snaptime_len <= 0) {
276                         DEBUG(10, ("snprintf failed\n"));
277                         return -1;
278                 }
279         } else {
280                 if (config->use_localtime) {
281                         if (localtime_r(&snapshot, &snap_tm) == 0) {
282                                 DEBUG(10, ("gmtime_r failed\n"));
283                                 return -1;
284                         }
285                 } else {
286                         if (gmtime_r(&snapshot, &snap_tm) == 0) {
287                                 DEBUG(10, ("gmtime_r failed\n"));
288                                 return -1;
289                         }
290                 }
291
292                 if (priv->snaps->regex != NULL) {
293                         snaptime_len = shadow_copy2_saved_snapname(priv,
294                                                 &snap_tm, snaptime_string, len);
295                         if (snaptime_len >= 0)
296                                 return snaptime_len;
297
298                         /*
299                          * If we fail to find the snapshot name, chances are
300                          * that we have not updated our snaplist. Make sure the
301                          * snaplist is updated.
302                          */
303                         if (!shadow_copy2_update_snaplist(handle, snapshot)) {
304                                 DBG_DEBUG("shadow_copy2_update_snaplist "
305                                           "failed\n");
306                                 return -1;
307                         }
308
309                         return shadow_copy2_saved_snapname(priv,
310                                                 &snap_tm, snaptime_string, len);
311                 }
312
313                 snaptime_len = strftime(snaptime_string,
314                                         len,
315                                         config->gmt_format,
316                                         &snap_tm);
317                 if (snaptime_len == 0) {
318                         DEBUG(10, ("strftime failed\n"));
319                         return -1;
320                 }
321         }
322
323         return snaptime_len;
324 }
325
326 /**
327  * Given a timestamp, build the string to insert into a path
328  * as a path component for creating the local path to the
329  * snapshot at the given timestamp of the input path.
330  *
331  * In the case of a parallel snapdir (specified with an
332  * absolute path), this is the inital portion of the
333  * local path of any snapshot file. The complete path is
334  * obtained by appending the portion of the file's path
335  * below the share root's mountpoint.
336  */
337 static char *shadow_copy2_insert_string(TALLOC_CTX *mem_ctx,
338                                         struct vfs_handle_struct *handle,
339                                         time_t snapshot)
340 {
341         fstring snaptime_string;
342         ssize_t snaptime_len = 0;
343         char *result = NULL;
344         struct shadow_copy2_config *config;
345         struct shadow_copy2_private *priv;
346
347         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
348                                 return NULL);
349
350         config = priv->config;
351
352         snaptime_len = shadow_copy2_posix_gmt_string(handle,
353                                                      snapshot,
354                                                      snaptime_string,
355                                                      sizeof(snaptime_string));
356         if (snaptime_len <= 0) {
357                 return NULL;
358         }
359
360         if (config->snapdir_absolute) {
361                 result = talloc_asprintf(mem_ctx, "%s/%s",
362                                          config->snapdir, snaptime_string);
363         } else {
364                 result = talloc_asprintf(mem_ctx, "/%s/%s",
365                                          config->snapdir, snaptime_string);
366         }
367         if (result == NULL) {
368                 DEBUG(1, (__location__ " talloc_asprintf failed\n"));
369         }
370
371         return result;
372 }
373
374 /**
375  * Build the posix snapshot path for the connection
376  * at the given timestamp, i.e. the absolute posix path
377  * that contains the snapshot for this file system.
378  *
379  * This only applies to classical case, i.e. not
380  * to the "snapdirseverywhere" mode.
381  */
382 static char *shadow_copy2_snapshot_path(TALLOC_CTX *mem_ctx,
383                                         struct vfs_handle_struct *handle,
384                                         time_t snapshot)
385 {
386         fstring snaptime_string;
387         ssize_t snaptime_len = 0;
388         char *result = NULL;
389         struct shadow_copy2_private *priv;
390
391         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
392                                 return NULL);
393
394         snaptime_len = shadow_copy2_posix_gmt_string(handle,
395                                                      snapshot,
396                                                      snaptime_string,
397                                                      sizeof(snaptime_string));
398         if (snaptime_len <= 0) {
399                 return NULL;
400         }
401
402         result = talloc_asprintf(mem_ctx, "%s/%s",
403                                  priv->config->snapshot_basepath, snaptime_string);
404         if (result == NULL) {
405                 DEBUG(1, (__location__ " talloc_asprintf failed\n"));
406         }
407
408         return result;
409 }
410
411 static char *make_path_absolute(TALLOC_CTX *mem_ctx,
412                                 struct shadow_copy2_private *priv,
413                                 const char *name)
414 {
415         char *newpath = NULL;
416         char *abs_path = NULL;
417
418         if (name[0] != '/') {
419                 newpath = talloc_asprintf(mem_ctx,
420                                         "%s/%s",
421                                         priv->shadow_cwd,
422                                         name);
423                 if (newpath == NULL) {
424                         return NULL;
425                 }
426                 name = newpath;
427         }
428         abs_path = canonicalize_absolute_path(mem_ctx, name);
429         TALLOC_FREE(newpath);
430         return abs_path;
431 }
432
433 /* Return a $cwd-relative path. */
434 static bool make_relative_path(const char *cwd, char *abs_path)
435 {
436         size_t cwd_len = strlen(cwd);
437         size_t abs_len = strlen(abs_path);
438
439         if (abs_len < cwd_len) {
440                 return false;
441         }
442         if (memcmp(abs_path, cwd, cwd_len) != 0) {
443                 return false;
444         }
445         if (abs_path[cwd_len] != '/' && abs_path[cwd_len] != '\0') {
446                 return false;
447         }
448         if (abs_path[cwd_len] == '/') {
449                 cwd_len++;
450         }
451         memmove(abs_path, &abs_path[cwd_len], abs_len + 1 - cwd_len);
452         return true;
453 }
454
455 /**
456  * Strip a snapshot component from a filename as
457  * handed in via the smb layer.
458  * Returns the parsed timestamp and the stripped filename.
459  */
460 static bool shadow_copy2_strip_snapshot_internal(TALLOC_CTX *mem_ctx,
461                                         struct vfs_handle_struct *handle,
462                                         const char *orig_name,
463                                         time_t *ptimestamp,
464                                         char **pstripped,
465                                         char **psnappath)
466 {
467         struct tm tm;
468         time_t timestamp = 0;
469         const char *p;
470         char *q;
471         char *stripped = NULL;
472         size_t rest_len, dst_len;
473         struct shadow_copy2_private *priv;
474         const char *snapdir;
475         ssize_t snapdirlen;
476         ptrdiff_t len_before_gmt;
477         const char *name = orig_name;
478
479         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
480                                 return false);
481
482         DEBUG(10, (__location__ ": enter path '%s'\n", name));
483
484         p = strstr_m(name, "@GMT-");
485         if (p == NULL) {
486                 DEBUG(11, ("@GMT not found\n"));
487                 goto no_snapshot;
488         }
489         if ((p > name) && (p[-1] != '/')) {
490                 /* the GMT-token does not start a path-component */
491                 DEBUG(10, ("not at start, p=%p, name=%p, p[-1]=%d\n",
492                            p, name, (int)p[-1]));
493                 goto no_snapshot;
494         }
495
496         /*
497          * Figure out whether we got an already converted string. One
498          * case where this happens is in a smb2 create call with the
499          * mxac create blob set. We do the get_acl call on
500          * fsp->fsp_name, which is already converted. We are converted
501          * if we got a file name of the form ".snapshots/@GMT-",
502          * i.e. ".snapshots/" precedes "p".
503          */
504
505         snapdir = lp_parm_const_string(SNUM(handle->conn), "shadow", "snapdir",
506                                        ".snapshots");
507         snapdirlen = strlen(snapdir);
508         len_before_gmt = p - name;
509
510         if ((len_before_gmt >= (snapdirlen + 1)) && (p[-1] == '/')) {
511                 const char *parent_snapdir = p - (snapdirlen+1);
512
513                 DEBUG(10, ("parent_snapdir = %s\n", parent_snapdir));
514
515                 if (strncmp(parent_snapdir, snapdir, snapdirlen) == 0) {
516                         DEBUG(10, ("name=%s is already converted\n", name));
517                         goto no_snapshot;
518                 }
519         }
520         q = strptime(p, GMT_FORMAT, &tm);
521         if (q == NULL) {
522                 DEBUG(10, ("strptime failed\n"));
523                 goto no_snapshot;
524         }
525         tm.tm_isdst = -1;
526         timestamp = timegm(&tm);
527         if (timestamp == (time_t)-1) {
528                 DEBUG(10, ("timestamp==-1\n"));
529                 goto no_snapshot;
530         }
531         if (q[0] == '\0') {
532                 /*
533                  * The name consists of only the GMT token or the GMT
534                  * token is at the end of the path. XP seems to send
535                  * @GMT- at the end under certain circumstances even
536                  * with a path prefix.
537                  */
538                 if (pstripped != NULL) {
539                         if (len_before_gmt > 0) {
540                                 /*
541                                  * There is a slash before
542                                  * the @GMT-. Remove it.
543                                  */
544                                 len_before_gmt -= 1;
545                         }
546                         stripped = talloc_strndup(mem_ctx, name,
547                                         len_before_gmt);
548                         if (stripped == NULL) {
549                                 return false;
550                         }
551                         *pstripped = stripped;
552                 }
553                 *ptimestamp = timestamp;
554                 return true;
555         }
556         if (q[0] != '/') {
557                 /*
558                  * It is not a complete path component, i.e. the path
559                  * component continues after the gmt-token.
560                  */
561                 DEBUG(10, ("q[0] = %d\n", (int)q[0]));
562                 goto no_snapshot;
563         }
564         q += 1;
565
566         rest_len = strlen(q);
567         dst_len = len_before_gmt + rest_len;
568
569         if (priv->config->snapdirseverywhere) {
570                 char *insert;
571                 bool have_insert;
572                 insert = shadow_copy2_insert_string(talloc_tos(), handle,
573                                                     timestamp);
574                 if (insert == NULL) {
575                         errno = ENOMEM;
576                         return false;
577                 }
578
579                 DEBUG(10, (__location__ ": snapdirseverywhere mode.\n"
580                            "path '%s'.\n"
581                            "insert string '%s'\n", name, insert));
582
583                 have_insert = (strstr(name, insert+1) != NULL);
584                 DEBUG(10, ("have_insert=%d, name=%s, insert+1=%s\n",
585                            (int)have_insert, name, insert+1));
586                 if (have_insert) {
587                         DEBUG(10, (__location__ ": insert string '%s' found in "
588                                    "path '%s' found in snapdirseverywhere mode "
589                                    "==> already converted\n", insert, name));
590                         TALLOC_FREE(insert);
591                         goto no_snapshot;
592                 }
593                 TALLOC_FREE(insert);
594         } else {
595                 char *snapshot_path;
596                 char *s;
597
598                 snapshot_path = shadow_copy2_snapshot_path(talloc_tos(),
599                                                            handle,
600                                                            timestamp);
601                 if (snapshot_path == NULL) {
602                         errno = ENOMEM;
603                         return false;
604                 }
605
606                 DEBUG(10, (__location__ " path: '%s'.\n"
607                            "snapshot path: '%s'\n", name, snapshot_path));
608
609                 s = strstr(name, snapshot_path);
610                 if (s == name) {
611                         /*
612                          * this starts with "snapshot_basepath/GMT-Token"
613                          * so it is already a converted absolute
614                          * path. Don't process further.
615                          */
616                         DEBUG(10, (__location__ ": path '%s' starts with "
617                                    "snapshot path '%s' (not in "
618                                    "snapdirseverywhere mode) ==> "
619                                    "already converted\n", name, snapshot_path));
620                         talloc_free(snapshot_path);
621                         goto no_snapshot;
622                 }
623                 talloc_free(snapshot_path);
624         }
625
626         if (pstripped != NULL) {
627                 stripped = talloc_array(mem_ctx, char, dst_len+1);
628                 if (stripped == NULL) {
629                         errno = ENOMEM;
630                         return false;
631                 }
632                 if (p > name) {
633                         memcpy(stripped, name, len_before_gmt);
634                 }
635                 if (rest_len > 0) {
636                         memcpy(stripped + len_before_gmt, q, rest_len);
637                 }
638                 stripped[dst_len] = '\0';
639                 *pstripped = stripped;
640         }
641         *ptimestamp = timestamp;
642         return true;
643 no_snapshot:
644         *ptimestamp = 0;
645         return true;
646 }
647
648 static bool shadow_copy2_strip_snapshot(TALLOC_CTX *mem_ctx,
649                                         struct vfs_handle_struct *handle,
650                                         const char *orig_name,
651                                         time_t *ptimestamp,
652                                         char **pstripped)
653 {
654         return shadow_copy2_strip_snapshot_internal(mem_ctx,
655                                         handle,
656                                         orig_name,
657                                         ptimestamp,
658                                         pstripped,
659                                         NULL);
660 }
661
662 static char *shadow_copy2_find_mount_point(TALLOC_CTX *mem_ctx,
663                                            vfs_handle_struct *handle)
664 {
665         char *path = talloc_strdup(mem_ctx, handle->conn->connectpath);
666         dev_t dev;
667         struct stat st;
668         char *p;
669
670         if (stat(path, &st) != 0) {
671                 talloc_free(path);
672                 return NULL;
673         }
674
675         dev = st.st_dev;
676
677         while ((p = strrchr(path, '/')) && p > path) {
678                 *p = 0;
679                 if (stat(path, &st) != 0) {
680                         talloc_free(path);
681                         return NULL;
682                 }
683                 if (st.st_dev != dev) {
684                         *p = '/';
685                         break;
686                 }
687         }
688
689         return path;
690 }
691
692 /**
693  * Convert from a name as handed in via the SMB layer
694  * and a timestamp into the local path of the snapshot
695  * of the provided file at the provided time.
696  * Also return the path in the snapshot corresponding
697  * to the file's share root.
698  */
699 static char *shadow_copy2_do_convert(TALLOC_CTX *mem_ctx,
700                                      struct vfs_handle_struct *handle,
701                                      const char *name, time_t timestamp,
702                                      size_t *snaproot_len)
703 {
704         struct smb_filename converted_fname;
705         char *result = NULL;
706         size_t *slashes = NULL;
707         unsigned num_slashes;
708         char *path = NULL;
709         size_t pathlen;
710         char *insert = NULL;
711         char *converted = NULL;
712         size_t insertlen, connectlen = 0;
713         int i, saved_errno;
714         size_t min_offset;
715         struct shadow_copy2_config *config;
716         struct shadow_copy2_private *priv;
717         size_t in_share_offset = 0;
718
719         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
720                                 return NULL);
721
722         config = priv->config;
723
724         DEBUG(10, ("converting '%s'\n", name));
725
726         if (!config->snapdirseverywhere) {
727                 int ret;
728                 char *snapshot_path;
729
730                 snapshot_path = shadow_copy2_snapshot_path(talloc_tos(),
731                                                            handle,
732                                                            timestamp);
733                 if (snapshot_path == NULL) {
734                         goto fail;
735                 }
736
737                 if (config->rel_connectpath == NULL) {
738                         converted = talloc_asprintf(mem_ctx, "%s/%s",
739                                                     snapshot_path, name);
740                 } else {
741                         converted = talloc_asprintf(mem_ctx, "%s/%s/%s",
742                                                     snapshot_path,
743                                                     config->rel_connectpath,
744                                                     name);
745                 }
746                 if (converted == NULL) {
747                         goto fail;
748                 }
749
750                 ZERO_STRUCT(converted_fname);
751                 converted_fname.base_name = converted;
752
753                 ret = SMB_VFS_NEXT_LSTAT(handle, &converted_fname);
754                 DEBUG(10, ("Trying[not snapdirseverywhere] %s: %d (%s)\n",
755                            converted,
756                            ret, ret == 0 ? "ok" : strerror(errno)));
757                 if (ret == 0) {
758                         DEBUG(10, ("Found %s\n", converted));
759                         result = converted;
760                         converted = NULL;
761                         if (snaproot_len != NULL) {
762                                 *snaproot_len = strlen(snapshot_path);
763                                 if (config->rel_connectpath != NULL) {
764                                         *snaproot_len +=
765                                             strlen(config->rel_connectpath) + 1;
766                                 }
767                         }
768                         goto fail;
769                 } else {
770                         errno = ENOENT;
771                         goto fail;
772                 }
773                 /* never reached ... */
774         }
775
776         connectlen = strlen(handle->conn->connectpath);
777         if (name[0] == 0) {
778                 path = talloc_strdup(mem_ctx, handle->conn->connectpath);
779         } else {
780                 path = talloc_asprintf(
781                         mem_ctx, "%s/%s", handle->conn->connectpath, name);
782         }
783         if (path == NULL) {
784                 errno = ENOMEM;
785                 goto fail;
786         }
787         pathlen = talloc_get_size(path)-1;
788
789         if (!shadow_copy2_find_slashes(talloc_tos(), path,
790                                        &slashes, &num_slashes)) {
791                 goto fail;
792         }
793
794         insert = shadow_copy2_insert_string(talloc_tos(), handle, timestamp);
795         if (insert == NULL) {
796                 goto fail;
797         }
798         insertlen = talloc_get_size(insert)-1;
799
800         /*
801          * Note: We deliberatly don't expensively initialize the
802          * array with talloc_zero here: Putting zero into
803          * converted[pathlen+insertlen] below is sufficient, because
804          * in the following for loop, the insert string is inserted
805          * at various slash places. So the memory up to position
806          * pathlen+insertlen will always be initialized when the
807          * converted string is used.
808          */
809         converted = talloc_array(mem_ctx, char, pathlen + insertlen + 1);
810         if (converted == NULL) {
811                 goto fail;
812         }
813
814         if (path[pathlen-1] != '/') {
815                 /*
816                  * Append a fake slash to find the snapshot root
817                  */
818                 size_t *tmp;
819                 tmp = talloc_realloc(talloc_tos(), slashes,
820                                      size_t, num_slashes+1);
821                 if (tmp == NULL) {
822                         goto fail;
823                 }
824                 slashes = tmp;
825                 slashes[num_slashes] = pathlen;
826                 num_slashes += 1;
827         }
828
829         min_offset = 0;
830
831         if (!config->crossmountpoints) {
832                 min_offset = strlen(config->mount_point);
833         }
834
835         memcpy(converted, path, pathlen+1);
836         converted[pathlen+insertlen] = '\0';
837
838         ZERO_STRUCT(converted_fname);
839         converted_fname.base_name = converted;
840
841         for (i = num_slashes-1; i>=0; i--) {
842                 int ret;
843                 size_t offset;
844
845                 offset = slashes[i];
846
847                 if (offset < min_offset) {
848                         errno = ENOENT;
849                         goto fail;
850                 }
851
852                 if (offset >= connectlen) {
853                         in_share_offset = offset;
854                 }
855
856                 memcpy(converted+offset, insert, insertlen);
857
858                 offset += insertlen;
859                 memcpy(converted+offset, path + slashes[i],
860                        pathlen - slashes[i]);
861
862                 ret = SMB_VFS_NEXT_LSTAT(handle, &converted_fname);
863
864                 DEBUG(10, ("Trying[snapdirseverywhere] %s: %d (%s)\n",
865                            converted,
866                            ret, ret == 0 ? "ok" : strerror(errno)));
867                 if (ret == 0) {
868                         /* success */
869                         if (snaproot_len != NULL) {
870                                 *snaproot_len = in_share_offset + insertlen;
871                         }
872                         break;
873                 }
874                 if (errno == ENOTDIR) {
875                         /*
876                          * This is a valid condition: We appended the
877                          * .snaphots/@GMT.. to a file name. Just try
878                          * with the upper levels.
879                          */
880                         continue;
881                 }
882                 if (errno != ENOENT) {
883                         /* Other problem than "not found" */
884                         goto fail;
885                 }
886         }
887
888         if (i >= 0) {
889                 /*
890                  * Found something
891                  */
892                 DEBUG(10, ("Found %s\n", converted));
893                 result = converted;
894                 converted = NULL;
895         } else {
896                 errno = ENOENT;
897         }
898 fail:
899         saved_errno = errno;
900         TALLOC_FREE(converted);
901         TALLOC_FREE(insert);
902         TALLOC_FREE(slashes);
903         TALLOC_FREE(path);
904         errno = saved_errno;
905         return result;
906 }
907
908 /**
909  * Convert from a name as handed in via the SMB layer
910  * and a timestamp into the local path of the snapshot
911  * of the provided file at the provided time.
912  */
913 static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
914                                   struct vfs_handle_struct *handle,
915                                   const char *name, time_t timestamp)
916 {
917         return shadow_copy2_do_convert(mem_ctx, handle, name, timestamp, NULL);
918 }
919
920 /*
921   modify a sbuf return to ensure that inodes in the shadow directory
922   are different from those in the main directory
923  */
924 static void convert_sbuf(vfs_handle_struct *handle, const char *fname,
925                          SMB_STRUCT_STAT *sbuf)
926 {
927         struct shadow_copy2_private *priv;
928
929         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
930                                 return);
931
932         if (priv->config->fixinodes) {
933                 /* some snapshot systems, like GPFS, return the name
934                    device:inode for the snapshot files as the current
935                    files. That breaks the 'restore' button in the shadow copy
936                    GUI, as the client gets a sharing violation.
937
938                    This is a crude way of allowing both files to be
939                    open at once. It has a slight chance of inode
940                    number collision, but I can't see a better approach
941                    without significant VFS changes
942                 */
943                 TDB_DATA key = { .dptr = discard_const_p(uint8_t, fname),
944                                  .dsize = strlen(fname) };
945                 uint32_t shash;
946
947                 shash = tdb_jenkins_hash(&key) & 0xFF000000;
948                 if (shash == 0) {
949                         shash = 1;
950                 }
951                 sbuf->st_ex_ino ^= shash;
952         }
953 }
954
955 static DIR *shadow_copy2_opendir(vfs_handle_struct *handle,
956                         const struct smb_filename *smb_fname,
957                         const char *mask,
958                         uint32_t attr)
959 {
960         time_t timestamp = 0;
961         char *stripped = NULL;
962         DIR *ret;
963         int saved_errno;
964         char *conv;
965         struct smb_filename *conv_smb_fname = NULL;
966
967         if (!shadow_copy2_strip_snapshot(talloc_tos(),
968                                 handle,
969                                 smb_fname->base_name,
970                                 &timestamp,
971                                 &stripped)) {
972                 return NULL;
973         }
974         if (timestamp == 0) {
975                 return SMB_VFS_NEXT_OPENDIR(handle, smb_fname, mask, attr);
976         }
977         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
978         TALLOC_FREE(stripped);
979         if (conv == NULL) {
980                 return NULL;
981         }
982         conv_smb_fname = synthetic_smb_fname(talloc_tos(),
983                                         conv,
984                                         NULL,
985                                         NULL,
986                                         smb_fname->flags);
987         if (conv_smb_fname == NULL) {
988                 TALLOC_FREE(conv);
989                 return NULL;
990         }
991         ret = SMB_VFS_NEXT_OPENDIR(handle, conv_smb_fname, mask, attr);
992         saved_errno = errno;
993         TALLOC_FREE(conv);
994         TALLOC_FREE(conv_smb_fname);
995         errno = saved_errno;
996         return ret;
997 }
998
999 static int shadow_copy2_rename(vfs_handle_struct *handle,
1000                                const struct smb_filename *smb_fname_src,
1001                                const struct smb_filename *smb_fname_dst)
1002 {
1003         time_t timestamp_src = 0;
1004         time_t timestamp_dst = 0;
1005
1006         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
1007                                          smb_fname_src->base_name,
1008                                          &timestamp_src, NULL)) {
1009                 return -1;
1010         }
1011         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
1012                                          smb_fname_dst->base_name,
1013                                          &timestamp_dst, NULL)) {
1014                 return -1;
1015         }
1016         if (timestamp_src != 0) {
1017                 errno = EXDEV;
1018                 return -1;
1019         }
1020         if (timestamp_dst != 0) {
1021                 errno = EROFS;
1022                 return -1;
1023         }
1024         return SMB_VFS_NEXT_RENAME(handle, smb_fname_src, smb_fname_dst);
1025 }
1026
1027 static int shadow_copy2_symlink(vfs_handle_struct *handle,
1028                                 const char *oldname, const char *newname)
1029 {
1030         time_t timestamp_old = 0;
1031         time_t timestamp_new = 0;
1032
1033         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, oldname,
1034                                          &timestamp_old, NULL)) {
1035                 return -1;
1036         }
1037         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, newname,
1038                                          &timestamp_new, NULL)) {
1039                 return -1;
1040         }
1041         if ((timestamp_old != 0) || (timestamp_new != 0)) {
1042                 errno = EROFS;
1043                 return -1;
1044         }
1045         return SMB_VFS_NEXT_SYMLINK(handle, oldname, newname);
1046 }
1047
1048 static int shadow_copy2_link(vfs_handle_struct *handle,
1049                              const char *oldname, const char *newname)
1050 {
1051         time_t timestamp_old = 0;
1052         time_t timestamp_new = 0;
1053
1054         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, oldname,
1055                                          &timestamp_old, NULL)) {
1056                 return -1;
1057         }
1058         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, newname,
1059                                          &timestamp_new, NULL)) {
1060                 return -1;
1061         }
1062         if ((timestamp_old != 0) || (timestamp_new != 0)) {
1063                 errno = EROFS;
1064                 return -1;
1065         }
1066         return SMB_VFS_NEXT_LINK(handle, oldname, newname);
1067 }
1068
1069 static int shadow_copy2_stat(vfs_handle_struct *handle,
1070                              struct smb_filename *smb_fname)
1071 {
1072         time_t timestamp = 0;
1073         char *stripped = NULL;
1074         char *tmp;
1075         int ret, saved_errno;
1076
1077         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
1078                                          smb_fname->base_name,
1079                                          &timestamp, &stripped)) {
1080                 return -1;
1081         }
1082         if (timestamp == 0) {
1083                 return SMB_VFS_NEXT_STAT(handle, smb_fname);
1084         }
1085
1086         tmp = smb_fname->base_name;
1087         smb_fname->base_name = shadow_copy2_convert(
1088                 talloc_tos(), handle, stripped, timestamp);
1089         TALLOC_FREE(stripped);
1090
1091         if (smb_fname->base_name == NULL) {
1092                 smb_fname->base_name = tmp;
1093                 return -1;
1094         }
1095
1096         ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
1097         saved_errno = errno;
1098
1099         TALLOC_FREE(smb_fname->base_name);
1100         smb_fname->base_name = tmp;
1101
1102         if (ret == 0) {
1103                 convert_sbuf(handle, smb_fname->base_name, &smb_fname->st);
1104         }
1105         errno = saved_errno;
1106         return ret;
1107 }
1108
1109 static int shadow_copy2_lstat(vfs_handle_struct *handle,
1110                               struct smb_filename *smb_fname)
1111 {
1112         time_t timestamp = 0;
1113         char *stripped = NULL;
1114         char *tmp;
1115         int ret, saved_errno;
1116
1117         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
1118                                          smb_fname->base_name,
1119                                          &timestamp, &stripped)) {
1120                 return -1;
1121         }
1122         if (timestamp == 0) {
1123                 return SMB_VFS_NEXT_LSTAT(handle, smb_fname);
1124         }
1125
1126         tmp = smb_fname->base_name;
1127         smb_fname->base_name = shadow_copy2_convert(
1128                 talloc_tos(), handle, stripped, timestamp);
1129         TALLOC_FREE(stripped);
1130
1131         if (smb_fname->base_name == NULL) {
1132                 smb_fname->base_name = tmp;
1133                 return -1;
1134         }
1135
1136         ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
1137         saved_errno = errno;
1138
1139         TALLOC_FREE(smb_fname->base_name);
1140         smb_fname->base_name = tmp;
1141
1142         if (ret == 0) {
1143                 convert_sbuf(handle, smb_fname->base_name, &smb_fname->st);
1144         }
1145         errno = saved_errno;
1146         return ret;
1147 }
1148
1149 static int shadow_copy2_fstat(vfs_handle_struct *handle, files_struct *fsp,
1150                               SMB_STRUCT_STAT *sbuf)
1151 {
1152         time_t timestamp = 0;
1153         int ret;
1154
1155         ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
1156         if (ret == -1) {
1157                 return ret;
1158         }
1159         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
1160                                          fsp->fsp_name->base_name,
1161                                          &timestamp, NULL)) {
1162                 return 0;
1163         }
1164         if (timestamp != 0) {
1165                 convert_sbuf(handle, fsp->fsp_name->base_name, sbuf);
1166         }
1167         return 0;
1168 }
1169
1170 static int shadow_copy2_open(vfs_handle_struct *handle,
1171                              struct smb_filename *smb_fname, files_struct *fsp,
1172                              int flags, mode_t mode)
1173 {
1174         time_t timestamp = 0;
1175         char *stripped = NULL;
1176         char *tmp;
1177         int ret, saved_errno;
1178
1179         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
1180                                          smb_fname->base_name,
1181                                          &timestamp, &stripped)) {
1182                 return -1;
1183         }
1184         if (timestamp == 0) {
1185                 return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
1186         }
1187
1188         tmp = smb_fname->base_name;
1189         smb_fname->base_name = shadow_copy2_convert(
1190                 talloc_tos(), handle, stripped, timestamp);
1191         TALLOC_FREE(stripped);
1192
1193         if (smb_fname->base_name == NULL) {
1194                 smb_fname->base_name = tmp;
1195                 return -1;
1196         }
1197
1198         ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
1199         saved_errno = errno;
1200
1201         TALLOC_FREE(smb_fname->base_name);
1202         smb_fname->base_name = tmp;
1203
1204         errno = saved_errno;
1205         return ret;
1206 }
1207
1208 static int shadow_copy2_unlink(vfs_handle_struct *handle,
1209                                const struct smb_filename *smb_fname)
1210 {
1211         time_t timestamp = 0;
1212         char *stripped = NULL;
1213         int ret, saved_errno;
1214         struct smb_filename *conv;
1215
1216         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
1217                                          smb_fname->base_name,
1218                                          &timestamp, &stripped)) {
1219                 return -1;
1220         }
1221         if (timestamp == 0) {
1222                 return SMB_VFS_NEXT_UNLINK(handle, smb_fname);
1223         }
1224         conv = cp_smb_filename(talloc_tos(), smb_fname);
1225         if (conv == NULL) {
1226                 errno = ENOMEM;
1227                 return -1;
1228         }
1229         conv->base_name = shadow_copy2_convert(
1230                 conv, handle, stripped, timestamp);
1231         TALLOC_FREE(stripped);
1232         if (conv->base_name == NULL) {
1233                 return -1;
1234         }
1235         ret = SMB_VFS_NEXT_UNLINK(handle, conv);
1236         saved_errno = errno;
1237         TALLOC_FREE(conv);
1238         errno = saved_errno;
1239         return ret;
1240 }
1241
1242 static int shadow_copy2_chmod(vfs_handle_struct *handle,
1243                         const struct smb_filename *smb_fname,
1244                         mode_t mode)
1245 {
1246         time_t timestamp = 0;
1247         char *stripped = NULL;
1248         int ret, saved_errno;
1249         char *conv = NULL;
1250         struct smb_filename *conv_smb_fname;
1251
1252         if (!shadow_copy2_strip_snapshot(talloc_tos(),
1253                                 handle,
1254                                 smb_fname->base_name,
1255                                 &timestamp,
1256                                 &stripped)) {
1257                 return -1;
1258         }
1259         if (timestamp == 0) {
1260                 TALLOC_FREE(stripped);
1261                 return SMB_VFS_NEXT_CHMOD(handle, smb_fname, mode);
1262         }
1263         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1264         TALLOC_FREE(stripped);
1265         if (conv == NULL) {
1266                 return -1;
1267         }
1268         conv_smb_fname = synthetic_smb_fname(talloc_tos(),
1269                                         conv,
1270                                         NULL,
1271                                         NULL,
1272                                         smb_fname->flags);
1273         if (conv_smb_fname == NULL) {
1274                 TALLOC_FREE(conv);
1275                 errno = ENOMEM;
1276                 return -1;
1277         }
1278
1279         ret = SMB_VFS_NEXT_CHMOD(handle, conv_smb_fname, mode);
1280         saved_errno = errno;
1281         TALLOC_FREE(conv);
1282         TALLOC_FREE(conv_smb_fname);
1283         errno = saved_errno;
1284         return ret;
1285 }
1286
1287 static int shadow_copy2_chown(vfs_handle_struct *handle,
1288                         const struct smb_filename *smb_fname,
1289                         uid_t uid,
1290                         gid_t gid)
1291 {
1292         time_t timestamp = 0;
1293         char *stripped = NULL;
1294         int ret, saved_errno;
1295         char *conv = NULL;
1296         struct smb_filename *conv_smb_fname = NULL;
1297
1298         if (!shadow_copy2_strip_snapshot(talloc_tos(),
1299                                 handle,
1300                                 smb_fname->base_name,
1301                                 &timestamp,
1302                                 &stripped)) {
1303                 return -1;
1304         }
1305         if (timestamp == 0) {
1306                 return SMB_VFS_NEXT_CHOWN(handle, smb_fname, uid, gid);
1307         }
1308         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1309         TALLOC_FREE(stripped);
1310         if (conv == NULL) {
1311                 return -1;
1312         }
1313         conv_smb_fname = synthetic_smb_fname(talloc_tos(),
1314                                         conv,
1315                                         NULL,
1316                                         NULL,
1317                                         smb_fname->flags);
1318         if (conv_smb_fname == NULL) {
1319                 TALLOC_FREE(conv);
1320                 errno = ENOMEM;
1321                 return -1;
1322         }
1323         ret = SMB_VFS_NEXT_CHOWN(handle, conv_smb_fname, uid, gid);
1324         saved_errno = errno;
1325         TALLOC_FREE(conv);
1326         TALLOC_FREE(conv_smb_fname);
1327         errno = saved_errno;
1328         return ret;
1329 }
1330
1331 static void store_cwd_data(vfs_handle_struct *handle,
1332                                 const char *connectpath)
1333 {
1334         struct shadow_copy2_private *priv = NULL;
1335         char *cwd = NULL;
1336
1337         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
1338                                 return);
1339
1340         TALLOC_FREE(priv->shadow_cwd);
1341         cwd = SMB_VFS_NEXT_GETWD(handle);
1342         if (cwd == NULL) {
1343                 smb_panic("getwd failed\n");
1344         }
1345         DBG_DEBUG("shadow cwd = %s\n", cwd);
1346         priv->shadow_cwd = talloc_strdup(priv, cwd);
1347         SAFE_FREE(cwd);
1348         if (priv->shadow_cwd == NULL) {
1349                 smb_panic("talloc failed\n");
1350         }
1351         TALLOC_FREE(priv->shadow_connectpath);
1352         if (connectpath) {
1353                 DBG_DEBUG("shadow conectpath = %s\n", connectpath);
1354                 priv->shadow_connectpath = talloc_strdup(priv, connectpath);
1355                 if (priv->shadow_connectpath == NULL) {
1356                         smb_panic("talloc failed\n");
1357                 }
1358         }
1359 }
1360
1361 static int shadow_copy2_chdir(vfs_handle_struct *handle,
1362                               const char *fname)
1363 {
1364         time_t timestamp = 0;
1365         char *stripped = NULL;
1366         char *snappath = NULL;
1367         int ret = -1;
1368         int saved_errno = 0;
1369         char *conv = NULL;
1370         size_t rootpath_len = 0;
1371
1372         if (!shadow_copy2_strip_snapshot_internal(talloc_tos(), handle, fname,
1373                                         &timestamp, &stripped, &snappath)) {
1374                 return -1;
1375         }
1376         if (stripped != NULL) {
1377                 conv = shadow_copy2_do_convert(talloc_tos(),
1378                                                 handle,
1379                                                 stripped,
1380                                                 timestamp,
1381                                                 &rootpath_len);
1382                 TALLOC_FREE(stripped);
1383                 if (conv == NULL) {
1384                         return -1;
1385                 }
1386                 fname = conv;
1387         }
1388
1389         ret = SMB_VFS_NEXT_CHDIR(handle, fname);
1390         if (ret == -1) {
1391                 saved_errno = errno;
1392         }
1393
1394         if (ret == 0) {
1395                 if (conv != NULL && rootpath_len != 0) {
1396                         conv[rootpath_len] = '\0';
1397                 } else if (snappath != 0) {
1398                         TALLOC_FREE(conv);
1399                         conv = snappath;
1400                 }
1401                 store_cwd_data(handle, conv);
1402         }
1403
1404         TALLOC_FREE(stripped);
1405         TALLOC_FREE(conv);
1406
1407         if (saved_errno != 0) {
1408                 errno = saved_errno;
1409         }
1410         return ret;
1411 }
1412
1413 static int shadow_copy2_ntimes(vfs_handle_struct *handle,
1414                                const struct smb_filename *smb_fname,
1415                                struct smb_file_time *ft)
1416 {
1417         time_t timestamp = 0;
1418         char *stripped = NULL;
1419         int ret, saved_errno;
1420         struct smb_filename *conv;
1421
1422         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
1423                                          smb_fname->base_name,
1424                                          &timestamp, &stripped)) {
1425                 return -1;
1426         }
1427         if (timestamp == 0) {
1428                 return SMB_VFS_NEXT_NTIMES(handle, smb_fname, ft);
1429         }
1430         conv = cp_smb_filename(talloc_tos(), smb_fname);
1431         if (conv == NULL) {
1432                 errno = ENOMEM;
1433                 return -1;
1434         }
1435         conv->base_name = shadow_copy2_convert(
1436                 conv, handle, stripped, timestamp);
1437         TALLOC_FREE(stripped);
1438         if (conv->base_name == NULL) {
1439                 return -1;
1440         }
1441         ret = SMB_VFS_NEXT_NTIMES(handle, conv, ft);
1442         saved_errno = errno;
1443         TALLOC_FREE(conv);
1444         errno = saved_errno;
1445         return ret;
1446 }
1447
1448 static int shadow_copy2_readlink(vfs_handle_struct *handle,
1449                                  const char *fname, char *buf, size_t bufsiz)
1450 {
1451         time_t timestamp = 0;
1452         char *stripped = NULL;
1453         int ret, saved_errno;
1454         char *conv;
1455
1456         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
1457                                          &timestamp, &stripped)) {
1458                 return -1;
1459         }
1460         if (timestamp == 0) {
1461                 return SMB_VFS_NEXT_READLINK(handle, fname, buf, bufsiz);
1462         }
1463         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1464         TALLOC_FREE(stripped);
1465         if (conv == NULL) {
1466                 return -1;
1467         }
1468         ret = SMB_VFS_NEXT_READLINK(handle, conv, buf, bufsiz);
1469         saved_errno = errno;
1470         TALLOC_FREE(conv);
1471         errno = saved_errno;
1472         return ret;
1473 }
1474
1475 static int shadow_copy2_mknod(vfs_handle_struct *handle,
1476                               const char *fname, mode_t mode, SMB_DEV_T dev)
1477 {
1478         time_t timestamp = 0;
1479         char *stripped = NULL;
1480         int ret, saved_errno;
1481         char *conv;
1482
1483         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
1484                                          &timestamp, &stripped)) {
1485                 return -1;
1486         }
1487         if (timestamp == 0) {
1488                 return SMB_VFS_NEXT_MKNOD(handle, fname, mode, dev);
1489         }
1490         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1491         TALLOC_FREE(stripped);
1492         if (conv == NULL) {
1493                 return -1;
1494         }
1495         ret = SMB_VFS_NEXT_MKNOD(handle, conv, mode, dev);
1496         saved_errno = errno;
1497         TALLOC_FREE(conv);
1498         errno = saved_errno;
1499         return ret;
1500 }
1501
1502 static char *shadow_copy2_realpath(vfs_handle_struct *handle,
1503                                    const char *fname)
1504 {
1505         time_t timestamp = 0;
1506         char *stripped = NULL;
1507         char *tmp = NULL;
1508         char *result = NULL;
1509         int saved_errno;
1510
1511         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
1512                                          &timestamp, &stripped)) {
1513                 goto done;
1514         }
1515         if (timestamp == 0) {
1516                 return SMB_VFS_NEXT_REALPATH(handle, fname);
1517         }
1518
1519         tmp = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1520         if (tmp == NULL) {
1521                 goto done;
1522         }
1523
1524         result = SMB_VFS_NEXT_REALPATH(handle, tmp);
1525
1526 done:
1527         saved_errno = errno;
1528         TALLOC_FREE(tmp);
1529         TALLOC_FREE(stripped);
1530         errno = saved_errno;
1531         return result;
1532 }
1533
1534 /**
1535  * Check whether a given directory contains a
1536  * snapshot directory as direct subdirectory.
1537  * If yes, return the path of the snapshot-subdir,
1538  * otherwise return NULL.
1539  */
1540 static char *have_snapdir(struct vfs_handle_struct *handle,
1541                           const char *path)
1542 {
1543         struct smb_filename smb_fname;
1544         int ret;
1545         struct shadow_copy2_private *priv;
1546
1547         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
1548                                 return NULL);
1549
1550         ZERO_STRUCT(smb_fname);
1551         smb_fname.base_name = talloc_asprintf(talloc_tos(), "%s/%s",
1552                                               path, priv->config->snapdir);
1553         if (smb_fname.base_name == NULL) {
1554                 return NULL;
1555         }
1556
1557         ret = SMB_VFS_NEXT_STAT(handle, &smb_fname);
1558         if ((ret == 0) && (S_ISDIR(smb_fname.st.st_ex_mode))) {
1559                 return smb_fname.base_name;
1560         }
1561         TALLOC_FREE(smb_fname.base_name);
1562         return NULL;
1563 }
1564
1565 static bool check_access_snapdir(struct vfs_handle_struct *handle,
1566                                 const char *path)
1567 {
1568         struct smb_filename smb_fname;
1569         int ret;
1570         NTSTATUS status;
1571
1572         ZERO_STRUCT(smb_fname);
1573         smb_fname.base_name = talloc_asprintf(talloc_tos(),
1574                                                 "%s",
1575                                                 path);
1576         if (smb_fname.base_name == NULL) {
1577                 return false;
1578         }
1579
1580         ret = SMB_VFS_NEXT_STAT(handle, &smb_fname);
1581         if (ret != 0 || !S_ISDIR(smb_fname.st.st_ex_mode)) {
1582                 TALLOC_FREE(smb_fname.base_name);
1583                 return false;
1584         }
1585
1586         status = smbd_check_access_rights(handle->conn,
1587                                         &smb_fname,
1588                                         false,
1589                                         SEC_DIR_LIST);
1590         if (!NT_STATUS_IS_OK(status)) {
1591                 DEBUG(0,("user does not have list permission "
1592                         "on snapdir %s\n",
1593                         smb_fname.base_name));
1594                 TALLOC_FREE(smb_fname.base_name);
1595                 return false;
1596         }
1597         TALLOC_FREE(smb_fname.base_name);
1598         return true;
1599 }
1600
1601 /**
1602  * Find the snapshot directory (if any) for the given
1603  * filename (which is relative to the share).
1604  */
1605 static const char *shadow_copy2_find_snapdir(TALLOC_CTX *mem_ctx,
1606                                              struct vfs_handle_struct *handle,
1607                                              struct smb_filename *smb_fname)
1608 {
1609         char *path, *p;
1610         const char *snapdir;
1611         struct shadow_copy2_config *config;
1612         struct shadow_copy2_private *priv;
1613
1614         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
1615                                 return NULL);
1616
1617         config = priv->config;
1618
1619         /*
1620          * If the non-snapdisrseverywhere mode, we should not search!
1621          */
1622         if (!config->snapdirseverywhere) {
1623                 return config->snapshot_basepath;
1624         }
1625
1626         path = talloc_asprintf(mem_ctx, "%s/%s",
1627                                handle->conn->connectpath,
1628                                smb_fname->base_name);
1629         if (path == NULL) {
1630                 return NULL;
1631         }
1632
1633         snapdir = have_snapdir(handle, path);
1634         if (snapdir != NULL) {
1635                 TALLOC_FREE(path);
1636                 return snapdir;
1637         }
1638
1639         while ((p = strrchr(path, '/')) && (p > path)) {
1640
1641                 p[0] = '\0';
1642
1643                 snapdir = have_snapdir(handle, path);
1644                 if (snapdir != NULL) {
1645                         TALLOC_FREE(path);
1646                         return snapdir;
1647                 }
1648         }
1649         TALLOC_FREE(path);
1650         return NULL;
1651 }
1652
1653 static bool shadow_copy2_snapshot_to_gmt(vfs_handle_struct *handle,
1654                                          const char *name,
1655                                          char *gmt, size_t gmt_len)
1656 {
1657         struct tm timestamp;
1658         time_t timestamp_t;
1659         unsigned long int timestamp_long;
1660         const char *fmt;
1661         struct shadow_copy2_config *config;
1662         struct shadow_copy2_private *priv;
1663         char *tmpstr = NULL;
1664         char *tmp = NULL;
1665         bool converted = false;
1666         int ret = -1;
1667
1668         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
1669                                 return NULL);
1670
1671         config = priv->config;
1672
1673         fmt = config->gmt_format;
1674
1675         /*
1676          * If regex is provided, then we will have to parse the
1677          * filename which will contain both the prefix and the time format.
1678          * e.g. <prefix><delimiter><time_format>
1679          */
1680         if (priv->snaps->regex != NULL) {
1681                 tmpstr = talloc_strdup(talloc_tos(), name);
1682                 /* point "name" to the time format */
1683                 name = strstr(name, priv->config->delimiter);
1684                 if (name == NULL) {
1685                         goto done;
1686                 }
1687                 /* Extract the prefix */
1688                 tmp = strstr(tmpstr, priv->config->delimiter);
1689                 *tmp = '\0';
1690
1691                 /* Parse regex */
1692                 ret = regexec(priv->snaps->regex, tmpstr, 0, NULL, 0);
1693                 if (ret) {
1694                         DBG_DEBUG("shadow_copy2_snapshot_to_gmt: "
1695                                   "no regex match for %s\n", tmpstr);
1696                         goto done;
1697                 }
1698         }
1699
1700         ZERO_STRUCT(timestamp);
1701         if (config->use_sscanf) {
1702                 if (sscanf(name, fmt, &timestamp_long) != 1) {
1703                         DEBUG(10, ("shadow_copy2_snapshot_to_gmt: "
1704                                    "no sscanf match %s: %s\n",
1705                                    fmt, name));
1706                         goto done;
1707                 }
1708                 timestamp_t = timestamp_long;
1709                 gmtime_r(&timestamp_t, &timestamp);
1710         } else {
1711                 if (strptime(name, fmt, &timestamp) == NULL) {
1712                         DEBUG(10, ("shadow_copy2_snapshot_to_gmt: "
1713                                    "no match %s: %s\n",
1714                                    fmt, name));
1715                         goto done;
1716                 }
1717                 DEBUG(10, ("shadow_copy2_snapshot_to_gmt: match %s: %s\n",
1718                            fmt, name));
1719                 
1720                 if (config->use_localtime) {
1721                         timestamp.tm_isdst = -1;
1722                         timestamp_t = mktime(&timestamp);
1723                         gmtime_r(&timestamp_t, &timestamp);
1724                 }
1725         }
1726
1727         strftime(gmt, gmt_len, GMT_FORMAT, &timestamp);
1728         converted = true;
1729
1730 done:
1731         TALLOC_FREE(tmpstr);
1732         return converted;
1733 }
1734
1735 static int shadow_copy2_label_cmp_asc(const void *x, const void *y)
1736 {
1737         return strncmp((const char *)x, (const char *)y, sizeof(SHADOW_COPY_LABEL));
1738 }
1739
1740 static int shadow_copy2_label_cmp_desc(const void *x, const void *y)
1741 {
1742         return -strncmp((const char *)x, (const char *)y, sizeof(SHADOW_COPY_LABEL));
1743 }
1744
1745 /*
1746   sort the shadow copy data in ascending or descending order
1747  */
1748 static void shadow_copy2_sort_data(vfs_handle_struct *handle,
1749                                    struct shadow_copy_data *shadow_copy2_data)
1750 {
1751         int (*cmpfunc)(const void *, const void *);
1752         const char *sort;
1753         struct shadow_copy2_private *priv;
1754
1755         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
1756                                 return);
1757
1758         sort = priv->config->sort_order;
1759         if (sort == NULL) {
1760                 return;
1761         }
1762
1763         if (strcmp(sort, "asc") == 0) {
1764                 cmpfunc = shadow_copy2_label_cmp_asc;
1765         } else if (strcmp(sort, "desc") == 0) {
1766                 cmpfunc = shadow_copy2_label_cmp_desc;
1767         } else {
1768                 return;
1769         }
1770
1771         if (shadow_copy2_data && shadow_copy2_data->num_volumes > 0 &&
1772             shadow_copy2_data->labels)
1773         {
1774                 TYPESAFE_QSORT(shadow_copy2_data->labels,
1775                                shadow_copy2_data->num_volumes,
1776                                cmpfunc);
1777         }
1778 }
1779
1780 static int shadow_copy2_get_shadow_copy_data(
1781         vfs_handle_struct *handle, files_struct *fsp,
1782         struct shadow_copy_data *shadow_copy2_data,
1783         bool labels)
1784 {
1785         DIR *p;
1786         const char *snapdir;
1787         struct smb_filename *snapdir_smb_fname = NULL;
1788         struct dirent *d;
1789         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1790         struct shadow_copy2_private *priv = NULL;
1791         struct shadow_copy2_snapentry *tmpentry = NULL;
1792         bool get_snaplist = false;
1793         bool access_granted = false;
1794         int ret = -1;
1795
1796         snapdir = shadow_copy2_find_snapdir(tmp_ctx, handle, fsp->fsp_name);
1797         if (snapdir == NULL) {
1798                 DEBUG(0,("shadow:snapdir not found for %s in get_shadow_copy_data\n",
1799                          handle->conn->connectpath));
1800                 errno = EINVAL;
1801                 goto done;
1802         }
1803
1804         access_granted = check_access_snapdir(handle, snapdir);
1805         if (!access_granted) {
1806                 DEBUG(0,("access denied on listing snapdir %s\n", snapdir));
1807                 errno = EACCES;
1808                 goto done;
1809         }
1810
1811         snapdir_smb_fname = synthetic_smb_fname(talloc_tos(),
1812                                         snapdir,
1813                                         NULL,
1814                                         NULL,
1815                                         fsp->fsp_name->flags);
1816         if (snapdir_smb_fname == NULL) {
1817                 errno = ENOMEM;
1818                 goto done;
1819         }
1820
1821         p = SMB_VFS_NEXT_OPENDIR(handle, snapdir_smb_fname, NULL, 0);
1822
1823         if (!p) {
1824                 DEBUG(2,("shadow_copy2: SMB_VFS_NEXT_OPENDIR() failed for '%s'"
1825                          " - %s\n", snapdir, strerror(errno)));
1826                 errno = ENOSYS;
1827                 goto done;
1828         }
1829
1830         if (shadow_copy2_data != NULL) {
1831                 shadow_copy2_data->num_volumes = 0;
1832                 shadow_copy2_data->labels      = NULL;
1833         }
1834
1835         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
1836                                 goto done);
1837
1838         /*
1839          * Normally this function is called twice once with labels = false and
1840          * then with labels = true. When labels is false it will return the
1841          * number of volumes so that the caller can allocate memory for that
1842          * many labels. Therefore to eliminate snaplist both the times it is
1843          * good to check if labels is set or not.
1844          *
1845          * shadow_copy2_data is NULL when we only want to update the list and
1846          * don't want any labels.
1847          */
1848         if ((priv->snaps->regex != NULL) && (labels || shadow_copy2_data == NULL)) {
1849                 get_snaplist = true;
1850                 /* Reset the global snaplist */
1851                 shadow_copy2_delete_snaplist(priv);
1852
1853                 /* Set the current time as snaplist update time */
1854                 time(&(priv->snaps->fetch_time));
1855         }
1856
1857         while ((d = SMB_VFS_NEXT_READDIR(handle, p, NULL))) {
1858                 char snapshot[GMT_NAME_LEN+1];
1859                 SHADOW_COPY_LABEL *tlabels;
1860
1861                 /*
1862                  * ignore names not of the right form in the snapshot
1863                  * directory
1864                  */
1865                 if (!shadow_copy2_snapshot_to_gmt(
1866                             handle, d->d_name,
1867                             snapshot, sizeof(snapshot))) {
1868
1869                         DEBUG(6, ("shadow_copy2_get_shadow_copy_data: "
1870                                   "ignoring %s\n", d->d_name));
1871                         continue;
1872                 }
1873                 DEBUG(6,("shadow_copy2_get_shadow_copy_data: %s -> %s\n",
1874                          d->d_name, snapshot));
1875
1876                 if (get_snaplist) {
1877                         /*
1878                          * Create a snap entry for each successful
1879                          * pattern match.
1880                          */
1881                         tmpentry = shadow_copy2_create_snapentry(priv);
1882                         if (tmpentry == NULL) {
1883                                 DBG_ERR("talloc_zero() failed\n");
1884                                 goto done;
1885                         }
1886                         tmpentry->snapname = talloc_strdup(tmpentry, d->d_name);
1887                         tmpentry->time_fmt = talloc_strdup(tmpentry, snapshot);
1888                 }
1889
1890                 if (shadow_copy2_data == NULL) {
1891                         continue;
1892                 }
1893
1894                 if (!labels) {
1895                         /* the caller doesn't want the labels */
1896                         shadow_copy2_data->num_volumes++;
1897                         continue;
1898                 }
1899
1900                 tlabels = talloc_realloc(shadow_copy2_data,
1901                                          shadow_copy2_data->labels,
1902                                          SHADOW_COPY_LABEL,
1903                                          shadow_copy2_data->num_volumes+1);
1904                 if (tlabels == NULL) {
1905                         DEBUG(0,("shadow_copy2: out of memory\n"));
1906                         SMB_VFS_NEXT_CLOSEDIR(handle, p);
1907                         goto done;
1908                 }
1909
1910                 strlcpy(tlabels[shadow_copy2_data->num_volumes], snapshot,
1911                         sizeof(*tlabels));
1912
1913                 shadow_copy2_data->num_volumes++;
1914                 shadow_copy2_data->labels = tlabels;
1915         }
1916
1917         SMB_VFS_NEXT_CLOSEDIR(handle,p);
1918
1919         shadow_copy2_sort_data(handle, shadow_copy2_data);
1920         ret = 0;
1921
1922 done:
1923         TALLOC_FREE(tmp_ctx);
1924         return ret;
1925 }
1926
1927 static NTSTATUS shadow_copy2_fget_nt_acl(vfs_handle_struct *handle,
1928                                         struct files_struct *fsp,
1929                                         uint32_t security_info,
1930                                          TALLOC_CTX *mem_ctx,
1931                                         struct security_descriptor **ppdesc)
1932 {
1933         time_t timestamp = 0;
1934         char *stripped = NULL;
1935         NTSTATUS status;
1936         char *conv;
1937         struct smb_filename *smb_fname = NULL;
1938
1939         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
1940                                          fsp->fsp_name->base_name,
1941                                          &timestamp, &stripped)) {
1942                 return map_nt_error_from_unix(errno);
1943         }
1944         if (timestamp == 0) {
1945                 return SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info,
1946                                                 mem_ctx,
1947                                                 ppdesc);
1948         }
1949         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1950         TALLOC_FREE(stripped);
1951         if (conv == NULL) {
1952                 return map_nt_error_from_unix(errno);
1953         }
1954         smb_fname = synthetic_smb_fname(talloc_tos(),
1955                                         conv,
1956                                         NULL,
1957                                         NULL,
1958                                         fsp->fsp_name->flags);
1959         if (smb_fname == NULL) {
1960                 TALLOC_FREE(conv);
1961                 return NT_STATUS_NO_MEMORY;
1962         }
1963
1964         status = SMB_VFS_NEXT_GET_NT_ACL(handle, smb_fname, security_info,
1965                                          mem_ctx, ppdesc);
1966         TALLOC_FREE(conv);
1967         TALLOC_FREE(smb_fname);
1968         return status;
1969 }
1970
1971 static NTSTATUS shadow_copy2_get_nt_acl(vfs_handle_struct *handle,
1972                                         const struct smb_filename *smb_fname,
1973                                         uint32_t security_info,
1974                                         TALLOC_CTX *mem_ctx,
1975                                         struct security_descriptor **ppdesc)
1976 {
1977         time_t timestamp = 0;
1978         char *stripped = NULL;
1979         NTSTATUS status;
1980         char *conv;
1981         struct smb_filename *conv_smb_fname = NULL;
1982
1983         if (!shadow_copy2_strip_snapshot(talloc_tos(),
1984                                         handle,
1985                                         smb_fname->base_name,
1986                                         &timestamp,
1987                                         &stripped)) {
1988                 return map_nt_error_from_unix(errno);
1989         }
1990         if (timestamp == 0) {
1991                 return SMB_VFS_NEXT_GET_NT_ACL(handle, smb_fname, security_info,
1992                                                mem_ctx, ppdesc);
1993         }
1994         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1995         TALLOC_FREE(stripped);
1996         if (conv == NULL) {
1997                 return map_nt_error_from_unix(errno);
1998         }
1999         conv_smb_fname = synthetic_smb_fname(talloc_tos(),
2000                                         conv,
2001                                         NULL,
2002                                         NULL,
2003                                         smb_fname->flags);
2004         if (conv_smb_fname == NULL) {
2005                 TALLOC_FREE(conv);
2006                 return NT_STATUS_NO_MEMORY;
2007         }
2008         status = SMB_VFS_NEXT_GET_NT_ACL(handle, conv_smb_fname, security_info,
2009                                          mem_ctx, ppdesc);
2010         TALLOC_FREE(conv);
2011         TALLOC_FREE(conv_smb_fname);
2012         return status;
2013 }
2014
2015 static int shadow_copy2_mkdir(vfs_handle_struct *handle,
2016                                 const struct smb_filename *smb_fname,
2017                                 mode_t mode)
2018 {
2019         time_t timestamp = 0;
2020         char *stripped = NULL;
2021         int ret, saved_errno;
2022         char *conv;
2023         struct smb_filename *conv_smb_fname = NULL;
2024
2025         if (!shadow_copy2_strip_snapshot(talloc_tos(),
2026                                         handle,
2027                                         smb_fname->base_name,
2028                                         &timestamp,
2029                                         &stripped)) {
2030                 return -1;
2031         }
2032         if (timestamp == 0) {
2033                 return SMB_VFS_NEXT_MKDIR(handle, smb_fname, mode);
2034         }
2035         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2036         TALLOC_FREE(stripped);
2037         if (conv == NULL) {
2038                 return -1;
2039         }
2040         conv_smb_fname = synthetic_smb_fname(talloc_tos(),
2041                                         conv,
2042                                         NULL,
2043                                         NULL,
2044                                         smb_fname->flags);
2045         if (conv_smb_fname == NULL) {
2046                 TALLOC_FREE(conv);
2047                 return -1;
2048         }
2049         ret = SMB_VFS_NEXT_MKDIR(handle, conv_smb_fname, mode);
2050         saved_errno = errno;
2051         TALLOC_FREE(conv);
2052         TALLOC_FREE(conv_smb_fname);
2053         errno = saved_errno;
2054         return ret;
2055 }
2056
2057 static int shadow_copy2_rmdir(vfs_handle_struct *handle,
2058                                 const struct smb_filename *smb_fname)
2059 {
2060         time_t timestamp = 0;
2061         char *stripped = NULL;
2062         int ret, saved_errno;
2063         char *conv;
2064         struct smb_filename *conv_smb_fname = NULL;
2065
2066         if (!shadow_copy2_strip_snapshot(talloc_tos(),
2067                                         handle,
2068                                         smb_fname->base_name,
2069                                         &timestamp,
2070                                         &stripped)) {
2071                 return -1;
2072         }
2073         if (timestamp == 0) {
2074                 return SMB_VFS_NEXT_RMDIR(handle, smb_fname);
2075         }
2076         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2077         TALLOC_FREE(stripped);
2078         if (conv == NULL) {
2079                 return -1;
2080         }
2081         conv_smb_fname = synthetic_smb_fname(talloc_tos(),
2082                                         conv,
2083                                         NULL,
2084                                         NULL,
2085                                         smb_fname->flags);
2086         if (conv_smb_fname == NULL) {
2087                 TALLOC_FREE(conv);
2088                 return -1;
2089         }
2090         ret = SMB_VFS_NEXT_RMDIR(handle, conv_smb_fname);
2091         saved_errno = errno;
2092         TALLOC_FREE(conv_smb_fname);
2093         TALLOC_FREE(conv);
2094         errno = saved_errno;
2095         return ret;
2096 }
2097
2098 static int shadow_copy2_chflags(vfs_handle_struct *handle, const char *fname,
2099                                 unsigned int flags)
2100 {
2101         time_t timestamp = 0;
2102         char *stripped = NULL;
2103         int ret, saved_errno;
2104         char *conv;
2105
2106         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
2107                                          &timestamp, &stripped)) {
2108                 return -1;
2109         }
2110         if (timestamp == 0) {
2111                 return SMB_VFS_NEXT_CHFLAGS(handle, fname, flags);
2112         }
2113         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2114         TALLOC_FREE(stripped);
2115         if (conv == NULL) {
2116                 return -1;
2117         }
2118         ret = SMB_VFS_NEXT_CHFLAGS(handle, conv, flags);
2119         saved_errno = errno;
2120         TALLOC_FREE(conv);
2121         errno = saved_errno;
2122         return ret;
2123 }
2124
2125 static ssize_t shadow_copy2_getxattr(vfs_handle_struct *handle,
2126                                      const char *fname, const char *aname,
2127                                      void *value, size_t size)
2128 {
2129         time_t timestamp = 0;
2130         char *stripped = NULL;
2131         ssize_t ret;
2132         int saved_errno;
2133         char *conv;
2134
2135         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
2136                                          &timestamp, &stripped)) {
2137                 return -1;
2138         }
2139         if (timestamp == 0) {
2140                 return SMB_VFS_NEXT_GETXATTR(handle, fname, aname, value,
2141                                              size);
2142         }
2143         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2144         TALLOC_FREE(stripped);
2145         if (conv == NULL) {
2146                 return -1;
2147         }
2148         ret = SMB_VFS_NEXT_GETXATTR(handle, conv, aname, value, size);
2149         saved_errno = errno;
2150         TALLOC_FREE(conv);
2151         errno = saved_errno;
2152         return ret;
2153 }
2154
2155 static ssize_t shadow_copy2_listxattr(struct vfs_handle_struct *handle,
2156                                       const char *fname,
2157                                       char *list, size_t size)
2158 {
2159         time_t timestamp = 0;
2160         char *stripped = NULL;
2161         ssize_t ret;
2162         int saved_errno;
2163         char *conv;
2164
2165         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
2166                                          &timestamp, &stripped)) {
2167                 return -1;
2168         }
2169         if (timestamp == 0) {
2170                 return SMB_VFS_NEXT_LISTXATTR(handle, fname, list, size);
2171         }
2172         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2173         TALLOC_FREE(stripped);
2174         if (conv == NULL) {
2175                 return -1;
2176         }
2177         ret = SMB_VFS_NEXT_LISTXATTR(handle, conv, list, size);
2178         saved_errno = errno;
2179         TALLOC_FREE(conv);
2180         errno = saved_errno;
2181         return ret;
2182 }
2183
2184 static int shadow_copy2_removexattr(vfs_handle_struct *handle,
2185                                     const char *fname, const char *aname)
2186 {
2187         time_t timestamp = 0;
2188         char *stripped = NULL;
2189         int ret, saved_errno;
2190         char *conv;
2191
2192         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
2193                                          &timestamp, &stripped)) {
2194                 return -1;
2195         }
2196         if (timestamp == 0) {
2197                 return SMB_VFS_NEXT_REMOVEXATTR(handle, fname, aname);
2198         }
2199         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2200         TALLOC_FREE(stripped);
2201         if (conv == NULL) {
2202                 return -1;
2203         }
2204         ret = SMB_VFS_NEXT_REMOVEXATTR(handle, conv, aname);
2205         saved_errno = errno;
2206         TALLOC_FREE(conv);
2207         errno = saved_errno;
2208         return ret;
2209 }
2210
2211 static int shadow_copy2_setxattr(struct vfs_handle_struct *handle,
2212                                  const char *fname,
2213                                  const char *aname, const void *value,
2214                                  size_t size, int flags)
2215 {
2216         time_t timestamp = 0;
2217         char *stripped = NULL;
2218         ssize_t ret;
2219         int saved_errno;
2220         char *conv;
2221
2222         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
2223                                          &timestamp, &stripped)) {
2224                 return -1;
2225         }
2226         if (timestamp == 0) {
2227                 return SMB_VFS_NEXT_SETXATTR(handle, fname, aname, value, size,
2228                                              flags);
2229         }
2230         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2231         TALLOC_FREE(stripped);
2232         if (conv == NULL) {
2233                 return -1;
2234         }
2235         ret = SMB_VFS_NEXT_SETXATTR(handle, conv, aname, value, size, flags);
2236         saved_errno = errno;
2237         TALLOC_FREE(conv);
2238         errno = saved_errno;
2239         return ret;
2240 }
2241
2242 static int shadow_copy2_chmod_acl(vfs_handle_struct *handle,
2243                         const struct smb_filename *smb_fname,
2244                         mode_t mode)
2245 {
2246         time_t timestamp = 0;
2247         char *stripped = NULL;
2248         ssize_t ret;
2249         int saved_errno;
2250         char *conv = NULL;
2251         struct smb_filename *conv_smb_fname = NULL;
2252
2253         if (!shadow_copy2_strip_snapshot(talloc_tos(),
2254                                 handle,
2255                                 smb_fname->base_name,
2256                                 &timestamp,
2257                                 &stripped)) {
2258                 return -1;
2259         }
2260         if (timestamp == 0) {
2261                 return SMB_VFS_NEXT_CHMOD_ACL(handle, smb_fname, mode);
2262         }
2263         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2264         TALLOC_FREE(stripped);
2265         if (conv == NULL) {
2266                 return -1;
2267         }
2268         conv_smb_fname = synthetic_smb_fname(talloc_tos(),
2269                                         conv,
2270                                         NULL,
2271                                         NULL,
2272                                         smb_fname->flags);
2273         if (conv_smb_fname == NULL) {
2274                 TALLOC_FREE(conv);
2275                 errno = ENOMEM;
2276                 return -1;
2277         }
2278         ret = SMB_VFS_NEXT_CHMOD_ACL(handle, conv_smb_fname, mode);
2279         saved_errno = errno;
2280         TALLOC_FREE(conv);
2281         TALLOC_FREE(conv_smb_fname);
2282         errno = saved_errno;
2283         return ret;
2284 }
2285
2286 static int shadow_copy2_get_real_filename(struct vfs_handle_struct *handle,
2287                                           const char *path,
2288                                           const char *name,
2289                                           TALLOC_CTX *mem_ctx,
2290                                           char **found_name)
2291 {
2292         time_t timestamp = 0;
2293         char *stripped = NULL;
2294         ssize_t ret;
2295         int saved_errno;
2296         char *conv;
2297
2298         DEBUG(10, ("shadow_copy2_get_real_filename called for path=[%s], "
2299                    "name=[%s]\n", path, name));
2300
2301         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, path,
2302                                          &timestamp, &stripped)) {
2303                 DEBUG(10, ("shadow_copy2_strip_snapshot failed\n"));
2304                 return -1;
2305         }
2306         if (timestamp == 0) {
2307                 DEBUG(10, ("timestamp == 0\n"));
2308                 return SMB_VFS_NEXT_GET_REAL_FILENAME(handle, path, name,
2309                                                       mem_ctx, found_name);
2310         }
2311         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2312         TALLOC_FREE(stripped);
2313         if (conv == NULL) {
2314                 DEBUG(10, ("shadow_copy2_convert failed\n"));
2315                 return -1;
2316         }
2317         DEBUG(10, ("Calling NEXT_GET_REAL_FILE_NAME for conv=[%s], "
2318                    "name=[%s]\n", conv, name));
2319         ret = SMB_VFS_NEXT_GET_REAL_FILENAME(handle, conv, name,
2320                                              mem_ctx, found_name);
2321         DEBUG(10, ("NEXT_REAL_FILE_NAME returned %d\n", (int)ret));
2322         saved_errno = errno;
2323         TALLOC_FREE(conv);
2324         errno = saved_errno;
2325         return ret;
2326 }
2327
2328 static const char *shadow_copy2_connectpath(struct vfs_handle_struct *handle,
2329                                             const char *fname)
2330 {
2331         time_t timestamp = 0;
2332         char *stripped = NULL;
2333         char *tmp = NULL;
2334         char *result = NULL;
2335         char *parent_dir = NULL;
2336         int saved_errno;
2337         size_t rootpath_len = 0;
2338
2339         DBG_DEBUG("Calc connect path for [%s]\n", fname);
2340
2341         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
2342                                          &timestamp, &stripped)) {
2343                 goto done;
2344         }
2345         if (timestamp == 0) {
2346                 return SMB_VFS_NEXT_CONNECTPATH(handle, fname);
2347         }
2348
2349         tmp = shadow_copy2_do_convert(talloc_tos(), handle, stripped, timestamp,
2350                                       &rootpath_len);
2351         if (tmp == NULL) {
2352                 if (errno != ENOENT) {
2353                         goto done;
2354                 }
2355
2356                 /*
2357                  * If the converted path does not exist, and converting
2358                  * the parent yields something that does exist, then
2359                  * this path refers to something that has not been
2360                  * created yet, relative to the parent path.
2361                  * The snapshot finding is relative to the parent.
2362                  * (usually snapshots are read/only but this is not
2363                  * necessarily true).
2364                  * This code also covers getting a wildcard in the
2365                  * last component, because this function is called
2366                  * prior to sanitizing the path, and in SMB1 we may
2367                  * get wildcards in path names.
2368                  */
2369                 if (!parent_dirname(talloc_tos(), stripped, &parent_dir,
2370                                     NULL)) {
2371                         errno = ENOMEM;
2372                         goto done;
2373                 }
2374
2375                 tmp = shadow_copy2_do_convert(talloc_tos(), handle, parent_dir,
2376                                               timestamp, &rootpath_len);
2377                 if (tmp == NULL) {
2378                         goto done;
2379                 }
2380         }
2381
2382         DBG_DEBUG("converted path is [%s] root path is [%.*s]\n", tmp,
2383                   (int)rootpath_len, tmp);
2384
2385         tmp[rootpath_len] = '\0';
2386         result = SMB_VFS_NEXT_REALPATH(handle, tmp);
2387         if (result == NULL) {
2388                 goto done;
2389         }
2390
2391         DBG_DEBUG("connect path is [%s]\n", result);
2392
2393 done:
2394         saved_errno = errno;
2395         TALLOC_FREE(tmp);
2396         TALLOC_FREE(stripped);
2397         TALLOC_FREE(parent_dir);
2398         errno = saved_errno;
2399         return result;
2400 }
2401
2402 static uint64_t shadow_copy2_disk_free(vfs_handle_struct *handle,
2403                                        const char *path, uint64_t *bsize,
2404                                        uint64_t *dfree, uint64_t *dsize)
2405 {
2406         time_t timestamp = 0;
2407         char *stripped = NULL;
2408         ssize_t ret;
2409         int saved_errno;
2410         char *conv;
2411
2412         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, path,
2413                                          &timestamp, &stripped)) {
2414                 return -1;
2415         }
2416         if (timestamp == 0) {
2417                 return SMB_VFS_NEXT_DISK_FREE(handle, path,
2418                                               bsize, dfree, dsize);
2419         }
2420
2421         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2422         TALLOC_FREE(stripped);
2423         if (conv == NULL) {
2424                 return -1;
2425         }
2426
2427         ret = SMB_VFS_NEXT_DISK_FREE(handle, conv, bsize, dfree, dsize);
2428
2429         saved_errno = errno;
2430         TALLOC_FREE(conv);
2431         errno = saved_errno;
2432
2433         return ret;
2434 }
2435
2436 static int shadow_copy2_get_quota(vfs_handle_struct *handle, const char *path,
2437                                   enum SMB_QUOTA_TYPE qtype, unid_t id,
2438                                   SMB_DISK_QUOTA *dq)
2439 {
2440         time_t timestamp = 0;
2441         char *stripped = NULL;
2442         int ret;
2443         int saved_errno;
2444         char *conv;
2445
2446         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, path, &timestamp,
2447                                          &stripped)) {
2448                 return -1;
2449         }
2450         if (timestamp == 0) {
2451                 return SMB_VFS_NEXT_GET_QUOTA(handle, path, qtype, id, dq);
2452         }
2453
2454         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2455         TALLOC_FREE(stripped);
2456         if (conv == NULL) {
2457                 return -1;
2458         }
2459
2460         ret = SMB_VFS_NEXT_GET_QUOTA(handle, conv, qtype, id, dq);
2461
2462         saved_errno = errno;
2463         TALLOC_FREE(conv);
2464         errno = saved_errno;
2465
2466         return ret;
2467 }
2468
2469 static int shadow_copy2_connect(struct vfs_handle_struct *handle,
2470                                 const char *service, const char *user)
2471 {
2472         struct shadow_copy2_config *config;
2473         struct shadow_copy2_private *priv;
2474         int ret;
2475         const char *snapdir;
2476         const char *snapprefix = NULL;
2477         const char *delimiter;
2478         const char *gmt_format;
2479         const char *sort_order;
2480         const char *basedir = NULL;
2481         const char *snapsharepath = NULL;
2482         const char *mount_point;
2483
2484         DEBUG(10, (__location__ ": cnum[%u], connectpath[%s]\n",
2485                    (unsigned)handle->conn->cnum,
2486                    handle->conn->connectpath));
2487
2488         ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
2489         if (ret < 0) {
2490                 return ret;
2491         }
2492
2493         priv = talloc_zero(handle->conn, struct shadow_copy2_private);
2494         if (priv == NULL) {
2495                 DBG_ERR("talloc_zero() failed\n");
2496                 errno = ENOMEM;
2497                 return -1;
2498         }
2499
2500         priv->snaps = talloc_zero(priv, struct shadow_copy2_snaplist_info);
2501         if (priv->snaps == NULL) {
2502                 DBG_ERR("talloc_zero() failed\n");
2503                 errno = ENOMEM;
2504                 return -1;
2505         }
2506
2507         config = talloc_zero(priv, struct shadow_copy2_config);
2508         if (config == NULL) {
2509                 DEBUG(0, ("talloc_zero() failed\n"));
2510                 errno = ENOMEM;
2511                 return -1;
2512         }
2513
2514         priv->config = config;
2515
2516         gmt_format = lp_parm_const_string(SNUM(handle->conn),
2517                                           "shadow", "format",
2518                                           GMT_FORMAT);
2519         config->gmt_format = talloc_strdup(config, gmt_format);
2520         if (config->gmt_format == NULL) {
2521                 DEBUG(0, ("talloc_strdup() failed\n"));
2522                 errno = ENOMEM;
2523                 return -1;
2524         }
2525
2526         config->use_sscanf = lp_parm_bool(SNUM(handle->conn),
2527                                           "shadow", "sscanf", false);
2528
2529         config->use_localtime = lp_parm_bool(SNUM(handle->conn),
2530                                              "shadow", "localtime",
2531                                              false);
2532
2533         snapdir = lp_parm_const_string(SNUM(handle->conn),
2534                                        "shadow", "snapdir",
2535                                        ".snapshots");
2536         config->snapdir = talloc_strdup(config, snapdir);
2537         if (config->snapdir == NULL) {
2538                 DEBUG(0, ("talloc_strdup() failed\n"));
2539                 errno = ENOMEM;
2540                 return -1;
2541         }
2542
2543         snapprefix = lp_parm_const_string(SNUM(handle->conn),
2544                                        "shadow", "snapprefix",
2545                                        NULL);
2546         if (snapprefix != NULL) {
2547                 priv->snaps->regex = talloc_zero(priv->snaps, regex_t);
2548                 if (priv->snaps->regex == NULL) {
2549                         DBG_ERR("talloc_zero() failed\n");
2550                         errno = ENOMEM;
2551                         return -1;
2552                 }
2553
2554                 /* pre-compute regex rule for matching pattern later */
2555                 ret = regcomp(priv->snaps->regex, snapprefix, 0);
2556                 if (ret) {
2557                         DBG_ERR("Failed to create regex object\n");
2558                         return -1;
2559                 }
2560         }
2561
2562         delimiter = lp_parm_const_string(SNUM(handle->conn),
2563                                        "shadow", "delimiter",
2564                                        "_GMT");
2565         if (delimiter != NULL) {
2566                 priv->config->delimiter = talloc_strdup(priv->config, delimiter);
2567                 if (priv->config->delimiter == NULL) {
2568                         DBG_ERR("talloc_strdup() failed\n");
2569                         errno = ENOMEM;
2570                         return -1;
2571                 }
2572         }
2573
2574         config->snapdirseverywhere = lp_parm_bool(SNUM(handle->conn),
2575                                                   "shadow",
2576                                                   "snapdirseverywhere",
2577                                                   false);
2578
2579         config->crossmountpoints = lp_parm_bool(SNUM(handle->conn),
2580                                                 "shadow", "crossmountpoints",
2581                                                 false);
2582
2583         if (config->crossmountpoints && !config->snapdirseverywhere) {
2584                 DBG_WARNING("Warning: 'crossmountpoints' depends on "
2585                             "'snapdirseverywhere'. Disabling crossmountpoints.\n");
2586         }
2587
2588         config->fixinodes = lp_parm_bool(SNUM(handle->conn),
2589                                          "shadow", "fixinodes",
2590                                          false);
2591
2592         sort_order = lp_parm_const_string(SNUM(handle->conn),
2593                                           "shadow", "sort", "desc");
2594         config->sort_order = talloc_strdup(config, sort_order);
2595         if (config->sort_order == NULL) {
2596                 DEBUG(0, ("talloc_strdup() failed\n"));
2597                 errno = ENOMEM;
2598                 return -1;
2599         }
2600
2601         mount_point = lp_parm_const_string(SNUM(handle->conn),
2602                                            "shadow", "mountpoint", NULL);
2603         if (mount_point != NULL) {
2604                 if (mount_point[0] != '/') {
2605                         DEBUG(1, (__location__ " Warning: 'mountpoint' is "
2606                                   "relative ('%s'), but it has to be an "
2607                                   "absolute path. Ignoring provided value.\n",
2608                                   mount_point));
2609                         mount_point = NULL;
2610                 } else {
2611                         char *p;
2612                         p = strstr(handle->conn->connectpath, mount_point);
2613                         if (p != handle->conn->connectpath) {
2614                                 DBG_WARNING("Warning: the share root (%s) is "
2615                                             "not a subdirectory of the "
2616                                             "specified mountpoint (%s). "
2617                                             "Ignoring provided value.\n",
2618                                             handle->conn->connectpath,
2619                                             mount_point);
2620                                 mount_point = NULL;
2621                         }
2622                 }
2623         }
2624
2625         if (mount_point != NULL) {
2626                 config->mount_point = talloc_strdup(config, mount_point);
2627                 if (config->mount_point == NULL) {
2628                         DEBUG(0, (__location__ " talloc_strdup() failed\n"));
2629                         return -1;
2630                 }
2631         } else {
2632                 config->mount_point = shadow_copy2_find_mount_point(config,
2633                                                                     handle);
2634                 if (config->mount_point == NULL) {
2635                         DBG_WARNING("shadow_copy2_find_mount_point "
2636                                     "of the share root '%s' failed: %s\n",
2637                                     handle->conn->connectpath, strerror(errno));
2638                         return -1;
2639                 }
2640         }
2641
2642         basedir = lp_parm_const_string(SNUM(handle->conn),
2643                                        "shadow", "basedir", NULL);
2644
2645         if (basedir != NULL) {
2646                 if (basedir[0] != '/') {
2647                         DEBUG(1, (__location__ " Warning: 'basedir' is "
2648                                   "relative ('%s'), but it has to be an "
2649                                   "absolute path. Disabling basedir.\n",
2650                                   basedir));
2651                         basedir = NULL;
2652                 } else {
2653                         char *p;
2654                         p = strstr(basedir, config->mount_point);
2655                         if (p != basedir) {
2656                                 DEBUG(1, ("Warning: basedir (%s) is not a "
2657                                           "subdirectory of the share root's "
2658                                           "mount point (%s). "
2659                                           "Disabling basedir\n",
2660                                           basedir, config->mount_point));
2661                                 basedir = NULL;
2662                         }
2663                 }
2664         }
2665
2666         if (config->snapdirseverywhere && basedir != NULL) {
2667                 DEBUG(1, (__location__ " Warning: 'basedir' is incompatible "
2668                           "with 'snapdirseverywhere'. Disabling basedir.\n"));
2669                 basedir = NULL;
2670         }
2671
2672         snapsharepath = lp_parm_const_string(SNUM(handle->conn), "shadow",
2673                                              "snapsharepath", NULL);
2674         if (snapsharepath != NULL) {
2675                 if (snapsharepath[0] == '/') {
2676                         DBG_WARNING("Warning: 'snapsharepath' is "
2677                                     "absolute ('%s'), but it has to be a "
2678                                     "relative path. Disabling snapsharepath.\n",
2679                                     snapsharepath);
2680                         snapsharepath = NULL;
2681                 }
2682                 if (config->snapdirseverywhere && snapsharepath != NULL) {
2683                         DBG_WARNING("Warning: 'snapsharepath' is incompatible "
2684                                     "with 'snapdirseverywhere'. Disabling "
2685                                     "snapsharepath.\n");
2686                         snapsharepath = NULL;
2687                 }
2688         }
2689
2690         if (basedir != NULL && snapsharepath != NULL) {
2691                 DBG_WARNING("Warning: 'snapsharepath' is incompatible with "
2692                             "'basedir'. Disabling snapsharepath\n");
2693                 snapsharepath = NULL;
2694         }
2695
2696         if (snapsharepath != NULL) {
2697                 config->rel_connectpath = talloc_strdup(config, snapsharepath);
2698                 if (config->rel_connectpath == NULL) {
2699                         DBG_ERR("talloc_strdup() failed\n");
2700                         errno = ENOMEM;
2701                         return -1;
2702                 }
2703         }
2704
2705         if (basedir == NULL) {
2706                 basedir = config->mount_point;
2707         }
2708
2709         if (config->rel_connectpath == NULL &&
2710             strlen(basedir) < strlen(handle->conn->connectpath)) {
2711                 config->rel_connectpath = talloc_strdup(config,
2712                         handle->conn->connectpath + strlen(basedir));
2713                 if (config->rel_connectpath == NULL) {
2714                         DEBUG(0, ("talloc_strdup() failed\n"));
2715                         errno = ENOMEM;
2716                         return -1;
2717                 }
2718         }
2719
2720         if (config->snapdir[0] == '/') {
2721                 config->snapdir_absolute = true;
2722
2723                 if (config->snapdirseverywhere == true) {
2724                         DEBUG(1, (__location__ " Warning: An absolute snapdir "
2725                                   "is incompatible with 'snapdirseverywhere', "
2726                                   "setting 'snapdirseverywhere' to false.\n"));
2727                         config->snapdirseverywhere = false;
2728                 }
2729
2730                 if (config->crossmountpoints == true) {
2731                         DEBUG(1, (__location__ " Warning: 'crossmountpoints' "
2732                                   "is not supported with an absolute snapdir. "
2733                                   "Disabling it.\n"));
2734                         config->crossmountpoints = false;
2735                 }
2736
2737                 config->snapshot_basepath = config->snapdir;
2738         } else {
2739                 config->snapshot_basepath = talloc_asprintf(config, "%s/%s",
2740                                 config->mount_point, config->snapdir);
2741                 if (config->snapshot_basepath == NULL) {
2742                         DEBUG(0, ("talloc_asprintf() failed\n"));
2743                         errno = ENOMEM;
2744                         return -1;
2745                 }
2746         }
2747
2748         trim_string(config->mount_point, NULL, "/");
2749         trim_string(config->rel_connectpath, "/", "/");
2750         trim_string(config->snapdir, NULL, "/");
2751         trim_string(config->snapshot_basepath, NULL, "/");
2752
2753         DEBUG(10, ("shadow_copy2_connect: configuration:\n"
2754                    "  share root: '%s'\n"
2755                    "  mountpoint: '%s'\n"
2756                    "  rel share root: '%s'\n"
2757                    "  snapdir: '%s'\n"
2758                    "  snapprefix: '%s'\n"
2759                    "  delimiter: '%s'\n"
2760                    "  snapshot base path: '%s'\n"
2761                    "  format: '%s'\n"
2762                    "  use sscanf: %s\n"
2763                    "  snapdirs everywhere: %s\n"
2764                    "  cross mountpoints: %s\n"
2765                    "  fix inodes: %s\n"
2766                    "  sort order: %s\n"
2767                    "",
2768                    handle->conn->connectpath,
2769                    config->mount_point,
2770                    config->rel_connectpath,
2771                    config->snapdir,
2772                    snapprefix,
2773                    config->delimiter,
2774                    config->snapshot_basepath,
2775                    config->gmt_format,
2776                    config->use_sscanf ? "yes" : "no",
2777                    config->snapdirseverywhere ? "yes" : "no",
2778                    config->crossmountpoints ? "yes" : "no",
2779                    config->fixinodes ? "yes" : "no",
2780                    config->sort_order
2781                    ));
2782
2783
2784         SMB_VFS_HANDLE_SET_DATA(handle, priv,
2785                                 NULL, struct shadow_copy2_private,
2786                                 return -1);
2787
2788         return 0;
2789 }
2790
2791 static struct vfs_fn_pointers vfs_shadow_copy2_fns = {
2792         .connect_fn = shadow_copy2_connect,
2793         .opendir_fn = shadow_copy2_opendir,
2794         .disk_free_fn = shadow_copy2_disk_free,
2795         .get_quota_fn = shadow_copy2_get_quota,
2796         .rename_fn = shadow_copy2_rename,
2797         .link_fn = shadow_copy2_link,
2798         .symlink_fn = shadow_copy2_symlink,
2799         .stat_fn = shadow_copy2_stat,
2800         .lstat_fn = shadow_copy2_lstat,
2801         .fstat_fn = shadow_copy2_fstat,
2802         .open_fn = shadow_copy2_open,
2803         .unlink_fn = shadow_copy2_unlink,
2804         .chmod_fn = shadow_copy2_chmod,
2805         .chown_fn = shadow_copy2_chown,
2806         .chdir_fn = shadow_copy2_chdir,
2807         .ntimes_fn = shadow_copy2_ntimes,
2808         .readlink_fn = shadow_copy2_readlink,
2809         .mknod_fn = shadow_copy2_mknod,
2810         .realpath_fn = shadow_copy2_realpath,
2811         .get_nt_acl_fn = shadow_copy2_get_nt_acl,
2812         .fget_nt_acl_fn = shadow_copy2_fget_nt_acl,
2813         .get_shadow_copy_data_fn = shadow_copy2_get_shadow_copy_data,
2814         .mkdir_fn = shadow_copy2_mkdir,
2815         .rmdir_fn = shadow_copy2_rmdir,
2816         .getxattr_fn = shadow_copy2_getxattr,
2817         .listxattr_fn = shadow_copy2_listxattr,
2818         .removexattr_fn = shadow_copy2_removexattr,
2819         .setxattr_fn = shadow_copy2_setxattr,
2820         .chmod_acl_fn = shadow_copy2_chmod_acl,
2821         .chflags_fn = shadow_copy2_chflags,
2822         .get_real_filename_fn = shadow_copy2_get_real_filename,
2823         .connectpath_fn = shadow_copy2_connectpath,
2824 };
2825
2826 NTSTATUS vfs_shadow_copy2_init(void);
2827 NTSTATUS vfs_shadow_copy2_init(void)
2828 {
2829         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2830                                 "shadow_copy2", &vfs_shadow_copy2_fns);
2831 }