Fix spelling mistakes
[bbaumbach/samba-autobuild/.git] / source3 / modules / vfs_shadow_copy2.c
1 /*
2  * shadow_copy2: a shadow copy module (second implementation)
3  *
4  * Copyright (C) Andrew Tridgell   2007 (portions taken from shadow_copy2)
5  * Copyright (C) Ed Plese          2009
6  * Copyright (C) Volker Lendecke   2011
7  * Copyright (C) Christian Ambach  2011
8  * Copyright (C) Michael Adam      2013
9  * Copyright (C) Rajesh Joseph     2016
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25
26 /*
27  * This is a second implemetation of a shadow copy module for exposing
28  * file system snapshots to windows clients as shadow copies.
29  *
30  * See the manual page for documentation.
31  */
32
33 #include "includes.h"
34 #include "smbd/smbd.h"
35 #include "system/filesys.h"
36 #include "include/ntioctl.h"
37 #include "util_tdb.h"
38 #include "lib/util_path.h"
39 #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_rename(vfs_handle_struct *handle,
1139                                const struct smb_filename *smb_fname_src,
1140                                const struct smb_filename *smb_fname_dst)
1141 {
1142         time_t timestamp_src = 0;
1143         time_t timestamp_dst = 0;
1144         char *snappath_src = NULL;
1145         char *snappath_dst = NULL;
1146
1147         if (!shadow_copy2_strip_snapshot_internal(talloc_tos(), handle,
1148                                          smb_fname_src->base_name,
1149                                          &timestamp_src, NULL, &snappath_src,
1150                                          NULL)) {
1151                 return -1;
1152         }
1153         if (!shadow_copy2_strip_snapshot_internal(talloc_tos(), handle,
1154                                          smb_fname_dst->base_name,
1155                                          &timestamp_dst, NULL, &snappath_dst,
1156                                          NULL)) {
1157                 return -1;
1158         }
1159         if (timestamp_src != 0) {
1160                 errno = EXDEV;
1161                 return -1;
1162         }
1163         if (timestamp_dst != 0) {
1164                 errno = EROFS;
1165                 return -1;
1166         }
1167         /*
1168          * Don't allow rename on already converted paths.
1169          */
1170         if (snappath_src != NULL) {
1171                 errno = EXDEV;
1172                 return -1;
1173         }
1174         if (snappath_dst != NULL) {
1175                 errno = EROFS;
1176                 return -1;
1177         }
1178         return SMB_VFS_NEXT_RENAME(handle, smb_fname_src, smb_fname_dst);
1179 }
1180
1181 static int shadow_copy2_symlink(vfs_handle_struct *handle,
1182                         const char *link_contents,
1183                         const struct smb_filename *new_smb_fname)
1184 {
1185         time_t timestamp_old = 0;
1186         time_t timestamp_new = 0;
1187         char *snappath_old = NULL;
1188         char *snappath_new = NULL;
1189
1190         if (!shadow_copy2_strip_snapshot_internal(talloc_tos(),
1191                                 handle,
1192                                 link_contents,
1193                                 &timestamp_old,
1194                                 NULL,
1195                                 &snappath_old,
1196                                 NULL)) {
1197                 return -1;
1198         }
1199         if (!shadow_copy2_strip_snapshot_internal(talloc_tos(),
1200                                 handle,
1201                                 new_smb_fname->base_name,
1202                                 &timestamp_new,
1203                                 NULL,
1204                                 &snappath_new,
1205                                 NULL)) {
1206                 return -1;
1207         }
1208         if ((timestamp_old != 0) || (timestamp_new != 0)) {
1209                 errno = EROFS;
1210                 return -1;
1211         }
1212         /*
1213          * Don't allow symlinks on already converted paths.
1214          */
1215         if ((snappath_old != NULL) || (snappath_new != NULL)) {
1216                 errno = EROFS;
1217                 return -1;
1218         }
1219         return SMB_VFS_NEXT_SYMLINK(handle, link_contents, new_smb_fname);
1220 }
1221
1222 static int shadow_copy2_link(vfs_handle_struct *handle,
1223                         const struct smb_filename *old_smb_fname,
1224                         const struct smb_filename *new_smb_fname)
1225 {
1226         time_t timestamp_old = 0;
1227         time_t timestamp_new = 0;
1228         char *snappath_old = NULL;
1229         char *snappath_new = NULL;
1230
1231         if (!shadow_copy2_strip_snapshot_internal(talloc_tos(),
1232                                 handle,
1233                                 old_smb_fname->base_name,
1234                                 &timestamp_old,
1235                                 NULL,
1236                                 &snappath_old,
1237                                 NULL)) {
1238                 return -1;
1239         }
1240         if (!shadow_copy2_strip_snapshot_internal(talloc_tos(),
1241                                 handle,
1242                                 new_smb_fname->base_name,
1243                                 &timestamp_new,
1244                                 NULL,
1245                                 &snappath_new,
1246                                 NULL)) {
1247                 return -1;
1248         }
1249         if ((timestamp_old != 0) || (timestamp_new != 0)) {
1250                 errno = EROFS;
1251                 return -1;
1252         }
1253         /*
1254          * Don't allow links on already converted paths.
1255          */
1256         if ((snappath_old != NULL) || (snappath_new != NULL)) {
1257                 errno = EROFS;
1258                 return -1;
1259         }
1260         return SMB_VFS_NEXT_LINK(handle, old_smb_fname, new_smb_fname);
1261 }
1262
1263 static int shadow_copy2_stat(vfs_handle_struct *handle,
1264                              struct smb_filename *smb_fname)
1265 {
1266         time_t timestamp = 0;
1267         char *stripped = NULL;
1268         char *tmp;
1269         int saved_errno = 0;
1270         int ret;
1271
1272         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
1273                                          smb_fname->base_name,
1274                                          &timestamp, &stripped)) {
1275                 return -1;
1276         }
1277         if (timestamp == 0) {
1278                 return SMB_VFS_NEXT_STAT(handle, smb_fname);
1279         }
1280
1281         tmp = smb_fname->base_name;
1282         smb_fname->base_name = shadow_copy2_convert(
1283                 talloc_tos(), handle, stripped, timestamp);
1284         TALLOC_FREE(stripped);
1285
1286         if (smb_fname->base_name == NULL) {
1287                 smb_fname->base_name = tmp;
1288                 return -1;
1289         }
1290
1291         ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
1292         if (ret == -1) {
1293                 saved_errno = errno;
1294         }
1295
1296         TALLOC_FREE(smb_fname->base_name);
1297         smb_fname->base_name = tmp;
1298
1299         if (ret == 0) {
1300                 convert_sbuf(handle, smb_fname->base_name, &smb_fname->st);
1301         }
1302         if (saved_errno != 0) {
1303                 errno = saved_errno;
1304         }
1305         return ret;
1306 }
1307
1308 static int shadow_copy2_lstat(vfs_handle_struct *handle,
1309                               struct smb_filename *smb_fname)
1310 {
1311         time_t timestamp = 0;
1312         char *stripped = NULL;
1313         char *tmp;
1314         int saved_errno = 0;
1315         int ret;
1316
1317         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
1318                                          smb_fname->base_name,
1319                                          &timestamp, &stripped)) {
1320                 return -1;
1321         }
1322         if (timestamp == 0) {
1323                 return SMB_VFS_NEXT_LSTAT(handle, smb_fname);
1324         }
1325
1326         tmp = smb_fname->base_name;
1327         smb_fname->base_name = shadow_copy2_convert(
1328                 talloc_tos(), handle, stripped, timestamp);
1329         TALLOC_FREE(stripped);
1330
1331         if (smb_fname->base_name == NULL) {
1332                 smb_fname->base_name = tmp;
1333                 return -1;
1334         }
1335
1336         ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
1337         if (ret == -1) {
1338                 saved_errno = errno;
1339         }
1340
1341         TALLOC_FREE(smb_fname->base_name);
1342         smb_fname->base_name = tmp;
1343
1344         if (ret == 0) {
1345                 convert_sbuf(handle, smb_fname->base_name, &smb_fname->st);
1346         }
1347         if (saved_errno != 0) {
1348                 errno = saved_errno;
1349         }
1350         return ret;
1351 }
1352
1353 static int shadow_copy2_fstat(vfs_handle_struct *handle, files_struct *fsp,
1354                               SMB_STRUCT_STAT *sbuf)
1355 {
1356         time_t timestamp = 0;
1357         struct smb_filename *orig_smb_fname = NULL;
1358         struct smb_filename vss_smb_fname;
1359         struct smb_filename *orig_base_smb_fname = NULL;
1360         struct smb_filename vss_base_smb_fname;
1361         char *stripped = NULL;
1362         int saved_errno = 0;
1363         bool ok;
1364         int ret;
1365
1366         ok = shadow_copy2_strip_snapshot(talloc_tos(), handle,
1367                                          fsp->fsp_name->base_name,
1368                                          &timestamp, &stripped);
1369         if (!ok) {
1370                 return -1;
1371         }
1372
1373         if (timestamp == 0) {
1374                 TALLOC_FREE(stripped);
1375                 return SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
1376         }
1377
1378         vss_smb_fname = *fsp->fsp_name;
1379         vss_smb_fname.base_name = shadow_copy2_convert(talloc_tos(),
1380                                                        handle,
1381                                                        stripped,
1382                                                        timestamp);
1383         TALLOC_FREE(stripped);
1384         if (vss_smb_fname.base_name == NULL) {
1385                 return -1;
1386         }
1387
1388         orig_smb_fname = fsp->fsp_name;
1389         fsp->fsp_name = &vss_smb_fname;
1390
1391         if (fsp->base_fsp != NULL) {
1392                 vss_base_smb_fname = *fsp->base_fsp->fsp_name;
1393                 vss_base_smb_fname.base_name = vss_smb_fname.base_name;
1394                 orig_base_smb_fname = fsp->base_fsp->fsp_name;
1395                 fsp->base_fsp->fsp_name = &vss_base_smb_fname;
1396         }
1397
1398         ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
1399         fsp->fsp_name = orig_smb_fname;
1400         if (fsp->base_fsp != NULL) {
1401                 fsp->base_fsp->fsp_name = orig_base_smb_fname;
1402         }
1403         if (ret == -1) {
1404                 saved_errno = errno;
1405         }
1406
1407         if (ret == 0) {
1408                 convert_sbuf(handle, fsp->fsp_name->base_name, sbuf);
1409         }
1410         if (saved_errno != 0) {
1411                 errno = saved_errno;
1412         }
1413         return ret;
1414 }
1415
1416 static int shadow_copy2_open(vfs_handle_struct *handle,
1417                              struct smb_filename *smb_fname, files_struct *fsp,
1418                              int flags, mode_t mode)
1419 {
1420         time_t timestamp = 0;
1421         char *stripped = NULL;
1422         char *tmp;
1423         bool is_converted = false;
1424         int saved_errno = 0;
1425         int ret;
1426
1427         if (!shadow_copy2_strip_snapshot_converted(talloc_tos(), handle,
1428                                          smb_fname->base_name,
1429                                          &timestamp, &stripped,
1430                                          &is_converted)) {
1431                 return -1;
1432         }
1433         if (timestamp == 0) {
1434                 if (is_converted) {
1435                         /*
1436                          * Just pave over the user requested mode and use
1437                          * O_RDONLY. Later attempts by the client to write on
1438                          * the handle will fail in the pwrite() syscall with
1439                          * EINVAL which we carefully map to EROFS. In sum, this
1440                          * matches Windows behaviour.
1441                          */
1442                         flags = O_RDONLY;
1443                 }
1444                 return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
1445         }
1446
1447         tmp = smb_fname->base_name;
1448         smb_fname->base_name = shadow_copy2_convert(
1449                 talloc_tos(), handle, stripped, timestamp);
1450         TALLOC_FREE(stripped);
1451
1452         if (smb_fname->base_name == NULL) {
1453                 smb_fname->base_name = tmp;
1454                 return -1;
1455         }
1456
1457         /*
1458          * Just pave over the user requested mode and use O_RDONLY. Later
1459          * attempts by the client to write on the handle will fail in the
1460          * pwrite() syscall with EINVAL which we carefully map to EROFS. In sum,
1461          * this matches Windows behaviour.
1462          */
1463         flags = O_RDONLY;
1464
1465         ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
1466         if (ret == -1) {
1467                 saved_errno = errno;
1468         }
1469
1470         TALLOC_FREE(smb_fname->base_name);
1471         smb_fname->base_name = tmp;
1472
1473         if (saved_errno != 0) {
1474                 errno = saved_errno;
1475         }
1476         return ret;
1477 }
1478
1479 static int shadow_copy2_unlink(vfs_handle_struct *handle,
1480                                const struct smb_filename *smb_fname)
1481 {
1482         time_t timestamp = 0;
1483         char *stripped = NULL;
1484         int saved_errno = 0;
1485         int ret;
1486         struct smb_filename *conv;
1487
1488         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
1489                                          smb_fname->base_name,
1490                                          &timestamp, &stripped)) {
1491                 return -1;
1492         }
1493         if (timestamp == 0) {
1494                 return SMB_VFS_NEXT_UNLINK(handle, smb_fname);
1495         }
1496         conv = cp_smb_filename(talloc_tos(), smb_fname);
1497         if (conv == NULL) {
1498                 errno = ENOMEM;
1499                 return -1;
1500         }
1501         conv->base_name = shadow_copy2_convert(
1502                 conv, handle, stripped, timestamp);
1503         TALLOC_FREE(stripped);
1504         if (conv->base_name == NULL) {
1505                 return -1;
1506         }
1507         ret = SMB_VFS_NEXT_UNLINK(handle, conv);
1508         if (ret == -1) {
1509                 saved_errno = errno;
1510         }
1511         TALLOC_FREE(conv);
1512         if (saved_errno != 0) {
1513                 errno = saved_errno;
1514         }
1515         return ret;
1516 }
1517
1518 static int shadow_copy2_chmod(vfs_handle_struct *handle,
1519                         const struct smb_filename *smb_fname,
1520                         mode_t mode)
1521 {
1522         time_t timestamp = 0;
1523         char *stripped = NULL;
1524         int saved_errno = 0;
1525         int ret;
1526         char *conv = NULL;
1527         struct smb_filename *conv_smb_fname;
1528
1529         if (!shadow_copy2_strip_snapshot(talloc_tos(),
1530                                 handle,
1531                                 smb_fname->base_name,
1532                                 &timestamp,
1533                                 &stripped)) {
1534                 return -1;
1535         }
1536         if (timestamp == 0) {
1537                 TALLOC_FREE(stripped);
1538                 return SMB_VFS_NEXT_CHMOD(handle, smb_fname, mode);
1539         }
1540         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1541         TALLOC_FREE(stripped);
1542         if (conv == NULL) {
1543                 return -1;
1544         }
1545         conv_smb_fname = synthetic_smb_fname(talloc_tos(),
1546                                         conv,
1547                                         NULL,
1548                                         NULL,
1549                                         smb_fname->flags);
1550         if (conv_smb_fname == NULL) {
1551                 TALLOC_FREE(conv);
1552                 errno = ENOMEM;
1553                 return -1;
1554         }
1555
1556         ret = SMB_VFS_NEXT_CHMOD(handle, conv_smb_fname, mode);
1557         if (ret == -1) {
1558                 saved_errno = errno;
1559         }
1560         TALLOC_FREE(conv);
1561         TALLOC_FREE(conv_smb_fname);
1562         if (saved_errno != 0) {
1563                 errno = saved_errno;
1564         }
1565         return ret;
1566 }
1567
1568 static int shadow_copy2_chown(vfs_handle_struct *handle,
1569                         const struct smb_filename *smb_fname,
1570                         uid_t uid,
1571                         gid_t gid)
1572 {
1573         time_t timestamp = 0;
1574         char *stripped = NULL;
1575         int saved_errno = 0;
1576         int ret;
1577         char *conv = NULL;
1578         struct smb_filename *conv_smb_fname = NULL;
1579
1580         if (!shadow_copy2_strip_snapshot(talloc_tos(),
1581                                 handle,
1582                                 smb_fname->base_name,
1583                                 &timestamp,
1584                                 &stripped)) {
1585                 return -1;
1586         }
1587         if (timestamp == 0) {
1588                 return SMB_VFS_NEXT_CHOWN(handle, smb_fname, uid, gid);
1589         }
1590         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1591         TALLOC_FREE(stripped);
1592         if (conv == NULL) {
1593                 return -1;
1594         }
1595         conv_smb_fname = synthetic_smb_fname(talloc_tos(),
1596                                         conv,
1597                                         NULL,
1598                                         NULL,
1599                                         smb_fname->flags);
1600         if (conv_smb_fname == NULL) {
1601                 TALLOC_FREE(conv);
1602                 errno = ENOMEM;
1603                 return -1;
1604         }
1605         ret = SMB_VFS_NEXT_CHOWN(handle, conv_smb_fname, uid, gid);
1606         if (ret == -1) {
1607                 saved_errno = errno;
1608         }
1609         TALLOC_FREE(conv);
1610         TALLOC_FREE(conv_smb_fname);
1611         if (saved_errno != 0) {
1612                 errno = saved_errno;
1613         }
1614         return ret;
1615 }
1616
1617 static void store_cwd_data(vfs_handle_struct *handle,
1618                                 const char *connectpath)
1619 {
1620         struct shadow_copy2_private *priv = NULL;
1621         struct smb_filename *cwd_fname = NULL;
1622
1623         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
1624                                 return);
1625
1626         TALLOC_FREE(priv->shadow_cwd);
1627         cwd_fname = SMB_VFS_NEXT_GETWD(handle, talloc_tos());
1628         if (cwd_fname == NULL) {
1629                 smb_panic("getwd failed\n");
1630         }
1631         DBG_DEBUG("shadow cwd = %s\n", cwd_fname->base_name);
1632         priv->shadow_cwd = talloc_strdup(priv, cwd_fname->base_name);
1633         TALLOC_FREE(cwd_fname);
1634         if (priv->shadow_cwd == NULL) {
1635                 smb_panic("talloc failed\n");
1636         }
1637         TALLOC_FREE(priv->shadow_connectpath);
1638         if (connectpath) {
1639                 DBG_DEBUG("shadow conectpath = %s\n", connectpath);
1640                 priv->shadow_connectpath = talloc_strdup(priv, connectpath);
1641                 if (priv->shadow_connectpath == NULL) {
1642                         smb_panic("talloc failed\n");
1643                 }
1644         }
1645 }
1646
1647 static int shadow_copy2_chdir(vfs_handle_struct *handle,
1648                                const struct smb_filename *smb_fname)
1649 {
1650         time_t timestamp = 0;
1651         char *stripped = NULL;
1652         char *snappath = NULL;
1653         int ret = -1;
1654         int saved_errno = 0;
1655         char *conv = NULL;
1656         size_t rootpath_len = 0;
1657         struct smb_filename *conv_smb_fname = NULL;
1658
1659         if (!shadow_copy2_strip_snapshot_internal(talloc_tos(),
1660                                         handle,
1661                                         smb_fname->base_name,
1662                                         &timestamp,
1663                                         &stripped,
1664                                         &snappath,
1665                                         NULL)) {
1666                 return -1;
1667         }
1668         if (stripped != NULL) {
1669                 conv = shadow_copy2_do_convert(talloc_tos(),
1670                                                 handle,
1671                                                 stripped,
1672                                                 timestamp,
1673                                                 &rootpath_len);
1674                 TALLOC_FREE(stripped);
1675                 if (conv == NULL) {
1676                         return -1;
1677                 }
1678                 conv_smb_fname = synthetic_smb_fname(talloc_tos(),
1679                                         conv,
1680                                         NULL,
1681                                         NULL,
1682                                         smb_fname->flags);
1683         } else {
1684                 conv_smb_fname = cp_smb_filename(talloc_tos(), smb_fname);
1685         }
1686
1687         if (conv_smb_fname == NULL) {
1688                 TALLOC_FREE(conv);
1689                 errno = ENOMEM;
1690                 return -1;
1691         }
1692
1693         ret = SMB_VFS_NEXT_CHDIR(handle, conv_smb_fname);
1694         if (ret == -1) {
1695                 saved_errno = errno;
1696         }
1697
1698         if (ret == 0) {
1699                 if (conv != NULL && rootpath_len != 0) {
1700                         conv[rootpath_len] = '\0';
1701                 } else if (snappath != 0) {
1702                         TALLOC_FREE(conv);
1703                         conv = snappath;
1704                 }
1705                 store_cwd_data(handle, conv);
1706         }
1707
1708         TALLOC_FREE(stripped);
1709         TALLOC_FREE(conv);
1710         TALLOC_FREE(conv_smb_fname);
1711
1712         if (saved_errno != 0) {
1713                 errno = saved_errno;
1714         }
1715         return ret;
1716 }
1717
1718 static int shadow_copy2_ntimes(vfs_handle_struct *handle,
1719                                const struct smb_filename *smb_fname,
1720                                struct smb_file_time *ft)
1721 {
1722         time_t timestamp = 0;
1723         char *stripped = NULL;
1724         int saved_errno = 0;
1725         int ret;
1726         struct smb_filename *conv;
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_NTIMES(handle, smb_fname, ft);
1735         }
1736         conv = cp_smb_filename(talloc_tos(), smb_fname);
1737         if (conv == NULL) {
1738                 errno = ENOMEM;
1739                 return -1;
1740         }
1741         conv->base_name = shadow_copy2_convert(
1742                 conv, handle, stripped, timestamp);
1743         TALLOC_FREE(stripped);
1744         if (conv->base_name == NULL) {
1745                 return -1;
1746         }
1747         ret = SMB_VFS_NEXT_NTIMES(handle, conv, ft);
1748         if (ret == -1) {
1749                 saved_errno = errno;
1750         }
1751         TALLOC_FREE(conv);
1752         if (saved_errno != 0) {
1753                 errno = saved_errno;
1754         }
1755         return ret;
1756 }
1757
1758 static int shadow_copy2_readlink(vfs_handle_struct *handle,
1759                                 const struct smb_filename *smb_fname,
1760                                 char *buf,
1761                                 size_t bufsiz)
1762 {
1763         time_t timestamp = 0;
1764         char *stripped = NULL;
1765         int saved_errno = 0;
1766         int ret;
1767         struct smb_filename *conv = NULL;
1768
1769         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
1770                                          smb_fname->base_name,
1771                                          &timestamp, &stripped)) {
1772                 return -1;
1773         }
1774         if (timestamp == 0) {
1775                 return SMB_VFS_NEXT_READLINK(handle, smb_fname, buf, bufsiz);
1776         }
1777         conv = cp_smb_filename(talloc_tos(), smb_fname);
1778         if (conv == NULL) {
1779                 TALLOC_FREE(stripped);
1780                 errno = ENOMEM;
1781                 return -1;
1782         }
1783         conv->base_name = shadow_copy2_convert(
1784                 conv, handle, stripped, timestamp);
1785         TALLOC_FREE(stripped);
1786         if (conv->base_name == NULL) {
1787                 return -1;
1788         }
1789         ret = SMB_VFS_NEXT_READLINK(handle, conv, buf, bufsiz);
1790         if (ret == -1) {
1791                 saved_errno = errno;
1792         }
1793         TALLOC_FREE(conv);
1794         if (saved_errno != 0) {
1795                 errno = saved_errno;
1796         }
1797         return ret;
1798 }
1799
1800 static int shadow_copy2_mknod(vfs_handle_struct *handle,
1801                                 const struct smb_filename *smb_fname,
1802                                 mode_t mode,
1803                                 SMB_DEV_T dev)
1804 {
1805         time_t timestamp = 0;
1806         char *stripped = NULL;
1807         int saved_errno = 0;
1808         int ret;
1809         struct smb_filename *conv = NULL;
1810
1811         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
1812                                          smb_fname->base_name,
1813                                          &timestamp, &stripped)) {
1814                 return -1;
1815         }
1816         if (timestamp == 0) {
1817                 return SMB_VFS_NEXT_MKNOD(handle, smb_fname, mode, dev);
1818         }
1819         conv = cp_smb_filename(talloc_tos(), smb_fname);
1820         if (conv == NULL) {
1821                 errno = ENOMEM;
1822                 return -1;
1823         }
1824         conv->base_name = shadow_copy2_convert(
1825                 conv, handle, stripped, timestamp);
1826         TALLOC_FREE(stripped);
1827         if (conv->base_name == NULL) {
1828                 return -1;
1829         }
1830         ret = SMB_VFS_NEXT_MKNOD(handle, conv, mode, dev);
1831         if (ret == -1) {
1832                 saved_errno = errno;
1833         }
1834         TALLOC_FREE(conv);
1835         if (saved_errno != 0) {
1836                 errno = saved_errno;
1837         }
1838         return ret;
1839 }
1840
1841 static struct smb_filename *shadow_copy2_realpath(vfs_handle_struct *handle,
1842                                 TALLOC_CTX *ctx,
1843                                 const struct smb_filename *smb_fname)
1844 {
1845         time_t timestamp = 0;
1846         char *stripped = NULL;
1847         struct smb_filename *result_fname = NULL;
1848         struct smb_filename *conv_fname = NULL;
1849         int saved_errno = 0;
1850
1851         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
1852                                 smb_fname->base_name,
1853                                 &timestamp, &stripped)) {
1854                 goto done;
1855         }
1856         if (timestamp == 0) {
1857                 return SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname);
1858         }
1859
1860         conv_fname = cp_smb_filename(talloc_tos(), smb_fname);
1861         if (conv_fname == NULL) {
1862                 goto done;
1863         }
1864         conv_fname->base_name = shadow_copy2_convert(
1865                 conv_fname, handle, stripped, timestamp);
1866         if (conv_fname->base_name == NULL) {
1867                 goto done;
1868         }
1869
1870         result_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, conv_fname);
1871
1872 done:
1873         if (result_fname == NULL) {
1874                 saved_errno = errno;
1875         }
1876         TALLOC_FREE(conv_fname);
1877         TALLOC_FREE(stripped);
1878         if (saved_errno != 0) {
1879                 errno = saved_errno;
1880         }
1881         return result_fname;
1882 }
1883
1884 /**
1885  * Check whether a given directory contains a
1886  * snapshot directory as direct subdirectory.
1887  * If yes, return the path of the snapshot-subdir,
1888  * otherwise return NULL.
1889  */
1890 static char *have_snapdir(struct vfs_handle_struct *handle,
1891                           const char *path)
1892 {
1893         struct smb_filename smb_fname;
1894         int ret;
1895         struct shadow_copy2_private *priv;
1896
1897         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
1898                                 return NULL);
1899
1900         ZERO_STRUCT(smb_fname);
1901         smb_fname.base_name = talloc_asprintf(talloc_tos(), "%s/%s",
1902                                               path, priv->config->snapdir);
1903         if (smb_fname.base_name == NULL) {
1904                 return NULL;
1905         }
1906
1907         ret = SMB_VFS_NEXT_STAT(handle, &smb_fname);
1908         if ((ret == 0) && (S_ISDIR(smb_fname.st.st_ex_mode))) {
1909                 return smb_fname.base_name;
1910         }
1911         TALLOC_FREE(smb_fname.base_name);
1912         return NULL;
1913 }
1914
1915 static bool check_access_snapdir(struct vfs_handle_struct *handle,
1916                                 const char *path)
1917 {
1918         struct smb_filename smb_fname;
1919         int ret;
1920         NTSTATUS status;
1921
1922         ZERO_STRUCT(smb_fname);
1923         smb_fname.base_name = talloc_asprintf(talloc_tos(),
1924                                                 "%s",
1925                                                 path);
1926         if (smb_fname.base_name == NULL) {
1927                 return false;
1928         }
1929
1930         ret = SMB_VFS_NEXT_STAT(handle, &smb_fname);
1931         if (ret != 0 || !S_ISDIR(smb_fname.st.st_ex_mode)) {
1932                 TALLOC_FREE(smb_fname.base_name);
1933                 return false;
1934         }
1935
1936         status = smbd_check_access_rights(handle->conn,
1937                                         &smb_fname,
1938                                         false,
1939                                         SEC_DIR_LIST);
1940         if (!NT_STATUS_IS_OK(status)) {
1941                 DEBUG(0,("user does not have list permission "
1942                         "on snapdir %s\n",
1943                         smb_fname.base_name));
1944                 TALLOC_FREE(smb_fname.base_name);
1945                 return false;
1946         }
1947         TALLOC_FREE(smb_fname.base_name);
1948         return true;
1949 }
1950
1951 /**
1952  * Find the snapshot directory (if any) for the given
1953  * filename (which is relative to the share).
1954  */
1955 static const char *shadow_copy2_find_snapdir(TALLOC_CTX *mem_ctx,
1956                                              struct vfs_handle_struct *handle,
1957                                              struct smb_filename *smb_fname)
1958 {
1959         char *path, *p;
1960         const char *snapdir;
1961         struct shadow_copy2_config *config;
1962         struct shadow_copy2_private *priv;
1963
1964         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
1965                                 return NULL);
1966
1967         config = priv->config;
1968
1969         /*
1970          * If the non-snapdisrseverywhere mode, we should not search!
1971          */
1972         if (!config->snapdirseverywhere) {
1973                 return config->snapshot_basepath;
1974         }
1975
1976         path = talloc_asprintf(mem_ctx, "%s/%s",
1977                                handle->conn->connectpath,
1978                                smb_fname->base_name);
1979         if (path == NULL) {
1980                 return NULL;
1981         }
1982
1983         snapdir = have_snapdir(handle, path);
1984         if (snapdir != NULL) {
1985                 TALLOC_FREE(path);
1986                 return snapdir;
1987         }
1988
1989         while ((p = strrchr(path, '/')) && (p > path)) {
1990
1991                 p[0] = '\0';
1992
1993                 snapdir = have_snapdir(handle, path);
1994                 if (snapdir != NULL) {
1995                         TALLOC_FREE(path);
1996                         return snapdir;
1997                 }
1998         }
1999         TALLOC_FREE(path);
2000         return NULL;
2001 }
2002
2003 static bool shadow_copy2_snapshot_to_gmt(vfs_handle_struct *handle,
2004                                          const char *name,
2005                                          char *gmt, size_t gmt_len)
2006 {
2007         struct tm timestamp;
2008         time_t timestamp_t;
2009         unsigned long int timestamp_long;
2010         const char *fmt;
2011         struct shadow_copy2_config *config;
2012         struct shadow_copy2_private *priv;
2013         char *tmpstr = NULL;
2014         char *tmp = NULL;
2015         bool converted = false;
2016         int ret = -1;
2017
2018         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
2019                                 return NULL);
2020
2021         config = priv->config;
2022
2023         fmt = config->gmt_format;
2024
2025         /*
2026          * If regex is provided, then we will have to parse the
2027          * filename which will contain both the prefix and the time format.
2028          * e.g. <prefix><delimiter><time_format>
2029          */
2030         if (priv->snaps->regex != NULL) {
2031                 tmpstr = talloc_strdup(talloc_tos(), name);
2032                 /* point "name" to the time format */
2033                 name = strstr(name, priv->config->delimiter);
2034                 if (name == NULL) {
2035                         goto done;
2036                 }
2037                 /* Extract the prefix */
2038                 tmp = strstr(tmpstr, priv->config->delimiter);
2039                 if (tmp == NULL) {
2040                         goto done;
2041                 }
2042                 *tmp = '\0';
2043
2044                 /* Parse regex */
2045                 ret = regexec(priv->snaps->regex, tmpstr, 0, NULL, 0);
2046                 if (ret) {
2047                         DBG_DEBUG("shadow_copy2_snapshot_to_gmt: "
2048                                   "no regex match for %s\n", tmpstr);
2049                         goto done;
2050                 }
2051         }
2052
2053         ZERO_STRUCT(timestamp);
2054         if (config->use_sscanf) {
2055                 if (sscanf(name, fmt, &timestamp_long) != 1) {
2056                         DEBUG(10, ("shadow_copy2_snapshot_to_gmt: "
2057                                    "no sscanf match %s: %s\n",
2058                                    fmt, name));
2059                         goto done;
2060                 }
2061                 timestamp_t = timestamp_long;
2062                 gmtime_r(&timestamp_t, &timestamp);
2063         } else {
2064                 if (strptime(name, fmt, &timestamp) == NULL) {
2065                         DEBUG(10, ("shadow_copy2_snapshot_to_gmt: "
2066                                    "no match %s: %s\n",
2067                                    fmt, name));
2068                         goto done;
2069                 }
2070                 DEBUG(10, ("shadow_copy2_snapshot_to_gmt: match %s: %s\n",
2071                            fmt, name));
2072                 
2073                 if (config->use_localtime) {
2074                         timestamp.tm_isdst = -1;
2075                         timestamp_t = mktime(&timestamp);
2076                         gmtime_r(&timestamp_t, &timestamp);
2077                 }
2078         }
2079
2080         strftime(gmt, gmt_len, GMT_FORMAT, &timestamp);
2081         converted = true;
2082
2083 done:
2084         TALLOC_FREE(tmpstr);
2085         return converted;
2086 }
2087
2088 static int shadow_copy2_label_cmp_asc(const void *x, const void *y)
2089 {
2090         return strncmp((const char *)x, (const char *)y, sizeof(SHADOW_COPY_LABEL));
2091 }
2092
2093 static int shadow_copy2_label_cmp_desc(const void *x, const void *y)
2094 {
2095         return -strncmp((const char *)x, (const char *)y, sizeof(SHADOW_COPY_LABEL));
2096 }
2097
2098 /*
2099   sort the shadow copy data in ascending or descending order
2100  */
2101 static void shadow_copy2_sort_data(vfs_handle_struct *handle,
2102                                    struct shadow_copy_data *shadow_copy2_data)
2103 {
2104         int (*cmpfunc)(const void *, const void *);
2105         const char *sort;
2106         struct shadow_copy2_private *priv;
2107
2108         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
2109                                 return);
2110
2111         sort = priv->config->sort_order;
2112         if (sort == NULL) {
2113                 return;
2114         }
2115
2116         if (strcmp(sort, "asc") == 0) {
2117                 cmpfunc = shadow_copy2_label_cmp_asc;
2118         } else if (strcmp(sort, "desc") == 0) {
2119                 cmpfunc = shadow_copy2_label_cmp_desc;
2120         } else {
2121                 return;
2122         }
2123
2124         if (shadow_copy2_data && shadow_copy2_data->num_volumes > 0 &&
2125             shadow_copy2_data->labels)
2126         {
2127                 TYPESAFE_QSORT(shadow_copy2_data->labels,
2128                                shadow_copy2_data->num_volumes,
2129                                cmpfunc);
2130         }
2131 }
2132
2133 static int shadow_copy2_get_shadow_copy_data(
2134         vfs_handle_struct *handle, files_struct *fsp,
2135         struct shadow_copy_data *shadow_copy2_data,
2136         bool labels)
2137 {
2138         DIR *p;
2139         const char *snapdir;
2140         struct smb_filename *snapdir_smb_fname = NULL;
2141         struct dirent *d;
2142         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2143         struct shadow_copy2_private *priv = NULL;
2144         struct shadow_copy2_snapentry *tmpentry = NULL;
2145         bool get_snaplist = false;
2146         bool access_granted = false;
2147         int ret = -1;
2148
2149         snapdir = shadow_copy2_find_snapdir(tmp_ctx, handle, fsp->fsp_name);
2150         if (snapdir == NULL) {
2151                 DEBUG(0,("shadow:snapdir not found for %s in get_shadow_copy_data\n",
2152                          handle->conn->connectpath));
2153                 errno = EINVAL;
2154                 goto done;
2155         }
2156
2157         access_granted = check_access_snapdir(handle, snapdir);
2158         if (!access_granted) {
2159                 DEBUG(0,("access denied on listing snapdir %s\n", snapdir));
2160                 errno = EACCES;
2161                 goto done;
2162         }
2163
2164         snapdir_smb_fname = synthetic_smb_fname(talloc_tos(),
2165                                         snapdir,
2166                                         NULL,
2167                                         NULL,
2168                                         fsp->fsp_name->flags);
2169         if (snapdir_smb_fname == NULL) {
2170                 errno = ENOMEM;
2171                 goto done;
2172         }
2173
2174         p = SMB_VFS_NEXT_OPENDIR(handle, snapdir_smb_fname, NULL, 0);
2175
2176         if (!p) {
2177                 DEBUG(2,("shadow_copy2: SMB_VFS_NEXT_OPENDIR() failed for '%s'"
2178                          " - %s\n", snapdir, strerror(errno)));
2179                 errno = ENOSYS;
2180                 goto done;
2181         }
2182
2183         if (shadow_copy2_data != NULL) {
2184                 shadow_copy2_data->num_volumes = 0;
2185                 shadow_copy2_data->labels      = NULL;
2186         }
2187
2188         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
2189                                 goto done);
2190
2191         /*
2192          * Normally this function is called twice once with labels = false and
2193          * then with labels = true. When labels is false it will return the
2194          * number of volumes so that the caller can allocate memory for that
2195          * many labels. Therefore to eliminate snaplist both the times it is
2196          * good to check if labels is set or not.
2197          *
2198          * shadow_copy2_data is NULL when we only want to update the list and
2199          * don't want any labels.
2200          */
2201         if ((priv->snaps->regex != NULL) && (labels || shadow_copy2_data == NULL)) {
2202                 get_snaplist = true;
2203                 /* Reset the global snaplist */
2204                 shadow_copy2_delete_snaplist(priv);
2205
2206                 /* Set the current time as snaplist update time */
2207                 time(&(priv->snaps->fetch_time));
2208         }
2209
2210         while ((d = SMB_VFS_NEXT_READDIR(handle, p, NULL))) {
2211                 char snapshot[GMT_NAME_LEN+1];
2212                 SHADOW_COPY_LABEL *tlabels;
2213
2214                 /*
2215                  * ignore names not of the right form in the snapshot
2216                  * directory
2217                  */
2218                 if (!shadow_copy2_snapshot_to_gmt(
2219                             handle, d->d_name,
2220                             snapshot, sizeof(snapshot))) {
2221
2222                         DEBUG(6, ("shadow_copy2_get_shadow_copy_data: "
2223                                   "ignoring %s\n", d->d_name));
2224                         continue;
2225                 }
2226                 DEBUG(6,("shadow_copy2_get_shadow_copy_data: %s -> %s\n",
2227                          d->d_name, snapshot));
2228
2229                 if (get_snaplist) {
2230                         /*
2231                          * Create a snap entry for each successful
2232                          * pattern match.
2233                          */
2234                         tmpentry = shadow_copy2_create_snapentry(priv);
2235                         if (tmpentry == NULL) {
2236                                 DBG_ERR("talloc_zero() failed\n");
2237                                 goto done;
2238                         }
2239                         tmpentry->snapname = talloc_strdup(tmpentry, d->d_name);
2240                         tmpentry->time_fmt = talloc_strdup(tmpentry, snapshot);
2241                 }
2242
2243                 if (shadow_copy2_data == NULL) {
2244                         continue;
2245                 }
2246
2247                 if (!labels) {
2248                         /* the caller doesn't want the labels */
2249                         shadow_copy2_data->num_volumes++;
2250                         continue;
2251                 }
2252
2253                 tlabels = talloc_realloc(shadow_copy2_data,
2254                                          shadow_copy2_data->labels,
2255                                          SHADOW_COPY_LABEL,
2256                                          shadow_copy2_data->num_volumes+1);
2257                 if (tlabels == NULL) {
2258                         DEBUG(0,("shadow_copy2: out of memory\n"));
2259                         SMB_VFS_NEXT_CLOSEDIR(handle, p);
2260                         goto done;
2261                 }
2262
2263                 strlcpy(tlabels[shadow_copy2_data->num_volumes], snapshot,
2264                         sizeof(*tlabels));
2265
2266                 shadow_copy2_data->num_volumes++;
2267                 shadow_copy2_data->labels = tlabels;
2268         }
2269
2270         SMB_VFS_NEXT_CLOSEDIR(handle,p);
2271
2272         shadow_copy2_sort_data(handle, shadow_copy2_data);
2273         ret = 0;
2274
2275 done:
2276         TALLOC_FREE(tmp_ctx);
2277         return ret;
2278 }
2279
2280 static NTSTATUS shadow_copy2_fget_nt_acl(vfs_handle_struct *handle,
2281                                         struct files_struct *fsp,
2282                                         uint32_t security_info,
2283                                          TALLOC_CTX *mem_ctx,
2284                                         struct security_descriptor **ppdesc)
2285 {
2286         time_t timestamp = 0;
2287         char *stripped = NULL;
2288         NTSTATUS status;
2289         char *conv;
2290         struct smb_filename *smb_fname = NULL;
2291
2292         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
2293                                          fsp->fsp_name->base_name,
2294                                          &timestamp, &stripped)) {
2295                 return map_nt_error_from_unix(errno);
2296         }
2297         if (timestamp == 0) {
2298                 return SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info,
2299                                                 mem_ctx,
2300                                                 ppdesc);
2301         }
2302         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2303         TALLOC_FREE(stripped);
2304         if (conv == NULL) {
2305                 return map_nt_error_from_unix(errno);
2306         }
2307         smb_fname = synthetic_smb_fname(talloc_tos(),
2308                                         conv,
2309                                         NULL,
2310                                         NULL,
2311                                         fsp->fsp_name->flags);
2312         if (smb_fname == NULL) {
2313                 TALLOC_FREE(conv);
2314                 return NT_STATUS_NO_MEMORY;
2315         }
2316
2317         status = SMB_VFS_NEXT_GET_NT_ACL(handle, smb_fname, security_info,
2318                                          mem_ctx, ppdesc);
2319         TALLOC_FREE(conv);
2320         TALLOC_FREE(smb_fname);
2321         return status;
2322 }
2323
2324 static NTSTATUS shadow_copy2_get_nt_acl(vfs_handle_struct *handle,
2325                                         const struct smb_filename *smb_fname,
2326                                         uint32_t security_info,
2327                                         TALLOC_CTX *mem_ctx,
2328                                         struct security_descriptor **ppdesc)
2329 {
2330         time_t timestamp = 0;
2331         char *stripped = NULL;
2332         NTSTATUS status;
2333         char *conv;
2334         struct smb_filename *conv_smb_fname = NULL;
2335
2336         if (!shadow_copy2_strip_snapshot(talloc_tos(),
2337                                         handle,
2338                                         smb_fname->base_name,
2339                                         &timestamp,
2340                                         &stripped)) {
2341                 return map_nt_error_from_unix(errno);
2342         }
2343         if (timestamp == 0) {
2344                 return SMB_VFS_NEXT_GET_NT_ACL(handle, smb_fname, security_info,
2345                                                mem_ctx, ppdesc);
2346         }
2347         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2348         TALLOC_FREE(stripped);
2349         if (conv == NULL) {
2350                 return map_nt_error_from_unix(errno);
2351         }
2352         conv_smb_fname = synthetic_smb_fname(talloc_tos(),
2353                                         conv,
2354                                         NULL,
2355                                         NULL,
2356                                         smb_fname->flags);
2357         if (conv_smb_fname == NULL) {
2358                 TALLOC_FREE(conv);
2359                 return NT_STATUS_NO_MEMORY;
2360         }
2361         status = SMB_VFS_NEXT_GET_NT_ACL(handle, conv_smb_fname, security_info,
2362                                          mem_ctx, ppdesc);
2363         TALLOC_FREE(conv);
2364         TALLOC_FREE(conv_smb_fname);
2365         return status;
2366 }
2367
2368 static int shadow_copy2_mkdir(vfs_handle_struct *handle,
2369                                 const struct smb_filename *smb_fname,
2370                                 mode_t mode)
2371 {
2372         time_t timestamp = 0;
2373         char *stripped = NULL;
2374         int saved_errno = 0;
2375         int ret;
2376         char *conv;
2377         struct smb_filename *conv_smb_fname = NULL;
2378
2379         if (!shadow_copy2_strip_snapshot(talloc_tos(),
2380                                         handle,
2381                                         smb_fname->base_name,
2382                                         &timestamp,
2383                                         &stripped)) {
2384                 return -1;
2385         }
2386         if (timestamp == 0) {
2387                 return SMB_VFS_NEXT_MKDIR(handle, smb_fname, mode);
2388         }
2389         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2390         TALLOC_FREE(stripped);
2391         if (conv == NULL) {
2392                 return -1;
2393         }
2394         conv_smb_fname = synthetic_smb_fname(talloc_tos(),
2395                                         conv,
2396                                         NULL,
2397                                         NULL,
2398                                         smb_fname->flags);
2399         if (conv_smb_fname == NULL) {
2400                 TALLOC_FREE(conv);
2401                 return -1;
2402         }
2403         ret = SMB_VFS_NEXT_MKDIR(handle, conv_smb_fname, mode);
2404         if (ret == -1) {
2405                 saved_errno = errno;
2406         }
2407         TALLOC_FREE(conv);
2408         TALLOC_FREE(conv_smb_fname);
2409         if (saved_errno != 0) {
2410                 errno = saved_errno;
2411         }
2412         return ret;
2413 }
2414
2415 static int shadow_copy2_rmdir(vfs_handle_struct *handle,
2416                                 const struct smb_filename *smb_fname)
2417 {
2418         time_t timestamp = 0;
2419         char *stripped = NULL;
2420         int saved_errno = 0;
2421         int ret;
2422         char *conv;
2423         struct smb_filename *conv_smb_fname = NULL;
2424
2425         if (!shadow_copy2_strip_snapshot(talloc_tos(),
2426                                         handle,
2427                                         smb_fname->base_name,
2428                                         &timestamp,
2429                                         &stripped)) {
2430                 return -1;
2431         }
2432         if (timestamp == 0) {
2433                 return SMB_VFS_NEXT_RMDIR(handle, smb_fname);
2434         }
2435         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2436         TALLOC_FREE(stripped);
2437         if (conv == NULL) {
2438                 return -1;
2439         }
2440         conv_smb_fname = synthetic_smb_fname(talloc_tos(),
2441                                         conv,
2442                                         NULL,
2443                                         NULL,
2444                                         smb_fname->flags);
2445         if (conv_smb_fname == NULL) {
2446                 TALLOC_FREE(conv);
2447                 return -1;
2448         }
2449         ret = SMB_VFS_NEXT_RMDIR(handle, conv_smb_fname);
2450         if (ret == -1) {
2451                 saved_errno = errno;
2452         }
2453         TALLOC_FREE(conv_smb_fname);
2454         TALLOC_FREE(conv);
2455         if (saved_errno != 0) {
2456                 errno = saved_errno;
2457         }
2458         return ret;
2459 }
2460
2461 static int shadow_copy2_chflags(vfs_handle_struct *handle,
2462                                 const struct smb_filename *smb_fname,
2463                                 unsigned int flags)
2464 {
2465         time_t timestamp = 0;
2466         char *stripped = NULL;
2467         int saved_errno = 0;
2468         int ret;
2469         char *conv;
2470         struct smb_filename *conv_smb_fname = NULL;
2471
2472         if (!shadow_copy2_strip_snapshot(talloc_tos(),
2473                                         handle,
2474                                         smb_fname->base_name,
2475                                         &timestamp,
2476                                         &stripped)) {
2477                 return -1;
2478         }
2479         if (timestamp == 0) {
2480                 return SMB_VFS_NEXT_CHFLAGS(handle, smb_fname, flags);
2481         }
2482         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2483         TALLOC_FREE(stripped);
2484         if (conv == NULL) {
2485                 return -1;
2486         }
2487         conv_smb_fname = synthetic_smb_fname(talloc_tos(),
2488                                         conv,
2489                                         NULL,
2490                                         NULL,
2491                                         smb_fname->flags);
2492         if (conv_smb_fname == NULL) {
2493                 TALLOC_FREE(conv);
2494                 return -1;
2495         }
2496         ret = SMB_VFS_NEXT_CHFLAGS(handle, smb_fname, flags);
2497         if (ret == -1) {
2498                 saved_errno = errno;
2499         }
2500         TALLOC_FREE(conv_smb_fname);
2501         TALLOC_FREE(conv);
2502         if (saved_errno != 0) {
2503                 errno = saved_errno;
2504         }
2505         return ret;
2506 }
2507
2508 static ssize_t shadow_copy2_getxattr(vfs_handle_struct *handle,
2509                                 const struct smb_filename *smb_fname,
2510                                 const char *aname,
2511                                 void *value,
2512                                 size_t size)
2513 {
2514         time_t timestamp = 0;
2515         char *stripped = NULL;
2516         ssize_t ret;
2517         int saved_errno = 0;
2518         char *conv;
2519         struct smb_filename *conv_smb_fname = NULL;
2520
2521         if (!shadow_copy2_strip_snapshot(talloc_tos(),
2522                                 handle,
2523                                 smb_fname->base_name,
2524                                 &timestamp,
2525                                 &stripped)) {
2526                 return -1;
2527         }
2528         if (timestamp == 0) {
2529                 return SMB_VFS_NEXT_GETXATTR(handle, smb_fname, aname, value,
2530                                              size);
2531         }
2532         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2533         TALLOC_FREE(stripped);
2534         if (conv == NULL) {
2535                 return -1;
2536         }
2537
2538         conv_smb_fname = synthetic_smb_fname(talloc_tos(),
2539                                         conv,
2540                                         NULL,
2541                                         NULL,
2542                                         smb_fname->flags);
2543         if (conv_smb_fname == NULL) {
2544                 TALLOC_FREE(conv);
2545                 return -1;
2546         }
2547
2548         ret = SMB_VFS_NEXT_GETXATTR(handle, conv_smb_fname, aname, value, size);
2549         if (ret == -1) {
2550                 saved_errno = errno;
2551         }
2552         TALLOC_FREE(conv_smb_fname);
2553         TALLOC_FREE(conv);
2554         if (saved_errno != 0) {
2555                 errno = saved_errno;
2556         }
2557         return ret;
2558 }
2559
2560 static ssize_t shadow_copy2_listxattr(struct vfs_handle_struct *handle,
2561                                       const struct smb_filename *smb_fname,
2562                                       char *list, size_t size)
2563 {
2564         time_t timestamp = 0;
2565         char *stripped = NULL;
2566         ssize_t ret;
2567         int saved_errno = 0;
2568         char *conv;
2569         struct smb_filename *conv_smb_fname = NULL;
2570
2571         if (!shadow_copy2_strip_snapshot(talloc_tos(),
2572                                 handle,
2573                                 smb_fname->base_name,
2574                                 &timestamp,
2575                                 &stripped)) {
2576                 return -1;
2577         }
2578         if (timestamp == 0) {
2579                 return SMB_VFS_NEXT_LISTXATTR(handle, smb_fname, list, size);
2580         }
2581         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2582         TALLOC_FREE(stripped);
2583         if (conv == NULL) {
2584                 return -1;
2585         }
2586         conv_smb_fname = synthetic_smb_fname(talloc_tos(),
2587                                         conv,
2588                                         NULL,
2589                                         NULL,
2590                                         smb_fname->flags);
2591         if (conv_smb_fname == NULL) {
2592                 TALLOC_FREE(conv);
2593                 return -1;
2594         }
2595         ret = SMB_VFS_NEXT_LISTXATTR(handle, conv_smb_fname, list, size);
2596         if (ret == -1) {
2597                 saved_errno = errno;
2598         }
2599         TALLOC_FREE(conv_smb_fname);
2600         TALLOC_FREE(conv);
2601         if (saved_errno != 0) {
2602                 errno = saved_errno;
2603         }
2604         return ret;
2605 }
2606
2607 static int shadow_copy2_removexattr(vfs_handle_struct *handle,
2608                                 const struct smb_filename *smb_fname,
2609                                 const char *aname)
2610 {
2611         time_t timestamp = 0;
2612         char *stripped = NULL;
2613         int saved_errno = 0;
2614         int ret;
2615         char *conv;
2616         struct smb_filename *conv_smb_fname = NULL;
2617
2618         if (!shadow_copy2_strip_snapshot(talloc_tos(),
2619                                 handle,
2620                                 smb_fname->base_name,
2621                                 &timestamp,
2622                                 &stripped)) {
2623                 return -1;
2624         }
2625         if (timestamp == 0) {
2626                 return SMB_VFS_NEXT_REMOVEXATTR(handle, smb_fname, aname);
2627         }
2628         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2629         TALLOC_FREE(stripped);
2630         if (conv == NULL) {
2631                 return -1;
2632         }
2633         conv_smb_fname = synthetic_smb_fname(talloc_tos(),
2634                                         conv,
2635                                         NULL,
2636                                         NULL,
2637                                         smb_fname->flags);
2638         if (conv_smb_fname == NULL) {
2639                 TALLOC_FREE(conv);
2640                 return -1;
2641         }
2642         ret = SMB_VFS_NEXT_REMOVEXATTR(handle, conv_smb_fname, aname);
2643         if (ret == -1) {
2644                 saved_errno = errno;
2645         }
2646         TALLOC_FREE(conv_smb_fname);
2647         TALLOC_FREE(conv);
2648         if (saved_errno != 0) {
2649                 errno = saved_errno;
2650         }
2651         return ret;
2652 }
2653
2654 static int shadow_copy2_setxattr(struct vfs_handle_struct *handle,
2655                                  const struct smb_filename *smb_fname,
2656                                  const char *aname, const void *value,
2657                                  size_t size, int flags)
2658 {
2659         time_t timestamp = 0;
2660         char *stripped = NULL;
2661         ssize_t ret;
2662         int saved_errno = 0;
2663         char *conv;
2664         struct smb_filename *conv_smb_fname = NULL;
2665
2666         if (!shadow_copy2_strip_snapshot(talloc_tos(),
2667                                 handle,
2668                                 smb_fname->base_name,
2669                                 &timestamp,
2670                                 &stripped)) {
2671                 return -1;
2672         }
2673         if (timestamp == 0) {
2674                 return SMB_VFS_NEXT_SETXATTR(handle, smb_fname,
2675                                         aname, value, size, flags);
2676         }
2677         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2678         TALLOC_FREE(stripped);
2679         if (conv == NULL) {
2680                 return -1;
2681         }
2682         conv_smb_fname = synthetic_smb_fname(talloc_tos(),
2683                                         conv,
2684                                         NULL,
2685                                         NULL,
2686                                         smb_fname->flags);
2687         if (conv_smb_fname == NULL) {
2688                 TALLOC_FREE(conv);
2689                 return -1;
2690         }
2691         ret = SMB_VFS_NEXT_SETXATTR(handle, conv_smb_fname,
2692                                 aname, value, size, flags);
2693         if (ret == -1) {
2694                 saved_errno = errno;
2695         }
2696         TALLOC_FREE(conv_smb_fname);
2697         TALLOC_FREE(conv);
2698         if (saved_errno != 0) {
2699                 errno = saved_errno;
2700         }
2701         return ret;
2702 }
2703
2704 static int shadow_copy2_get_real_filename(struct vfs_handle_struct *handle,
2705                                           const char *path,
2706                                           const char *name,
2707                                           TALLOC_CTX *mem_ctx,
2708                                           char **found_name)
2709 {
2710         time_t timestamp = 0;
2711         char *stripped = NULL;
2712         ssize_t ret;
2713         int saved_errno = 0;
2714         char *conv;
2715
2716         DEBUG(10, ("shadow_copy2_get_real_filename called for path=[%s], "
2717                    "name=[%s]\n", path, name));
2718
2719         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, path,
2720                                          &timestamp, &stripped)) {
2721                 DEBUG(10, ("shadow_copy2_strip_snapshot failed\n"));
2722                 return -1;
2723         }
2724         if (timestamp == 0) {
2725                 DEBUG(10, ("timestamp == 0\n"));
2726                 return SMB_VFS_NEXT_GET_REAL_FILENAME(handle, path, name,
2727                                                       mem_ctx, found_name);
2728         }
2729         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2730         TALLOC_FREE(stripped);
2731         if (conv == NULL) {
2732                 DEBUG(10, ("shadow_copy2_convert failed\n"));
2733                 return -1;
2734         }
2735         DEBUG(10, ("Calling NEXT_GET_REAL_FILE_NAME for conv=[%s], "
2736                    "name=[%s]\n", conv, name));
2737         ret = SMB_VFS_NEXT_GET_REAL_FILENAME(handle, conv, name,
2738                                              mem_ctx, found_name);
2739         DEBUG(10, ("NEXT_REAL_FILE_NAME returned %d\n", (int)ret));
2740         if (ret == -1) {
2741                 saved_errno = errno;
2742         }
2743         TALLOC_FREE(conv);
2744         if (saved_errno != 0) {
2745                 errno = saved_errno;
2746         }
2747         return ret;
2748 }
2749
2750 static const char *shadow_copy2_connectpath(struct vfs_handle_struct *handle,
2751                                         const struct smb_filename *smb_fname_in)
2752 {
2753         time_t timestamp = 0;
2754         char *stripped = NULL;
2755         char *tmp = NULL;
2756         const char *fname = smb_fname_in->base_name;
2757         struct smb_filename smb_fname = {0};
2758         struct smb_filename *result_fname = NULL;
2759         char *result = NULL;
2760         char *parent_dir = NULL;
2761         int saved_errno = 0;
2762         size_t rootpath_len = 0;
2763         struct shadow_copy2_private *priv = NULL;
2764
2765         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
2766                                 return NULL);
2767
2768         DBG_DEBUG("Calc connect path for [%s]\n", fname);
2769
2770         if (priv->shadow_connectpath != NULL) {
2771                 DBG_DEBUG("cached connect path is [%s]\n",
2772                         priv->shadow_connectpath);
2773                 return priv->shadow_connectpath;
2774         }
2775
2776         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
2777                                          &timestamp, &stripped)) {
2778                 goto done;
2779         }
2780         if (timestamp == 0) {
2781                 return SMB_VFS_NEXT_CONNECTPATH(handle, smb_fname_in);
2782         }
2783
2784         tmp = shadow_copy2_do_convert(talloc_tos(), handle, stripped, timestamp,
2785                                       &rootpath_len);
2786         if (tmp == NULL) {
2787                 if (errno != ENOENT) {
2788                         goto done;
2789                 }
2790
2791                 /*
2792                  * If the converted path does not exist, and converting
2793                  * the parent yields something that does exist, then
2794                  * this path refers to something that has not been
2795                  * created yet, relative to the parent path.
2796                  * The snapshot finding is relative to the parent.
2797                  * (usually snapshots are read/only but this is not
2798                  * necessarily true).
2799                  * This code also covers getting a wildcard in the
2800                  * last component, because this function is called
2801                  * prior to sanitizing the path, and in SMB1 we may
2802                  * get wildcards in path names.
2803                  */
2804                 if (!parent_dirname(talloc_tos(), stripped, &parent_dir,
2805                                     NULL)) {
2806                         errno = ENOMEM;
2807                         goto done;
2808                 }
2809
2810                 tmp = shadow_copy2_do_convert(talloc_tos(), handle, parent_dir,
2811                                               timestamp, &rootpath_len);
2812                 if (tmp == NULL) {
2813                         goto done;
2814                 }
2815         }
2816
2817         DBG_DEBUG("converted path is [%s] root path is [%.*s]\n", tmp,
2818                   (int)rootpath_len, tmp);
2819
2820         tmp[rootpath_len] = '\0';
2821         smb_fname = (struct smb_filename) { .base_name = tmp };
2822
2823         result_fname = SMB_VFS_NEXT_REALPATH(handle, priv, &smb_fname);
2824         if (result_fname == NULL) {
2825                 goto done;
2826         }
2827
2828         /*
2829          * SMB_VFS_NEXT_REALPATH returns a talloc'ed string.
2830          * Don't leak memory.
2831          */
2832         TALLOC_FREE(priv->shadow_realpath);
2833         priv->shadow_realpath = result_fname;
2834         result = priv->shadow_realpath->base_name;
2835
2836         DBG_DEBUG("connect path is [%s]\n", result);
2837
2838 done:
2839         if (result == NULL) {
2840                 saved_errno = errno;
2841         }
2842         TALLOC_FREE(tmp);
2843         TALLOC_FREE(stripped);
2844         TALLOC_FREE(parent_dir);
2845         if (saved_errno != 0) {
2846                 errno = saved_errno;
2847         }
2848         return result;
2849 }
2850
2851 static uint64_t shadow_copy2_disk_free(vfs_handle_struct *handle,
2852                                 const struct smb_filename *smb_fname,
2853                                 uint64_t *bsize,
2854                                 uint64_t *dfree,
2855                                 uint64_t *dsize)
2856 {
2857         time_t timestamp = 0;
2858         char *stripped = NULL;
2859         int saved_errno = 0;
2860         char *conv = NULL;
2861         struct smb_filename *conv_smb_fname = NULL;
2862         uint64_t ret = (uint64_t)-1;
2863
2864         if (!shadow_copy2_strip_snapshot(talloc_tos(),
2865                                 handle,
2866                                 smb_fname->base_name,
2867                                 &timestamp,
2868                                 &stripped)) {
2869                 return (uint64_t)-1;
2870         }
2871         if (timestamp == 0) {
2872                 return SMB_VFS_NEXT_DISK_FREE(handle, smb_fname,
2873                                               bsize, dfree, dsize);
2874         }
2875         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
2876         TALLOC_FREE(stripped);
2877         if (conv == NULL) {
2878                 return (uint64_t)-1;
2879         }
2880         conv_smb_fname = synthetic_smb_fname(talloc_tos(),
2881                                         conv,
2882                                         NULL,
2883                                         NULL,
2884                                         smb_fname->flags);
2885         if (conv_smb_fname == NULL) {
2886                 TALLOC_FREE(conv);
2887                 return (uint64_t)-1;
2888         }
2889         ret = SMB_VFS_NEXT_DISK_FREE(handle, conv_smb_fname,
2890                                 bsize, dfree, dsize);
2891         if (ret == (uint64_t)-1) {
2892                 saved_errno = errno;
2893         }
2894         TALLOC_FREE(conv);
2895         TALLOC_FREE(conv_smb_fname);
2896         if (saved_errno != 0) {
2897                 errno = saved_errno;
2898         }
2899         return ret;
2900 }
2901
2902 static int shadow_copy2_get_quota(vfs_handle_struct *h