xref: /titanic_50/usr/src/uts/common/fs/smbsrv/smb_vss.c (revision a90cf9f29973990687fa61de9f1f6ea22e924e40)
189dc44ceSjose borrego /*
289dc44ceSjose borrego  * CDDL HEADER START
389dc44ceSjose borrego  *
489dc44ceSjose borrego  * The contents of this file are subject to the terms of the
589dc44ceSjose borrego  * Common Development and Distribution License (the "License").
689dc44ceSjose borrego  * You may not use this file except in compliance with the License.
789dc44ceSjose borrego  *
889dc44ceSjose borrego  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
989dc44ceSjose borrego  * or http://www.opensolaris.org/os/licensing.
1089dc44ceSjose borrego  * See the License for the specific language governing permissions
1189dc44ceSjose borrego  * and limitations under the License.
1289dc44ceSjose borrego  *
1389dc44ceSjose borrego  * When distributing Covered Code, include this CDDL HEADER in each
1489dc44ceSjose borrego  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1589dc44ceSjose borrego  * If applicable, add the following below this CDDL HEADER, with the
1689dc44ceSjose borrego  * fields enclosed by brackets "[]" replaced with your own identifying
1789dc44ceSjose borrego  * information: Portions Copyright [yyyy] [name of copyright owner]
1889dc44ceSjose borrego  *
1989dc44ceSjose borrego  * CDDL HEADER END
2089dc44ceSjose borrego  */
2189dc44ceSjose borrego /*
22148c5f43SAlan Wright  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
23*a90cf9f2SGordon Ross  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
2489dc44ceSjose borrego  */
2589dc44ceSjose borrego 
2689dc44ceSjose borrego /*
2789dc44ceSjose borrego  * Volume Copy Shadow Services (VSS) provides a way for users to
2889dc44ceSjose borrego  * restore/recover deleted files/directories.
2989dc44ceSjose borrego  * For the server to support VSS for Microsoft clients, there is
3089dc44ceSjose borrego  * two basic functions that need to be implemented.
3189dc44ceSjose borrego  * The first is to intercept the NT_TRANSACT_IOCTL command with
3289dc44ceSjose borrego  * the function code of FSCTL_SRV_ENUMERATE_SNAPSHOTS (0x00144064).
3389dc44ceSjose borrego  * This is to report the count or the count and list of snapshots
3489dc44ceSjose borrego  * for that share.
3589dc44ceSjose borrego  * The second function need to trap commands with the
3689dc44ceSjose borrego  * SMB_FLAGS2_REPARSE_PATH bit set in the smb header.  This bit
3789dc44ceSjose borrego  * means that there is a @GMT token in path that needs to be
3889dc44ceSjose borrego  * processed.  The @GMT token means to process this command, but
3989dc44ceSjose borrego  * in the snapshot.
4089dc44ceSjose borrego  */
4189dc44ceSjose borrego 
42bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h>
43bbf6f00cSJordan Brown #include <smbsrv/string.h>
4489dc44ceSjose borrego #include <smbsrv/winioctl.h>
459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #include <smbsrv/smb_door.h>
4689dc44ceSjose borrego 
4789dc44ceSjose borrego /* Size of the token on the wire due to encoding */
4889dc44ceSjose borrego #define	SMB_VSS_GMT_NET_SIZE(sr) (smb_ascii_or_unicode_null_len(sr) * \
4989dc44ceSjose borrego     SMB_VSS_GMT_SIZE)
5089dc44ceSjose borrego 
5189dc44ceSjose borrego #define	SMB_VSS_COUNT_SIZE 16
5289dc44ceSjose borrego 
539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static boolean_t smb_vss_is_gmttoken(const char *);
549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static const char *smb_vss_find_gmttoken(const char *);
55*a90cf9f2SGordon Ross static uint32_t smb_vss_encode_gmttokens(smb_request_t *, smb_fsctl_t *,
569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States     int32_t, smb_gmttoken_response_t *);
579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void smb_vss_remove_first_token_from_path(char *);
589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
598622ec45SGordon Ross static uint32_t smb_vss_get_count(smb_tree_t *, char *);
60*a90cf9f2SGordon Ross static void smb_vss_map_gmttoken(smb_tree_t *, char *, char *, time_t, char *);
618622ec45SGordon Ross static void smb_vss_get_snapshots(smb_tree_t *, char *,
628622ec45SGordon Ross     uint32_t, smb_gmttoken_response_t *);
639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void smb_vss_get_snapshots_free(smb_gmttoken_response_t *);
64148c5f43SAlan Wright static int smb_vss_lookup_node(smb_request_t *sr, smb_node_t *, vnode_t *,
65*a90cf9f2SGordon Ross     char *, smb_node_t *, smb_node_t **);
6689dc44ceSjose borrego 
6789dc44ceSjose borrego /*
6889dc44ceSjose borrego  * This is to respond to the nt_transact_ioctl to either respond with the
6989dc44ceSjose borrego  * number of snapshots, or to respond with the list.  It needs to be sorted
7089dc44ceSjose borrego  * before the reply.  If the the max data bytes to return is
7189dc44ceSjose borrego  * SMB_VSS_COUNT_SIZE, then all that is requested is the count, otherwise
7289dc44ceSjose borrego  * return the count and the list of @GMT tokens (one token for each
7389dc44ceSjose borrego  * snapshot).
7489dc44ceSjose borrego  */
7589dc44ceSjose borrego uint32_t
smb_vss_enum_snapshots(smb_request_t * sr,smb_fsctl_t * fsctl)76*a90cf9f2SGordon Ross smb_vss_enum_snapshots(smb_request_t *sr, smb_fsctl_t *fsctl)
7789dc44ceSjose borrego {
7889dc44ceSjose borrego 	uint32_t count = 0;
7989dc44ceSjose borrego 	char *root_path;
80b1352070SAlan Wright 	uint32_t status = NT_STATUS_SUCCESS;
819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_node_t *tnode;
82*a90cf9f2SGordon Ross 	smb_gmttoken_response_t snaps;
839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	ASSERT(sr->tid_tree);
859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	ASSERT(sr->tid_tree->t_snode);
8689dc44ceSjose borrego 
87*a90cf9f2SGordon Ross 	if (fsctl->MaxOutputResp < SMB_VSS_COUNT_SIZE)
88b1352070SAlan Wright 		return (NT_STATUS_INVALID_PARAMETER);
8989dc44ceSjose borrego 
909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	tnode = sr->tid_tree->t_snode;
9189dc44ceSjose borrego 	root_path  = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (smb_node_getmntpath(tnode, root_path, MAXPATHLEN) != 0)
93b1352070SAlan Wright 		return (NT_STATUS_INVALID_PARAMETER);
9489dc44ceSjose borrego 
95*a90cf9f2SGordon Ross 	if (fsctl->MaxOutputResp == SMB_VSS_COUNT_SIZE) {
968622ec45SGordon Ross 		count = smb_vss_get_count(sr->tid_tree, root_path);
97*a90cf9f2SGordon Ross 		if (smb_mbc_encodef(fsctl->out_mbc, "lllw", count, 0,
9889dc44ceSjose borrego 		    (count * SMB_VSS_GMT_NET_SIZE(sr) +
9989dc44ceSjose borrego 		    smb_ascii_or_unicode_null_len(sr)), 0) != 0) {
100b1352070SAlan Wright 			status = NT_STATUS_INVALID_PARAMETER;
10189dc44ceSjose borrego 		}
10289dc44ceSjose borrego 	} else {
103*a90cf9f2SGordon Ross 		count = fsctl->MaxOutputResp / SMB_VSS_GMT_NET_SIZE(sr);
10489dc44ceSjose borrego 
1058622ec45SGordon Ross 		smb_vss_get_snapshots(sr->tid_tree, root_path,
106*a90cf9f2SGordon Ross 		    count, &snaps);
10789dc44ceSjose borrego 
108*a90cf9f2SGordon Ross 		status = smb_vss_encode_gmttokens(sr, fsctl, count, &snaps);
10989dc44ceSjose borrego 
110*a90cf9f2SGordon Ross 		smb_vss_get_snapshots_free(&snaps);
11189dc44ceSjose borrego 	}
11289dc44ceSjose borrego 
11389dc44ceSjose borrego 	kmem_free(root_path, MAXPATHLEN);
114b1352070SAlan Wright 	return (status);
11589dc44ceSjose borrego }
11689dc44ceSjose borrego 
11789dc44ceSjose borrego /*
11889dc44ceSjose borrego  * sr - the request info, used to find root of dataset,
11989dc44ceSjose borrego  *      unicode or ascii, where the share is rooted in the
12089dc44ceSjose borrego  *      dataset
12189dc44ceSjose borrego  * root_node - root of the share
12289dc44ceSjose borrego  * cur_node - where in the share for the command
12389dc44ceSjose borrego  * buf - is the path for the command to be processed
12489dc44ceSjose borrego  *       returned without @GMT if processed
12589dc44ceSjose borrego  * vss_cur_node - returned value for the snapshot version
12689dc44ceSjose borrego  *                of the cur_node
12789dc44ceSjose borrego  * vss_root_node - returned value for the snapshot version
12889dc44ceSjose borrego  *                 of the root_node
12989dc44ceSjose borrego  *
13089dc44ceSjose borrego  * This routine is the processing for handling the
13189dc44ceSjose borrego  * SMB_FLAGS2_REPARSE_PATH bit being set in the smb header.
13289dc44ceSjose borrego  *
13389dc44ceSjose borrego  * By using the cur_node passed in, a new node is found or
13489dc44ceSjose borrego  * created that is the same place in the directory tree, but
13589dc44ceSjose borrego  * in the snapshot. We also use root_node to do the same for
13689dc44ceSjose borrego  * the root.
137148c5f43SAlan Wright  * Once the new smb node is found, the path is modified by
13889dc44ceSjose borrego  * removing the @GMT token from the path in the buf.
13989dc44ceSjose borrego  */
14089dc44ceSjose borrego int
smb_vss_lookup_nodes(smb_request_t * sr,smb_node_t * root_node,smb_node_t * cur_node,char * buf,smb_node_t ** vss_cur_node,smb_node_t ** vss_root_node)14189dc44ceSjose borrego smb_vss_lookup_nodes(smb_request_t *sr, smb_node_t *root_node,
14289dc44ceSjose borrego     smb_node_t *cur_node, char *buf, smb_node_t **vss_cur_node,
14389dc44ceSjose borrego     smb_node_t **vss_root_node)
14489dc44ceSjose borrego {
145*a90cf9f2SGordon Ross 	smb_arg_open_t	*op = &sr->arg.open;
1469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_node_t	*tnode;
147148c5f43SAlan Wright 	char		*snapname, *path;
148*a90cf9f2SGordon Ross 	char		*gmttoken;
149*a90cf9f2SGordon Ross 	char		gmttok_buf[SMB_VSS_GMT_SIZE];
150148c5f43SAlan Wright 	vnode_t		*fsrootvp = NULL;
151*a90cf9f2SGordon Ross 	time_t		toktime;
15289dc44ceSjose borrego 	int		err = 0;
153*a90cf9f2SGordon Ross 	boolean_t	smb1;
15489dc44ceSjose borrego 
15589dc44ceSjose borrego 	if (sr->tid_tree == NULL)
15689dc44ceSjose borrego 		return (ESTALE);
15789dc44ceSjose borrego 
158148c5f43SAlan Wright 	tnode = sr->tid_tree->t_snode;
15989dc44ceSjose borrego 
160148c5f43SAlan Wright 	ASSERT(tnode);
161148c5f43SAlan Wright 	ASSERT(tnode->vp);
162148c5f43SAlan Wright 	ASSERT(tnode->vp->v_vfsp);
163148c5f43SAlan Wright 
164*a90cf9f2SGordon Ross 	smb1 = (sr->session->dialect < SMB_VERS_2_BASE);
165*a90cf9f2SGordon Ross 	if (smb1) {
166*a90cf9f2SGordon Ross 		const char *p;
167*a90cf9f2SGordon Ross 
168*a90cf9f2SGordon Ross 		/* get gmttoken from buf */
1696e3e9d9cSafshin salek ardakani - Sun Microsystems - Irvine United States 		if ((p = smb_vss_find_gmttoken(buf)) == NULL)
17089dc44ceSjose borrego 			return (ENOENT);
17189dc44ceSjose borrego 
172*a90cf9f2SGordon Ross 		bcopy(p, gmttok_buf, SMB_VSS_GMT_SIZE);
173*a90cf9f2SGordon Ross 		gmttok_buf[SMB_VSS_GMT_SIZE - 1] = '\0';
174*a90cf9f2SGordon Ross 		gmttoken = gmttok_buf;
175*a90cf9f2SGordon Ross 		toktime = 0;
176*a90cf9f2SGordon Ross 	} else {
177*a90cf9f2SGordon Ross 		/* SMB2 and later */
178*a90cf9f2SGordon Ross 		gmttoken = NULL;
179*a90cf9f2SGordon Ross 		toktime = op->timewarp.tv_sec;
180*a90cf9f2SGordon Ross 	}
18189dc44ceSjose borrego 
182148c5f43SAlan Wright 	path = smb_srm_alloc(sr, MAXPATHLEN);
183148c5f43SAlan Wright 	snapname = smb_srm_alloc(sr, MAXPATHLEN);
184148c5f43SAlan Wright 
185148c5f43SAlan Wright 	err = smb_node_getmntpath(tnode, path, MAXPATHLEN);
186148c5f43SAlan Wright 	if (err != 0)
187148c5f43SAlan Wright 		return (err);
188148c5f43SAlan Wright 
189*a90cf9f2SGordon Ross 	/*
190*a90cf9f2SGordon Ross 	 * Find the corresponding snapshot name.  If snapname is
191*a90cf9f2SGordon Ross 	 * empty after the map call, no such snapshot was found.
192*a90cf9f2SGordon Ross 	 */
193148c5f43SAlan Wright 	*snapname = '\0';
194*a90cf9f2SGordon Ross 	smb_vss_map_gmttoken(sr->tid_tree, path, gmttoken, toktime,
195*a90cf9f2SGordon Ross 	    snapname);
196*a90cf9f2SGordon Ross 	if (*snapname == '\0')
197148c5f43SAlan Wright 		return (ENOENT);
198148c5f43SAlan Wright 
199148c5f43SAlan Wright 	/* find snapshot nodes */
2009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	err = VFS_ROOT(tnode->vp->v_vfsp, &fsrootvp);
2016e3e9d9cSafshin salek ardakani - Sun Microsystems - Irvine United States 	if (err != 0)
2026e3e9d9cSafshin salek ardakani - Sun Microsystems - Irvine United States 		return (err);
20389dc44ceSjose borrego 
204148c5f43SAlan Wright 	/* find snapshot node corresponding to root_node */
205148c5f43SAlan Wright 	err = smb_vss_lookup_node(sr, root_node, fsrootvp,
206*a90cf9f2SGordon Ross 	    snapname, cur_node, vss_root_node);
207148c5f43SAlan Wright 	if (err == 0) {
208148c5f43SAlan Wright 		/* find snapshot node corresponding to cur_node */
209148c5f43SAlan Wright 		err = smb_vss_lookup_node(sr, cur_node, fsrootvp,
210*a90cf9f2SGordon Ross 		    snapname, cur_node, vss_cur_node);
2116e3e9d9cSafshin salek ardakani - Sun Microsystems - Irvine United States 		if (err != 0)
212148c5f43SAlan Wright 			smb_node_release(*vss_root_node);
21389dc44ceSjose borrego 	}
21489dc44ceSjose borrego 
21589dc44ceSjose borrego 	VN_RELE(fsrootvp);
21689dc44ceSjose borrego 
217*a90cf9f2SGordon Ross 	if (smb1)
218148c5f43SAlan Wright 		smb_vss_remove_first_token_from_path(buf);
219*a90cf9f2SGordon Ross 
22089dc44ceSjose borrego 	return (err);
22189dc44ceSjose borrego }
22289dc44ceSjose borrego 
223148c5f43SAlan Wright /*
224148c5f43SAlan Wright  * Find snapshot node corresponding to 'node', and return it in
225148c5f43SAlan Wright  * 'vss_node', as follows:
226148c5f43SAlan Wright  * - find the path from fsrootvp to node, appending it to the
227148c5f43SAlan Wright  *   the snapshot path
228148c5f43SAlan Wright  * - lookup the vnode and smb_node (vss_node).
229148c5f43SAlan Wright  */
230148c5f43SAlan Wright static int
smb_vss_lookup_node(smb_request_t * sr,smb_node_t * node,vnode_t * fsrootvp,char * snapname,smb_node_t * dnode,smb_node_t ** vss_node)231148c5f43SAlan Wright smb_vss_lookup_node(smb_request_t *sr, smb_node_t *node, vnode_t *fsrootvp,
232*a90cf9f2SGordon Ross     char *snapname, smb_node_t *dnode, smb_node_t **vss_node)
233148c5f43SAlan Wright {
234148c5f43SAlan Wright 	char *p, *path;
235148c5f43SAlan Wright 	int err, len;
236148c5f43SAlan Wright 	vnode_t *vp = NULL;
237148c5f43SAlan Wright 
238148c5f43SAlan Wright 	*vss_node = NULL;
239148c5f43SAlan Wright 
240148c5f43SAlan Wright 	path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
241148c5f43SAlan Wright 	(void) snprintf(path, MAXPATHLEN, ".zfs/snapshot/%s/", snapname);
242148c5f43SAlan Wright 	len = strlen(path);
243148c5f43SAlan Wright 	p = path + len;
244148c5f43SAlan Wright 
245148c5f43SAlan Wright 	err = smb_node_getpath(node, fsrootvp, p, MAXPATHLEN - len);
246148c5f43SAlan Wright 	if (err == 0) {
247148c5f43SAlan Wright 		vp = smb_lookuppathvptovp(sr, path, fsrootvp, fsrootvp);
248148c5f43SAlan Wright 		if (vp) {
2498622ec45SGordon Ross 			*vss_node = smb_node_lookup(sr, NULL, zone_kcred(),
250*a90cf9f2SGordon Ross 			    vp, snapname, dnode, NULL);
251148c5f43SAlan Wright 			VN_RELE(vp);
252148c5f43SAlan Wright 		}
253148c5f43SAlan Wright 	}
254148c5f43SAlan Wright 
255148c5f43SAlan Wright 	kmem_free(path, MAXPATHLEN);
256148c5f43SAlan Wright 
257148c5f43SAlan Wright 	if (*vss_node != NULL)
258148c5f43SAlan Wright 		return (0);
259148c5f43SAlan Wright 
260148c5f43SAlan Wright 	return (err ? err : ENOENT);
261148c5f43SAlan Wright }
262148c5f43SAlan Wright 
263148c5f43SAlan Wright 
26489dc44ceSjose borrego static boolean_t
smb_vss_is_gmttoken(const char * s)26589dc44ceSjose borrego smb_vss_is_gmttoken(const char *s)
26689dc44ceSjose borrego {
26789dc44ceSjose borrego 	char *t = "@GMT-NNNN.NN.NN-NN.NN.NN";
26889dc44ceSjose borrego 	const char *str;
26989dc44ceSjose borrego 	char *template;
27089dc44ceSjose borrego 
27189dc44ceSjose borrego 	template = t;
27289dc44ceSjose borrego 	str = s;
27389dc44ceSjose borrego 
27489dc44ceSjose borrego 	while (*template) {
27589dc44ceSjose borrego 		if (*template == 'N') {
276bbf6f00cSJordan Brown 			if (!smb_isdigit(*str))
27789dc44ceSjose borrego 				return (B_FALSE);
27889dc44ceSjose borrego 		} else if (*template != *str) {
27989dc44ceSjose borrego 			return (B_FALSE);
28089dc44ceSjose borrego 		}
28189dc44ceSjose borrego 
28289dc44ceSjose borrego 		template++;
28389dc44ceSjose borrego 		str++;
28489dc44ceSjose borrego 	}
28589dc44ceSjose borrego 
28689dc44ceSjose borrego 	/* Make sure it is JUST the @GMT token */
28789dc44ceSjose borrego 	if ((*str == '\0') || (*str == '/'))
28889dc44ceSjose borrego 		return (B_TRUE);
28989dc44ceSjose borrego 
29089dc44ceSjose borrego 	return (B_FALSE);
29189dc44ceSjose borrego }
29289dc44ceSjose borrego 
29389dc44ceSjose borrego static const char *
smb_vss_find_gmttoken(const char * path)29489dc44ceSjose borrego smb_vss_find_gmttoken(const char *path)
29589dc44ceSjose borrego {
29689dc44ceSjose borrego 	const char *p;
29789dc44ceSjose borrego 
29889dc44ceSjose borrego 	p = path;
29989dc44ceSjose borrego 
30089dc44ceSjose borrego 	while (*p) {
301*a90cf9f2SGordon Ross 		if (*p == '@' && smb_vss_is_gmttoken(p))
30289dc44ceSjose borrego 			return (p);
30389dc44ceSjose borrego 		p++;
30489dc44ceSjose borrego 	}
30589dc44ceSjose borrego 	return (NULL);
30689dc44ceSjose borrego }
30789dc44ceSjose borrego 
30889dc44ceSjose borrego static uint32_t
smb_vss_encode_gmttokens(smb_request_t * sr,smb_fsctl_t * fsctl,int32_t count,smb_gmttoken_response_t * snap_data)309*a90cf9f2SGordon Ross smb_vss_encode_gmttokens(smb_request_t *sr, smb_fsctl_t *fsctl,
3109fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States     int32_t count, smb_gmttoken_response_t *snap_data)
31189dc44ceSjose borrego {
31289dc44ceSjose borrego 	uint32_t i;
31389dc44ceSjose borrego 	uint32_t returned_count;
31489dc44ceSjose borrego 	uint32_t num_gmttokens;
31589dc44ceSjose borrego 	char **gmttokens;
316b1352070SAlan Wright 	uint32_t status = NT_STATUS_SUCCESS;
31789dc44ceSjose borrego 	uint32_t data_size;
31889dc44ceSjose borrego 
3199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	returned_count = snap_data->gtr_count;
3209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	num_gmttokens = snap_data->gtr_gmttokens.gtr_gmttokens_len;
3219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	gmttokens = snap_data->gtr_gmttokens.gtr_gmttokens_val;
32289dc44ceSjose borrego 
323b1352070SAlan Wright 	if (returned_count > count)
324b1352070SAlan Wright 		status = NT_STATUS_BUFFER_TOO_SMALL;
32589dc44ceSjose borrego 
32689dc44ceSjose borrego 	data_size = returned_count * SMB_VSS_GMT_NET_SIZE(sr) +
32789dc44ceSjose borrego 	    smb_ascii_or_unicode_null_len(sr);
32889dc44ceSjose borrego 
329*a90cf9f2SGordon Ross 	if (smb_mbc_encodef(fsctl->out_mbc, "lll", returned_count,
330b1352070SAlan Wright 	    num_gmttokens, data_size) != 0)
331b1352070SAlan Wright 		return (NT_STATUS_INVALID_PARAMETER);
33289dc44ceSjose borrego 
333b1352070SAlan Wright 	if (status == NT_STATUS_SUCCESS) {
33489dc44ceSjose borrego 		for (i = 0; i < num_gmttokens; i++) {
335*a90cf9f2SGordon Ross 			if (smb_mbc_encodef(fsctl->out_mbc, "%u", sr,
336b1352070SAlan Wright 			    *gmttokens) != 0)
337b1352070SAlan Wright 				status = NT_STATUS_INVALID_PARAMETER;
33889dc44ceSjose borrego 			gmttokens++;
33989dc44ceSjose borrego 		}
34089dc44ceSjose borrego 	}
34189dc44ceSjose borrego 
342b1352070SAlan Wright 	return (status);
34389dc44ceSjose borrego }
34489dc44ceSjose borrego 
34589dc44ceSjose borrego /* This removes the first @GMT from the path */
34689dc44ceSjose borrego static void
smb_vss_remove_first_token_from_path(char * path)34789dc44ceSjose borrego smb_vss_remove_first_token_from_path(char *path)
34889dc44ceSjose borrego {
34989dc44ceSjose borrego 	boolean_t found;
35089dc44ceSjose borrego 	char *src, *dest;
35189dc44ceSjose borrego 
35289dc44ceSjose borrego 	src = path;
35389dc44ceSjose borrego 	dest = path;
35489dc44ceSjose borrego 
35589dc44ceSjose borrego 	found = B_FALSE;
35689dc44ceSjose borrego 
35789dc44ceSjose borrego 	while (*src != '\0') {
35889dc44ceSjose borrego 		if (!found && smb_vss_is_gmttoken(src)) {
35989dc44ceSjose borrego 			src += SMB_VSS_GMT_SIZE - 1;
36089dc44ceSjose borrego 			if (*src == '/')
36189dc44ceSjose borrego 				src += 1;
36289dc44ceSjose borrego 			found = B_TRUE;
36389dc44ceSjose borrego 			continue;
36489dc44ceSjose borrego 		}
36589dc44ceSjose borrego 		*dest = *src;
36689dc44ceSjose borrego 		src++;
36789dc44ceSjose borrego 		dest++;
36889dc44ceSjose borrego 	}
36989dc44ceSjose borrego 	*dest = *src;
37089dc44ceSjose borrego }
3719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
3729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
3739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * This returns the number of snapshots for the dataset
3749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * of the path provided.
3759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
3769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static uint32_t
smb_vss_get_count(smb_tree_t * tree,char * resource_path)3778622ec45SGordon Ross smb_vss_get_count(smb_tree_t *tree, char *resource_path)
3789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
3799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	uint32_t	count = 0;
3809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	int		rc;
3819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_string_t	path;
3829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
3839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	path.buf = resource_path;
3849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
3858622ec45SGordon Ross 	rc = smb_kdoor_upcall(tree->t_server, SMB_DR_VSS_GET_COUNT,
3869fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	    &path, smb_string_xdr, &count, xdr_uint32_t);
3879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
3889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (rc != 0)
3899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		count = 0;
3909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
3919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (count);
3929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
3939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
3949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
3959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * This takes a path for the root of the dataset and gets the counts of
3969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * snapshots for that dataset and the list of @GMT tokens (one for each
3979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * snapshot) up to the count provided.
3989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *
3999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Call smb_vss_get_snapshots_free after to free up the data.
4009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
4019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void
smb_vss_get_snapshots(smb_tree_t * tree,char * resource_path,uint32_t count,smb_gmttoken_response_t * gmttokens)4028622ec45SGordon Ross smb_vss_get_snapshots(smb_tree_t *tree, char *resource_path,
4038622ec45SGordon Ross     uint32_t count, smb_gmttoken_response_t *gmttokens)
4049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
4059fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_gmttoken_query_t	request;
4069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
4079fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	request.gtq_count = count;
4089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	request.gtq_path = resource_path;
4099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	bzero(gmttokens, sizeof (smb_gmttoken_response_t));
4109fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
4118622ec45SGordon Ross 	(void) smb_kdoor_upcall(tree->t_server, SMB_DR_VSS_GET_SNAPSHOTS,
4129fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	    &request, smb_gmttoken_query_xdr,
4139fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	    gmttokens, smb_gmttoken_response_xdr);
4149fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
4159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
4169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void
smb_vss_get_snapshots_free(smb_gmttoken_response_t * reply)4179fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_vss_get_snapshots_free(smb_gmttoken_response_t *reply)
4189fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
4199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	xdr_free(smb_gmttoken_response_xdr, (char *)reply);
4209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
4219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
4229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
4239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Returns the snapshot name for the @GMT token provided for the dataset
4249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * of the path.  If the snapshot cannot be found, a string with a NULL
4259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * is returned.
4269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
4279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void
smb_vss_map_gmttoken(smb_tree_t * tree,char * path,char * gmttoken,time_t toktime,char * snapname)4288622ec45SGordon Ross smb_vss_map_gmttoken(smb_tree_t *tree, char *path, char *gmttoken,
429*a90cf9f2SGordon Ross 	time_t toktime, char *snapname)
4309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
4319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_gmttoken_snapname_t	request;
4329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_string_t		result;
4339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
4349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	bzero(&result, sizeof (smb_string_t));
4359fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	result.buf = snapname;
4369fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
4379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	request.gts_path = path;
4389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	request.gts_gmttoken = gmttoken;
439*a90cf9f2SGordon Ross 	request.gts_toktime = toktime;
4409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
4418622ec45SGordon Ross 	(void) smb_kdoor_upcall(tree->t_server, SMB_DR_VSS_MAP_GMTTOKEN,
4429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	    &request, smb_gmttoken_snapname_xdr,
4439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	    &result, smb_string_xdr);
4449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
445