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