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