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