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