shadow_copy2: fix shadow_copy2_strip_snapshot() in the classical case
[mat/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         path = talloc_asprintf(mem_ctx, "%s/%s", handle->conn->connectpath,
494                                name);
495         if (path == NULL) {
496                 errno = ENOMEM;
497                 goto fail;
498         }
499         pathlen = talloc_get_size(path)-1;
500
501         DEBUG(10, ("converting %s\n", path));
502
503         if (!shadow_copy2_find_slashes(talloc_tos(), path,
504                                        &slashes, &num_slashes)) {
505                 goto fail;
506         }
507         insert = shadow_copy2_insert_string(talloc_tos(), handle, timestamp);
508         if (insert == NULL) {
509                 goto fail;
510         }
511         insertlen = talloc_get_size(insert)-1;
512         converted = talloc_array(mem_ctx, char, pathlen + insertlen + 1);
513         if (converted == NULL) {
514                 goto fail;
515         }
516
517         if (path[pathlen-1] != '/') {
518                 /*
519                  * Append a fake slash to find the snapshot root
520                  */
521                 size_t *tmp;
522                 tmp = talloc_realloc(talloc_tos(), slashes,
523                                      size_t, num_slashes+1);
524                 if (tmp == NULL) {
525                         goto fail;
526                 }
527                 slashes = tmp;
528                 slashes[num_slashes] = pathlen;
529                 num_slashes += 1;
530         }
531
532         min_offset = 0;
533
534         if (!config->crossmountpoints) {
535                 char *mount_point;
536
537                 mount_point = shadow_copy2_find_mount_point(talloc_tos(),
538                                                             handle);
539                 if (mount_point == NULL) {
540                         goto fail;
541                 }
542                 min_offset = strlen(mount_point);
543                 TALLOC_FREE(mount_point);
544         }
545
546         memcpy(converted, path, pathlen+1);
547         converted[pathlen+insertlen] = '\0';
548
549         ZERO_STRUCT(converted_fname);
550         converted_fname.base_name = converted;
551
552         for (i = num_slashes-1; i>=0; i--) {
553                 int ret;
554                 size_t offset;
555
556                 offset = slashes[i];
557
558                 if (offset < min_offset) {
559                         errno = ENOENT;
560                         goto fail;
561                 }
562
563                 memcpy(converted+offset, insert, insertlen);
564
565                 offset += insertlen;
566                 memcpy(converted+offset, path + slashes[i],
567                        pathlen - slashes[i]);
568
569                 ret = SMB_VFS_NEXT_LSTAT(handle, &converted_fname);
570
571                 DEBUG(10, ("Trying %s: %d (%s)\n", converted,
572                            ret, ret == 0 ? "ok" : strerror(errno)));
573                 if (ret == 0) {
574                         /* success */
575                         break;
576                 }
577                 if (errno == ENOTDIR) {
578                         /*
579                          * This is a valid condition: We appended the
580                          * .snaphots/@GMT.. to a file name. Just try
581                          * with the upper levels.
582                          */
583                         continue;
584                 }
585                 if (errno != ENOENT) {
586                         /* Other problem than "not found" */
587                         goto fail;
588                 }
589         }
590
591         if (i >= 0) {
592                 /*
593                  * Found something
594                  */
595                 DEBUG(10, ("Found %s\n", converted));
596                 result = converted;
597                 converted = NULL;
598         } else {
599                 errno = ENOENT;
600         }
601 fail:
602         saved_errno = errno;
603         TALLOC_FREE(converted);
604         TALLOC_FREE(insert);
605         TALLOC_FREE(slashes);
606         TALLOC_FREE(path);
607         errno = saved_errno;
608         return result;
609 }
610
611 /*
612   modify a sbuf return to ensure that inodes in the shadow directory
613   are different from those in the main directory
614  */
615 static void convert_sbuf(vfs_handle_struct *handle, const char *fname,
616                          SMB_STRUCT_STAT *sbuf)
617 {
618         struct shadow_copy2_config *config;
619
620         SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config,
621                                 return);
622
623         if (config->fixinodes) {
624                 /* some snapshot systems, like GPFS, return the name
625                    device:inode for the snapshot files as the current
626                    files. That breaks the 'restore' button in the shadow copy
627                    GUI, as the client gets a sharing violation.
628
629                    This is a crude way of allowing both files to be
630                    open at once. It has a slight chance of inode
631                    number collision, but I can't see a better approach
632                    without significant VFS changes
633                 */
634                 uint32_t shash;
635
636                 shash = hash(fname, strlen(fname), 0) & 0xFF000000;
637                 if (shash == 0) {
638                         shash = 1;
639                 }
640                 sbuf->st_ex_ino ^= shash;
641         }
642 }
643
644 static DIR *shadow_copy2_opendir(vfs_handle_struct *handle,
645                                             const char *fname,
646                                             const char *mask,
647                                             uint32 attr)
648 {
649         time_t timestamp;
650         char *stripped;
651         DIR *ret;
652         int saved_errno;
653         char *conv;
654
655         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
656                                          &timestamp, &stripped)) {
657                 return NULL;
658         }
659         if (timestamp == 0) {
660                 return SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
661         }
662         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
663         TALLOC_FREE(stripped);
664         if (conv == NULL) {
665                 return NULL;
666         }
667         ret = SMB_VFS_NEXT_OPENDIR(handle, conv, mask, attr);
668         saved_errno = errno;
669         TALLOC_FREE(conv);
670         errno = saved_errno;
671         return ret;
672 }
673
674 static int shadow_copy2_rename(vfs_handle_struct *handle,
675                                const struct smb_filename *smb_fname_src,
676                                const struct smb_filename *smb_fname_dst)
677 {
678         time_t timestamp_src, timestamp_dst;
679
680         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
681                                          smb_fname_src->base_name,
682                                          &timestamp_src, NULL)) {
683                 return -1;
684         }
685         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
686                                          smb_fname_dst->base_name,
687                                          &timestamp_dst, NULL)) {
688                 return -1;
689         }
690         if (timestamp_src != 0) {
691                 errno = EXDEV;
692                 return -1;
693         }
694         if (timestamp_dst != 0) {
695                 errno = EROFS;
696                 return -1;
697         }
698         return SMB_VFS_NEXT_RENAME(handle, smb_fname_src, smb_fname_dst);
699 }
700
701 static int shadow_copy2_symlink(vfs_handle_struct *handle,
702                                 const char *oldname, const char *newname)
703 {
704         time_t timestamp_old, timestamp_new;
705
706         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, oldname,
707                                          &timestamp_old, NULL)) {
708                 return -1;
709         }
710         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, newname,
711                                          &timestamp_new, NULL)) {
712                 return -1;
713         }
714         if ((timestamp_old != 0) || (timestamp_new != 0)) {
715                 errno = EROFS;
716                 return -1;
717         }
718         return SMB_VFS_NEXT_SYMLINK(handle, oldname, newname);
719 }
720
721 static int shadow_copy2_link(vfs_handle_struct *handle,
722                              const char *oldname, const char *newname)
723 {
724         time_t timestamp_old, timestamp_new;
725
726         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, oldname,
727                                          &timestamp_old, NULL)) {
728                 return -1;
729         }
730         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, newname,
731                                          &timestamp_new, NULL)) {
732                 return -1;
733         }
734         if ((timestamp_old != 0) || (timestamp_new != 0)) {
735                 errno = EROFS;
736                 return -1;
737         }
738         return SMB_VFS_NEXT_LINK(handle, oldname, newname);
739 }
740
741 static int shadow_copy2_stat(vfs_handle_struct *handle,
742                              struct smb_filename *smb_fname)
743 {
744         time_t timestamp;
745         char *stripped, *tmp;
746         int ret, saved_errno;
747
748         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
749                                          smb_fname->base_name,
750                                          &timestamp, &stripped)) {
751                 return -1;
752         }
753         if (timestamp == 0) {
754                 return SMB_VFS_NEXT_STAT(handle, smb_fname);
755         }
756
757         tmp = smb_fname->base_name;
758         smb_fname->base_name = shadow_copy2_convert(
759                 talloc_tos(), handle, stripped, timestamp);
760         TALLOC_FREE(stripped);
761
762         if (smb_fname->base_name == NULL) {
763                 smb_fname->base_name = tmp;
764                 return -1;
765         }
766
767         ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
768         saved_errno = errno;
769
770         TALLOC_FREE(smb_fname->base_name);
771         smb_fname->base_name = tmp;
772
773         if (ret == 0) {
774                 convert_sbuf(handle, smb_fname->base_name, &smb_fname->st);
775         }
776         errno = saved_errno;
777         return ret;
778 }
779
780 static int shadow_copy2_lstat(vfs_handle_struct *handle,
781                               struct smb_filename *smb_fname)
782 {
783         time_t timestamp;
784         char *stripped, *tmp;
785         int ret, saved_errno;
786
787         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
788                                          smb_fname->base_name,
789                                          &timestamp, &stripped)) {
790                 return -1;
791         }
792         if (timestamp == 0) {
793                 return SMB_VFS_NEXT_LSTAT(handle, smb_fname);
794         }
795
796         tmp = smb_fname->base_name;
797         smb_fname->base_name = shadow_copy2_convert(
798                 talloc_tos(), handle, stripped, timestamp);
799         TALLOC_FREE(stripped);
800
801         if (smb_fname->base_name == NULL) {
802                 smb_fname->base_name = tmp;
803                 return -1;
804         }
805
806         ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
807         saved_errno = errno;
808
809         TALLOC_FREE(smb_fname->base_name);
810         smb_fname->base_name = tmp;
811
812         if (ret == 0) {
813                 convert_sbuf(handle, smb_fname->base_name, &smb_fname->st);
814         }
815         errno = saved_errno;
816         return ret;
817 }
818
819 static int shadow_copy2_fstat(vfs_handle_struct *handle, files_struct *fsp,
820                               SMB_STRUCT_STAT *sbuf)
821 {
822         time_t timestamp;
823         int ret;
824
825         ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
826         if (ret == -1) {
827                 return ret;
828         }
829         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
830                                          fsp->fsp_name->base_name,
831                                          &timestamp, NULL)) {
832                 return 0;
833         }
834         if (timestamp != 0) {
835                 convert_sbuf(handle, fsp->fsp_name->base_name, sbuf);
836         }
837         return 0;
838 }
839
840 static int shadow_copy2_open(vfs_handle_struct *handle,
841                              struct smb_filename *smb_fname, files_struct *fsp,
842                              int flags, mode_t mode)
843 {
844         time_t timestamp;
845         char *stripped, *tmp;
846         int ret, saved_errno;
847
848         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
849                                          smb_fname->base_name,
850                                          &timestamp, &stripped)) {
851                 return -1;
852         }
853         if (timestamp == 0) {
854                 return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
855         }
856
857         tmp = smb_fname->base_name;
858         smb_fname->base_name = shadow_copy2_convert(
859                 talloc_tos(), handle, stripped, timestamp);
860         TALLOC_FREE(stripped);
861
862         if (smb_fname->base_name == NULL) {
863                 smb_fname->base_name = tmp;
864                 return -1;
865         }
866
867         ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
868         saved_errno = errno;
869
870         TALLOC_FREE(smb_fname->base_name);
871         smb_fname->base_name = tmp;
872
873         errno = saved_errno;
874         return ret;
875 }
876
877 static int shadow_copy2_unlink(vfs_handle_struct *handle,
878                                const struct smb_filename *smb_fname)
879 {
880         time_t timestamp;
881         char *stripped;
882         int ret, saved_errno;
883         struct smb_filename *conv;
884
885         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
886                                          smb_fname->base_name,
887                                          &timestamp, &stripped)) {
888                 return -1;
889         }
890         if (timestamp == 0) {
891                 return SMB_VFS_NEXT_UNLINK(handle, smb_fname);
892         }
893         conv = cp_smb_filename(talloc_tos(), smb_fname);
894         if (conv == NULL) {
895                 errno = ENOMEM;
896                 return -1;
897         }
898         conv->base_name = shadow_copy2_convert(
899                 conv, handle, stripped, timestamp);
900         TALLOC_FREE(stripped);
901         if (conv->base_name == NULL) {
902                 return -1;
903         }
904         ret = SMB_VFS_NEXT_UNLINK(handle, conv);
905         saved_errno = errno;
906         TALLOC_FREE(conv);
907         errno = saved_errno;
908         return ret;
909 }
910
911 static int shadow_copy2_chmod(vfs_handle_struct *handle, const char *fname,
912                               mode_t mode)
913 {
914         time_t timestamp;
915         char *stripped;
916         int ret, saved_errno;
917         char *conv;
918
919         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
920                                          &timestamp, &stripped)) {
921                 return -1;
922         }
923         if (timestamp == 0) {
924                 return SMB_VFS_NEXT_CHMOD(handle, fname, mode);
925         }
926         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
927         TALLOC_FREE(stripped);
928         if (conv == NULL) {
929                 return -1;
930         }
931         ret = SMB_VFS_NEXT_CHMOD(handle, conv, mode);
932         saved_errno = errno;
933         TALLOC_FREE(conv);
934         errno = saved_errno;
935         return ret;
936 }
937
938 static int shadow_copy2_chown(vfs_handle_struct *handle, const char *fname,
939                               uid_t uid, gid_t gid)
940 {
941         time_t timestamp;
942         char *stripped;
943         int ret, saved_errno;
944         char *conv;
945
946         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
947                                          &timestamp, &stripped)) {
948                 return -1;
949         }
950         if (timestamp == 0) {
951                 return SMB_VFS_NEXT_CHOWN(handle, fname, uid, gid);
952         }
953         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
954         TALLOC_FREE(stripped);
955         if (conv == NULL) {
956                 return -1;
957         }
958         ret = SMB_VFS_NEXT_CHOWN(handle, conv, uid, gid);
959         saved_errno = errno;
960         TALLOC_FREE(conv);
961         errno = saved_errno;
962         return ret;
963 }
964
965 static int shadow_copy2_chdir(vfs_handle_struct *handle,
966                               const char *fname)
967 {
968         time_t timestamp;
969         char *stripped;
970         int ret, saved_errno;
971         char *conv;
972
973         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
974                                          &timestamp, &stripped)) {
975                 return -1;
976         }
977         if (timestamp == 0) {
978                 return SMB_VFS_NEXT_CHDIR(handle, fname);
979         }
980         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
981         TALLOC_FREE(stripped);
982         if (conv == NULL) {
983                 return -1;
984         }
985         ret = SMB_VFS_NEXT_CHDIR(handle, conv);
986         saved_errno = errno;
987         TALLOC_FREE(conv);
988         errno = saved_errno;
989         return ret;
990 }
991
992 static int shadow_copy2_ntimes(vfs_handle_struct *handle,
993                                const struct smb_filename *smb_fname,
994                                struct smb_file_time *ft)
995 {
996         time_t timestamp;
997         char *stripped;
998         int ret, saved_errno;
999         struct smb_filename *conv;
1000
1001         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
1002                                          smb_fname->base_name,
1003                                          &timestamp, &stripped)) {
1004                 return -1;
1005         }
1006         if (timestamp == 0) {
1007                 return SMB_VFS_NEXT_NTIMES(handle, smb_fname, ft);
1008         }
1009         conv = cp_smb_filename(talloc_tos(), smb_fname);
1010         if (conv == NULL) {
1011                 errno = ENOMEM;
1012                 return -1;
1013         }
1014         conv->base_name = shadow_copy2_convert(
1015                 conv, handle, stripped, timestamp);
1016         TALLOC_FREE(stripped);
1017         if (conv->base_name == NULL) {
1018                 return -1;
1019         }
1020         ret = SMB_VFS_NEXT_NTIMES(handle, conv, ft);
1021         saved_errno = errno;
1022         TALLOC_FREE(conv);
1023         errno = saved_errno;
1024         return ret;
1025 }
1026
1027 static int shadow_copy2_readlink(vfs_handle_struct *handle,
1028                                  const char *fname, char *buf, size_t bufsiz)
1029 {
1030         time_t timestamp;
1031         char *stripped;
1032         int ret, saved_errno;
1033         char *conv;
1034
1035         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
1036                                          &timestamp, &stripped)) {
1037                 return -1;
1038         }
1039         if (timestamp == 0) {
1040                 return SMB_VFS_NEXT_READLINK(handle, fname, buf, bufsiz);
1041         }
1042         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1043         TALLOC_FREE(stripped);
1044         if (conv == NULL) {
1045                 return -1;
1046         }
1047         ret = SMB_VFS_NEXT_READLINK(handle, conv, buf, bufsiz);
1048         saved_errno = errno;
1049         TALLOC_FREE(conv);
1050         errno = saved_errno;
1051         return ret;
1052 }
1053
1054 static int shadow_copy2_mknod(vfs_handle_struct *handle,
1055                               const char *fname, mode_t mode, SMB_DEV_T dev)
1056 {
1057         time_t timestamp;
1058         char *stripped;
1059         int ret, saved_errno;
1060         char *conv;
1061
1062         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
1063                                          &timestamp, &stripped)) {
1064                 return -1;
1065         }
1066         if (timestamp == 0) {
1067                 return SMB_VFS_NEXT_MKNOD(handle, fname, mode, dev);
1068         }
1069         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1070         TALLOC_FREE(stripped);
1071         if (conv == NULL) {
1072                 return -1;
1073         }
1074         ret = SMB_VFS_NEXT_MKNOD(handle, conv, mode, dev);
1075         saved_errno = errno;
1076         TALLOC_FREE(conv);
1077         errno = saved_errno;
1078         return ret;
1079 }
1080
1081 static char *shadow_copy2_realpath(vfs_handle_struct *handle,
1082                                    const char *fname)
1083 {
1084         time_t timestamp;
1085         char *stripped = NULL;
1086         char *tmp = NULL;
1087         char *result = NULL;
1088         char *inserted = NULL;
1089         char *inserted_to, *inserted_end;
1090         int saved_errno;
1091
1092         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
1093                                          &timestamp, &stripped)) {
1094                 goto done;
1095         }
1096         if (timestamp == 0) {
1097                 return SMB_VFS_NEXT_REALPATH(handle, fname);
1098         }
1099
1100         tmp = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1101         if (tmp == NULL) {
1102                 goto done;
1103         }
1104
1105         result = SMB_VFS_NEXT_REALPATH(handle, tmp);
1106         if (result == NULL) {
1107                 goto done;
1108         }
1109
1110         /*
1111          * Take away what we've inserted. This removes the @GMT-thingy
1112          * completely, but will give a path under the share root.
1113          */
1114         inserted = shadow_copy2_insert_string(talloc_tos(), handle, timestamp);
1115         if (inserted == NULL) {
1116                 goto done;
1117         }
1118         inserted_to = strstr_m(result, inserted);
1119         if (inserted_to == NULL) {
1120                 DEBUG(2, ("SMB_VFS_NEXT_REALPATH removed %s\n", inserted));
1121                 goto done;
1122         }
1123         inserted_end = inserted_to + talloc_get_size(inserted) - 1;
1124         memmove(inserted_to, inserted_end, strlen(inserted_end)+1);
1125
1126 done:
1127         saved_errno = errno;
1128         TALLOC_FREE(inserted);
1129         TALLOC_FREE(tmp);
1130         TALLOC_FREE(stripped);
1131         errno = saved_errno;
1132         return result;
1133 }
1134
1135 /**
1136  * Check whether a given directory contains a
1137  * snapshot directory as direct subdirectory.
1138  * If yes, return the path of the snapshot-subdir,
1139  * otherwise return NULL.
1140  */
1141 static char *have_snapdir(struct vfs_handle_struct *handle,
1142                           const char *path)
1143 {
1144         struct smb_filename smb_fname;
1145         int ret;
1146         struct shadow_copy2_config *config;
1147
1148         SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config,
1149                                 return NULL);
1150
1151         ZERO_STRUCT(smb_fname);
1152         smb_fname.base_name = talloc_asprintf(talloc_tos(), "%s/%s",
1153                                               path, config->snapdir);
1154         if (smb_fname.base_name == NULL) {
1155                 return NULL;
1156         }
1157
1158         ret = SMB_VFS_NEXT_STAT(handle, &smb_fname);
1159         if ((ret == 0) && (S_ISDIR(smb_fname.st.st_ex_mode))) {
1160                 return smb_fname.base_name;
1161         }
1162         TALLOC_FREE(smb_fname.base_name);
1163         return NULL;
1164 }
1165
1166 /**
1167  * Find the snapshot directory (if any) for the given
1168  * filename (which is relative to the share).
1169  */
1170 static const char *shadow_copy2_find_snapdir(TALLOC_CTX *mem_ctx,
1171                                              struct vfs_handle_struct *handle,
1172                                              struct smb_filename *smb_fname)
1173 {
1174         char *path, *p;
1175         const char *snapdir;
1176         struct shadow_copy2_config *config;
1177
1178         SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config,
1179                                 return NULL);
1180
1181         /*
1182          * If the non-snapdisrseverywhere mode, we should not search!
1183          */
1184         if (!config->snapdirseverywhere) {
1185                 return config->snapshot_basepath;
1186         }
1187
1188         path = talloc_asprintf(mem_ctx, "%s/%s",
1189                                handle->conn->connectpath,
1190                                smb_fname->base_name);
1191         if (path == NULL) {
1192                 return NULL;
1193         }
1194
1195         snapdir = have_snapdir(handle, path);
1196         if (snapdir != NULL) {
1197                 TALLOC_FREE(path);
1198                 return snapdir;
1199         }
1200
1201         while ((p = strrchr(path, '/')) && (p > path)) {
1202
1203                 p[0] = '\0';
1204
1205                 snapdir = have_snapdir(handle, path);
1206                 if (snapdir != NULL) {
1207                         TALLOC_FREE(path);
1208                         return snapdir;
1209                 }
1210         }
1211         TALLOC_FREE(path);
1212         return NULL;
1213 }
1214
1215 static bool shadow_copy2_snapshot_to_gmt(vfs_handle_struct *handle,
1216                                          const char *name,
1217                                          char *gmt, size_t gmt_len)
1218 {
1219         struct tm timestamp;
1220         time_t timestamp_t;
1221         unsigned long int timestamp_long;
1222         const char *fmt;
1223         struct shadow_copy2_config *config;
1224
1225         SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config,
1226                                 return NULL);
1227
1228         fmt = config->gmt_format;
1229
1230         ZERO_STRUCT(timestamp);
1231         if (config->use_sscanf) {
1232                 if (sscanf(name, fmt, &timestamp_long) != 1) {
1233                         DEBUG(10, ("shadow_copy2_snapshot_to_gmt: "
1234                                    "no sscanf match %s: %s\n",
1235                                    fmt, name));
1236                         return false;
1237                 }
1238                 timestamp_t = timestamp_long;
1239                 gmtime_r(&timestamp_t, &timestamp);
1240         } else {
1241                 if (strptime(name, fmt, &timestamp) == NULL) {
1242                         DEBUG(10, ("shadow_copy2_snapshot_to_gmt: "
1243                                    "no match %s: %s\n",
1244                                    fmt, name));
1245                         return false;
1246                 }
1247                 DEBUG(10, ("shadow_copy2_snapshot_to_gmt: match %s: %s\n",
1248                            fmt, name));
1249                 
1250                 if (config->use_localtime) {
1251                         timestamp.tm_isdst = -1;
1252                         timestamp_t = mktime(&timestamp);
1253                         gmtime_r(&timestamp_t, &timestamp);
1254                 }
1255         }
1256
1257         strftime(gmt, gmt_len, GMT_FORMAT, &timestamp);
1258         return true;
1259 }
1260
1261 static int shadow_copy2_label_cmp_asc(const void *x, const void *y)
1262 {
1263         return strncmp((const char *)x, (const char *)y, sizeof(SHADOW_COPY_LABEL));
1264 }
1265
1266 static int shadow_copy2_label_cmp_desc(const void *x, const void *y)
1267 {
1268         return -strncmp((const char *)x, (const char *)y, sizeof(SHADOW_COPY_LABEL));
1269 }
1270
1271 /*
1272   sort the shadow copy data in ascending or descending order
1273  */
1274 static void shadow_copy2_sort_data(vfs_handle_struct *handle,
1275                                    struct shadow_copy_data *shadow_copy2_data)
1276 {
1277         int (*cmpfunc)(const void *, const void *);
1278         const char *sort;
1279         struct shadow_copy2_config *config;
1280
1281         SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config,
1282                                 return);
1283
1284         sort = config->sort_order;
1285         if (sort == NULL) {
1286                 return;
1287         }
1288
1289         if (strcmp(sort, "asc") == 0) {
1290                 cmpfunc = shadow_copy2_label_cmp_asc;
1291         } else if (strcmp(sort, "desc") == 0) {
1292                 cmpfunc = shadow_copy2_label_cmp_desc;
1293         } else {
1294                 return;
1295         }
1296
1297         if (shadow_copy2_data && shadow_copy2_data->num_volumes > 0 &&
1298             shadow_copy2_data->labels)
1299         {
1300                 TYPESAFE_QSORT(shadow_copy2_data->labels,
1301                                shadow_copy2_data->num_volumes,
1302                                cmpfunc);
1303         }
1304 }
1305
1306 static int shadow_copy2_get_shadow_copy_data(
1307         vfs_handle_struct *handle, files_struct *fsp,
1308         struct shadow_copy_data *shadow_copy2_data,
1309         bool labels)
1310 {
1311         DIR *p;
1312         const char *snapdir;
1313         struct dirent *d;
1314         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1315
1316         snapdir = shadow_copy2_find_snapdir(tmp_ctx, handle, fsp->fsp_name);
1317         if (snapdir == NULL) {
1318                 DEBUG(0,("shadow:snapdir not found for %s in get_shadow_copy_data\n",
1319                          handle->conn->connectpath));
1320                 errno = EINVAL;
1321                 talloc_free(tmp_ctx);
1322                 return -1;
1323         }
1324
1325         p = SMB_VFS_NEXT_OPENDIR(handle, snapdir, NULL, 0);
1326
1327         if (!p) {
1328                 DEBUG(2,("shadow_copy2: SMB_VFS_NEXT_OPENDIR() failed for '%s'"
1329                          " - %s\n", snapdir, strerror(errno)));
1330                 talloc_free(tmp_ctx);
1331                 errno = ENOSYS;
1332                 return -1;
1333         }
1334
1335         shadow_copy2_data->num_volumes = 0;
1336         shadow_copy2_data->labels      = NULL;
1337
1338         while ((d = SMB_VFS_NEXT_READDIR(handle, p, NULL))) {
1339                 char snapshot[GMT_NAME_LEN+1];
1340                 SHADOW_COPY_LABEL *tlabels;
1341
1342                 /*
1343                  * ignore names not of the right form in the snapshot
1344                  * directory
1345                  */
1346                 if (!shadow_copy2_snapshot_to_gmt(
1347                             handle, d->d_name,
1348                             snapshot, sizeof(snapshot))) {
1349
1350                         DEBUG(6, ("shadow_copy2_get_shadow_copy_data: "
1351                                   "ignoring %s\n", d->d_name));
1352                         continue;
1353                 }
1354                 DEBUG(6,("shadow_copy2_get_shadow_copy_data: %s -> %s\n",
1355                          d->d_name, snapshot));
1356
1357                 if (!labels) {
1358                         /* the caller doesn't want the labels */
1359                         shadow_copy2_data->num_volumes++;
1360                         continue;
1361                 }
1362
1363                 tlabels = talloc_realloc(shadow_copy2_data,
1364                                          shadow_copy2_data->labels,
1365                                          SHADOW_COPY_LABEL,
1366                                          shadow_copy2_data->num_volumes+1);
1367                 if (tlabels == NULL) {
1368                         DEBUG(0,("shadow_copy2: out of memory\n"));
1369                         SMB_VFS_NEXT_CLOSEDIR(handle, p);
1370                         talloc_free(tmp_ctx);
1371                         return -1;
1372                 }
1373
1374                 strlcpy(tlabels[shadow_copy2_data->num_volumes], snapshot,
1375                         sizeof(*tlabels));
1376
1377                 shadow_copy2_data->num_volumes++;
1378                 shadow_copy2_data->labels = tlabels;
1379         }
1380
1381         SMB_VFS_NEXT_CLOSEDIR(handle,p);
1382
1383         shadow_copy2_sort_data(handle, shadow_copy2_data);
1384
1385         talloc_free(tmp_ctx);
1386         return 0;
1387 }
1388
1389 static NTSTATUS shadow_copy2_fget_nt_acl(vfs_handle_struct *handle,
1390                                         struct files_struct *fsp,
1391                                         uint32 security_info,
1392                                          TALLOC_CTX *mem_ctx,
1393                                         struct security_descriptor **ppdesc)
1394 {
1395         time_t timestamp;
1396         char *stripped;
1397         NTSTATUS status;
1398         char *conv;
1399
1400         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
1401                                          fsp->fsp_name->base_name,
1402                                          &timestamp, &stripped)) {
1403                 return map_nt_error_from_unix(errno);
1404         }
1405         if (timestamp == 0) {
1406                 return SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info,
1407                                                 mem_ctx,
1408                                                 ppdesc);
1409         }
1410         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1411         TALLOC_FREE(stripped);
1412         if (conv == NULL) {
1413                 return map_nt_error_from_unix(errno);
1414         }
1415         status = SMB_VFS_NEXT_GET_NT_ACL(handle, conv, security_info,
1416                                          mem_ctx, ppdesc);
1417         TALLOC_FREE(conv);
1418         return status;
1419 }
1420
1421 static NTSTATUS shadow_copy2_get_nt_acl(vfs_handle_struct *handle,
1422                                         const char *fname,
1423                                         uint32 security_info,
1424                                         TALLOC_CTX *mem_ctx,
1425                                         struct security_descriptor **ppdesc)
1426 {
1427         time_t timestamp;
1428         char *stripped;
1429         NTSTATUS status;
1430         char *conv;
1431
1432         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
1433                                          &timestamp, &stripped)) {
1434                 return map_nt_error_from_unix(errno);
1435         }
1436         if (timestamp == 0) {
1437                 return SMB_VFS_NEXT_GET_NT_ACL(handle, fname, security_info,
1438                                                mem_ctx, ppdesc);
1439         }
1440         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1441         TALLOC_FREE(stripped);
1442         if (conv == NULL) {
1443                 return map_nt_error_from_unix(errno);
1444         }
1445         status = SMB_VFS_NEXT_GET_NT_ACL(handle, conv, security_info,
1446                                          mem_ctx, ppdesc);
1447         TALLOC_FREE(conv);
1448         return status;
1449 }
1450
1451 static int shadow_copy2_mkdir(vfs_handle_struct *handle,
1452                               const char *fname, mode_t mode)
1453 {
1454         time_t timestamp;
1455         char *stripped;
1456         int ret, saved_errno;
1457         char *conv;
1458
1459         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
1460                                          &timestamp, &stripped)) {
1461                 return -1;
1462         }
1463         if (timestamp == 0) {
1464                 return SMB_VFS_NEXT_MKDIR(handle, fname, mode);
1465         }
1466         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1467         TALLOC_FREE(stripped);
1468         if (conv == NULL) {
1469                 return -1;
1470         }
1471         ret = SMB_VFS_NEXT_MKDIR(handle, conv, mode);
1472         saved_errno = errno;
1473         TALLOC_FREE(conv);
1474         errno = saved_errno;
1475         return ret;
1476 }
1477
1478 static int shadow_copy2_rmdir(vfs_handle_struct *handle, const char *fname)
1479 {
1480         time_t timestamp;
1481         char *stripped;
1482         int ret, saved_errno;
1483         char *conv;
1484
1485         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
1486                                          &timestamp, &stripped)) {
1487                 return -1;
1488         }
1489         if (timestamp == 0) {
1490                 return SMB_VFS_NEXT_RMDIR(handle, fname);
1491         }
1492         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1493         TALLOC_FREE(stripped);
1494         if (conv == NULL) {
1495                 return -1;
1496         }
1497         ret = SMB_VFS_NEXT_RMDIR(handle, conv);
1498         saved_errno = errno;
1499         TALLOC_FREE(conv);
1500         errno = saved_errno;
1501         return ret;
1502 }
1503
1504 static int shadow_copy2_chflags(vfs_handle_struct *handle, const char *fname,
1505                                 unsigned int flags)
1506 {
1507         time_t timestamp;
1508         char *stripped;
1509         int ret, saved_errno;
1510         char *conv;
1511
1512         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
1513                                          &timestamp, &stripped)) {
1514                 return -1;
1515         }
1516         if (timestamp == 0) {
1517                 return SMB_VFS_NEXT_CHFLAGS(handle, fname, flags);
1518         }
1519         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1520         TALLOC_FREE(stripped);
1521         if (conv == NULL) {
1522                 return -1;
1523         }
1524         ret = SMB_VFS_NEXT_CHFLAGS(handle, conv, flags);
1525         saved_errno = errno;
1526         TALLOC_FREE(conv);
1527         errno = saved_errno;
1528         return ret;
1529 }
1530
1531 static ssize_t shadow_copy2_getxattr(vfs_handle_struct *handle,
1532                                      const char *fname, const char *aname,
1533                                      void *value, size_t size)
1534 {
1535         time_t timestamp;
1536         char *stripped;
1537         ssize_t ret;
1538         int saved_errno;
1539         char *conv;
1540
1541         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
1542                                          &timestamp, &stripped)) {
1543                 return -1;
1544         }
1545         if (timestamp == 0) {
1546                 return SMB_VFS_NEXT_GETXATTR(handle, fname, aname, value,
1547                                              size);
1548         }
1549         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1550         TALLOC_FREE(stripped);
1551         if (conv == NULL) {
1552                 return -1;
1553         }
1554         ret = SMB_VFS_NEXT_GETXATTR(handle, conv, aname, value, size);
1555         saved_errno = errno;
1556         TALLOC_FREE(conv);
1557         errno = saved_errno;
1558         return ret;
1559 }
1560
1561 static ssize_t shadow_copy2_listxattr(struct vfs_handle_struct *handle,
1562                                       const char *fname,
1563                                       char *list, size_t size)
1564 {
1565         time_t timestamp;
1566         char *stripped;
1567         ssize_t ret;
1568         int saved_errno;
1569         char *conv;
1570
1571         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
1572                                          &timestamp, &stripped)) {
1573                 return -1;
1574         }
1575         if (timestamp == 0) {
1576                 return SMB_VFS_NEXT_LISTXATTR(handle, fname, list, size);
1577         }
1578         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1579         TALLOC_FREE(stripped);
1580         if (conv == NULL) {
1581                 return -1;
1582         }
1583         ret = SMB_VFS_NEXT_LISTXATTR(handle, conv, list, size);
1584         saved_errno = errno;
1585         TALLOC_FREE(conv);
1586         errno = saved_errno;
1587         return ret;
1588 }
1589
1590 static int shadow_copy2_removexattr(vfs_handle_struct *handle,
1591                                     const char *fname, const char *aname)
1592 {
1593         time_t timestamp;
1594         char *stripped;
1595         int ret, saved_errno;
1596         char *conv;
1597
1598         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
1599                                          &timestamp, &stripped)) {
1600                 return -1;
1601         }
1602         if (timestamp == 0) {
1603                 return SMB_VFS_NEXT_REMOVEXATTR(handle, fname, aname);
1604         }
1605         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1606         TALLOC_FREE(stripped);
1607         if (conv == NULL) {
1608                 return -1;
1609         }
1610         ret = SMB_VFS_NEXT_REMOVEXATTR(handle, conv, aname);
1611         saved_errno = errno;
1612         TALLOC_FREE(conv);
1613         errno = saved_errno;
1614         return ret;
1615 }
1616
1617 static int shadow_copy2_setxattr(struct vfs_handle_struct *handle,
1618                                  const char *fname,
1619                                  const char *aname, const void *value,
1620                                  size_t size, int flags)
1621 {
1622         time_t timestamp;
1623         char *stripped;
1624         ssize_t ret;
1625         int saved_errno;
1626         char *conv;
1627
1628         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
1629                                          &timestamp, &stripped)) {
1630                 return -1;
1631         }
1632         if (timestamp == 0) {
1633                 return SMB_VFS_NEXT_SETXATTR(handle, fname, aname, value, size,
1634                                              flags);
1635         }
1636         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1637         TALLOC_FREE(stripped);
1638         if (conv == NULL) {
1639                 return -1;
1640         }
1641         ret = SMB_VFS_NEXT_SETXATTR(handle, conv, aname, value, size, flags);
1642         saved_errno = errno;
1643         TALLOC_FREE(conv);
1644         errno = saved_errno;
1645         return ret;
1646 }
1647
1648 static int shadow_copy2_chmod_acl(vfs_handle_struct *handle,
1649                                   const char *fname, mode_t mode)
1650 {
1651         time_t timestamp;
1652         char *stripped;
1653         ssize_t ret;
1654         int saved_errno;
1655         char *conv;
1656
1657         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
1658                                          &timestamp, &stripped)) {
1659                 return -1;
1660         }
1661         if (timestamp == 0) {
1662                 return SMB_VFS_NEXT_CHMOD_ACL(handle, fname, mode);
1663         }
1664         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1665         TALLOC_FREE(stripped);
1666         if (conv == NULL) {
1667                 return -1;
1668         }
1669         ret = SMB_VFS_NEXT_CHMOD_ACL(handle, conv, mode);
1670         saved_errno = errno;
1671         TALLOC_FREE(conv);
1672         errno = saved_errno;
1673         return ret;
1674 }
1675
1676 static int shadow_copy2_get_real_filename(struct vfs_handle_struct *handle,
1677                                           const char *path,
1678                                           const char *name,
1679                                           TALLOC_CTX *mem_ctx,
1680                                           char **found_name)
1681 {
1682         time_t timestamp;
1683         char *stripped;
1684         ssize_t ret;
1685         int saved_errno;
1686         char *conv;
1687
1688         if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, path,
1689                                          &timestamp, &stripped)) {
1690                 return -1;
1691         }
1692         if (timestamp == 0) {
1693                 return SMB_VFS_NEXT_GET_REAL_FILENAME(handle, path, name,
1694                                                       mem_ctx, found_name);
1695         }
1696         if (stripped[0] == '\0') {
1697                 *found_name = talloc_strdup(mem_ctx, name);
1698                 if (*found_name == NULL) {
1699                         errno = ENOMEM;
1700                         return -1;
1701                 }
1702                 return 0;
1703         }
1704         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1705         TALLOC_FREE(stripped);
1706         if (conv == NULL) {
1707                 return -1;
1708         }
1709         ret = SMB_VFS_NEXT_GET_REAL_FILENAME(handle, conv, name,
1710                                              mem_ctx, found_name);
1711         saved_errno = errno;
1712         TALLOC_FREE(conv);
1713         errno = saved_errno;
1714         return ret;
1715 }
1716
1717 static uint64_t shadow_copy2_disk_free(vfs_handle_struct *handle,
1718                                        const char *path, bool small_query,
1719                                        uint64_t *bsize, uint64_t *dfree,
1720                                        uint64_t *dsize)
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, path,
1729                                          &timestamp, &stripped)) {
1730                 return -1;
1731         }
1732         if (timestamp == 0) {
1733                 return SMB_VFS_NEXT_DISK_FREE(handle, path, small_query,
1734                                               bsize, dfree, dsize);
1735         }
1736
1737         conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
1738         TALLOC_FREE(stripped);
1739         if (conv == NULL) {
1740                 return -1;
1741         }
1742
1743         ret = SMB_VFS_NEXT_DISK_FREE(handle, conv, small_query, bsize, dfree,
1744                                      dsize);
1745
1746         saved_errno = errno;
1747         TALLOC_FREE(conv);
1748         errno = saved_errno;
1749
1750         return ret;
1751 }
1752
1753 static int shadow_copy2_connect(struct vfs_handle_struct *handle,
1754                                 const char *service, const char *user)
1755 {
1756         struct shadow_copy2_config *config;
1757         int ret;
1758         const char *snapdir;
1759         const char *gmt_format;
1760         const char *sort_order;
1761         const char *basedir;
1762         const char *mount_point;
1763
1764         DEBUG(10, (__location__ ": cnum[%u], connectpath[%s]\n",
1765                    (unsigned)handle->conn->cnum,
1766                    handle->conn->connectpath));
1767
1768         ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
1769         if (ret < 0) {
1770                 return ret;
1771         }
1772
1773         config = talloc_zero(handle->conn, struct shadow_copy2_config);
1774         if (config == NULL) {
1775                 DEBUG(0, ("talloc_zero() failed\n"));
1776                 errno = ENOMEM;
1777                 return -1;
1778         }
1779
1780         gmt_format = lp_parm_const_string(SNUM(handle->conn),
1781                                           "shadow", "format",
1782                                           GMT_FORMAT);
1783         config->gmt_format = talloc_strdup(config, gmt_format);
1784         if (config->gmt_format == NULL) {
1785                 DEBUG(0, ("talloc_strdup() failed\n"));
1786                 errno = ENOMEM;
1787                 return -1;
1788         }
1789
1790         config->use_sscanf = lp_parm_bool(SNUM(handle->conn),
1791                                           "shadow", "sscanf", false);
1792
1793         config->use_localtime = lp_parm_bool(SNUM(handle->conn),
1794                                              "shadow", "localtime",
1795                                              false);
1796
1797         snapdir = lp_parm_const_string(SNUM(handle->conn),
1798                                        "shadow", "snapdir",
1799                                        ".snapshots");
1800         config->snapdir = talloc_strdup(config, snapdir);
1801         if (config->snapdir == NULL) {
1802                 DEBUG(0, ("talloc_strdup() failed\n"));
1803                 errno = ENOMEM;
1804                 return -1;
1805         }
1806
1807         config->snapdirseverywhere = lp_parm_bool(SNUM(handle->conn),
1808                                                   "shadow",
1809                                                   "snapdirseverywhere",
1810                                                   false);
1811
1812         config->crossmountpoints = lp_parm_bool(SNUM(handle->conn),
1813                                                 "shadow", "crossmountpoints",
1814                                                 false);
1815
1816         config->fixinodes = lp_parm_bool(SNUM(handle->conn),
1817                                          "shadow", "fixinodes",
1818                                          false);
1819
1820         sort_order = lp_parm_const_string(SNUM(handle->conn),
1821                                           "shadow", "sort", "desc");
1822         config->sort_order = talloc_strdup(config, sort_order);
1823         if (config->sort_order == NULL) {
1824                 DEBUG(0, ("talloc_strdup() failed\n"));
1825                 errno = ENOMEM;
1826                 return -1;
1827         }
1828
1829         mount_point = lp_parm_const_string(SNUM(handle->conn),
1830                                            "shadow", "mountpoint", NULL);
1831         if (mount_point != NULL) {
1832                 if (mount_point[0] != '/') {
1833                         DEBUG(1, (__location__ " Warning: 'mountpoint' is "
1834                                   "relative ('%s'), but it has to be an "
1835                                   "absolute path. Ignoring provided value.\n",
1836                                   mount_point));
1837                         mount_point = NULL;
1838                 } else {
1839                         char *p;
1840                         p = strstr(handle->conn->connectpath, mount_point);
1841                         if (p != handle->conn->connectpath) {
1842                                 DEBUG(1, ("Warning: mount_point (%s) is not a "
1843                                           "subdirectory of the share root "
1844                                           "(%s). Ignoring provided value.\n",
1845                                           mount_point,
1846                                           handle->conn->connectpath));
1847                                 mount_point = NULL;
1848                         }
1849                 }
1850         }
1851
1852         if (mount_point != NULL) {
1853                 config->mount_point = talloc_strdup(config, mount_point);
1854                 if (config->mount_point == NULL) {
1855                         DEBUG(0, (__location__ " talloc_strdup() failed\n"));
1856                         return -1;
1857                 }
1858         } else {
1859                 config->mount_point = shadow_copy2_find_mount_point(config,
1860                                                                     handle);
1861                 if (config->mount_point == NULL) {
1862                         DEBUG(0, (__location__ ": shadow_copy2_find_mount_point"
1863                                   " failed: %s\n", strerror(errno)));
1864                         return -1;
1865                 }
1866         }
1867
1868         basedir = lp_parm_const_string(SNUM(handle->conn),
1869                                        "shadow", "basedir", NULL);
1870
1871         if (basedir != NULL) {
1872                 if (basedir[0] != '/') {
1873                         DEBUG(1, (__location__ " Warning: 'basedir' is "
1874                                   "relative ('%s'), but it has to be an "
1875                                   "absolute path. Disabling basedir.\n",
1876                                   basedir));
1877                 } else {
1878                         char *p;
1879                         p = strstr(basedir, config->mount_point);
1880                         if (p != basedir) {
1881                                 DEBUG(1, ("Warning: basedir (%s) is not a "
1882                                           "subdirectory of the share root's "
1883                                           "mount point (%s). "
1884                                           "Disabling basedir\n",
1885                                           basedir, config->mount_point));
1886                         } else {
1887                                 config->basedir = talloc_strdup(config,
1888                                                                 basedir);
1889                                 if (config->basedir == NULL) {
1890                                         DEBUG(0, ("talloc_strdup() failed\n"));
1891                                         errno = ENOMEM;
1892                                         return -1;
1893                                 }
1894                         }
1895                 }
1896         }
1897
1898         if (config->snapdirseverywhere && config->basedir != NULL) {
1899                 DEBUG(1, (__location__ " Warning: 'basedir' is incompatible "
1900                           "with 'snapdirseverywhere'. Disabling basedir.\n"));
1901                 TALLOC_FREE(config->basedir);
1902         }
1903
1904         if (config->crossmountpoints && config->basedir != NULL) {
1905                 DEBUG(1, (__location__ " Warning: 'basedir' is incompatible "
1906                           "with 'crossmountpoints'. Disabling basedir.\n"));
1907                 TALLOC_FREE(config->basedir);
1908         }
1909
1910         if (config->basedir == NULL) {
1911                 config->basedir = config->mount_point;
1912         }
1913
1914         if (strlen(config->basedir) != strlen(handle->conn->connectpath)) {
1915                 config->rel_connectpath = talloc_strdup(config,
1916                         handle->conn->connectpath + strlen(config->basedir));
1917                 if (config->rel_connectpath == NULL) {
1918                         DEBUG(0, ("talloc_strdup() failed\n"));
1919                         errno = ENOMEM;
1920                         return -1;
1921                 }
1922         }
1923
1924         if (config->snapdir[0] == '/') {
1925                 config->snapdir_absolute = true;
1926
1927                 if (config->snapdirseverywhere == true) {
1928                         DEBUG(1, (__location__ " Warning: An absolute snapdir "
1929                                   "is incompatible with 'snapdirseverywhere', "
1930                                   "setting 'snapdirseverywhere' to false.\n"));
1931                         config->snapdirseverywhere = false;
1932                 }
1933
1934                 if (config->crossmountpoints == true) {
1935                         DEBUG(1, (__location__ " Warning: 'crossmountpoints' "
1936                                   "is not supported with an absolute snapdir. "
1937                                   "Disabling it.\n"));
1938                         config->crossmountpoints = false;
1939                 }
1940
1941                 config->snapshot_basepath = config->snapdir;
1942         } else {
1943                 config->snapshot_basepath = talloc_asprintf(config, "%s/%s",
1944                                 config->mount_point, config->snapdir);
1945                 if (config->snapshot_basepath == NULL) {
1946                         DEBUG(0, ("talloc_asprintf() failed\n"));
1947                         errno = ENOMEM;
1948                         return -1;
1949                 }
1950         }
1951
1952         DEBUG(10, ("shadow_copy2_connect: configuration:\n"
1953                    "  share root: '%s'\n"
1954                    "  basedir: '%s'\n"
1955                    "  mountpoint: '%s'\n"
1956                    "  rel share root: '%s'\n"
1957                    "  snapdir: '%s'\n"
1958                    "  snapshot base path: '%s'\n"
1959                    "  format: '%s'\n"
1960                    "  use sscanf: %s\n"
1961                    "  snapdirs everywhere: %s\n"
1962                    "  cross mountpoints: %s\n"
1963                    "  fix inodes: %s\n"
1964                    "  sort order: %s\n"
1965                    "",
1966                    handle->conn->connectpath,
1967                    config->basedir,
1968                    config->mount_point,
1969                    config->rel_connectpath,
1970                    config->snapdir,
1971                    config->snapshot_basepath,
1972                    config->gmt_format,
1973                    config->use_sscanf ? "yes" : "no",
1974                    config->snapdirseverywhere ? "yes" : "no",
1975                    config->crossmountpoints ? "yes" : "no",
1976                    config->fixinodes ? "yes" : "no",
1977                    config->sort_order
1978                    ));
1979
1980
1981         SMB_VFS_HANDLE_SET_DATA(handle, config,
1982                                 NULL, struct shadow_copy2_config,
1983                                 return -1);
1984
1985         return 0;
1986 }
1987
1988 static struct vfs_fn_pointers vfs_shadow_copy2_fns = {
1989         .connect_fn = shadow_copy2_connect,
1990         .opendir_fn = shadow_copy2_opendir,
1991         .disk_free_fn = shadow_copy2_disk_free,
1992         .rename_fn = shadow_copy2_rename,
1993         .link_fn = shadow_copy2_link,
1994         .symlink_fn = shadow_copy2_symlink,
1995         .stat_fn = shadow_copy2_stat,
1996         .lstat_fn = shadow_copy2_lstat,
1997         .fstat_fn = shadow_copy2_fstat,
1998         .open_fn = shadow_copy2_open,
1999         .unlink_fn = shadow_copy2_unlink,
2000         .chmod_fn = shadow_copy2_chmod,
2001         .chown_fn = shadow_copy2_chown,
2002         .chdir_fn = shadow_copy2_chdir,
2003         .ntimes_fn = shadow_copy2_ntimes,
2004         .readlink_fn = shadow_copy2_readlink,
2005         .mknod_fn = shadow_copy2_mknod,
2006         .realpath_fn = shadow_copy2_realpath,
2007         .get_nt_acl_fn = shadow_copy2_get_nt_acl,
2008         .fget_nt_acl_fn = shadow_copy2_fget_nt_acl,
2009         .get_shadow_copy_data_fn = shadow_copy2_get_shadow_copy_data,
2010         .mkdir_fn = shadow_copy2_mkdir,
2011         .rmdir_fn = shadow_copy2_rmdir,
2012         .getxattr_fn = shadow_copy2_getxattr,
2013         .listxattr_fn = shadow_copy2_listxattr,
2014         .removexattr_fn = shadow_copy2_removexattr,
2015         .setxattr_fn = shadow_copy2_setxattr,
2016         .chmod_acl_fn = shadow_copy2_chmod_acl,
2017         .chflags_fn = shadow_copy2_chflags,
2018         .get_real_filename_fn = shadow_copy2_get_real_filename,
2019 };
2020
2021 NTSTATUS vfs_shadow_copy2_init(void);
2022 NTSTATUS vfs_shadow_copy2_init(void)
2023 {
2024         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2025                                 "shadow_copy2", &vfs_shadow_copy2_fns);
2026 }