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