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