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