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