18474SJose.Borrego@Sun.COM /* 28474SJose.Borrego@Sun.COM * CDDL HEADER START 38474SJose.Borrego@Sun.COM * 48474SJose.Borrego@Sun.COM * The contents of this file are subject to the terms of the 58474SJose.Borrego@Sun.COM * Common Development and Distribution License (the "License"). 68474SJose.Borrego@Sun.COM * You may not use this file except in compliance with the License. 78474SJose.Borrego@Sun.COM * 88474SJose.Borrego@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 98474SJose.Borrego@Sun.COM * or http://www.opensolaris.org/os/licensing. 108474SJose.Borrego@Sun.COM * See the License for the specific language governing permissions 118474SJose.Borrego@Sun.COM * and limitations under the License. 128474SJose.Borrego@Sun.COM * 138474SJose.Borrego@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 148474SJose.Borrego@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 158474SJose.Borrego@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 168474SJose.Borrego@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 178474SJose.Borrego@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 188474SJose.Borrego@Sun.COM * 198474SJose.Borrego@Sun.COM * CDDL HEADER END 208474SJose.Borrego@Sun.COM */ 218474SJose.Borrego@Sun.COM /* 228474SJose.Borrego@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 238474SJose.Borrego@Sun.COM * Use is subject to license terms. 248474SJose.Borrego@Sun.COM */ 258474SJose.Borrego@Sun.COM 268474SJose.Borrego@Sun.COM /* 278474SJose.Borrego@Sun.COM * Volume Copy Shadow Services (VSS) provides a way for users to 288474SJose.Borrego@Sun.COM * restore/recover deleted files/directories. 298474SJose.Borrego@Sun.COM * For the server to support VSS for Microsoft clients, there is 308474SJose.Borrego@Sun.COM * two basic functions that need to be implemented. 318474SJose.Borrego@Sun.COM * The first is to intercept the NT_TRANSACT_IOCTL command with 328474SJose.Borrego@Sun.COM * the function code of FSCTL_SRV_ENUMERATE_SNAPSHOTS (0x00144064). 338474SJose.Borrego@Sun.COM * This is to report the count or the count and list of snapshots 348474SJose.Borrego@Sun.COM * for that share. 358474SJose.Borrego@Sun.COM * The second function need to trap commands with the 368474SJose.Borrego@Sun.COM * SMB_FLAGS2_REPARSE_PATH bit set in the smb header. This bit 378474SJose.Borrego@Sun.COM * means that there is a @GMT token in path that needs to be 388474SJose.Borrego@Sun.COM * processed. The @GMT token means to process this command, but 398474SJose.Borrego@Sun.COM * in the snapshot. 408474SJose.Borrego@Sun.COM */ 418474SJose.Borrego@Sun.COM 428474SJose.Borrego@Sun.COM #include <smbsrv/smb_incl.h> 438474SJose.Borrego@Sun.COM #include <smbsrv/winioctl.h> 448474SJose.Borrego@Sun.COM #include <smbsrv/ntstatus.h> 458474SJose.Borrego@Sun.COM #include <smbsrv/smb_door_svc.h> 468474SJose.Borrego@Sun.COM 478474SJose.Borrego@Sun.COM /* Size of the token on the wire due to encoding */ 488474SJose.Borrego@Sun.COM #define SMB_VSS_GMT_NET_SIZE(sr) (smb_ascii_or_unicode_null_len(sr) * \ 498474SJose.Borrego@Sun.COM SMB_VSS_GMT_SIZE) 508474SJose.Borrego@Sun.COM 518474SJose.Borrego@Sun.COM #define SMB_VSS_COUNT_SIZE 16 528474SJose.Borrego@Sun.COM 538474SJose.Borrego@Sun.COM static boolean_t smb_vss_is_gmttoken(const char *str); 548474SJose.Borrego@Sun.COM static const char *smb_vss_find_gmttoken(const char *path); 558474SJose.Borrego@Sun.COM static int smb_vss_get_fsmountpath(smb_request_t *sr, char *buf, 568474SJose.Borrego@Sun.COM uint32_t buflen); 578474SJose.Borrego@Sun.COM static uint32_t smb_vss_encode_gmttokens(smb_request_t *sr, smb_xa_t *xa, 588474SJose.Borrego@Sun.COM int32_t count, smb_dr_return_gmttokens_t *snap_data); 598474SJose.Borrego@Sun.COM static void smb_vss_remove_first_token_from_path(char *c); 608474SJose.Borrego@Sun.COM 618474SJose.Borrego@Sun.COM /* 628474SJose.Borrego@Sun.COM * This is to respond to the nt_transact_ioctl to either respond with the 638474SJose.Borrego@Sun.COM * number of snapshots, or to respond with the list. It needs to be sorted 648474SJose.Borrego@Sun.COM * before the reply. If the the max data bytes to return is 658474SJose.Borrego@Sun.COM * SMB_VSS_COUNT_SIZE, then all that is requested is the count, otherwise 668474SJose.Borrego@Sun.COM * return the count and the list of @GMT tokens (one token for each 678474SJose.Borrego@Sun.COM * snapshot). 688474SJose.Borrego@Sun.COM */ 698474SJose.Borrego@Sun.COM uint32_t 708474SJose.Borrego@Sun.COM smb_vss_ioctl_enumerate_snaps(smb_request_t *sr, smb_xa_t *xa) 718474SJose.Borrego@Sun.COM { 728474SJose.Borrego@Sun.COM uint32_t count = 0; 738474SJose.Borrego@Sun.COM char *root_path; 748474SJose.Borrego@Sun.COM uint32_t err = SDRC_SUCCESS; 758474SJose.Borrego@Sun.COM smb_dr_return_gmttokens_t gmttokens; 768474SJose.Borrego@Sun.COM 778474SJose.Borrego@Sun.COM if (xa->smb_mdrcnt < SMB_VSS_COUNT_SIZE) { 788474SJose.Borrego@Sun.COM smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); 798474SJose.Borrego@Sun.COM return (SDRC_ERROR); 808474SJose.Borrego@Sun.COM } 818474SJose.Borrego@Sun.COM 828474SJose.Borrego@Sun.COM root_path = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 838474SJose.Borrego@Sun.COM err = smb_vss_get_fsmountpath(sr, root_path, MAXPATHLEN); 848474SJose.Borrego@Sun.COM 858474SJose.Borrego@Sun.COM if (err != SDRC_SUCCESS) { 868474SJose.Borrego@Sun.COM smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); 878474SJose.Borrego@Sun.COM return (SDRC_ERROR); 888474SJose.Borrego@Sun.COM } 898474SJose.Borrego@Sun.COM if (xa->smb_mdrcnt == SMB_VSS_COUNT_SIZE) { 908474SJose.Borrego@Sun.COM count = smb_upcall_vss_get_count(root_path); 918474SJose.Borrego@Sun.COM if (smb_mbc_encodef(&xa->rep_data_mb, "lllw", count, 0, 928474SJose.Borrego@Sun.COM (count * SMB_VSS_GMT_NET_SIZE(sr) + 938474SJose.Borrego@Sun.COM smb_ascii_or_unicode_null_len(sr)), 0) != 0) { 948474SJose.Borrego@Sun.COM smbsr_error(sr, 0, ERRSRV, ERRerror); 958474SJose.Borrego@Sun.COM err = SDRC_ERROR; 968474SJose.Borrego@Sun.COM } 978474SJose.Borrego@Sun.COM } else { 988474SJose.Borrego@Sun.COM count = xa->smb_mdrcnt / SMB_VSS_GMT_NET_SIZE(sr); 998474SJose.Borrego@Sun.COM 1008474SJose.Borrego@Sun.COM smb_upcall_vss_get_snapshots(root_path, count, &gmttokens); 1018474SJose.Borrego@Sun.COM 1028474SJose.Borrego@Sun.COM err = smb_vss_encode_gmttokens(sr, xa, count, &gmttokens); 1038474SJose.Borrego@Sun.COM 1048474SJose.Borrego@Sun.COM smb_upcall_vss_get_snapshots_free(&gmttokens); 1058474SJose.Borrego@Sun.COM } 1068474SJose.Borrego@Sun.COM 1078474SJose.Borrego@Sun.COM kmem_free(root_path, MAXPATHLEN); 1088474SJose.Borrego@Sun.COM 1098474SJose.Borrego@Sun.COM return (err); 1108474SJose.Borrego@Sun.COM } 1118474SJose.Borrego@Sun.COM 1128474SJose.Borrego@Sun.COM 1138474SJose.Borrego@Sun.COM /* 1148474SJose.Borrego@Sun.COM * sr - the request info, used to find root of dataset, 1158474SJose.Borrego@Sun.COM * unicode or ascii, where the share is rooted in the 1168474SJose.Borrego@Sun.COM * dataset 1178474SJose.Borrego@Sun.COM * root_node - root of the share 1188474SJose.Borrego@Sun.COM * cur_node - where in the share for the command 1198474SJose.Borrego@Sun.COM * buf - is the path for the command to be processed 1208474SJose.Borrego@Sun.COM * returned without @GMT if processed 1218474SJose.Borrego@Sun.COM * vss_cur_node - returned value for the snapshot version 1228474SJose.Borrego@Sun.COM * of the cur_node 1238474SJose.Borrego@Sun.COM * vss_root_node - returned value for the snapshot version 1248474SJose.Borrego@Sun.COM * of the root_node 1258474SJose.Borrego@Sun.COM * 1268474SJose.Borrego@Sun.COM * This routine is the processing for handling the 1278474SJose.Borrego@Sun.COM * SMB_FLAGS2_REPARSE_PATH bit being set in the smb header. 1288474SJose.Borrego@Sun.COM * 1298474SJose.Borrego@Sun.COM * By using the cur_node passed in, a new node is found or 1308474SJose.Borrego@Sun.COM * created that is the same place in the directory tree, but 1318474SJose.Borrego@Sun.COM * in the snapshot. We also use root_node to do the same for 1328474SJose.Borrego@Sun.COM * the root. 1338474SJose.Borrego@Sun.COM * One the new smb node is found, the path is modified by 1348474SJose.Borrego@Sun.COM * removing the @GMT token from the path in the buf. 1358474SJose.Borrego@Sun.COM */ 1368474SJose.Borrego@Sun.COM 1378474SJose.Borrego@Sun.COM int 1388474SJose.Borrego@Sun.COM smb_vss_lookup_nodes(smb_request_t *sr, smb_node_t *root_node, 1398474SJose.Borrego@Sun.COM smb_node_t *cur_node, char *buf, smb_node_t **vss_cur_node, 1408474SJose.Borrego@Sun.COM smb_node_t **vss_root_node) 1418474SJose.Borrego@Sun.COM { 1428474SJose.Borrego@Sun.COM const char *p; 1438474SJose.Borrego@Sun.COM char *rootpath; 1448474SJose.Borrego@Sun.COM char *snapname; 1458474SJose.Borrego@Sun.COM char *nodepath; 1468474SJose.Borrego@Sun.COM char gmttoken[SMB_VSS_GMT_SIZE]; 1478474SJose.Borrego@Sun.COM smb_attr_t attr; 1488474SJose.Borrego@Sun.COM vnode_t *fsrootvp; 1498474SJose.Borrego@Sun.COM vnode_t *vp = NULL; 1508474SJose.Borrego@Sun.COM int err = 0; 1518474SJose.Borrego@Sun.COM 1528474SJose.Borrego@Sun.COM if (sr->tid_tree == NULL) 1538474SJose.Borrego@Sun.COM return (ESTALE); 1548474SJose.Borrego@Sun.COM 1558474SJose.Borrego@Sun.COM ASSERT(sr->tid_tree->t_snode); 1568474SJose.Borrego@Sun.COM ASSERT(sr->tid_tree->t_snode->vp); 1578474SJose.Borrego@Sun.COM ASSERT(sr->tid_tree->t_snode->vp->v_vfsp); 1588474SJose.Borrego@Sun.COM 1598474SJose.Borrego@Sun.COM p = smb_vss_find_gmttoken(buf); 1608474SJose.Borrego@Sun.COM 1618474SJose.Borrego@Sun.COM if (!p) 1628474SJose.Borrego@Sun.COM return (ENOENT); 1638474SJose.Borrego@Sun.COM 1648474SJose.Borrego@Sun.COM bcopy(p, gmttoken, SMB_VSS_GMT_SIZE); 1658474SJose.Borrego@Sun.COM gmttoken[SMB_VSS_GMT_SIZE - 1] = '\0'; 1668474SJose.Borrego@Sun.COM 1678474SJose.Borrego@Sun.COM (void) VFS_ROOT(sr->tid_tree->t_snode->vp->v_vfsp, &fsrootvp); 1688474SJose.Borrego@Sun.COM 1698474SJose.Borrego@Sun.COM rootpath = kmem_alloc(MAXPATHLEN, KM_SLEEP); 1708474SJose.Borrego@Sun.COM snapname = kmem_alloc(MAXNAMELEN, KM_SLEEP); 1718474SJose.Borrego@Sun.COM nodepath = kmem_alloc(MAXPATHLEN, KM_SLEEP); 1728474SJose.Borrego@Sun.COM 1738474SJose.Borrego@Sun.COM err = smb_vss_get_fsmountpath(sr, rootpath, MAXPATHLEN); 1748474SJose.Borrego@Sun.COM 1758474SJose.Borrego@Sun.COM if (err != 0) { 1768474SJose.Borrego@Sun.COM goto error; 1778474SJose.Borrego@Sun.COM } 1788474SJose.Borrego@Sun.COM 1798474SJose.Borrego@Sun.COM *snapname = '\0'; 1808474SJose.Borrego@Sun.COM 1818474SJose.Borrego@Sun.COM smb_upcall_vss_map_gmttoken(rootpath, gmttoken, snapname); 1828474SJose.Borrego@Sun.COM 1838474SJose.Borrego@Sun.COM if (!*snapname) { 1848474SJose.Borrego@Sun.COM err = ENOENT; 1858474SJose.Borrego@Sun.COM goto error; 1868474SJose.Borrego@Sun.COM } 1878474SJose.Borrego@Sun.COM 1888474SJose.Borrego@Sun.COM /* note the value of root_node->vp */ 1898474SJose.Borrego@Sun.COM err = vnodetopath(fsrootvp, root_node->vp, nodepath, 1908474SJose.Borrego@Sun.COM MAXPATHLEN, kcred); 1918474SJose.Borrego@Sun.COM 1928474SJose.Borrego@Sun.COM if (err != 0) 1938474SJose.Borrego@Sun.COM goto error; 1948474SJose.Borrego@Sun.COM 1958474SJose.Borrego@Sun.COM (void) snprintf(rootpath, MAXPATHLEN, ".zfs/snapshot/%s/%s", 1968474SJose.Borrego@Sun.COM snapname, nodepath); 1978474SJose.Borrego@Sun.COM 1988474SJose.Borrego@Sun.COM vp = smb_lookuppathvptovp(sr, rootpath, fsrootvp, fsrootvp); 1998474SJose.Borrego@Sun.COM 2008474SJose.Borrego@Sun.COM if (vp) { 2018474SJose.Borrego@Sun.COM /* note the value of cur_node->vp */ 2028474SJose.Borrego@Sun.COM err = vnodetopath(fsrootvp, cur_node->vp, nodepath, 2038474SJose.Borrego@Sun.COM MAXPATHLEN, kcred); 204*8670SJose.Borrego@Sun.COM if (err != 0) { 205*8670SJose.Borrego@Sun.COM VN_RELE(vp); 2068474SJose.Borrego@Sun.COM goto error; 207*8670SJose.Borrego@Sun.COM } 2088474SJose.Borrego@Sun.COM 2098474SJose.Borrego@Sun.COM *vss_root_node = smb_node_lookup(sr, NULL, kcred, vp, 2108474SJose.Borrego@Sun.COM gmttoken, cur_node, NULL, &attr); 211*8670SJose.Borrego@Sun.COM VN_RELE(vp); 212*8670SJose.Borrego@Sun.COM 213*8670SJose.Borrego@Sun.COM if (*vss_root_node == NULL) { 214*8670SJose.Borrego@Sun.COM err = ENOENT; 215*8670SJose.Borrego@Sun.COM goto error; 216*8670SJose.Borrego@Sun.COM } 2178474SJose.Borrego@Sun.COM 2188474SJose.Borrego@Sun.COM (void) snprintf(rootpath, MAXPATHLEN, ".zfs/snapshot/%s/%s", 2198474SJose.Borrego@Sun.COM snapname, nodepath); 2208474SJose.Borrego@Sun.COM 2218474SJose.Borrego@Sun.COM 2228474SJose.Borrego@Sun.COM vp = smb_lookuppathvptovp(sr, rootpath, fsrootvp, fsrootvp); 2238474SJose.Borrego@Sun.COM 2248474SJose.Borrego@Sun.COM if (vp) { 2258474SJose.Borrego@Sun.COM *vss_cur_node = smb_node_lookup(sr, NULL, kcred, vp, 2268474SJose.Borrego@Sun.COM gmttoken, cur_node, NULL, &attr); 227*8670SJose.Borrego@Sun.COM VN_RELE(vp); 228*8670SJose.Borrego@Sun.COM 2298474SJose.Borrego@Sun.COM if (*vss_cur_node != NULL) { 2308474SJose.Borrego@Sun.COM smb_vss_remove_first_token_from_path(buf); 2318474SJose.Borrego@Sun.COM } else { 2328474SJose.Borrego@Sun.COM (void) smb_node_release(*vss_root_node); 2338474SJose.Borrego@Sun.COM err = ENOENT; 2348474SJose.Borrego@Sun.COM } 2358474SJose.Borrego@Sun.COM } else { 2368474SJose.Borrego@Sun.COM (void) smb_node_release(*vss_root_node); 2378474SJose.Borrego@Sun.COM err = ENOENT; 2388474SJose.Borrego@Sun.COM } 2398474SJose.Borrego@Sun.COM } else { 2408474SJose.Borrego@Sun.COM err = ENOENT; 2418474SJose.Borrego@Sun.COM } 2428474SJose.Borrego@Sun.COM 2438474SJose.Borrego@Sun.COM error: 2448474SJose.Borrego@Sun.COM VN_RELE(fsrootvp); 2458474SJose.Borrego@Sun.COM kmem_free(rootpath, MAXPATHLEN); 2468474SJose.Borrego@Sun.COM kmem_free(snapname, MAXNAMELEN); 2478474SJose.Borrego@Sun.COM kmem_free(nodepath, MAXPATHLEN); 2488474SJose.Borrego@Sun.COM 2498474SJose.Borrego@Sun.COM return (err); 2508474SJose.Borrego@Sun.COM } 2518474SJose.Borrego@Sun.COM 2528474SJose.Borrego@Sun.COM 2538474SJose.Borrego@Sun.COM static boolean_t 2548474SJose.Borrego@Sun.COM smb_vss_is_gmttoken(const char *s) 2558474SJose.Borrego@Sun.COM { 2568474SJose.Borrego@Sun.COM char *t = "@GMT-NNNN.NN.NN-NN.NN.NN"; 2578474SJose.Borrego@Sun.COM const char *str; 2588474SJose.Borrego@Sun.COM char *template; 2598474SJose.Borrego@Sun.COM 2608474SJose.Borrego@Sun.COM template = t; 2618474SJose.Borrego@Sun.COM str = s; 2628474SJose.Borrego@Sun.COM 2638474SJose.Borrego@Sun.COM while (*template) { 2648474SJose.Borrego@Sun.COM if (*template == 'N') { 2658474SJose.Borrego@Sun.COM if (!mts_isdigit(*str)) 2668474SJose.Borrego@Sun.COM return (B_FALSE); 2678474SJose.Borrego@Sun.COM } else if (*template != *str) { 2688474SJose.Borrego@Sun.COM return (B_FALSE); 2698474SJose.Borrego@Sun.COM } 2708474SJose.Borrego@Sun.COM 2718474SJose.Borrego@Sun.COM template++; 2728474SJose.Borrego@Sun.COM str++; 2738474SJose.Borrego@Sun.COM } 2748474SJose.Borrego@Sun.COM 2758474SJose.Borrego@Sun.COM /* Make sure it is JUST the @GMT token */ 2768474SJose.Borrego@Sun.COM if ((*str == '\0') || (*str == '/')) 2778474SJose.Borrego@Sun.COM return (B_TRUE); 2788474SJose.Borrego@Sun.COM 2798474SJose.Borrego@Sun.COM return (B_FALSE); 2808474SJose.Borrego@Sun.COM } 2818474SJose.Borrego@Sun.COM 2828474SJose.Borrego@Sun.COM static const char * 2838474SJose.Borrego@Sun.COM smb_vss_find_gmttoken(const char *path) 2848474SJose.Borrego@Sun.COM { 2858474SJose.Borrego@Sun.COM const char *p; 2868474SJose.Borrego@Sun.COM 2878474SJose.Borrego@Sun.COM p = path; 2888474SJose.Borrego@Sun.COM 2898474SJose.Borrego@Sun.COM while (*p) { 2908474SJose.Borrego@Sun.COM if (smb_vss_is_gmttoken(p)) 2918474SJose.Borrego@Sun.COM return (p); 2928474SJose.Borrego@Sun.COM p++; 2938474SJose.Borrego@Sun.COM } 2948474SJose.Borrego@Sun.COM return (NULL); 2958474SJose.Borrego@Sun.COM } 2968474SJose.Borrego@Sun.COM 2978474SJose.Borrego@Sun.COM static int 2988474SJose.Borrego@Sun.COM smb_vss_get_fsmountpath(smb_request_t *sr, char *buf, uint32_t buflen) 2998474SJose.Borrego@Sun.COM { 3008474SJose.Borrego@Sun.COM vnode_t *vp, *root_vp; 3018474SJose.Borrego@Sun.COM vfs_t *vfsp; 3028474SJose.Borrego@Sun.COM int err; 3038474SJose.Borrego@Sun.COM 3048474SJose.Borrego@Sun.COM ASSERT(sr->tid_tree); 3058474SJose.Borrego@Sun.COM ASSERT(sr->tid_tree->t_snode); 3068474SJose.Borrego@Sun.COM ASSERT(sr->tid_tree->t_snode->vp); 3078474SJose.Borrego@Sun.COM ASSERT(sr->tid_tree->t_snode->vp->v_vfsp); 3088474SJose.Borrego@Sun.COM 3098474SJose.Borrego@Sun.COM vp = sr->tid_tree->t_snode->vp; 3108474SJose.Borrego@Sun.COM vfsp = vp->v_vfsp; 3118474SJose.Borrego@Sun.COM 3128474SJose.Borrego@Sun.COM if (VFS_ROOT(vfsp, &root_vp)) 3138474SJose.Borrego@Sun.COM return (ENOENT); 3148474SJose.Borrego@Sun.COM 3158474SJose.Borrego@Sun.COM VN_HOLD(vp); 3168474SJose.Borrego@Sun.COM 3178474SJose.Borrego@Sun.COM /* NULL is passed in as we want to start at "/" */ 3188474SJose.Borrego@Sun.COM err = vnodetopath(NULL, root_vp, buf, buflen, sr->user_cr); 3198474SJose.Borrego@Sun.COM 3208474SJose.Borrego@Sun.COM VN_RELE(vp); 3218474SJose.Borrego@Sun.COM VN_RELE(root_vp); 3228474SJose.Borrego@Sun.COM return (err); 3238474SJose.Borrego@Sun.COM } 3248474SJose.Borrego@Sun.COM 3258474SJose.Borrego@Sun.COM static uint32_t 3268474SJose.Borrego@Sun.COM smb_vss_encode_gmttokens(smb_request_t *sr, smb_xa_t *xa, 3278474SJose.Borrego@Sun.COM int32_t count, smb_dr_return_gmttokens_t *snap_data) 3288474SJose.Borrego@Sun.COM { 3298474SJose.Borrego@Sun.COM uint32_t i; 3308474SJose.Borrego@Sun.COM uint32_t returned_count; 3318474SJose.Borrego@Sun.COM uint32_t num_gmttokens; 3328474SJose.Borrego@Sun.COM char **gmttokens; 3338474SJose.Borrego@Sun.COM uint32_t err = SDRC_SUCCESS; 3348474SJose.Borrego@Sun.COM uint32_t data_size; 3358474SJose.Borrego@Sun.COM 3368474SJose.Borrego@Sun.COM returned_count = snap_data->rg_count; 3378474SJose.Borrego@Sun.COM num_gmttokens = snap_data->rg_gmttokens.rg_gmttokens_len; 3388474SJose.Borrego@Sun.COM gmttokens = snap_data->rg_gmttokens.rg_gmttokens_val; 3398474SJose.Borrego@Sun.COM 3408474SJose.Borrego@Sun.COM if (returned_count > count) { 3418474SJose.Borrego@Sun.COM err = NT_STATUS_BUFFER_TOO_SMALL; 3428474SJose.Borrego@Sun.COM } 3438474SJose.Borrego@Sun.COM 3448474SJose.Borrego@Sun.COM data_size = returned_count * SMB_VSS_GMT_NET_SIZE(sr) + 3458474SJose.Borrego@Sun.COM smb_ascii_or_unicode_null_len(sr); 3468474SJose.Borrego@Sun.COM 3478474SJose.Borrego@Sun.COM if (smb_mbc_encodef(&xa->rep_data_mb, "lll", returned_count, 3488474SJose.Borrego@Sun.COM num_gmttokens, data_size) != 0) { 3498474SJose.Borrego@Sun.COM smbsr_error(sr, 0, ERRSRV, ERRerror); 3508474SJose.Borrego@Sun.COM err = SDRC_ERROR; 3518474SJose.Borrego@Sun.COM } 3528474SJose.Borrego@Sun.COM 3538474SJose.Borrego@Sun.COM if (err == SDRC_SUCCESS) { 3548474SJose.Borrego@Sun.COM for (i = 0; i < num_gmttokens; i++) { 3558474SJose.Borrego@Sun.COM if (smb_mbc_encodef(&xa->rep_data_mb, "%u", sr, 3568474SJose.Borrego@Sun.COM *gmttokens) != 0) { 3578474SJose.Borrego@Sun.COM smbsr_error(sr, 0, ERRSRV, ERRerror); 3588474SJose.Borrego@Sun.COM err = SDRC_ERROR; 3598474SJose.Borrego@Sun.COM } 3608474SJose.Borrego@Sun.COM gmttokens++; 3618474SJose.Borrego@Sun.COM } 3628474SJose.Borrego@Sun.COM } 3638474SJose.Borrego@Sun.COM 3648474SJose.Borrego@Sun.COM return (err); 3658474SJose.Borrego@Sun.COM } 3668474SJose.Borrego@Sun.COM 3678474SJose.Borrego@Sun.COM /* This removes the first @GMT from the path */ 3688474SJose.Borrego@Sun.COM static void 3698474SJose.Borrego@Sun.COM smb_vss_remove_first_token_from_path(char *path) 3708474SJose.Borrego@Sun.COM { 3718474SJose.Borrego@Sun.COM boolean_t found; 3728474SJose.Borrego@Sun.COM char *src, *dest; 3738474SJose.Borrego@Sun.COM 3748474SJose.Borrego@Sun.COM src = path; 3758474SJose.Borrego@Sun.COM dest = path; 3768474SJose.Borrego@Sun.COM 3778474SJose.Borrego@Sun.COM found = B_FALSE; 3788474SJose.Borrego@Sun.COM 3798474SJose.Borrego@Sun.COM while (*src != '\0') { 3808474SJose.Borrego@Sun.COM if (!found && smb_vss_is_gmttoken(src)) { 3818474SJose.Borrego@Sun.COM src += SMB_VSS_GMT_SIZE - 1; 3828474SJose.Borrego@Sun.COM if (*src == '/') 3838474SJose.Borrego@Sun.COM src += 1; 3848474SJose.Borrego@Sun.COM found = B_TRUE; 3858474SJose.Borrego@Sun.COM continue; 3868474SJose.Borrego@Sun.COM } 3878474SJose.Borrego@Sun.COM *dest = *src; 3888474SJose.Borrego@Sun.COM src++; 3898474SJose.Borrego@Sun.COM dest++; 3908474SJose.Borrego@Sun.COM } 3918474SJose.Borrego@Sun.COM *dest = *src; 3928474SJose.Borrego@Sun.COM } 393