s3: VFS: vfs_shadow_copy2. Implement symlinkat().
[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 char *orig_name,
590                                         time_t *ptimestamp,
591                                         char **pstripped,
592                                         char **psnappath,
593                                         bool *_already_converted)
594 {
595         struct tm tm;
596         time_t timestamp = 0;
597         const char *p;
598         char *q;
599         char *stripped = NULL;
600         size_t rest_len, dst_len;
601         struct shadow_copy2_private *priv;
602         ptrdiff_t len_before_gmt;
603         const char *name = orig_name;
604         char *abs_path = NULL;
605         bool ret = true;
606         bool already_converted = false;
607         int err = 0;
608
609         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
610                                 return false);
611
612         DEBUG(10, (__location__ ": enter path '%s'\n", name));
613
614         if (_already_converted != NULL) {
615                 *_already_converted = false;
616         }
617
618         abs_path = make_path_absolute(mem_ctx, priv, name);
619         if (abs_path == NULL) {
620                 ret = false;
621                 goto out;
622         }
623         name = abs_path;
624
625         DEBUG(10, (__location__ ": abs path '%s'\n", name));
626
627         err = check_for_converted_path(mem_ctx,
628                                         handle,
629                                         priv,
630                                         abs_path,
631                                         &already_converted,
632                                         psnappath);
633         if (err != 0) {
634                 /* error in conversion. */
635                 ret = false;
636                 goto out;
637         }
638
639         if (already_converted) {
640                 if (_already_converted != NULL) {
641                         *_already_converted = true;
642                 }
643                 goto out;
644         }
645
646         /*
647          * From here we're only looking to strip an
648          * SMB-layer @GMT- token.
649          */
650
651         p = strstr_m(name, "@GMT-");
652         if (p == NULL) {
653                 DEBUG(11, ("@GMT not found\n"));
654                 goto out;
655         }
656         if ((p > name) && (p[-1] != '/')) {
657                 /* the GMT-token does not start a path-component */
658                 DEBUG(10, ("not at start, p=%p, name=%p, p[-1]=%d\n",
659                            p, name, (int)p[-1]));
660                 goto out;
661         }
662
663         len_before_gmt = p - name;
664
665         q = strptime(p, GMT_FORMAT, &tm);
666         if (q == NULL) {
667                 DEBUG(10, ("strptime failed\n"));
668                 goto out;
669         }
670         tm.tm_isdst = -1;
671         timestamp = timegm(&tm);
672         if (timestamp == (time_t)-1) {
673                 DEBUG(10, ("timestamp==-1\n"));
674                 goto out;
675         }
676         if (q[0] == '\0') {
677                 /*
678                  * The name consists of only the GMT token or the GMT
679                  * token is at the end of the path. XP seems to send
680                  * @GMT- at the end under certain circumstances even
681                  * with a path prefix.
682                  */
683                 if (pstripped != NULL) {
684                         if (len_before_gmt > 1) {
685                                 /*
686                                  * There is a path (and not only a slash)
687                                  * before the @GMT-. Remove the trailing
688                                  * slash character.
689                                  */
690                                 len_before_gmt -= 1;
691                         }
692                         stripped = talloc_strndup(mem_ctx, name,
693                                         len_before_gmt);
694                         if (stripped == NULL) {
695                                 ret = false;
696                                 goto out;
697                         }
698                         if (orig_name[0] != '/') {
699                                 if (make_relative_path(priv->shadow_cwd,
700                                                 stripped) == false) {
701                                         DEBUG(10, (__location__ ": path '%s' "
702                                                 "doesn't start with cwd '%s'\n",
703                                                 stripped, priv->shadow_cwd));
704                                                 ret = false;
705                                         errno = ENOENT;
706                                         goto out;
707                                 }
708                         }
709                         *pstripped = stripped;
710                 }
711                 *ptimestamp = timestamp;
712                 goto out;
713         }
714         if (q[0] != '/') {
715                 /*
716                  * It is not a complete path component, i.e. the path
717                  * component continues after the gmt-token.
718                  */
719                 DEBUG(10, ("q[0] = %d\n", (int)q[0]));
720                 goto out;
721         }
722         q += 1;
723
724         rest_len = strlen(q);
725         dst_len = len_before_gmt + rest_len;
726
727         if (pstripped != NULL) {
728                 stripped = talloc_array(mem_ctx, char, dst_len+1);
729                 if (stripped == NULL) {
730                         ret = false;
731                         goto out;
732                 }
733                 if (p > name) {
734                         memcpy(stripped, name, len_before_gmt);
735                 }
736                 if (rest_len > 0) {
737                         memcpy(stripped + len_before_gmt, q, rest_len);
738                 }
739                 stripped[dst_len] = '\0';
740                 if (orig_name[0] != '/') {
741                         if (make_relative_path(priv->shadow_cwd,
742                                         stripped) == false) {
743                                 DEBUG(10, (__location__ ": path '%s' "
744                                         "doesn't start with cwd '%s'\n",
745                                         stripped, priv->shadow_cwd));
746                                 ret = false;
747                                 errno = ENOENT;
748                                 goto out;
749                         }
750                 }
751                 *pstripped = stripped;
752         }
753         *ptimestamp = timestamp;
754         ret = true;
755
756   out:
757         TALLOC_FREE(abs_path);
758         return ret;
759 }
760
761 static bool shadow_copy2_strip_snapshot(TALLOC_CTX *mem_ctx,
762                                         struct vfs_handle_struct *handle,
763                                         const char *orig_name,
764                                         time_t *ptimestamp,
765                                         char **pstripped)
766 {
767         return shadow_copy2_strip_snapshot_internal(mem_ctx,
768                                         handle,
769                                         orig_name,
770                                         ptimestamp,
771                                         pstripped,
772                                         NULL,
773                                         NULL);
774 }
775
776 static bool shadow_copy2_strip_snapshot_converted(TALLOC_CTX *mem_ctx,
777                                         struct vfs_handle_struct *handle,
778                                         const char *orig_name,
779                                         time_t *ptimestamp,
780                                         char **pstripped,
781                                         bool *is_converted)
782 {
783         return shadow_copy2_strip_snapshot_internal(mem_ctx,
784                                         handle,
785                                         orig_name,
786                                         ptimestamp,
787                                         pstripped,
788                                         NULL,
789                                         is_converted);
790 }
791
792 static char *shadow_copy2_find_mount_point(TALLOC_CTX *mem_ctx,
793                                            vfs_handle_struct *handle)
794 {
795         char *path = talloc_strdup(mem_ctx, handle->conn->connectpath);
796         dev_t dev;
797         struct stat st;
798         char *p;
799
800         if (stat(path, &st) != 0) {
801                 talloc_free(path);
802                 return NULL;
803         }
804
805         dev = st.st_dev;
806
807         while ((p = strrchr(path, '/')) && p > path) {
808                 *p = 0;
809                 if (stat(path, &st) != 0) {
810                         talloc_free(path);
811                         return NULL;
812                 }
813                 if (st.st_dev != dev) {
814                         *p = '/';
815                         break;
816                 }
817         }
818
819         return path;
820 }
821
822 /**
823  * Convert from a name as handed in via the SMB layer
824  * and a timestamp into the local path of the snapshot
825  * of the provided file at the provided time.
826  * Also return the path in the snapshot corresponding
827  * to the file's share root.
828  */
829 static char *shadow_copy2_do_convert(TALLOC_CTX *mem_ctx,
830                                      struct vfs_handle_struct *handle,
831                                      const char *name, time_t timestamp,
832                                      size_t *snaproot_len)
833 {
834         struct smb_filename converted_fname;
835         char *result = NULL;
836         size_t *slashes = NULL;
837         unsigned num_slashes;
838         char *path = NULL;
839         size_t pathlen;
840         char *insert = NULL;
841         char *converted = NULL;
842         size_t insertlen, connectlen = 0;
843         int saved_errno = 0;
844         int i;
845         size_t min_offset;
846         struct shadow_copy2_config *config;
847         struct shadow_copy2_private *priv;
848         size_t in_share_offset = 0;
849
850         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
851                                 return NULL);
852
853         config = priv->config;
854
855         DEBUG(10, ("converting '%s'\n", name));
856
857         if (!config->snapdirseverywhere) {
858                 int ret;
859                 char *snapshot_path;
860
861                 snapshot_path = shadow_copy2_snapshot_path(talloc_tos(),
862                                                            handle,
863                                                            timestamp);
864                 if (snapshot_path == NULL) {
865                         goto fail;
866                 }
867
868                 if (config->rel_connectpath == NULL) {
869                         converted = talloc_asprintf(mem_ctx, "%s/%s",
870                                                     snapshot_path, name);
871                 } else {
872                         converted = talloc_asprintf(mem_ctx, "%s/%s/%s",
873                                                     snapshot_path,
874                                                     config->rel_connectpath,
875                                                     name);
876                 }
877                 if (converted == NULL) {
878                         goto fail;
879                 }
880
881                 ZERO_STRUCT(converted_fname);
882                 converted_fname.base_name = converted;
883
884                 ret = SMB_VFS_NEXT_LSTAT(handle, &converted_fname);
885                 DEBUG(10, ("Trying[not snapdirseverywhere] %s: %d (%s)\n",
886                            converted,
887                            ret, ret == 0 ? "ok" : strerror(errno)));
888                 if (ret == 0) {
889                         DEBUG(10, ("Found %s\n", converted));
890                         result = converted;
891                         converted = NULL;
892                         if (snaproot_len != NULL) {
893                                 *snaproot_len = strlen(snapshot_path);
894                                 if (config->rel_connectpath != NULL) {
895                                         *snaproot_len +=
896                                             strlen(config->rel_connectpath) + 1;
897                                 }
898                         }
899                         goto fail;
900                 } else {
901                         errno = ENOENT;
902                         goto fail;
903                 }
904                 /* never reached ... */
905         }
906
907         connectlen = strlen(handle->conn->connectpath);
908         if (name[0] == 0) {
909                 path = talloc_strdup(mem_ctx, handle->conn->connectpath);
910         } else {
911                 path = talloc_asprintf(
912                         mem_ctx, "%s/%s", handle->conn->connectpath, name);
913         }
914         if (path == NULL) {
915                 errno = ENOMEM;
916                 goto fail;
917         }
918         pathlen = talloc_get_size(path)-1;
919
920         if (!shadow_copy2_find_slashes(talloc_tos(), path,
921                                        &slashes, &num_slashes)) {
922                 goto fail;
923         }
924
925         insert = shadow_copy2_insert_string(talloc_tos(), handle, timestamp);
926         if (insert == NULL) {
927                 goto fail;
928         }
929         insertlen = talloc_get_size(insert)-1;
930
931         /*
932          * Note: We deliberatly don't expensively initialize the
933          * array with talloc_zero here: Putting zero into
934          * converted[pathlen+insertlen] below is sufficient, because
935          * in the following for loop, the insert string is inserted
936          * at various slash places. So the memory up to position
937          * pathlen+insertlen will always be initialized when the
938          * converted string is used.
939          */
940         converted = talloc_array(mem_ctx, char, pathlen + insertlen + 1);
941         if (converted == NULL) {
942                 goto fail;
943         }
944
945         if (path[pathlen-1] != '/') {
946                 /*
947                  * Append a fake slash to find the snapshot root
948                  */
949                 size_t *tmp;
950                 tmp = talloc_realloc(talloc_tos(), slashes,
951                                      size_t, num_slashes+1);
952                 if (tmp == NULL) {
953                         goto fail;
954                 }
955                 slashes = tmp;
956                 slashes[num_slashes] = pathlen;
957                 num_slashes += 1;
958         }
959
960         min_offset = 0;
961
962         if (!config->crossmountpoints) {
963                 min_offset = strlen(config->mount_point);
964         }
965
966         memcpy(converted, path, pathlen+1);
967         converted[pathlen+insertlen] = '\0';
968
969         ZERO_STRUCT(converted_fname);
970         converted_fname.base_name = converted;
971
972         for (i = num_slashes-1; i>=0; i--) {
973                 int ret;
974                 size_t offset;
975
976                 offset = slashes[i];
977
978                 if (offset < min_offset) {
979                         errno = ENOENT;
980                         goto fail;
981                 }
982
983                 if (offset >= connectlen) {
984                         in_share_offset = offset;
985                 }
986
987                 memcpy(converted+offset, insert, insertlen);
988
989                 offset += insertlen;
990                 memcpy(converted+offset, path + slashes[i],
991                        pathlen - slashes[i]);
992
993                 ret = SMB_VFS_NEXT_LSTAT(handle, &converted_fname);
994
995                 DEBUG(10, ("Trying[snapdirseverywhere] %s: %d (%s)\n",
996                            converted,
997                            ret, ret == 0 ? "ok" : strerror(errno)));
998                 if (ret == 0) {
999                         /* success */
1000                         if (snaproot_len != NULL) {
1001                                 *snaproot_len = in_share_offset + insertlen;
1002                         }
1003                         break;
1004                 }
1005                 if (errno == ENOTDIR) {
1006                         /*
1007                          * This is a valid condition: We appended the
1008                          * .snaphots/@GMT.. to a file name. Just try
1009                          * with the upper levels.
1010                          */
1011                         continue;
1012                 }
1013                 if (errno != ENOENT) {
1014                         /* Other problem than "not found" */
1015                         goto fail;
1016                 }
1017         }
1018
1019         if (i >= 0) {
1020                 /*
1021                  * Found something
1022                  */
1023                 DEBUG(10, ("Found %s\n", converted));
1024                 result = converted;
1025                 converted = NULL;
1026         } else {
1027                 errno = ENOENT;
1028         }
1029 fail:
1030         if (result == NULL) {
1031                 saved_errno = errno;
1032         }
1033         TALLOC_FREE(converted);
1034         TALLOC_FREE(insert);
1035         TALLOC_FREE(slashes);
1036         TALLOC_FREE(path);
1037         if (saved_errno != 0) {
1038                 errno = saved_errno;
1039         }
1040         return result;
1041 }
1042
1043 /**
1044  * Convert from a name as handed in via the SMB layer
1045  * and a timestamp into the local path of the snapshot
1046  * of the provided file at the provided time.
1047  */
1048 static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
1049                                   struct vfs_handle_struct *handle,
1050                                   const char *name, time_t timestamp)
1051 {
1052         return shadow_copy2_do_convert(mem_ctx, handle, name, timestamp, NULL);
1053 }
1054
1055 /*
1056   modify a sbuf return to ensure that inodes in the shadow directory
1057   are different from those in the main directory
1058  */
1059 static void convert_sbuf(vfs_handle_struct *handle, const char *fname,
1060                          SMB_STRUCT_STAT *sbuf)
1061 {
1062         struct shadow_copy2_private *priv;
1063
1064         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
1065                                 return);
1066
1067         if (priv->config->fixinodes) {
1068                 /* some snapshot systems, like GPFS, return the name
1069                    device:inode for the snapshot files as the current
1070                    files. That breaks the 'restore' button in the shadow copy
1071                    GUI, as the client gets a sharing violation.
1072
1073                    This is a crude way of allowing both files to be
1074                    open at once. It has a slight chance of inode
1075                    number collision, but I can't see a better approach
1076                    without significant VFS changes
1077                 */
1078                 TDB_DATA key = { .dptr = discard_const_p(uint8_t, fname),
1079                                  .dsize = strlen(fname) };
1080                 uint32_t shash;
1081
1082                 shash = tdb_jenkins_hash(&key) & 0xFF000000;
1083                 if (shash == 0) {
1084                         shash = 1;
1085                 }
1086                 sbuf->st_ex_ino ^= shash;
1087         }
1088 }
1089
1090 static DIR *shadow_copy2_opendir(vfs_handle_struct *handle,
1091                         const struct smb_filename *smb_fname,
1092                         const char *mask,
1093                         uint32_t attr)
1094 {
1095         time_t timestamp = 0;
1096         char *stripped = NULL;
1097         DIR *ret;
1098         int saved_errno = 0;
1099         char *conv;
1100         struct smb_filename *conv_smb_fname = NULL;
1101
1102         if (!shadow_copy2_strip_snapshot(talloc_tos(),
1103                                 handle,
1104                                 smb_fname->base_name,
1105                                 &timestamp,
1106                                 &stripped)) {
1107                 return NULL;
1108         }
1109         if (timestamp == 0) {
1110                 return SMB_VFS_NEXT_OPENDIR(handle, smb_fname, mask, attr);
1111         }
1112         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1113         TALLOC_FREE(stripped);
1114         if (conv == NULL) {
1115                 return NULL;
1116         }
1117         conv_smb_fname = synthetic_smb_fname(talloc_tos(),
1118                                         conv,
1119                                         NULL,
1120                                         NULL,
1121                                         smb_fname->flags);
1122         if (conv_smb_fname == NULL) {
1123                 TALLOC_FREE(conv);
1124                 return NULL;
1125         }
1126         ret = SMB_VFS_NEXT_OPENDIR(handle, conv_smb_fname, mask, attr);
1127         if (ret == NULL) {
1128                 saved_errno = errno;
1129         }
1130         TALLOC_FREE(conv);
1131         TALLOC_FREE(conv_smb_fname);
1132         if (saved_errno != 0) {
1133                 errno = saved_errno;
1134         }
1135         return ret;
1136 }
1137
1138 static int shadow_copy2_renameat(vfs_handle_struct *handle,
1139                                 files_struct *srcfsp,
1140                                 const struct smb_filename *smb_fname_src,
1141                                 files_struct *dstfsp,
1142                                 const struct smb_filename *smb_fname_dst)
1143 {
1144         time_t timestamp_src = 0;
1145         time_t timestamp_dst = 0;
1146         char *snappath_src = NULL;
1147         char *snappath_dst = NULL;
1148
1149         if (!shadow_copy2_strip_snapshot_internal(talloc_tos(), handle,
1150                                          smb_fname_src->base_name,
1151                                          &timestamp_src, NULL, &snappath_src,
1152                                          NULL)) {
1153                 return -1;
1154         }
1155         if (!shadow_copy2_strip_snapshot_internal(talloc_tos(), handle,
1156                                          smb_fname_dst->base_name,
1157                                          &timestamp_dst, NULL, &snappath_dst,
1158                                          NULL)) {
1159                 return -1;
1160         }
1161         if (timestamp_src != 0) {
1162                 errno = EXDEV;
1163                 return -1;
1164         }
1165         if (timestamp_dst != 0) {
1166                 errno = EROFS;
1167                 return -1;
1168         }
1169         /*
1170          * Don't allow rename on already converted paths.
1171          */
1172         if (snappath_src != NULL) {
1173                 errno = EXDEV;
1174                 return -1;
1175         }
1176         if (snappath_dst != NULL) {
1177                 errno = EROFS;
1178                 return -1;
1179         }
1180         return SMB_VFS_NEXT_RENAMEAT(handle,
1181                         srcfsp,
1182                         smb_fname_src,
1183                         dstfsp,
1184                         smb_fname_dst);
1185 }
1186
1187
1188 static int shadow_copy2_symlink(vfs_handle_struct *handle,
1189                         const char *link_contents,
1190                         const struct smb_filename *new_smb_fname)
1191 {
1192         time_t timestamp_old = 0;
1193         time_t timestamp_new = 0;
1194         char *snappath_old = NULL;
1195         char *snappath_new = NULL;
1196
1197         if (!shadow_copy2_strip_snapshot_internal(talloc_tos(),
1198                                 handle,
1199                                 link_contents,
1200                                 &timestamp_old,
1201                                 NULL,
1202                                 &snappath_old,
1203                                 NULL)) {
1204                 return -1;
1205         }
1206         if (!shadow_copy2_strip_snapshot_internal(talloc_tos(),
1207                                 handle,
1208                                 new_smb_fname->base_name,
1209                                 &timestamp_new,
1210                                 NULL,
1211                                 &snappath_new,
1212                                 NULL)) {
1213                 return -1;
1214         }
1215         if ((timestamp_old != 0) || (timestamp_new != 0)) {
1216                 errno = EROFS;
1217                 return -1;
1218         }
1219         /*
1220          * Don't allow symlinks on already converted paths.
1221          */
1222         if ((snappath_old != NULL) || (snappath_new != NULL)) {
1223                 errno = EROFS;
1224                 return -1;
1225         }
1226         return SMB_VFS_NEXT_SYMLINK(handle, link_contents, new_smb_fname);
1227 }
1228
1229 static int shadow_copy2_symlinkat(vfs_handle_struct *handle,
1230                         const char *link_contents,
1231                         struct files_struct *dirfsp,
1232                         const struct smb_filename *new_smb_fname)
1233 {
1234         time_t timestamp_old = 0;
1235         time_t timestamp_new = 0;
1236         char *snappath_old = NULL;
1237         char *snappath_new = NULL;
1238
1239         if (!shadow_copy2_strip_snapshot_internal(talloc_tos(),
1240                                 handle,
1241                                 link_contents,
1242                                 &timestamp_old,
1243                                 NULL,
1244                                 &snappath_old,
1245                                 NULL)) {
1246                 return -1;
1247         }
1248         if (!shadow_copy2_strip_snapshot_internal(talloc_tos(),
1249                                 handle,
1250                                 new_smb_fname->base_name,
1251                                 &timestamp_new,
1252                                 NULL,
1253                                 &snappath_new,
1254                                 NULL)) {
1255                 return -1;
1256         }
1257         if ((timestamp_old != 0) || (timestamp_new != 0)) {
1258                 errno = EROFS;
1259                 return -1;
1260         }
1261         /*
1262          * Don't allow symlinks on already converted paths.
1263          */
1264         if ((snappath_old != NULL) || (snappath_new != NULL)) {
1265                 errno = EROFS;
1266                 return -1;
1267         }
1268         return SMB_VFS_NEXT_SYMLINKAT(handle,
1269                                 link_contents,
1270                                 dirfsp,
1271                                 new_smb_fname);
1272 }
1273
1274 static int shadow_copy2_linkat(vfs_handle_struct *handle,
1275                         files_struct *srcfsp,
1276                         const struct smb_filename *old_smb_fname,
1277                         files_struct *dstfsp,
1278                         const struct smb_filename *new_smb_fname,
1279                         int flags)
1280 {
1281         time_t timestamp_old = 0;
1282         time_t timestamp_new = 0;
1283         char *snappath_old = NULL;
1284         char *snappath_new = NULL;
1285
1286         if (!shadow_copy2_strip_snapshot_internal(talloc_tos(),
1287                                 handle,
1288                                 old_smb_fname->base_name,
1289                                 &timestamp_old,
1290                                 NULL,
1291                                 &snappath_old,
1292                                 NULL)) {
1293                 return -1;
1294         }
1295         if (!shadow_copy2_strip_snapshot_internal(talloc_tos(),
1296                                 handle,
1297                                 new_smb_fname->base_name,
1298                                 &timestamp_new,
1299                                 NULL,
1300                                 &snappath_new,
1301                                 NULL)) {
1302                 return -1;
1303         }
1304         if ((timestamp_old != 0) || (timestamp_new != 0)) {
1305                 errno = EROFS;
1306                 return -1;
1307         }
1308         /*
1309          * Don't allow links on already converted paths.
1310          */
1311         if ((snappath_old != NULL) || (snappath_new != NULL)) {
1312                 errno = EROFS;
1313                 return -1;
1314         }
1315         return SMB_VFS_NEXT_LINKAT(handle,
1316                         srcfsp,
1317                         old_smb_fname,
1318                         dstfsp,
1319                         new_smb_fname,
1320                         flags);
1321 }
1322
1323 static int shadow_copy2_stat(vfs_handle_struct *handle,
1324                              struct smb_filename *smb_fname)
1325 {
1326         time_t timestamp = 0;
1327         char *stripped = NULL;
1328         char *tmp;
1329         int saved_errno = 0;
1330         int ret;
1331
1332         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
1333                                          smb_fname->base_name,
1334                                          &timestamp, &stripped)) {
1335                 return -1;
1336         }
1337         if (timestamp == 0) {
1338                 return SMB_VFS_NEXT_STAT(handle, smb_fname);
1339         }
1340
1341         tmp = smb_fname->base_name;
1342         smb_fname->base_name = shadow_copy2_convert(
1343                 talloc_tos(), handle, stripped, timestamp);
1344         TALLOC_FREE(stripped);
1345
1346         if (smb_fname->base_name == NULL) {
1347                 smb_fname->base_name = tmp;
1348                 return -1;
1349         }
1350
1351         ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
1352         if (ret == -1) {
1353                 saved_errno = errno;
1354         }
1355
1356         TALLOC_FREE(smb_fname->base_name);
1357         smb_fname->base_name = tmp;
1358
1359         if (ret == 0) {
1360                 convert_sbuf(handle, smb_fname->base_name, &smb_fname->st);
1361         }
1362         if (saved_errno != 0) {
1363                 errno = saved_errno;
1364         }
1365         return ret;
1366 }
1367
1368 static int shadow_copy2_lstat(vfs_handle_struct *handle,
1369                               struct smb_filename *smb_fname)
1370 {
1371         time_t timestamp = 0;
1372         char *stripped = NULL;
1373         char *tmp;
1374         int saved_errno = 0;
1375         int ret;
1376
1377         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
1378                                          smb_fname->base_name,
1379                                          &timestamp, &stripped)) {
1380                 return -1;
1381         }
1382         if (timestamp == 0) {
1383                 return SMB_VFS_NEXT_LSTAT(handle, smb_fname);
1384         }
1385
1386         tmp = smb_fname->base_name;
1387         smb_fname->base_name = shadow_copy2_convert(
1388                 talloc_tos(), handle, stripped, timestamp);
1389         TALLOC_FREE(stripped);
1390
1391         if (smb_fname->base_name == NULL) {
1392                 smb_fname->base_name = tmp;
1393                 return -1;
1394         }
1395
1396         ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
1397         if (ret == -1) {
1398                 saved_errno = errno;
1399         }
1400
1401         TALLOC_FREE(smb_fname->base_name);
1402         smb_fname->base_name = tmp;
1403
1404         if (ret == 0) {
1405                 convert_sbuf(handle, smb_fname->base_name, &smb_fname->st);
1406         }
1407         if (saved_errno != 0) {
1408                 errno = saved_errno;
1409         }
1410         return ret;
1411 }
1412
1413 static int shadow_copy2_fstat(vfs_handle_struct *handle, files_struct *fsp,
1414                               SMB_STRUCT_STAT *sbuf)
1415 {
1416         time_t timestamp = 0;
1417         struct smb_filename *orig_smb_fname = NULL;
1418         struct smb_filename vss_smb_fname;
1419         struct smb_filename *orig_base_smb_fname = NULL;
1420         struct smb_filename vss_base_smb_fname;
1421         char *stripped = NULL;
1422         int saved_errno = 0;
1423         bool ok;
1424         int ret;
1425
1426         ok = shadow_copy2_strip_snapshot(talloc_tos(), handle,
1427                                          fsp->fsp_name->base_name,
1428                                          &timestamp, &stripped);
1429         if (!ok) {
1430                 return -1;
1431         }
1432
1433         if (timestamp == 0) {
1434                 TALLOC_FREE(stripped);
1435                 return SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
1436         }
1437
1438         vss_smb_fname = *fsp->fsp_name;
1439         vss_smb_fname.base_name = shadow_copy2_convert(talloc_tos(),
1440                                                        handle,
1441                                                        stripped,
1442                                                        timestamp);
1443         TALLOC_FREE(stripped);
1444         if (vss_smb_fname.base_name == NULL) {
1445                 return -1;
1446         }
1447
1448         orig_smb_fname = fsp->fsp_name;
1449         fsp->fsp_name = &vss_smb_fname;
1450
1451         if (fsp->base_fsp != NULL) {
1452                 vss_base_smb_fname = *fsp->base_fsp->fsp_name;
1453                 vss_base_smb_fname.base_name = vss_smb_fname.base_name;
1454                 orig_base_smb_fname = fsp->base_fsp->fsp_name;
1455                 fsp->base_fsp->fsp_name = &vss_base_smb_fname;
1456         }
1457
1458         ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
1459         fsp->fsp_name = orig_smb_fname;
1460         if (fsp->base_fsp != NULL) {
1461                 fsp->base_fsp->fsp_name = orig_base_smb_fname;
1462         }
1463         if (ret == -1) {
1464                 saved_errno = errno;
1465         }
1466
1467         if (ret == 0) {
1468                 convert_sbuf(handle, fsp->fsp_name->base_name, sbuf);
1469         }
1470         if (saved_errno != 0) {
1471                 errno = saved_errno;
1472         }
1473         return ret;
1474 }
1475
1476 static int shadow_copy2_open(vfs_handle_struct *handle,
1477                              struct smb_filename *smb_fname, files_struct *fsp,
1478                              int flags, mode_t mode)
1479 {
1480         time_t timestamp = 0;
1481         char *stripped = NULL;
1482         char *tmp;
1483         bool is_converted = false;
1484         int saved_errno = 0;
1485         int ret;
1486
1487         if (!shadow_copy2_strip_snapshot_converted(talloc_tos(), handle,
1488                                          smb_fname->base_name,
1489                                          &timestamp, &stripped,
1490                                          &is_converted)) {
1491                 return -1;
1492         }
1493         if (timestamp == 0) {
1494                 if (is_converted) {
1495                         /*
1496                          * Just pave over the user requested mode and use
1497                          * O_RDONLY. Later attempts by the client to write on
1498                          * the handle will fail in the pwrite() syscall with
1499                          * EINVAL which we carefully map to EROFS. In sum, this
1500                          * matches Windows behaviour.
1501                          */
1502                         flags = O_RDONLY;
1503                 }
1504                 return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
1505         }
1506
1507         tmp = smb_fname->base_name;
1508         smb_fname->base_name = shadow_copy2_convert(
1509                 talloc_tos(), handle, stripped, timestamp);
1510         TALLOC_FREE(stripped);
1511
1512         if (smb_fname->base_name == NULL) {
1513                 smb_fname->base_name = tmp;
1514                 return -1;
1515         }
1516
1517         /*
1518          * Just pave over the user requested mode and use O_RDONLY. Later
1519          * attempts by the client to write on the handle will fail in the
1520          * pwrite() syscall with EINVAL which we carefully map to EROFS. In sum,
1521          * this matches Windows behaviour.
1522          */
1523         flags = O_RDONLY;
1524
1525         ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
1526         if (ret == -1) {
1527                 saved_errno = errno;
1528         }
1529
1530         TALLOC_FREE(smb_fname->base_name);
1531         smb_fname->base_name = tmp;
1532
1533         if (saved_errno != 0) {
1534                 errno = saved_errno;
1535         }
1536         return ret;
1537 }
1538
1539 static int shadow_copy2_unlink(vfs_handle_struct *handle,
1540                                const struct smb_filename *smb_fname)
1541 {
1542         time_t timestamp = 0;
1543
1544         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
1545                                          smb_fname->base_name,
1546                                          &timestamp, NULL)) {
1547                 return -1;
1548         }
1549         if (timestamp != 0) {
1550                 errno = EROFS;
1551                 return -1;
1552         }
1553         return SMB_VFS_NEXT_UNLINK(handle, smb_fname);
1554 }
1555
1556 static int shadow_copy2_chmod(vfs_handle_struct *handle,
1557                         const struct smb_filename *smb_fname,
1558                         mode_t mode)
1559 {
1560         time_t timestamp = 0;
1561
1562         if (!shadow_copy2_strip_snapshot(talloc_tos(),
1563                                 handle,
1564                                 smb_fname->base_name,
1565                                 &timestamp,
1566                                 NULL)) {
1567                 return -1;
1568         }
1569         if (timestamp != 0) {
1570                 errno = EROFS;
1571                 return -1;
1572         }
1573         return SMB_VFS_NEXT_CHMOD(handle, smb_fname, mode);
1574 }
1575
1576 static int shadow_copy2_chown(vfs_handle_struct *handle,
1577                         const struct smb_filename *smb_fname,
1578                         uid_t uid,
1579                         gid_t gid)
1580 {
1581         time_t timestamp = 0;
1582
1583         if (!shadow_copy2_strip_snapshot(talloc_tos(),
1584                                 handle,
1585                                 smb_fname->base_name,
1586                                 &timestamp,
1587                                 NULL)) {
1588                 return -1;
1589         }
1590         if (timestamp != 0) {
1591                 errno = EROFS;
1592                 return -1;
1593         }
1594         return SMB_VFS_NEXT_CHOWN(handle, smb_fname, uid, gid);
1595 }
1596
1597 static void store_cwd_data(vfs_handle_struct *handle,
1598                                 const char *connectpath)
1599 {
1600         struct shadow_copy2_private *priv = NULL;
1601         struct smb_filename *cwd_fname = NULL;
1602
1603         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
1604                                 return);
1605
1606         TALLOC_FREE(priv->shadow_cwd);
1607         cwd_fname = SMB_VFS_NEXT_GETWD(handle, talloc_tos());
1608         if (cwd_fname == NULL) {
1609                 smb_panic("getwd failed\n");
1610         }
1611         DBG_DEBUG("shadow cwd = %s\n", cwd_fname->base_name);
1612         priv->shadow_cwd = talloc_strdup(priv, cwd_fname->base_name);
1613         TALLOC_FREE(cwd_fname);
1614         if (priv->shadow_cwd == NULL) {
1615                 smb_panic("talloc failed\n");
1616         }
1617         TALLOC_FREE(priv->shadow_connectpath);
1618         if (connectpath) {
1619                 DBG_DEBUG("shadow conectpath = %s\n", connectpath);
1620                 priv->shadow_connectpath = talloc_strdup(priv, connectpath);
1621                 if (priv->shadow_connectpath == NULL) {
1622                         smb_panic("talloc failed\n");
1623                 }
1624         }
1625 }
1626
1627 static int shadow_copy2_chdir(vfs_handle_struct *handle,
1628                                const struct smb_filename *smb_fname)
1629 {
1630         time_t timestamp = 0;
1631         char *stripped = NULL;
1632         char *snappath = NULL;
1633         int ret = -1;
1634         int saved_errno = 0;
1635         char *conv = NULL;
1636         size_t rootpath_len = 0;
1637         struct smb_filename *conv_smb_fname = NULL;
1638
1639         if (!shadow_copy2_strip_snapshot_internal(talloc_tos(),
1640                                         handle,
1641                                         smb_fname->base_name,
1642                                         &timestamp,
1643                                         &stripped,
1644                                         &snappath,
1645                                         NULL)) {
1646                 return -1;
1647         }
1648         if (stripped != NULL) {
1649                 conv = shadow_copy2_do_convert(talloc_tos(),
1650                                                 handle,
1651                                                 stripped,
1652                                                 timestamp,
1653                                                 &rootpath_len);
1654                 TALLOC_FREE(stripped);
1655                 if (conv == NULL) {
1656                         return -1;
1657                 }
1658                 conv_smb_fname = synthetic_smb_fname(talloc_tos(),
1659                                         conv,
1660                                         NULL,
1661                                         NULL,
1662                                         smb_fname->flags);
1663         } else {
1664                 conv_smb_fname = cp_smb_filename(talloc_tos(), smb_fname);
1665         }
1666
1667         if (conv_smb_fname == NULL) {
1668                 TALLOC_FREE(conv);
1669                 errno = ENOMEM;
1670                 return -1;
1671         }
1672
1673         ret = SMB_VFS_NEXT_CHDIR(handle, conv_smb_fname);
1674         if (ret == -1) {
1675                 saved_errno = errno;
1676         }
1677
1678         if (ret == 0) {
1679                 if (conv != NULL && rootpath_len != 0) {
1680                         conv[rootpath_len] = '\0';
1681                 } else if (snappath != 0) {
1682                         TALLOC_FREE(conv);
1683                         conv = snappath;
1684                 }
1685                 store_cwd_data(handle, conv);
1686         }
1687
1688         TALLOC_FREE(stripped);
1689         TALLOC_FREE(conv);
1690         TALLOC_FREE(conv_smb_fname);
1691
1692         if (saved_errno != 0) {
1693                 errno = saved_errno;
1694         }
1695         return ret;
1696 }
1697
1698 static int shadow_copy2_ntimes(vfs_handle_struct *handle,
1699                                const struct smb_filename *smb_fname,
1700                                struct smb_file_time *ft)
1701 {
1702         time_t timestamp = 0;
1703
1704         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
1705                                          smb_fname->base_name,
1706                                          &timestamp, NULL)) {
1707                 return -1;
1708         }
1709         if (timestamp != 0) {
1710                 errno = EROFS;
1711                 return -1;
1712         }
1713         return SMB_VFS_NEXT_NTIMES(handle, smb_fname, ft);
1714 }
1715
1716 static int shadow_copy2_readlinkat(vfs_handle_struct *handle,
1717                                 files_struct *dirfsp,
1718                                 const struct smb_filename *smb_fname,
1719                                 char *buf,
1720                                 size_t bufsiz)
1721 {
1722         time_t timestamp = 0;
1723         char *stripped = NULL;
1724         int saved_errno = 0;
1725         int ret;
1726         struct smb_filename *conv = NULL;
1727
1728         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
1729                                          smb_fname->base_name,
1730                                          &timestamp, &stripped)) {
1731                 return -1;
1732         }
1733         if (timestamp == 0) {
1734                 return SMB_VFS_NEXT_READLINKAT(handle,
1735                                 dirfsp,
1736                                 smb_fname,
1737                                 buf,
1738                                 bufsiz);
1739         }
1740         conv = cp_smb_filename(talloc_tos(), smb_fname);
1741         if (conv == NULL) {
1742                 TALLOC_FREE(stripped);
1743                 errno = ENOMEM;
1744                 return -1;
1745         }
1746         conv->base_name = shadow_copy2_convert(
1747                 conv, handle, stripped, timestamp);
1748         TALLOC_FREE(stripped);
1749         if (conv->base_name == NULL) {
1750                 return -1;
1751         }
1752         ret = SMB_VFS_NEXT_READLINKAT(handle,
1753                                 dirfsp,
1754                                 conv,
1755                                 buf,
1756                                 bufsiz);
1757         if (ret == -1) {
1758                 saved_errno = errno;
1759         }
1760         TALLOC_FREE(conv);
1761         if (saved_errno != 0) {
1762                 errno = saved_errno;
1763         }
1764         return ret;
1765 }
1766
1767 static int shadow_copy2_mknodat(vfs_handle_struct *handle,
1768                         files_struct *dirfsp,
1769                         const struct smb_filename *smb_fname,
1770                         mode_t mode,
1771                         SMB_DEV_T dev)
1772 {
1773         time_t timestamp = 0;
1774
1775         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
1776                                          smb_fname->base_name,
1777                                          &timestamp, NULL)) {
1778                 return -1;
1779         }
1780         if (timestamp != 0) {
1781                 errno = EROFS;
1782                 return -1;
1783         }
1784         return SMB_VFS_NEXT_MKNODAT(handle,
1785                         dirfsp,
1786                         smb_fname,
1787                         mode,
1788                         dev);
1789 }
1790
1791 static struct smb_filename *shadow_copy2_realpath(vfs_handle_struct *handle,
1792                                 TALLOC_CTX *ctx,
1793                                 const struct smb_filename *smb_fname)
1794 {
1795         time_t timestamp = 0;
1796         char *stripped = NULL;
1797         struct smb_filename *result_fname = NULL;
1798         struct smb_filename *conv_fname = NULL;
1799         int saved_errno = 0;
1800
1801         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
1802                                 smb_fname->base_name,
1803                                 &timestamp, &stripped)) {
1804                 goto done;
1805         }
1806         if (timestamp == 0) {
1807                 return SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname);
1808         }
1809
1810         conv_fname = cp_smb_filename(talloc_tos(), smb_fname);
1811         if (conv_fname == NULL) {
1812                 goto done;
1813         }
1814         conv_fname->base_name = shadow_copy2_convert(
1815                 conv_fname, handle, stripped, timestamp);
1816         if (conv_fname->base_name == NULL) {
1817                 goto done;
1818         }
1819
1820         result_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, conv_fname);
1821
1822 done:
1823         if (result_fname == NULL) {
1824                 saved_errno = errno;
1825         }
1826         TALLOC_FREE(conv_fname);
1827         TALLOC_FREE(stripped);
1828         if (saved_errno != 0) {
1829                 errno = saved_errno;
1830         }
1831         return result_fname;
1832 }
1833
1834 /**
1835  * Check whether a given directory contains a
1836  * snapshot directory as direct subdirectory.
1837  * If yes, return the path of the snapshot-subdir,
1838  * otherwise return NULL.
1839  */
1840 static char *have_snapdir(struct vfs_handle_struct *handle,
1841                           const char *path)
1842 {
1843         struct smb_filename smb_fname;
1844         int ret;
1845         struct shadow_copy2_private *priv;
1846
1847         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
1848                                 return NULL);
1849
1850         ZERO_STRUCT(smb_fname);
1851         smb_fname.base_name = talloc_asprintf(talloc_tos(), "%s/%s",
1852                                               path, priv->config->snapdir);
1853         if (smb_fname.base_name == NULL) {
1854                 return NULL;
1855         }
1856
1857         ret = SMB_VFS_NEXT_STAT(handle, &smb_fname);
1858         if ((ret == 0) && (S_ISDIR(smb_fname.st.st_ex_mode))) {
1859                 return smb_fname.base_name;
1860         }
1861         TALLOC_FREE(smb_fname.base_name);
1862         return NULL;
1863 }
1864
1865 static bool check_access_snapdir(struct vfs_handle_struct *handle,
1866                                 const char *path)
1867 {
1868         struct smb_filename smb_fname;
1869         int ret;
1870         NTSTATUS status;
1871
1872         ZERO_STRUCT(smb_fname);
1873         smb_fname.base_name = talloc_asprintf(talloc_tos(),
1874                                                 "%s",
1875                                                 path);
1876         if (smb_fname.base_name == NULL) {
1877                 return false;
1878         }
1879
1880         ret = SMB_VFS_NEXT_STAT(handle, &smb_fname);
1881         if (ret != 0 || !S_ISDIR(smb_fname.st.st_ex_mode)) {
1882                 TALLOC_FREE(smb_fname.base_name);
1883                 return false;
1884         }
1885
1886         status = smbd_check_access_rights(handle->conn,
1887                                         &smb_fname,
1888                                         false,
1889                                         SEC_DIR_LIST);
1890         if (!NT_STATUS_IS_OK(status)) {
1891                 DEBUG(0,("user does not have list permission "
1892                         "on snapdir %s\n",
1893                         smb_fname.base_name));
1894                 TALLOC_FREE(smb_fname.base_name);
1895                 return false;
1896         }
1897         TALLOC_FREE(smb_fname.base_name);
1898         return true;
1899 }
1900
1901 /**
1902  * Find the snapshot directory (if any) for the given
1903  * filename (which is relative to the share).
1904  */
1905 static const char *shadow_copy2_find_snapdir(TALLOC_CTX *mem_ctx,
1906                                              struct vfs_handle_struct *handle,
1907                                              struct smb_filename *smb_fname)
1908 {
1909         char *path, *p;
1910         const char *snapdir;
1911         struct shadow_copy2_config *config;
1912         struct shadow_copy2_private *priv;
1913
1914         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
1915                                 return NULL);
1916
1917         config = priv->config;
1918
1919         /*
1920          * If the non-snapdisrseverywhere mode, we should not search!
1921          */
1922         if (!config->snapdirseverywhere) {
1923                 return config->snapshot_basepath;
1924         }
1925
1926         path = talloc_asprintf(mem_ctx, "%s/%s",
1927                                handle->conn->connectpath,
1928                                smb_fname->base_name);
1929         if (path == NULL) {
1930                 return NULL;
1931         }
1932
1933         snapdir = have_snapdir(handle, path);
1934         if (snapdir != NULL) {
1935                 TALLOC_FREE(path);
1936                 return snapdir;
1937         }
1938
1939         while ((p = strrchr(path, '/')) && (p > path)) {
1940
1941                 p[0] = '\0';
1942
1943                 snapdir = have_snapdir(handle, path);
1944                 if (snapdir != NULL) {
1945                         TALLOC_FREE(path);
1946                         return snapdir;
1947                 }
1948         }
1949         TALLOC_FREE(path);
1950         return NULL;
1951 }
1952
1953 static bool shadow_copy2_snapshot_to_gmt(vfs_handle_struct *handle,
1954                                          const char *name,
1955                                          char *gmt, size_t gmt_len)
1956 {
1957         struct tm timestamp;
1958         time_t timestamp_t;
1959         unsigned long int timestamp_long;
1960         const char *fmt;
1961         struct shadow_copy2_config *config;
1962         struct shadow_copy2_private *priv;
1963         char *tmpstr = NULL;
1964         char *tmp = NULL;
1965         bool converted = false;
1966         int ret = -1;
1967
1968         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
1969                                 return NULL);
1970
1971         config = priv->config;
1972
1973         fmt = config->gmt_format;
1974
1975         /*
1976          * If regex is provided, then we will have to parse the
1977          * filename which will contain both the prefix and the time format.
1978          * e.g. <prefix><delimiter><time_format>
1979          */
1980         if (priv->snaps->regex != NULL) {
1981                 tmpstr = talloc_strdup(talloc_tos(), name);
1982                 /* point "name" to the time format */
1983                 name = strstr(name, priv->config->delimiter);
1984                 if (name == NULL) {
1985                         goto done;
1986                 }
1987                 /* Extract the prefix */
1988                 tmp = strstr(tmpstr, priv->config->delimiter);
1989                 if (tmp == NULL) {
1990                         goto done;
1991                 }
1992                 *tmp = '\0';
1993
1994                 /* Parse regex */
1995                 ret = regexec(priv->snaps->regex, tmpstr, 0, NULL, 0);
1996                 if (ret) {
1997                         DBG_DEBUG("shadow_copy2_snapshot_to_gmt: "
1998                                   "no regex match for %s\n", tmpstr);
1999                         goto done;
2000                 }
2001         }
2002
2003         ZERO_STRUCT(timestamp);
2004         if (config->use_sscanf) {
2005                 if (sscanf(name, fmt, &timestamp_long) != 1) {
2006                         DEBUG(10, ("shadow_copy2_snapshot_to_gmt: "
2007                                    "no sscanf match %s: %s\n",
2008                                    fmt, name));
2009                         goto done;
2010                 }
2011                 timestamp_t = timestamp_long;
2012                 gmtime_r(&timestamp_t, &timestamp);
2013         } else {
2014                 if (strptime(name, fmt, &timestamp) == NULL) {
2015                         DEBUG(10, ("shadow_copy2_snapshot_to_gmt: "
2016                                    "no match %s: %s\n",
2017                                    fmt, name));
2018                         goto done;
2019                 }
2020                 DEBUG(10, ("shadow_copy2_snapshot_to_gmt: match %s: %s\n",
2021                            fmt, name));
2022                 
2023                 if (config->use_localtime) {
2024                         timestamp.tm_isdst = -1;
2025                         timestamp_t = mktime(&timestamp);
2026                         gmtime_r(&timestamp_t, &timestamp);
2027                 }
2028         }
2029
2030         strftime(gmt, gmt_len, GMT_FORMAT, &timestamp);
2031         converted = true;
2032
2033 done:
2034         TALLOC_FREE(tmpstr);
2035         return converted;
2036 }
2037
2038 static int shadow_copy2_label_cmp_asc(const void *x, const void *y)
2039 {
2040         return strncmp((const char *)x, (const char *)y, sizeof(SHADOW_COPY_LABEL));
2041 }
2042
2043 static int shadow_copy2_label_cmp_desc(const void *x, const void *y)
2044 {
2045         return -strncmp((const char *)x, (const char *)y, sizeof(SHADOW_COPY_LABEL));
2046 }
2047
2048 /*
2049   sort the shadow copy data in ascending or descending order
2050  */
2051 static void shadow_copy2_sort_data(vfs_handle_struct *handle,
2052                                    struct shadow_copy_data *shadow_copy2_data)
2053 {
2054         int (*cmpfunc)(const void *, const void *);
2055         const char *sort;
2056         struct shadow_copy2_private *priv;
2057
2058         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
2059                                 return);
2060
2061         sort = priv->config->sort_order;
2062         if (sort == NULL) {
2063                 return;
2064         }
2065
2066         if (strcmp(sort, "asc") == 0) {
2067                 cmpfunc = shadow_copy2_label_cmp_asc;
2068         } else if (strcmp(sort, "desc") == 0) {
2069                 cmpfunc = shadow_copy2_label_cmp_desc;
2070         } else {
2071                 return;
2072         }
2073
2074         if (shadow_copy2_data && shadow_copy2_data->num_volumes > 0 &&
2075             shadow_copy2_data->labels)
2076         {
2077                 TYPESAFE_QSORT(shadow_copy2_data->labels,
2078                                shadow_copy2_data->num_volumes,
2079                                cmpfunc);
2080         }
2081 }
2082
2083 static int shadow_copy2_get_shadow_copy_data(
2084         vfs_handle_struct *handle, files_struct *fsp,
2085         struct shadow_copy_data *shadow_copy2_data,
2086         bool labels)
2087 {
2088         DIR *p;
2089         const char *snapdir;
2090         struct smb_filename *snapdir_smb_fname = NULL;
2091         struct dirent *d;
2092         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2093         struct shadow_copy2_private *priv = NULL;
2094         struct shadow_copy2_snapentry *tmpentry = NULL;
2095         bool get_snaplist = false;
2096         bool access_granted = false;
2097         int ret = -1;
2098
2099         snapdir = shadow_copy2_find_snapdir(tmp_ctx, handle, fsp->fsp_name);
2100         if (snapdir == NULL) {
2101                 DEBUG(0,("shadow:snapdir not found for %s in get_shadow_copy_data\n",
2102                          handle->conn->connectpath));
2103                 errno = EINVAL;
2104                 goto done;
2105         }
2106
2107         access_granted = check_access_snapdir(handle, snapdir);
2108         if (!access_granted) {
2109                 DEBUG(0,("access denied on listing snapdir %s\n", snapdir));
2110                 errno = EACCES;
2111                 goto done;
2112         }
2113
2114         snapdir_smb_fname = synthetic_smb_fname(talloc_tos(),
2115                                         snapdir,
2116                                         NULL,
2117                                         NULL,
2118                                         fsp->fsp_name->flags);
2119         if (snapdir_smb_fname == NULL) {
2120                 errno = ENOMEM;
2121                 goto done;
2122         }
2123
2124         p = SMB_VFS_NEXT_OPENDIR(handle, snapdir_smb_fname, NULL, 0);
2125
2126         if (!p) {
2127                 DEBUG(2,("shadow_copy2: SMB_VFS_NEXT_OPENDIR() failed for '%s'"
2128                          " - %s\n", snapdir, strerror(errno)));
2129                 errno = ENOSYS;
2130                 goto done;
2131         }
2132
2133         if (shadow_copy2_data != NULL) {
2134                 shadow_copy2_data->num_volumes = 0;
2135                 shadow_copy2_data->labels      = NULL;
2136         }
2137
2138         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
2139                                 goto done);
2140
2141         /*
2142          * Normally this function is called twice once with labels = false and
2143          * then with labels = true. When labels is false it will return the
2144          * number of volumes so that the caller can allocate memory for that
2145          * many labels. Therefore to eliminate snaplist both the times it is
2146          * good to check if labels is set or not.
2147          *
2148          * shadow_copy2_data is NULL when we only want to update the list and
2149          * don't want any labels.
2150          */
2151         if ((priv->snaps->regex != NULL) && (labels || shadow_copy2_data == NULL)) {
2152                 get_snaplist = true;
2153                 /* Reset the global snaplist */
2154                 shadow_copy2_delete_snaplist(priv);
2155
2156                 /* Set the current time as snaplist update time */
2157                 time(&(priv->snaps->fetch_time));
2158         }
2159
2160         while ((d = SMB_VFS_NEXT_READDIR(handle, p, NULL))) {
2161                 char snapshot[GMT_NAME_LEN+1];
2162                 SHADOW_COPY_LABEL *tlabels;
2163
2164                 /*
2165                  * ignore names not of the right form in the snapshot
2166                  * directory
2167                  */
2168                 if (!shadow_copy2_snapshot_to_gmt(
2169                             handle, d->d_name,
2170                             snapshot, sizeof(snapshot))) {
2171
2172                         DEBUG(6, ("shadow_copy2_get_shadow_copy_data: "
2173                                   "ignoring %s\n", d->d_name));
2174                         continue;
2175                 }
2176                 DEBUG(6,("shadow_copy2_get_shadow_copy_data: %s -> %s\n",
2177                          d->d_name, snapshot));
2178
2179                 if (get_snaplist) {
2180                         /*
2181                          * Create a snap entry for each successful
2182                          * pattern match.
2183                          */
2184                         tmpentry = shadow_copy2_create_snapentry(priv);
2185                         if (tmpentry == NULL) {
2186                                 DBG_ERR("talloc_zero() failed\n");
2187                                 goto done;
2188                         }
2189                         tmpentry->snapname = talloc_strdup(tmpentry, d->d_name);
2190                         tmpentry->time_fmt = talloc_strdup(tmpentry, snapshot);
2191                 }
2192
2193                 if (shadow_copy2_data == NULL) {
2194                         continue;
2195                 }
2196
2197                 if (!labels) {
2198                         /* the caller doesn't want the labels */
2199                         shadow_copy2_data->num_volumes++;
2200                         continue;
2201                 }
2202
2203                 tlabels = talloc_realloc(shadow_copy2_data,
2204                                          shadow_copy2_data->labels,
2205                                          SHADOW_COPY_LABEL,
2206                                          shadow_copy2_data->num_volumes+1);
2207                 if (tlabels == NULL) {
2208                         DEBUG(0,("shadow_copy2: out of memory\n"));
2209                         SMB_VFS_NEXT_CLOSEDIR(handle, p);
2210                         goto done;
2211                 }
2212
2213                 strlcpy(tlabels[shadow_copy2_data->num_volumes], snapshot,
2214                         sizeof(*tlabels));
2215
2216                 shadow_copy2_data->num_volumes++;
2217                 shadow_copy2_data->labels = tlabels;
2218         }
2219
2220         SMB_VFS_NEXT_CLOSEDIR(handle,p);
2221
2222         shadow_copy2_sort_data(handle, shadow_copy2_data);
2223         ret = 0;
2224
2225 done:
2226         TALLOC_FREE(tmp_ctx);
2227         return ret;
2228 }
2229
2230 static NTSTATUS shadow_copy2_fget_nt_acl(vfs_handle_struct *handle,
2231                                         struct files_struct *fsp,
2232                                         uint32_t security_info,
2233                                          TALLOC_CTX *mem_ctx,
2234                                         struct security_descriptor **ppdesc)
2235 {
2236         time_t timestamp = 0;
2237         char *stripped = NULL;
2238         NTSTATUS status;
2239         char *conv;
2240         struct smb_filename *smb_fname = NULL;
2241
2242         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
2243                                          fsp->fsp_name->base_name,
2244                                          &timestamp, &stripped)) {
2245                 return map_nt_error_from_unix(errno);
2246         }
2247         if (timestamp == 0) {
2248                 return SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info,
2249                                                 mem_ctx,
2250                                                 ppdesc);
2251         }
2252         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2253         TALLOC_FREE(stripped);
2254         if (conv == NULL) {
2255                 return map_nt_error_from_unix(errno);
2256         }
2257         smb_fname = synthetic_smb_fname(talloc_tos(),
2258                                         conv,
2259                                         NULL,
2260                                         NULL,
2261                                         fsp->fsp_name->flags);
2262         if (smb_fname == NULL) {
2263                 TALLOC_FREE(conv);
2264                 return NT_STATUS_NO_MEMORY;
2265         }
2266
2267         status = SMB_VFS_NEXT_GET_NT_ACL(handle, smb_fname, security_info,
2268                                          mem_ctx, ppdesc);
2269         TALLOC_FREE(conv);
2270         TALLOC_FREE(smb_fname);
2271         return status;
2272 }
2273
2274 static NTSTATUS shadow_copy2_get_nt_acl(vfs_handle_struct *handle,
2275                                         const struct smb_filename *smb_fname,
2276                                         uint32_t security_info,
2277                                         TALLOC_CTX *mem_ctx,
2278                                         struct security_descriptor **ppdesc)
2279 {
2280         time_t timestamp = 0;
2281         char *stripped = NULL;
2282         NTSTATUS status;
2283         char *conv;
2284         struct smb_filename *conv_smb_fname = NULL;
2285
2286         if (!shadow_copy2_strip_snapshot(talloc_tos(),
2287                                         handle,
2288                                         smb_fname->base_name,
2289                                         &timestamp,
2290                                         &stripped)) {
2291                 return map_nt_error_from_unix(errno);
2292         }
2293         if (timestamp == 0) {
2294                 return SMB_VFS_NEXT_GET_NT_ACL(handle, smb_fname, security_info,
2295                                                mem_ctx, ppdesc);
2296         }
2297         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2298         TALLOC_FREE(stripped);
2299         if (conv == NULL) {
2300                 return map_nt_error_from_unix(errno);
2301         }
2302         conv_smb_fname = synthetic_smb_fname(talloc_tos(),
2303                                         conv,
2304                                         NULL,
2305                                         NULL,
2306                                         smb_fname->flags);
2307         if (conv_smb_fname == NULL) {
2308                 TALLOC_FREE(conv);
2309                 return NT_STATUS_NO_MEMORY;
2310         }
2311         status = SMB_VFS_NEXT_GET_NT_ACL(handle, conv_smb_fname, security_info,
2312                                          mem_ctx, ppdesc);
2313         TALLOC_FREE(conv);
2314         TALLOC_FREE(conv_smb_fname);
2315         return status;
2316 }
2317
2318 static int shadow_copy2_mkdir(vfs_handle_struct *handle,
2319                                 const struct smb_filename *smb_fname,
2320                                 mode_t mode)
2321 {
2322         time_t timestamp = 0;
2323
2324         if (!shadow_copy2_strip_snapshot(talloc_tos(),
2325                                         handle,
2326                                         smb_fname->base_name,
2327                                         &timestamp,
2328                                         NULL)) {
2329                 return -1;
2330         }
2331         if (timestamp != 0) {
2332                 errno = EROFS;
2333                 return -1;
2334         }
2335         return SMB_VFS_NEXT_MKDIR(handle, smb_fname, mode);
2336 }
2337
2338 static int shadow_copy2_rmdir(vfs_handle_struct *handle,
2339                                 const struct smb_filename *smb_fname)
2340 {
2341         time_t timestamp = 0;
2342
2343         if (!shadow_copy2_strip_snapshot(talloc_tos(),
2344                                         handle,
2345                                         smb_fname->base_name,
2346                                         &timestamp,
2347                                         NULL)) {
2348                 return -1;
2349         }
2350         if (timestamp != 0) {
2351                 errno = EROFS;
2352                 return -1;
2353         }
2354         return SMB_VFS_NEXT_RMDIR(handle, smb_fname);
2355 }
2356
2357 static int shadow_copy2_chflags(vfs_handle_struct *handle,
2358                                 const struct smb_filename *smb_fname,
2359                                 unsigned int flags)
2360 {
2361         time_t timestamp = 0;
2362
2363         if (!shadow_copy2_strip_snapshot(talloc_tos(),
2364                                         handle,
2365                                         smb_fname->base_name,
2366                                         &timestamp,
2367                                         NULL)) {
2368                 return -1;
2369         }
2370         if (timestamp != 0) {
2371                 errno = EROFS;
2372                 return -1;
2373         }
2374         return SMB_VFS_NEXT_CHFLAGS(handle, smb_fname, flags);
2375 }
2376
2377 static ssize_t shadow_copy2_getxattr(vfs_handle_struct *handle,
2378                                 const struct smb_filename *smb_fname,
2379                                 const char *aname,
2380                                 void *value,
2381                                 size_t size)
2382 {
2383         time_t timestamp = 0;
2384         char *stripped = NULL;
2385         ssize_t ret;
2386         int saved_errno = 0;
2387         char *conv;
2388         struct smb_filename *conv_smb_fname = NULL;
2389
2390         if (!shadow_copy2_strip_snapshot(talloc_tos(),
2391                                 handle,
2392                                 smb_fname->base_name,
2393                                 &timestamp,
2394                                 &stripped)) {
2395                 return -1;
2396         }
2397         if (timestamp == 0) {
2398                 return SMB_VFS_NEXT_GETXATTR(handle, smb_fname, aname, value,
2399                                              size);
2400         }
2401         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2402         TALLOC_FREE(stripped);
2403         if (conv == NULL) {
2404                 return -1;
2405         }
2406
2407         conv_smb_fname = synthetic_smb_fname(talloc_tos(),
2408                                         conv,
2409                                         NULL,
2410                                         NULL,
2411                                         smb_fname->flags);
2412         if (conv_smb_fname == NULL) {
2413                 TALLOC_FREE(conv);
2414                 return -1;
2415         }
2416
2417         ret = SMB_VFS_NEXT_GETXATTR(handle, conv_smb_fname, aname, value, size);
2418         if (ret == -1) {
2419                 saved_errno = errno;
2420         }
2421         TALLOC_FREE(conv_smb_fname);
2422         TALLOC_FREE(conv);
2423         if (saved_errno != 0) {
2424                 errno = saved_errno;
2425         }
2426         return ret;
2427 }
2428
2429 static ssize_t shadow_copy2_listxattr(struct vfs_handle_struct *handle,
2430                                       const struct smb_filename *smb_fname,
2431                                       char *list, size_t size)
2432 {
2433         time_t timestamp = 0;
2434         char *stripped = NULL;
2435         ssize_t ret;
2436         int saved_errno = 0;
2437         char *conv;
2438         struct smb_filename *conv_smb_fname = NULL;
2439
2440         if (!shadow_copy2_strip_snapshot(talloc_tos(),
2441                                 handle,
2442                                 smb_fname->base_name,
2443                                 &timestamp,
2444                                 &stripped)) {
2445                 return -1;
2446         }
2447         if (timestamp == 0) {
2448                 return SMB_VFS_NEXT_LISTXATTR(handle, smb_fname, list, size);
2449         }
2450         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2451         TALLOC_FREE(stripped);
2452         if (conv == NULL) {
2453                 return -1;
2454         }
2455         conv_smb_fname = synthetic_smb_fname(talloc_tos(),
2456                                         conv,
2457                                         NULL,
2458                                         NULL,
2459                                         smb_fname->flags);
2460         if (conv_smb_fname == NULL) {
2461                 TALLOC_FREE(conv);
2462                 return -1;
2463         }
2464         ret = SMB_VFS_NEXT_LISTXATTR(handle, conv_smb_fname, list, size);
2465         if (ret == -1) {
2466                 saved_errno = errno;
2467         }
2468         TALLOC_FREE(conv_smb_fname);
2469         TALLOC_FREE(conv);
2470         if (saved_errno != 0) {
2471                 errno = saved_errno;
2472         }
2473         return ret;
2474 }
2475
2476 static int shadow_copy2_removexattr(vfs_handle_struct *handle,
2477                                 const struct smb_filename *smb_fname,
2478                                 const char *aname)
2479 {
2480         time_t timestamp = 0;
2481
2482         if (!shadow_copy2_strip_snapshot(talloc_tos(),
2483                                 handle,
2484                                 smb_fname->base_name,
2485                                 &timestamp,
2486                                 NULL)) {
2487                 return -1;
2488         }
2489         if (timestamp != 0) {
2490                 errno = EROFS;
2491                 return -1;
2492         }
2493         return SMB_VFS_NEXT_REMOVEXATTR(handle, smb_fname, aname);
2494 }
2495
2496 static int shadow_copy2_setxattr(struct vfs_handle_struct *handle,
2497                                  const struct smb_filename *smb_fname,
2498                                  const char *aname, const void *value,
2499                                  size_t size, int flags)
2500 {
2501         time_t timestamp = 0;
2502
2503         if (!shadow_copy2_strip_snapshot(talloc_tos(),
2504                                 handle,
2505                                 smb_fname->base_name,
2506                                 &timestamp,
2507                                 NULL)) {
2508                 return -1;
2509         }
2510         if (timestamp != 0) {
2511                 errno = EROFS;
2512                 return -1;
2513         }
2514         return SMB_VFS_NEXT_SETXATTR(handle, smb_fname,
2515                                 aname, value, size, flags);
2516 }
2517
2518 static int shadow_copy2_get_real_filename(struct vfs_handle_struct *handle,
2519                                           const char *path,
2520                                           const char *name,
2521                                           TALLOC_CTX *mem_ctx,
2522                                           char **found_name)
2523 {
2524         time_t timestamp = 0;
2525         char *stripped = NULL;
2526         ssize_t ret;
2527         int saved_errno = 0;
2528         char *conv;
2529
2530         DEBUG(10, ("shadow_copy2_get_real_filename called for path=[%s], "
2531                    "name=[%s]\n", path, name));
2532
2533         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, path,
2534                                          &timestamp, &stripped)) {
2535                 DEBUG(10, ("shadow_copy2_strip_snapshot failed\n"));
2536                 return -1;
2537         }
2538         if (timestamp == 0) {
2539                 DEBUG(10, ("timestamp == 0\n"));
2540                 return SMB_VFS_NEXT_GET_REAL_FILENAME(handle, path, name,
2541                                                       mem_ctx, found_name);
2542         }
2543         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2544         TALLOC_FREE(stripped);
2545         if (conv == NULL) {
2546                 DEBUG(10, ("shadow_copy2_convert failed\n"));
2547                 return -1;
2548         }
2549         DEBUG(10, ("Calling NEXT_GET_REAL_FILE_NAME for conv=[%s], "
2550                    "name=[%s]\n", conv, name));
2551         ret = SMB_VFS_NEXT_GET_REAL_FILENAME(handle, conv, name,
2552                                              mem_ctx, found_name);
2553         DEBUG(10, ("NEXT_REAL_FILE_NAME returned %d\n", (int)ret));
2554         if (ret == -1) {
2555                 saved_errno = errno;
2556         }
2557         TALLOC_FREE(conv);
2558         if (saved_errno != 0) {
2559                 errno = saved_errno;
2560         }
2561         return ret;
2562 }
2563
2564 static const char *shadow_copy2_connectpath(struct vfs_handle_struct *handle,
2565                                         const struct smb_filename *smb_fname_in)
2566 {
2567         time_t timestamp = 0;
2568         char *stripped = NULL;
2569         char *tmp = NULL;
2570         const char *fname = smb_fname_in->base_name;
2571         struct smb_filename smb_fname = {0};
2572         struct smb_filename *result_fname = NULL;
2573         char *result = NULL;
2574         char *parent_dir = NULL;
2575         int saved_errno = 0;
2576         size_t rootpath_len = 0;
2577         struct shadow_copy2_private *priv = NULL;
2578
2579         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
2580                                 return NULL);
2581
2582         DBG_DEBUG("Calc connect path for [%s]\n", fname);
2583
2584         if (priv->shadow_connectpath != NULL) {
2585                 DBG_DEBUG("cached connect path is [%s]\n",
2586                         priv->shadow_connectpath);
2587                 return priv->shadow_connectpath;
2588         }
2589
2590         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
2591                                          &timestamp, &stripped)) {
2592                 goto done;
2593         }
2594         if (timestamp == 0) {
2595                 return SMB_VFS_NEXT_CONNECTPATH(handle, smb_fname_in);
2596         }
2597
2598         tmp = shadow_copy2_do_convert(talloc_tos(), handle, stripped, timestamp,
2599                                       &rootpath_len);
2600         if (tmp == NULL) {
2601                 if (errno != ENOENT) {
2602                         goto done;
2603                 }
2604
2605                 /*
2606                  * If the converted path does not exist, and converting
2607                  * the parent yields something that does exist, then
2608                  * this path refers to something that has not been
2609                  * created yet, relative to the parent path.
2610                  * The snapshot finding is relative to the parent.
2611                  * (usually snapshots are read/only but this is not
2612                  * necessarily true).
2613                  * This code also covers getting a wildcard in the
2614                  * last component, because this function is called
2615                  * prior to sanitizing the path, and in SMB1 we may
2616                  * get wildcards in path names.
2617                  */
2618                 if (!parent_dirname(talloc_tos(), stripped, &parent_dir,
2619                                     NULL)) {
2620                         errno = ENOMEM;
2621                         goto done;
2622                 }
2623
2624                 tmp = shadow_copy2_do_convert(talloc_tos(), handle, parent_dir,
2625                                               timestamp, &rootpath_len);
2626                 if (tmp == NULL) {
2627                         goto done;
2628                 }
2629         }
2630
2631         DBG_DEBUG("converted path is [%s] root path is [%.*s]\n", tmp,
2632                   (int)rootpath_len, tmp);
2633
2634         tmp[rootpath_len] = '\0';
2635         smb_fname = (struct smb_filename) { .base_name = tmp };
2636
2637         result_fname = SMB_VFS_NEXT_REALPATH(handle, priv, &smb_fname);
2638         if (result_fname == NULL) {
2639                 goto done;
2640         }
2641
2642         /*
2643          * SMB_VFS_NEXT_REALPATH returns a talloc'ed string.
2644          * Don't leak memory.
2645          */
2646         TALLOC_FREE(priv->shadow_realpath);
2647         priv->shadow_realpath = result_fname;
2648         result = priv->shadow_realpath->base_name;
2649
2650         DBG_DEBUG("connect path is [%s]\n", result);
2651
2652 done:
2653         if (result == NULL) {
2654                 saved_errno = errno;
2655         }
2656         TALLOC_FREE(tmp);
2657         TALLOC_FREE(stripped);
2658         TALLOC_FREE(parent_dir);
2659         if (saved_errno != 0) {
2660                 errno = saved_errno;
2661         }
2662         return result;
2663 }
2664
2665 static uint64_t shadow_copy2_disk_free(vfs_handle_struct *handle,
2666                                 const struct smb_filename *smb_fname,
2667                                 uint64_t *bsize,
2668                                 uint64_t *dfree,
2669                                 uint64_t *dsize)
2670 {
2671         time_t timestamp = 0;
2672         char *stripped = NULL;
2673         int saved_errno = 0;
2674         char *conv = NULL;
2675         struct smb_filename *conv_smb_fname = NULL;
2676         uint64_t ret = (uint64_t)-1;
2677
2678         if (!shadow_copy2_strip_snapshot(talloc_tos(),
2679                                 handle,
2680                                 smb_fname->base_name,
2681                                 &timestamp,
2682                                 &stripped)) {
2683                 return (uint64_t)-1;
2684         }
2685         if (timestamp == 0) {
2686                 return SMB_VFS_NEXT_DISK_FREE(handle, smb_fname,
2687                                               bsize, dfree, dsize);
2688         }
2689         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2690         TALLOC_FREE(stripped);
2691         if (conv == NULL) {
2692                 return (uint64_t)-1;
2693         }
2694         conv_smb_fname = synthetic_smb_fname(talloc_tos(),
2695                                         conv,
2696                                         NULL,
2697                                         NULL,
2698                                         smb_fname->flags);
2699         if (conv_smb_fname == NULL) {
2700                 TALLOC_FREE(conv);
2701                 return (uint64_t)-1;
2702         }
2703         ret = SMB_VFS_NEXT_DISK_FREE(handle, conv_smb_fname,
2704                                 bsize, dfree, dsize);
2705         if (ret == (uint64_t)-1) {
2706                 saved_errno = errno;
2707         }
2708         TALLOC_FREE(conv);
2709         TALLOC_FREE(conv_smb_fname);
2710         if (saved_errno != 0) {
2711                 errno = saved_errno;
2712         }
2713         return ret;
2714 }
2715
2716 static int shadow_copy2_get_quota(vfs_handle_struct *handle,
2717                                 const struct smb_filename *smb_fname,
2718                                 enum SMB_QUOTA_TYPE qtype,
2719                                 unid_t id,
2720                                 SMB_DISK_QUOTA *dq)
2721 {
2722         time_t timestamp = 0;
2723         char *stripped = NULL;
2724         int ret;
2725         int saved_errno = 0;
2726         char *conv;
2727         struct smb_filename *conv_smb_fname = NULL;
2728
2729         if (!shadow_copy2_strip_snapshot(talloc_tos(),
2730                                 handle,
2731                                 smb_fname->base_name,
2732                                 &timestamp,
2733                                 &stripped)) {
2734                 return -1;
2735         }
2736         if (timestamp == 0) {
2737                 return SMB_VFS_NEXT_GET_QUOTA(handle, smb_fname, qtype, id, dq);
2738         }
2739
2740         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2741         TALLOC_FREE(stripped);
2742         if (conv == NULL) {
2743                 return -1;
2744         }
2745         conv_smb_fname = synthetic_smb_fname(talloc_tos(),
2746                                         conv,
2747                                         NULL,
2748                                         NULL,
2749                                         smb_fname->flags);
2750         if (conv_smb_fname == NULL) {
2751                 TALLOC_FREE(conv);
2752                 return -1;
2753         }
2754         ret = SMB_VFS_NEXT_GET_QUOTA(handle, conv_smb_fname, qtype, id, dq);
2755
2756         if (ret == -1) {
2757                 saved_errno = errno;
2758         }
2759         TALLOC_FREE(conv);
2760         TALLOC_FREE(conv_smb_fname);
2761         if (saved_errno != 0) {
2762                 errno = saved_errno;
2763         }
2764
2765         return ret;
2766 }
2767
2768 static ssize_t shadow_copy2_pwrite(vfs_handle_struct *handle,
2769                                    files_struct *fsp,
2770                                    const void *data,
2771                                    size_t n,
2772                                    off_t offset)
2773 {
2774         ssize_t nwritten;
2775
2776         nwritten = SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset);
2777         if (nwritten == -1) {
2778                 if (errno == EBADF && fsp->can_write) {
2779                         errno = EROFS;
2780                 }
2781         }
2782
2783         return nwritten;
2784 }
2785
2786 struct shadow_copy2_pwrite_state {
2787         vfs_handle_struct *handle;
2788         files_struct *fsp;
2789         ssize_t ret;
2790         struct vfs_aio_state vfs_aio_state;
2791 };
2792
2793 static void shadow_copy2_pwrite_done(struct tevent_req *subreq);
2794
2795 static struct tevent_req *shadow_copy2_pwrite_send(
2796         struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx,
2797         struct tevent_context *ev, struct files_struct *fsp,
2798         const void *data, size_t n, off_t offset)
2799 {
2800         struct tevent_req *req = NULL, *subreq = NULL;
2801         struct shadow_copy2_pwrite_state *state = NULL;
2802
2803         req = tevent_req_create(mem_ctx, &state,
2804                                 struct shadow_copy2_pwrite_state);
2805         if (req == NULL) {
2806                 return NULL;
2807         }
2808         state->handle = handle;
2809         state->fsp = fsp;
2810
2811         subreq = SMB_VFS_NEXT_PWRITE_SEND(state,
2812                                           ev,
2813                                           handle,
2814                                           fsp,
2815                                           data,
2816                                           n,
2817                                           offset);
2818         if (tevent_req_nomem(subreq, req)) {
2819                 return tevent_req_post(req, ev);
2820         }
2821         tevent_req_set_callback(subreq, shadow_copy2_pwrite_done, req);
2822
2823         return req;
2824 }
2825
2826 static void shadow_copy2_pwrite_done(struct tevent_req *subreq)
2827 {
2828         struct tevent_req *req = tevent_req_callback_data(
2829                 subreq, struct tevent_req);
2830         struct shadow_copy2_pwrite_state *state = tevent_req_data(
2831                 req, struct shadow_copy2_pwrite_state);
2832
2833         state->ret = SMB_VFS_PWRITE_RECV(subreq, &state->vfs_aio_state);
2834         TALLOC_FREE(subreq);
2835         if (state->ret == -1) {
2836                 tevent_req_error(req, state->vfs_aio_state.error);
2837                 return;
2838         }
2839
2840         tevent_req_done(req);
2841 }
2842
2843 static ssize_t shadow_copy2_pwrite_recv(struct tevent_req *req,
2844                                           struct vfs_aio_state *vfs_aio_state)
2845 {
2846         struct shadow_copy2_pwrite_state *state = tevent_req_data(
2847                 req, struct shadow_copy2_pwrite_state);
2848
2849         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
2850                 if ((vfs_aio_state->error == EBADF) &&
2851                     state->fsp->can_write)
2852                 {
2853                         vfs_aio_state->error = EROFS;
2854                         errno = EROFS;
2855                 }
2856                 return -1;
2857         }
2858
2859         *vfs_aio_state = state->vfs_aio_state;
2860         return state->ret;
2861 }
2862
2863 static int shadow_copy2_connect(struct vfs_handle_struct *handle,
2864                                 const char *service, const char *user)
2865 {
2866         struct shadow_copy2_config *config;
2867         struct shadow_copy2_private *priv;
2868         int ret;
2869         const char *snapdir;
2870         const char *snapprefix = NULL;
2871         const char *delimiter;
2872         const char *gmt_format;
2873         const char *sort_order;
2874         const char *basedir = NULL;
2875         const char *snapsharepath = NULL;
2876         const char *mount_point;
2877
2878         DEBUG(10, (__location__ ": cnum[%u], connectpath[%s]\n",
2879                    (unsigned)handle->conn->cnum,
2880                    handle->conn->connectpath));
2881
2882         ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
2883         if (ret < 0) {
2884                 return ret;
2885         }
2886
2887         priv = talloc_zero(handle->conn, struct shadow_copy2_private);
2888         if (priv == NULL) {
2889                 DBG_ERR("talloc_zero() failed\n");
2890                 errno = ENOMEM;
2891                 return -1;
2892         }
2893
2894         priv->snaps = talloc_zero(priv, struct shadow_copy2_snaplist_info);
2895         if (priv->snaps == NULL) {
2896                 DBG_ERR("talloc_zero() failed\n");
2897                 errno = ENOMEM;
2898                 return -1;
2899         }
2900
2901         config = talloc_zero(priv, struct shadow_copy2_config);
2902         if (config == NULL) {
2903                 DEBUG(0, ("talloc_zero() failed\n"));
2904                 errno = ENOMEM;
2905                 return -1;
2906         }
2907
2908         priv->config = config;
2909
2910         gmt_format = lp_parm_const_string(SNUM(handle->conn),
2911                                           "shadow", "format",
2912                                           GMT_FORMAT);
2913         config->gmt_format = talloc_strdup(config, gmt_format);
2914         if (config->gmt_format == NULL) {
2915                 DEBUG(0, ("talloc_strdup() failed\n"));
2916                 errno = ENOMEM;
2917                 return -1;
2918         }
2919
2920         /* config->gmt_format must not contain a path separator. */
2921         if (strchr(config->gmt_format, '/') != NULL) {
2922                 DEBUG(0, ("shadow:format %s must not contain a /"
2923                         "character. Unable to initialize module.\n",
2924                         config->gmt_format));
2925                 errno = EINVAL;
2926                 return -1;
2927         }
2928
2929         config->use_sscanf = lp_parm_bool(SNUM(handle->conn),
2930                                           "shadow", "sscanf", false);
2931
2932         config->use_localtime = lp_parm_bool(SNUM(handle->conn),
2933                                              "shadow", "localtime",
2934                                              false);
2935
2936         snapdir = lp_parm_const_string(SNUM(handle->conn),
2937                                        "shadow", "snapdir",
2938                                        ".snapshots");
2939         config->snapdir = talloc_strdup(config, snapdir);
2940         if (config->snapdir == NULL) {
2941                 DEBUG(0, ("talloc_strdup() failed\n"));
2942                 errno = ENOMEM;
2943                 return -1;
2944         }
2945
2946         snapprefix = lp_parm_const_string(SNUM(handle->conn),
2947                                        "shadow", "snapprefix",
2948                                        NULL);
2949         if (snapprefix != NULL) {
2950                 priv->snaps->regex = talloc_zero(priv->snaps, regex_t);
2951                 if (priv->snaps->regex == NULL) {
2952                         DBG_ERR("talloc_zero() failed\n");
2953                         errno = ENOMEM;
2954                         return -1;
2955                 }
2956
2957                 /* pre-compute regex rule for matching pattern later */
2958                 ret = regcomp(priv->snaps->regex, snapprefix, 0);
2959                 if (ret) {
2960                         DBG_ERR("Failed to create regex object\n");
2961                         return -1;
2962                 }
2963         }
2964
2965         delimiter = lp_parm_const_string(SNUM(handle->conn),
2966                                        "shadow", "delimiter",
2967                                        "_GMT");
2968         if (delimiter != NULL) {
2969                 priv->config->delimiter = talloc_strdup(priv->config, delimiter);
2970                 if (priv->config->delimiter == NULL) {
2971                         DBG_ERR("talloc_strdup() failed\n");
2972                         errno = ENOMEM;
2973                         return -1;
2974                 }
2975         }
2976
2977         config->snapdirseverywhere = lp_parm_bool(SNUM(handle->conn),
2978                                                   "shadow",
2979                                                   "snapdirseverywhere",
2980                                                   false);
2981
2982         config->crossmountpoints = lp_parm_bool(SNUM(handle->conn),
2983                                                 "shadow", "crossmountpoints",
2984                                                 false);
2985
2986         if (config->crossmountpoints && !config->snapdirseverywhere) {
2987                 DBG_WARNING("Warning: 'crossmountpoints' depends on "
2988                             "'snapdirseverywhere'. Disabling crossmountpoints.\n");
2989         }
2990
2991         config->fixinodes = lp_parm_bool(SNUM(handle->conn),
2992                                          "shadow", "fixinodes",
2993                                          false);
2994
2995         sort_order = lp_parm_const_string(SNUM(handle->conn),
2996                                           "shadow", "sort", "desc");
2997         config->sort_order = talloc_strdup(config, sort_order);
2998         if (config->sort_order == NULL) {
2999                 DEBUG(0, ("talloc_strdup() failed\n"));
3000                 errno = ENOMEM;
3001                 return -1;
3002         }
3003
3004         mount_point = lp_parm_const_string(SNUM(handle->conn),
3005                                            "shadow", "mountpoint", NULL);
3006         if (mount_point != NULL) {
3007                 if (mount_point[0] != '/') {
3008                         DEBUG(1, (__location__ " Warning: 'mountpoint' is "
3009                                   "relative ('%s'), but it has to be an "
3010                                   "absolute path. Ignoring provided value.\n",
3011                                   mount_point));
3012                         mount_point = NULL;
3013                 } else {
3014                         char *p;
3015                         p = strstr(handle->conn->connectpath, mount_point);
3016                         if (p != handle->conn->connectpath) {
3017                                 DBG_WARNING("Warning: the share root (%s) is "
3018                                             "not a subdirectory of the "
3019                                             "specified mountpoint (%s). "
3020                                             "Ignoring provided value.\n",
3021                                             handle->conn->connectpath,
3022                                             mount_point);
3023                                 mount_point = NULL;
3024                         }
3025                 }
3026         }
3027
3028         if (mount_point != NULL) {
3029                 config->mount_point = talloc_strdup(config, mount_point);
3030                 if (config->mount_point == NULL) {
3031                         DEBUG(0, (__location__ " talloc_strdup() failed\n"));
3032                         return -1;
3033                 }
3034         } else {
3035                 config->mount_point = shadow_copy2_find_mount_point(config,
3036                                                                     handle);
3037                 if (config->mount_point == NULL) {
3038                         DBG_WARNING("shadow_copy2_find_mount_point "
3039                                     "of the share root '%s' failed: %s\n",
3040                                     handle->conn->connectpath, strerror(errno));
3041                         return -1;
3042                 }
3043         }
3044
3045         basedir = lp_parm_const_string(SNUM(handle->conn),
3046                                        "shadow", "basedir", NULL);
3047
3048         if (basedir != NULL) {
3049                 if (basedir[0] != '/') {
3050                         DEBUG(1, (__location__ " Warning: 'basedir' is "
3051                                   "relative ('%s'), but it has to be an "
3052                                   "absolute path. Disabling basedir.\n",
3053                                   basedir));
3054                         basedir = NULL;
3055                 } else {
3056                         char *p;
3057                         p = strstr(basedir, config->mount_point);
3058                         if (p != basedir) {
3059                                 DEBUG(1, ("Warning: basedir (%s) is not a "
3060                                           "subdirectory of the share root's "
3061                                           "mount point (%s). "
3062                                           "Disabling basedir\n",
3063                                           basedir, config->mount_point));
3064                                 basedir = NULL;
3065                         }
3066                 }
3067         }
3068
3069         if (config->snapdirseverywhere && basedir != NULL) {
3070                 DEBUG(1, (__location__ " Warning: 'basedir' is incompatible "
3071                           "with 'snapdirseverywhere'. Disabling basedir.\n"));
3072                 basedir = NULL;
3073         }
3074
3075         snapsharepath = lp_parm_const_string(SNUM(handle->conn), "shadow",
3076                                              "snapsharepath", NULL);
3077         if (snapsharepath != NULL) {
3078                 if (snapsharepath[0] == '/') {
3079                         DBG_WARNING("Warning: 'snapsharepath' is "
3080                                     "absolute ('%s'), but it has to be a "
3081                                     "relative path. Disabling snapsharepath.\n",
3082                                     snapsharepath);
3083                         snapsharepath = NULL;
3084                 }
3085                 if (config->snapdirseverywhere && snapsharepath != NULL) {
3086                         DBG_WARNING("Warning: 'snapsharepath' is incompatible "
3087                                     "with 'snapdirseverywhere'. Disabling "
3088                                     "snapsharepath.\n");
3089                         snapsharepath = NULL;
3090                 }
3091         }
3092
3093         if (basedir != NULL && snapsharepath != NULL) {
3094                 DBG_WARNING("Warning: 'snapsharepath' is incompatible with "
3095                             "'basedir'. Disabling snapsharepath\n");
3096                 snapsharepath = NULL;
3097         }
3098
3099         if (snapsharepath != NULL) {
3100                 config->rel_connectpath = talloc_strdup(config, snapsharepath);
3101                 if (config->rel_connectpath == NULL) {
3102                         DBG_ERR("talloc_strdup() failed\n");
3103                         errno = ENOMEM;
3104                         return -1;
3105                 }
3106         }
3107
3108         if (basedir == NULL) {
3109                 basedir = config->mount_point;
3110         }
3111
3112         if (config->rel_connectpath == NULL &&
3113             strlen(basedir) < strlen(handle->conn->connectpath)) {
3114                 config->rel_connectpath = talloc_strdup(config,
3115                         handle->conn->connectpath + strlen(basedir));
3116                 if (config->rel_connectpath == NULL) {
3117                         DEBUG(0, ("talloc_strdup() failed\n"));
3118                         errno = ENOMEM;
3119                         return -1;
3120                 }
3121         }
3122
3123         if (config->snapdir[0] == '/') {
3124                 config->snapdir_absolute = true;
3125
3126                 if (config->snapdirseverywhere == true) {
3127                         DEBUG(1, (__location__ " Warning: An absolute snapdir "
3128                                   "is incompatible with 'snapdirseverywhere', "
3129                                   "setting 'snapdirseverywhere' to false.\n"));
3130                         config->snapdirseverywhere = false;
3131                 }
3132
3133                 if (config->crossmountpoints == true) {
3134                         DEBUG(1, (__location__ " Warning: 'crossmountpoints' "
3135                                   "is not supported with an absolute snapdir. "
3136                                   "Disabling it.\n"));
3137                         config->crossmountpoints = false;
3138                 }
3139
3140                 config->snapshot_basepath = config->snapdir;
3141         } else {
3142                 config->snapshot_basepath = talloc_asprintf(config, "%s/%s",
3143                                 config->mount_point, config->snapdir);
3144                 if (config->snapshot_basepath == NULL) {
3145                         DEBUG(0, ("talloc_asprintf() failed\n"));
3146                         errno = ENOMEM;
3147                         return -1;
3148                 }
3149         }
3150
3151         trim_string(config->mount_point, NULL, "/");
3152         trim_string(config->rel_connectpath, "/", "/");
3153         trim_string(config->snapdir, NULL, "/");
3154         trim_string(config->snapshot_basepath, NULL, "/");
3155
3156         DEBUG(10, ("shadow_copy2_connect: configuration:\n"
3157                    "  share root: '%s'\n"
3158                    "  mountpoint: '%s'\n"
3159                    "  rel share root: '%s'\n"
3160                    "  snapdir: '%s'\n"
3161                    "  snapprefix: '%s'\n"
3162                    "  delimiter: '%s'\n"
3163                    "  snapshot base path: '%s'\n"
3164                    "  format: '%s'\n"
3165                    "  use sscanf: %s\n"
3166                    "  snapdirs everywhere: %s\n"
3167                    "  cross mountpoints: %s\n"
3168                    "  fix inodes: %s\n"
3169                    "  sort order: %s\n"
3170                    "",
3171                    handle->conn->connectpath,
3172                    config->mount_point,
3173                    config->rel_connectpath,
3174                    config->snapdir,
3175                    snapprefix,
3176                    config->delimiter,
3177                    config->snapshot_basepath,
3178                    config->gmt_format,
3179                    config->use_sscanf ? "yes" : "no",
3180                    config->snapdirseverywhere ? "yes" : "no",
3181                    config->crossmountpoints ? "yes" : "no",
3182                    config->fixinodes ? "yes" : "no",
3183                    config->sort_order
3184                    ));
3185
3186
3187         SMB_VFS_HANDLE_SET_DATA(handle, priv,
3188                                 NULL, struct shadow_copy2_private,
3189                                 return -1);
3190
3191         return 0;
3192 }
3193
3194 static struct vfs_fn_pointers vfs_shadow_copy2_fns = {
3195         .connect_fn = shadow_copy2_connect,
3196         .opendir_fn = shadow_copy2_opendir,
3197         .disk_free_fn = shadow_copy2_disk_free,
3198         .get_quota_fn = shadow_copy2_get_quota,
3199         .renameat_fn = shadow_copy2_renameat,
3200         .linkat_fn = shadow_copy2_linkat,
3201         .symlink_fn = shadow_copy2_symlink,
3202         .symlinkat_fn = shadow_copy2_symlinkat,
3203         .stat_fn = shadow_copy2_stat,
3204         .lstat_fn = shadow_copy2_lstat,
3205         .fstat_fn = shadow_copy2_fstat,
3206         .open_fn = shadow_copy2_open,
3207         .unlink_fn = shadow_copy2_unlink,
3208         .chmod_fn = shadow_copy2_chmod,
3209         .chown_fn = shadow_copy2_chown,
3210         .chdir_fn = shadow_copy2_chdir,
3211         .ntimes_fn = shadow_copy2_ntimes,
3212         .readlinkat_fn = shadow_copy2_readlinkat,
3213         .mknodat_fn = shadow_copy2_mknodat,
3214         .realpath_fn = shadow_copy2_realpath,
3215         .get_nt_acl_fn = shadow_copy2_get_nt_acl,
3216         .fget_nt_acl_fn = shadow_copy2_fget_nt_acl,
3217         .get_shadow_copy_data_fn = shadow_copy2_get_shadow_copy_data,
3218         .mkdir_fn = shadow_copy2_mkdir,
3219         .rmdir_fn = shadow_copy2_rmdir,
3220         .getxattr_fn = shadow_copy2_getxattr,
3221         .getxattrat_send_fn = vfs_not_implemented_getxattrat_send,
3222         .getxattrat_recv_fn = vfs_not_implemented_getxattrat_recv,
3223         .listxattr_fn = shadow_copy2_listxattr,
3224         .removexattr_fn = shadow_copy2_removexattr,
3225         .setxattr_fn = shadow_copy2_setxattr,
3226         .chflags_fn = shadow_copy2_chflags,
3227         .get_real_filename_fn = shadow_copy2_get_real_filename,
3228         .pwrite_fn = shadow_copy2_pwrite,
3229         .pwrite_send_fn = shadow_copy2_pwrite_send,
3230         .pwrite_recv_fn = shadow_copy2_pwrite_recv,
3231         .connectpath_fn = shadow_copy2_connectpath,
3232 };
3233
3234 static_decl_vfs;
3235 NTSTATUS vfs_shadow_copy2_init(TALLOC_CTX *ctx)
3236 {
3237         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3238                                 "shadow_copy2", &vfs_shadow_copy2_fns);
3239 }