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 42*10966SJordan.Brown@Sun.COM #include <smbsrv/smb_kproto.h> 43*10966SJordan.Brown@Sun.COM #include <smbsrv/string.h> 448474SJose.Borrego@Sun.COM #include <smbsrv/winioctl.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; 749914Samw@Sun.COM uint32_t status = NT_STATUS_SUCCESS; 758474SJose.Borrego@Sun.COM smb_dr_return_gmttokens_t gmttokens; 768474SJose.Borrego@Sun.COM 779914Samw@Sun.COM if (xa->smb_mdrcnt < SMB_VSS_COUNT_SIZE) 789914Samw@Sun.COM return (NT_STATUS_INVALID_PARAMETER); 798474SJose.Borrego@Sun.COM 808474SJose.Borrego@Sun.COM root_path = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 819914Samw@Sun.COM if (smb_vss_get_fsmountpath(sr, root_path, MAXPATHLEN) != 0) 829914Samw@Sun.COM return (NT_STATUS_INVALID_PARAMETER); 838474SJose.Borrego@Sun.COM 848474SJose.Borrego@Sun.COM if (xa->smb_mdrcnt == SMB_VSS_COUNT_SIZE) { 858474SJose.Borrego@Sun.COM count = smb_upcall_vss_get_count(root_path); 868474SJose.Borrego@Sun.COM if (smb_mbc_encodef(&xa->rep_data_mb, "lllw", count, 0, 878474SJose.Borrego@Sun.COM (count * SMB_VSS_GMT_NET_SIZE(sr) + 888474SJose.Borrego@Sun.COM smb_ascii_or_unicode_null_len(sr)), 0) != 0) { 899914Samw@Sun.COM status = NT_STATUS_INVALID_PARAMETER; 908474SJose.Borrego@Sun.COM } 918474SJose.Borrego@Sun.COM } else { 928474SJose.Borrego@Sun.COM count = xa->smb_mdrcnt / SMB_VSS_GMT_NET_SIZE(sr); 938474SJose.Borrego@Sun.COM 948474SJose.Borrego@Sun.COM smb_upcall_vss_get_snapshots(root_path, count, &gmttokens); 958474SJose.Borrego@Sun.COM 969914Samw@Sun.COM status = smb_vss_encode_gmttokens(sr, xa, count, &gmttokens); 978474SJose.Borrego@Sun.COM 988474SJose.Borrego@Sun.COM smb_upcall_vss_get_snapshots_free(&gmttokens); 998474SJose.Borrego@Sun.COM } 1008474SJose.Borrego@Sun.COM 1018474SJose.Borrego@Sun.COM kmem_free(root_path, MAXPATHLEN); 1029914Samw@Sun.COM return (status); 1038474SJose.Borrego@Sun.COM } 1048474SJose.Borrego@Sun.COM 1058474SJose.Borrego@Sun.COM /* 1068474SJose.Borrego@Sun.COM * sr - the request info, used to find root of dataset, 1078474SJose.Borrego@Sun.COM * unicode or ascii, where the share is rooted in the 1088474SJose.Borrego@Sun.COM * dataset 1098474SJose.Borrego@Sun.COM * root_node - root of the share 1108474SJose.Borrego@Sun.COM * cur_node - where in the share for the command 1118474SJose.Borrego@Sun.COM * buf - is the path for the command to be processed 1128474SJose.Borrego@Sun.COM * returned without @GMT if processed 1138474SJose.Borrego@Sun.COM * vss_cur_node - returned value for the snapshot version 1148474SJose.Borrego@Sun.COM * of the cur_node 1158474SJose.Borrego@Sun.COM * vss_root_node - returned value for the snapshot version 1168474SJose.Borrego@Sun.COM * of the root_node 1178474SJose.Borrego@Sun.COM * 1188474SJose.Borrego@Sun.COM * This routine is the processing for handling the 1198474SJose.Borrego@Sun.COM * SMB_FLAGS2_REPARSE_PATH bit being set in the smb header. 1208474SJose.Borrego@Sun.COM * 1218474SJose.Borrego@Sun.COM * By using the cur_node passed in, a new node is found or 1228474SJose.Borrego@Sun.COM * created that is the same place in the directory tree, but 1238474SJose.Borrego@Sun.COM * in the snapshot. We also use root_node to do the same for 1248474SJose.Borrego@Sun.COM * the root. 1258474SJose.Borrego@Sun.COM * One the new smb node is found, the path is modified by 1268474SJose.Borrego@Sun.COM * removing the @GMT token from the path in the buf. 1278474SJose.Borrego@Sun.COM */ 1288474SJose.Borrego@Sun.COM int 1298474SJose.Borrego@Sun.COM smb_vss_lookup_nodes(smb_request_t *sr, smb_node_t *root_node, 1308474SJose.Borrego@Sun.COM smb_node_t *cur_node, char *buf, smb_node_t **vss_cur_node, 1318474SJose.Borrego@Sun.COM smb_node_t **vss_root_node) 1328474SJose.Borrego@Sun.COM { 1338474SJose.Borrego@Sun.COM const char *p; 1348474SJose.Borrego@Sun.COM char *rootpath; 1358474SJose.Borrego@Sun.COM char *snapname; 1368474SJose.Borrego@Sun.COM char *nodepath; 1378474SJose.Borrego@Sun.COM char gmttoken[SMB_VSS_GMT_SIZE]; 1388474SJose.Borrego@Sun.COM vnode_t *fsrootvp; 1398474SJose.Borrego@Sun.COM vnode_t *vp = NULL; 1408474SJose.Borrego@Sun.COM int err = 0; 1418474SJose.Borrego@Sun.COM 1428474SJose.Borrego@Sun.COM if (sr->tid_tree == NULL) 1438474SJose.Borrego@Sun.COM return (ESTALE); 1448474SJose.Borrego@Sun.COM 1458474SJose.Borrego@Sun.COM ASSERT(sr->tid_tree->t_snode); 1468474SJose.Borrego@Sun.COM ASSERT(sr->tid_tree->t_snode->vp); 1478474SJose.Borrego@Sun.COM ASSERT(sr->tid_tree->t_snode->vp->v_vfsp); 1488474SJose.Borrego@Sun.COM 1499555SAfshin.Ardakani@Sun.COM if ((p = smb_vss_find_gmttoken(buf)) == NULL) 1508474SJose.Borrego@Sun.COM return (ENOENT); 1518474SJose.Borrego@Sun.COM 1528474SJose.Borrego@Sun.COM bcopy(p, gmttoken, SMB_VSS_GMT_SIZE); 1538474SJose.Borrego@Sun.COM gmttoken[SMB_VSS_GMT_SIZE - 1] = '\0'; 1548474SJose.Borrego@Sun.COM 1559555SAfshin.Ardakani@Sun.COM err = VFS_ROOT(sr->tid_tree->t_snode->vp->v_vfsp, &fsrootvp); 1569555SAfshin.Ardakani@Sun.COM if (err != 0) 1579555SAfshin.Ardakani@Sun.COM return (err); 1588474SJose.Borrego@Sun.COM 1598474SJose.Borrego@Sun.COM rootpath = kmem_alloc(MAXPATHLEN, KM_SLEEP); 1608474SJose.Borrego@Sun.COM snapname = kmem_alloc(MAXNAMELEN, KM_SLEEP); 1618474SJose.Borrego@Sun.COM nodepath = kmem_alloc(MAXPATHLEN, KM_SLEEP); 1628474SJose.Borrego@Sun.COM 1638474SJose.Borrego@Sun.COM err = smb_vss_get_fsmountpath(sr, rootpath, MAXPATHLEN); 1649555SAfshin.Ardakani@Sun.COM if (err != 0) 1658474SJose.Borrego@Sun.COM goto error; 1668474SJose.Borrego@Sun.COM 1678474SJose.Borrego@Sun.COM *snapname = '\0'; 1688474SJose.Borrego@Sun.COM 1698474SJose.Borrego@Sun.COM smb_upcall_vss_map_gmttoken(rootpath, gmttoken, snapname); 1708474SJose.Borrego@Sun.COM 1718474SJose.Borrego@Sun.COM if (!*snapname) { 1728474SJose.Borrego@Sun.COM err = ENOENT; 1738474SJose.Borrego@Sun.COM goto error; 1748474SJose.Borrego@Sun.COM } 1758474SJose.Borrego@Sun.COM 1768474SJose.Borrego@Sun.COM /* note the value of root_node->vp */ 1778474SJose.Borrego@Sun.COM err = vnodetopath(fsrootvp, root_node->vp, nodepath, 1788474SJose.Borrego@Sun.COM MAXPATHLEN, kcred); 1798474SJose.Borrego@Sun.COM 1808474SJose.Borrego@Sun.COM if (err != 0) 1818474SJose.Borrego@Sun.COM goto error; 1828474SJose.Borrego@Sun.COM 1838474SJose.Borrego@Sun.COM (void) snprintf(rootpath, MAXPATHLEN, ".zfs/snapshot/%s/%s", 1848474SJose.Borrego@Sun.COM snapname, nodepath); 1858474SJose.Borrego@Sun.COM 1868474SJose.Borrego@Sun.COM vp = smb_lookuppathvptovp(sr, rootpath, fsrootvp, fsrootvp); 1878474SJose.Borrego@Sun.COM 1888474SJose.Borrego@Sun.COM if (vp) { 1898474SJose.Borrego@Sun.COM /* note the value of cur_node->vp */ 1908474SJose.Borrego@Sun.COM err = vnodetopath(fsrootvp, cur_node->vp, nodepath, 1918474SJose.Borrego@Sun.COM MAXPATHLEN, kcred); 1928670SJose.Borrego@Sun.COM if (err != 0) { 1938670SJose.Borrego@Sun.COM VN_RELE(vp); 1948474SJose.Borrego@Sun.COM goto error; 1958670SJose.Borrego@Sun.COM } 1968474SJose.Borrego@Sun.COM 1978474SJose.Borrego@Sun.COM *vss_root_node = smb_node_lookup(sr, NULL, kcred, vp, 19810001SJoyce.McIntosh@Sun.COM gmttoken, cur_node, NULL); 1998670SJose.Borrego@Sun.COM VN_RELE(vp); 2008670SJose.Borrego@Sun.COM 2018670SJose.Borrego@Sun.COM if (*vss_root_node == NULL) { 2028670SJose.Borrego@Sun.COM err = ENOENT; 2038670SJose.Borrego@Sun.COM goto error; 2048670SJose.Borrego@Sun.COM } 2058474SJose.Borrego@Sun.COM 2068474SJose.Borrego@Sun.COM (void) snprintf(rootpath, MAXPATHLEN, ".zfs/snapshot/%s/%s", 2078474SJose.Borrego@Sun.COM snapname, nodepath); 2088474SJose.Borrego@Sun.COM 2098474SJose.Borrego@Sun.COM 2108474SJose.Borrego@Sun.COM vp = smb_lookuppathvptovp(sr, rootpath, fsrootvp, fsrootvp); 2118474SJose.Borrego@Sun.COM 2128474SJose.Borrego@Sun.COM if (vp) { 2138474SJose.Borrego@Sun.COM *vss_cur_node = smb_node_lookup(sr, NULL, kcred, vp, 21410001SJoyce.McIntosh@Sun.COM gmttoken, cur_node, NULL); 2158670SJose.Borrego@Sun.COM VN_RELE(vp); 2168670SJose.Borrego@Sun.COM 2178474SJose.Borrego@Sun.COM if (*vss_cur_node != NULL) { 2188474SJose.Borrego@Sun.COM smb_vss_remove_first_token_from_path(buf); 2198474SJose.Borrego@Sun.COM } else { 2208474SJose.Borrego@Sun.COM (void) smb_node_release(*vss_root_node); 2218474SJose.Borrego@Sun.COM err = ENOENT; 2228474SJose.Borrego@Sun.COM } 2238474SJose.Borrego@Sun.COM } else { 2248474SJose.Borrego@Sun.COM (void) smb_node_release(*vss_root_node); 2258474SJose.Borrego@Sun.COM err = ENOENT; 2268474SJose.Borrego@Sun.COM } 2278474SJose.Borrego@Sun.COM } else { 2288474SJose.Borrego@Sun.COM err = ENOENT; 2298474SJose.Borrego@Sun.COM } 2308474SJose.Borrego@Sun.COM 2318474SJose.Borrego@Sun.COM error: 2328474SJose.Borrego@Sun.COM VN_RELE(fsrootvp); 2338474SJose.Borrego@Sun.COM kmem_free(rootpath, MAXPATHLEN); 2348474SJose.Borrego@Sun.COM kmem_free(snapname, MAXNAMELEN); 2358474SJose.Borrego@Sun.COM kmem_free(nodepath, MAXPATHLEN); 2368474SJose.Borrego@Sun.COM 2378474SJose.Borrego@Sun.COM return (err); 2388474SJose.Borrego@Sun.COM } 2398474SJose.Borrego@Sun.COM 2408474SJose.Borrego@Sun.COM static boolean_t 2418474SJose.Borrego@Sun.COM smb_vss_is_gmttoken(const char *s) 2428474SJose.Borrego@Sun.COM { 2438474SJose.Borrego@Sun.COM char *t = "@GMT-NNNN.NN.NN-NN.NN.NN"; 2448474SJose.Borrego@Sun.COM const char *str; 2458474SJose.Borrego@Sun.COM char *template; 2468474SJose.Borrego@Sun.COM 2478474SJose.Borrego@Sun.COM template = t; 2488474SJose.Borrego@Sun.COM str = s; 2498474SJose.Borrego@Sun.COM 2508474SJose.Borrego@Sun.COM while (*template) { 2518474SJose.Borrego@Sun.COM if (*template == 'N') { 252*10966SJordan.Brown@Sun.COM if (!smb_isdigit(*str)) 2538474SJose.Borrego@Sun.COM return (B_FALSE); 2548474SJose.Borrego@Sun.COM } else if (*template != *str) { 2558474SJose.Borrego@Sun.COM return (B_FALSE); 2568474SJose.Borrego@Sun.COM } 2578474SJose.Borrego@Sun.COM 2588474SJose.Borrego@Sun.COM template++; 2598474SJose.Borrego@Sun.COM str++; 2608474SJose.Borrego@Sun.COM } 2618474SJose.Borrego@Sun.COM 2628474SJose.Borrego@Sun.COM /* Make sure it is JUST the @GMT token */ 2638474SJose.Borrego@Sun.COM if ((*str == '\0') || (*str == '/')) 2648474SJose.Borrego@Sun.COM return (B_TRUE); 2658474SJose.Borrego@Sun.COM 2668474SJose.Borrego@Sun.COM return (B_FALSE); 2678474SJose.Borrego@Sun.COM } 2688474SJose.Borrego@Sun.COM 2698474SJose.Borrego@Sun.COM static const char * 2708474SJose.Borrego@Sun.COM smb_vss_find_gmttoken(const char *path) 2718474SJose.Borrego@Sun.COM { 2728474SJose.Borrego@Sun.COM const char *p; 2738474SJose.Borrego@Sun.COM 2748474SJose.Borrego@Sun.COM p = path; 2758474SJose.Borrego@Sun.COM 2768474SJose.Borrego@Sun.COM while (*p) { 2778474SJose.Borrego@Sun.COM if (smb_vss_is_gmttoken(p)) 2788474SJose.Borrego@Sun.COM return (p); 2798474SJose.Borrego@Sun.COM p++; 2808474SJose.Borrego@Sun.COM } 2818474SJose.Borrego@Sun.COM return (NULL); 2828474SJose.Borrego@Sun.COM } 2838474SJose.Borrego@Sun.COM 2848474SJose.Borrego@Sun.COM static int 2858474SJose.Borrego@Sun.COM smb_vss_get_fsmountpath(smb_request_t *sr, char *buf, uint32_t buflen) 2868474SJose.Borrego@Sun.COM { 2878474SJose.Borrego@Sun.COM vnode_t *vp, *root_vp; 2888474SJose.Borrego@Sun.COM vfs_t *vfsp; 2898474SJose.Borrego@Sun.COM int err; 2908474SJose.Borrego@Sun.COM 2918474SJose.Borrego@Sun.COM ASSERT(sr->tid_tree); 2928474SJose.Borrego@Sun.COM ASSERT(sr->tid_tree->t_snode); 2938474SJose.Borrego@Sun.COM ASSERT(sr->tid_tree->t_snode->vp); 2948474SJose.Borrego@Sun.COM ASSERT(sr->tid_tree->t_snode->vp->v_vfsp); 2958474SJose.Borrego@Sun.COM 2968474SJose.Borrego@Sun.COM vp = sr->tid_tree->t_snode->vp; 2978474SJose.Borrego@Sun.COM vfsp = vp->v_vfsp; 2988474SJose.Borrego@Sun.COM 2998474SJose.Borrego@Sun.COM if (VFS_ROOT(vfsp, &root_vp)) 3008474SJose.Borrego@Sun.COM return (ENOENT); 3018474SJose.Borrego@Sun.COM 3028474SJose.Borrego@Sun.COM VN_HOLD(vp); 3038474SJose.Borrego@Sun.COM 3048474SJose.Borrego@Sun.COM /* NULL is passed in as we want to start at "/" */ 3058474SJose.Borrego@Sun.COM err = vnodetopath(NULL, root_vp, buf, buflen, sr->user_cr); 3068474SJose.Borrego@Sun.COM 3078474SJose.Borrego@Sun.COM VN_RELE(vp); 3088474SJose.Borrego@Sun.COM VN_RELE(root_vp); 3098474SJose.Borrego@Sun.COM return (err); 3108474SJose.Borrego@Sun.COM } 3118474SJose.Borrego@Sun.COM 3128474SJose.Borrego@Sun.COM static uint32_t 3138474SJose.Borrego@Sun.COM smb_vss_encode_gmttokens(smb_request_t *sr, smb_xa_t *xa, 3148474SJose.Borrego@Sun.COM int32_t count, smb_dr_return_gmttokens_t *snap_data) 3158474SJose.Borrego@Sun.COM { 3168474SJose.Borrego@Sun.COM uint32_t i; 3178474SJose.Borrego@Sun.COM uint32_t returned_count; 3188474SJose.Borrego@Sun.COM uint32_t num_gmttokens; 3198474SJose.Borrego@Sun.COM char **gmttokens; 3209914Samw@Sun.COM uint32_t status = NT_STATUS_SUCCESS; 3218474SJose.Borrego@Sun.COM uint32_t data_size; 3228474SJose.Borrego@Sun.COM 3238474SJose.Borrego@Sun.COM returned_count = snap_data->rg_count; 3248474SJose.Borrego@Sun.COM num_gmttokens = snap_data->rg_gmttokens.rg_gmttokens_len; 3258474SJose.Borrego@Sun.COM gmttokens = snap_data->rg_gmttokens.rg_gmttokens_val; 3268474SJose.Borrego@Sun.COM 3279914Samw@Sun.COM if (returned_count > count) 3289914Samw@Sun.COM status = NT_STATUS_BUFFER_TOO_SMALL; 3298474SJose.Borrego@Sun.COM 3308474SJose.Borrego@Sun.COM data_size = returned_count * SMB_VSS_GMT_NET_SIZE(sr) + 3318474SJose.Borrego@Sun.COM smb_ascii_or_unicode_null_len(sr); 3328474SJose.Borrego@Sun.COM 3338474SJose.Borrego@Sun.COM if (smb_mbc_encodef(&xa->rep_data_mb, "lll", returned_count, 3349914Samw@Sun.COM num_gmttokens, data_size) != 0) 3359914Samw@Sun.COM return (NT_STATUS_INVALID_PARAMETER); 3368474SJose.Borrego@Sun.COM 3379914Samw@Sun.COM if (status == NT_STATUS_SUCCESS) { 3388474SJose.Borrego@Sun.COM for (i = 0; i < num_gmttokens; i++) { 3398474SJose.Borrego@Sun.COM if (smb_mbc_encodef(&xa->rep_data_mb, "%u", sr, 3409914Samw@Sun.COM *gmttokens) != 0) 3419914Samw@Sun.COM status = NT_STATUS_INVALID_PARAMETER; 3428474SJose.Borrego@Sun.COM gmttokens++; 3438474SJose.Borrego@Sun.COM } 3448474SJose.Borrego@Sun.COM } 3458474SJose.Borrego@Sun.COM 3469914Samw@Sun.COM return (status); 3478474SJose.Borrego@Sun.COM } 3488474SJose.Borrego@Sun.COM 3498474SJose.Borrego@Sun.COM /* This removes the first @GMT from the path */ 3508474SJose.Borrego@Sun.COM static void 3518474SJose.Borrego@Sun.COM smb_vss_remove_first_token_from_path(char *path) 3528474SJose.Borrego@Sun.COM { 3538474SJose.Borrego@Sun.COM boolean_t found; 3548474SJose.Borrego@Sun.COM char *src, *dest; 3558474SJose.Borrego@Sun.COM 3568474SJose.Borrego@Sun.COM src = path; 3578474SJose.Borrego@Sun.COM dest = path; 3588474SJose.Borrego@Sun.COM 3598474SJose.Borrego@Sun.COM found = B_FALSE; 3608474SJose.Borrego@Sun.COM 3618474SJose.Borrego@Sun.COM while (*src != '\0') { 3628474SJose.Borrego@Sun.COM if (!found && smb_vss_is_gmttoken(src)) { 3638474SJose.Borrego@Sun.COM src += SMB_VSS_GMT_SIZE - 1; 3648474SJose.Borrego@Sun.COM if (*src == '/') 3658474SJose.Borrego@Sun.COM src += 1; 3668474SJose.Borrego@Sun.COM found = B_TRUE; 3678474SJose.Borrego@Sun.COM continue; 3688474SJose.Borrego@Sun.COM } 3698474SJose.Borrego@Sun.COM *dest = *src; 3708474SJose.Borrego@Sun.COM src++; 3718474SJose.Borrego@Sun.COM dest++; 3728474SJose.Borrego@Sun.COM } 3738474SJose.Borrego@Sun.COM *dest = *src; 3748474SJose.Borrego@Sun.COM } 375