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