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