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