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