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