1*11963SAfshin.Ardakani@Sun.COM /*
2*11963SAfshin.Ardakani@Sun.COM * CDDL HEADER START
3*11963SAfshin.Ardakani@Sun.COM *
4*11963SAfshin.Ardakani@Sun.COM * The contents of this file are subject to the terms of the
5*11963SAfshin.Ardakani@Sun.COM * Common Development and Distribution License (the "License").
6*11963SAfshin.Ardakani@Sun.COM * You may not use this file except in compliance with the License.
7*11963SAfshin.Ardakani@Sun.COM *
8*11963SAfshin.Ardakani@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*11963SAfshin.Ardakani@Sun.COM * or http://www.opensolaris.org/os/licensing.
10*11963SAfshin.Ardakani@Sun.COM * See the License for the specific language governing permissions
11*11963SAfshin.Ardakani@Sun.COM * and limitations under the License.
12*11963SAfshin.Ardakani@Sun.COM *
13*11963SAfshin.Ardakani@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
14*11963SAfshin.Ardakani@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*11963SAfshin.Ardakani@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
16*11963SAfshin.Ardakani@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
17*11963SAfshin.Ardakani@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
18*11963SAfshin.Ardakani@Sun.COM *
19*11963SAfshin.Ardakani@Sun.COM * CDDL HEADER END
20*11963SAfshin.Ardakani@Sun.COM */
21*11963SAfshin.Ardakani@Sun.COM /*
22*11963SAfshin.Ardakani@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23*11963SAfshin.Ardakani@Sun.COM * Use is subject to license terms.
24*11963SAfshin.Ardakani@Sun.COM */
25*11963SAfshin.Ardakani@Sun.COM
26*11963SAfshin.Ardakani@Sun.COM #include <errno.h>
27*11963SAfshin.Ardakani@Sun.COM #include <unistd.h>
28*11963SAfshin.Ardakani@Sun.COM #include <strings.h>
29*11963SAfshin.Ardakani@Sun.COM #include <sys/fs_reparse.h>
30*11963SAfshin.Ardakani@Sun.COM #include <smbsrv/libsmb.h>
31*11963SAfshin.Ardakani@Sun.COM
32*11963SAfshin.Ardakani@Sun.COM #include <syslog.h>
33*11963SAfshin.Ardakani@Sun.COM
34*11963SAfshin.Ardakani@Sun.COM static int smb_reparse_init(const char *, nvlist_t **);
35*11963SAfshin.Ardakani@Sun.COM static void smb_reparse_free(nvlist_t *);
36*11963SAfshin.Ardakani@Sun.COM static int smb_reparse_set(const char *, nvlist_t *);
37*11963SAfshin.Ardakani@Sun.COM
38*11963SAfshin.Ardakani@Sun.COM /*
39*11963SAfshin.Ardakani@Sun.COM * Checks the status of the object specified by 'path'
40*11963SAfshin.Ardakani@Sun.COM *
41*11963SAfshin.Ardakani@Sun.COM * Returns 0 and fills 'stat' with the proper status on
42*11963SAfshin.Ardakani@Sun.COM * success, otherwise returns an error code.
43*11963SAfshin.Ardakani@Sun.COM */
44*11963SAfshin.Ardakani@Sun.COM int
smb_reparse_stat(const char * path,uint32_t * stat)45*11963SAfshin.Ardakani@Sun.COM smb_reparse_stat(const char *path, uint32_t *stat)
46*11963SAfshin.Ardakani@Sun.COM {
47*11963SAfshin.Ardakani@Sun.COM struct stat statbuf;
48*11963SAfshin.Ardakani@Sun.COM char symbuf[MAXREPARSELEN];
49*11963SAfshin.Ardakani@Sun.COM int rptaglen;
50*11963SAfshin.Ardakani@Sun.COM
51*11963SAfshin.Ardakani@Sun.COM if (lstat(path, &statbuf) != 0) {
52*11963SAfshin.Ardakani@Sun.COM if (errno == ENOENT) {
53*11963SAfshin.Ardakani@Sun.COM *stat = SMB_REPARSE_NOTFOUND;
54*11963SAfshin.Ardakani@Sun.COM return (0);
55*11963SAfshin.Ardakani@Sun.COM }
56*11963SAfshin.Ardakani@Sun.COM return (errno);
57*11963SAfshin.Ardakani@Sun.COM }
58*11963SAfshin.Ardakani@Sun.COM
59*11963SAfshin.Ardakani@Sun.COM if ((statbuf.st_mode & S_IFMT) != S_IFLNK) {
60*11963SAfshin.Ardakani@Sun.COM *stat = SMB_REPARSE_NOTREPARSE;
61*11963SAfshin.Ardakani@Sun.COM return (0);
62*11963SAfshin.Ardakani@Sun.COM }
63*11963SAfshin.Ardakani@Sun.COM
64*11963SAfshin.Ardakani@Sun.COM bzero(symbuf, MAXREPARSELEN);
65*11963SAfshin.Ardakani@Sun.COM if (readlink(path, symbuf, MAXREPARSELEN) == -1)
66*11963SAfshin.Ardakani@Sun.COM return (errno);
67*11963SAfshin.Ardakani@Sun.COM
68*11963SAfshin.Ardakani@Sun.COM rptaglen = strlen(FS_REPARSE_TAG_STR);
69*11963SAfshin.Ardakani@Sun.COM if (strncmp(symbuf, FS_REPARSE_TAG_STR, rptaglen) != 0)
70*11963SAfshin.Ardakani@Sun.COM *stat = SMB_REPARSE_NOTREPARSE;
71*11963SAfshin.Ardakani@Sun.COM else
72*11963SAfshin.Ardakani@Sun.COM *stat = SMB_REPARSE_ISREPARSE;
73*11963SAfshin.Ardakani@Sun.COM
74*11963SAfshin.Ardakani@Sun.COM return (0);
75*11963SAfshin.Ardakani@Sun.COM }
76*11963SAfshin.Ardakani@Sun.COM
77*11963SAfshin.Ardakani@Sun.COM /*
78*11963SAfshin.Ardakani@Sun.COM * If the reparse point specified by the path already exists
79*11963SAfshin.Ardakani@Sun.COM * it is updated by given service type and its data. Update means
80*11963SAfshin.Ardakani@Sun.COM * that if such service type does not already exist, it is added
81*11963SAfshin.Ardakani@Sun.COM * otherwise it is overwritten by given data.
82*11963SAfshin.Ardakani@Sun.COM *
83*11963SAfshin.Ardakani@Sun.COM * If the reparse point does not exist, one is created with given
84*11963SAfshin.Ardakani@Sun.COM * service type and its data.
85*11963SAfshin.Ardakani@Sun.COM */
86*11963SAfshin.Ardakani@Sun.COM int
smb_reparse_svcadd(const char * path,const char * svctype,const char * svcdata)87*11963SAfshin.Ardakani@Sun.COM smb_reparse_svcadd(const char *path, const char *svctype, const char *svcdata)
88*11963SAfshin.Ardakani@Sun.COM {
89*11963SAfshin.Ardakani@Sun.COM nvlist_t *nvl;
90*11963SAfshin.Ardakani@Sun.COM int rc;
91*11963SAfshin.Ardakani@Sun.COM
92*11963SAfshin.Ardakani@Sun.COM if ((rc = smb_reparse_init(path, &nvl)) != 0)
93*11963SAfshin.Ardakani@Sun.COM return (rc);
94*11963SAfshin.Ardakani@Sun.COM
95*11963SAfshin.Ardakani@Sun.COM if ((rc = reparse_add(nvl, svctype, svcdata)) != 0) {
96*11963SAfshin.Ardakani@Sun.COM smb_reparse_free(nvl);
97*11963SAfshin.Ardakani@Sun.COM return (rc);
98*11963SAfshin.Ardakani@Sun.COM }
99*11963SAfshin.Ardakani@Sun.COM
100*11963SAfshin.Ardakani@Sun.COM rc = smb_reparse_set(path, nvl);
101*11963SAfshin.Ardakani@Sun.COM smb_reparse_free(nvl);
102*11963SAfshin.Ardakani@Sun.COM
103*11963SAfshin.Ardakani@Sun.COM return (rc);
104*11963SAfshin.Ardakani@Sun.COM }
105*11963SAfshin.Ardakani@Sun.COM
106*11963SAfshin.Ardakani@Sun.COM /*
107*11963SAfshin.Ardakani@Sun.COM * Removes the entry for the given service type from the
108*11963SAfshin.Ardakani@Sun.COM * specified reparse point. If there is no service entry
109*11963SAfshin.Ardakani@Sun.COM * left, the reparse point object will be deleted.
110*11963SAfshin.Ardakani@Sun.COM */
111*11963SAfshin.Ardakani@Sun.COM int
smb_reparse_svcdel(const char * path,const char * svctype)112*11963SAfshin.Ardakani@Sun.COM smb_reparse_svcdel(const char *path, const char *svctype)
113*11963SAfshin.Ardakani@Sun.COM {
114*11963SAfshin.Ardakani@Sun.COM nvlist_t *nvl;
115*11963SAfshin.Ardakani@Sun.COM int rc;
116*11963SAfshin.Ardakani@Sun.COM
117*11963SAfshin.Ardakani@Sun.COM if ((rc = smb_reparse_init(path, &nvl)) != 0)
118*11963SAfshin.Ardakani@Sun.COM return (rc);
119*11963SAfshin.Ardakani@Sun.COM
120*11963SAfshin.Ardakani@Sun.COM if ((rc = reparse_remove(nvl, svctype)) != 0) {
121*11963SAfshin.Ardakani@Sun.COM smb_reparse_free(nvl);
122*11963SAfshin.Ardakani@Sun.COM return (rc);
123*11963SAfshin.Ardakani@Sun.COM }
124*11963SAfshin.Ardakani@Sun.COM
125*11963SAfshin.Ardakani@Sun.COM if (nvlist_next_nvpair(nvl, NULL) == NULL) {
126*11963SAfshin.Ardakani@Sun.COM /* list is empty remove the object */
127*11963SAfshin.Ardakani@Sun.COM rc = reparse_delete(path);
128*11963SAfshin.Ardakani@Sun.COM if ((rc != 0) && (rc == ENOENT))
129*11963SAfshin.Ardakani@Sun.COM rc = 0;
130*11963SAfshin.Ardakani@Sun.COM } else {
131*11963SAfshin.Ardakani@Sun.COM rc = smb_reparse_set(path, nvl);
132*11963SAfshin.Ardakani@Sun.COM }
133*11963SAfshin.Ardakani@Sun.COM
134*11963SAfshin.Ardakani@Sun.COM smb_reparse_free(nvl);
135*11963SAfshin.Ardakani@Sun.COM return (rc);
136*11963SAfshin.Ardakani@Sun.COM }
137*11963SAfshin.Ardakani@Sun.COM
138*11963SAfshin.Ardakani@Sun.COM /*
139*11963SAfshin.Ardakani@Sun.COM * Obtains data of the given service type from the specified
140*11963SAfshin.Ardakani@Sun.COM * reparse point. Function allocates the memory needed to hold
141*11963SAfshin.Ardakani@Sun.COM * the service data so the caller must free this memory by
142*11963SAfshin.Ardakani@Sun.COM * calling free().
143*11963SAfshin.Ardakani@Sun.COM *
144*11963SAfshin.Ardakani@Sun.COM * If 'svcdata' is NULL, successful return means that the reparse
145*11963SAfshin.Ardakani@Sun.COM * point contains a record for the given service type.
146*11963SAfshin.Ardakani@Sun.COM */
147*11963SAfshin.Ardakani@Sun.COM int
smb_reparse_svcget(const char * path,const char * svctype,char ** svcdata)148*11963SAfshin.Ardakani@Sun.COM smb_reparse_svcget(const char *path, const char *svctype, char **svcdata)
149*11963SAfshin.Ardakani@Sun.COM {
150*11963SAfshin.Ardakani@Sun.COM nvlist_t *nvl;
151*11963SAfshin.Ardakani@Sun.COM nvpair_t *nvp;
152*11963SAfshin.Ardakani@Sun.COM char *stype, *sdata;
153*11963SAfshin.Ardakani@Sun.COM int rc;
154*11963SAfshin.Ardakani@Sun.COM
155*11963SAfshin.Ardakani@Sun.COM if ((rc = smb_reparse_init(path, &nvl)) != 0)
156*11963SAfshin.Ardakani@Sun.COM return (rc);
157*11963SAfshin.Ardakani@Sun.COM
158*11963SAfshin.Ardakani@Sun.COM rc = ENODATA;
159*11963SAfshin.Ardakani@Sun.COM nvp = nvlist_next_nvpair(nvl, NULL);
160*11963SAfshin.Ardakani@Sun.COM
161*11963SAfshin.Ardakani@Sun.COM while (nvp != NULL) {
162*11963SAfshin.Ardakani@Sun.COM stype = nvpair_name(nvp);
163*11963SAfshin.Ardakani@Sun.COM
164*11963SAfshin.Ardakani@Sun.COM if ((stype != NULL) && (strcasecmp(stype, svctype) == 0)) {
165*11963SAfshin.Ardakani@Sun.COM if ((rc = nvpair_value_string(nvp, &sdata)) != 0)
166*11963SAfshin.Ardakani@Sun.COM break;
167*11963SAfshin.Ardakani@Sun.COM
168*11963SAfshin.Ardakani@Sun.COM if (svcdata != NULL) {
169*11963SAfshin.Ardakani@Sun.COM if ((*svcdata = strdup(sdata)) == NULL)
170*11963SAfshin.Ardakani@Sun.COM rc = ENOMEM;
171*11963SAfshin.Ardakani@Sun.COM }
172*11963SAfshin.Ardakani@Sun.COM
173*11963SAfshin.Ardakani@Sun.COM rc = 0;
174*11963SAfshin.Ardakani@Sun.COM break;
175*11963SAfshin.Ardakani@Sun.COM }
176*11963SAfshin.Ardakani@Sun.COM nvp = nvlist_next_nvpair(nvl, nvp);
177*11963SAfshin.Ardakani@Sun.COM }
178*11963SAfshin.Ardakani@Sun.COM
179*11963SAfshin.Ardakani@Sun.COM smb_reparse_free(nvl);
180*11963SAfshin.Ardakani@Sun.COM return (rc);
181*11963SAfshin.Ardakani@Sun.COM }
182*11963SAfshin.Ardakani@Sun.COM
183*11963SAfshin.Ardakani@Sun.COM /*
184*11963SAfshin.Ardakani@Sun.COM * Initializes the given nvpair list.
185*11963SAfshin.Ardakani@Sun.COM *
186*11963SAfshin.Ardakani@Sun.COM * This function assumes that the object specified by this path
187*11963SAfshin.Ardakani@Sun.COM * is a reparse point, so it does not do any verification.
188*11963SAfshin.Ardakani@Sun.COM *
189*11963SAfshin.Ardakani@Sun.COM * If specified reparse point does not exist the function
190*11963SAfshin.Ardakani@Sun.COM * returns successfully with an empty nvpair list.
191*11963SAfshin.Ardakani@Sun.COM *
192*11963SAfshin.Ardakani@Sun.COM * If the object exists and readlink is successful then nvpair
193*11963SAfshin.Ardakani@Sun.COM * list is polulated with the reparse service information, otherwise
194*11963SAfshin.Ardakani@Sun.COM * an error code is returned.
195*11963SAfshin.Ardakani@Sun.COM */
196*11963SAfshin.Ardakani@Sun.COM static int
smb_reparse_init(const char * path,nvlist_t ** nvl)197*11963SAfshin.Ardakani@Sun.COM smb_reparse_init(const char *path, nvlist_t **nvl)
198*11963SAfshin.Ardakani@Sun.COM {
199*11963SAfshin.Ardakani@Sun.COM char rp_data[MAXREPARSELEN];
200*11963SAfshin.Ardakani@Sun.COM int rc;
201*11963SAfshin.Ardakani@Sun.COM
202*11963SAfshin.Ardakani@Sun.COM if ((*nvl = reparse_init()) == NULL)
203*11963SAfshin.Ardakani@Sun.COM return (ENOMEM);
204*11963SAfshin.Ardakani@Sun.COM
205*11963SAfshin.Ardakani@Sun.COM bzero(rp_data, MAXREPARSELEN);
206*11963SAfshin.Ardakani@Sun.COM if ((rc = readlink(path, rp_data, MAXREPARSELEN)) == -1) {
207*11963SAfshin.Ardakani@Sun.COM if (errno == ENOENT)
208*11963SAfshin.Ardakani@Sun.COM return (0);
209*11963SAfshin.Ardakani@Sun.COM
210*11963SAfshin.Ardakani@Sun.COM reparse_free(*nvl);
211*11963SAfshin.Ardakani@Sun.COM return (errno);
212*11963SAfshin.Ardakani@Sun.COM }
213*11963SAfshin.Ardakani@Sun.COM
214*11963SAfshin.Ardakani@Sun.COM if ((rc = reparse_parse(rp_data, *nvl)) != 0) {
215*11963SAfshin.Ardakani@Sun.COM reparse_free(*nvl);
216*11963SAfshin.Ardakani@Sun.COM return (rc);
217*11963SAfshin.Ardakani@Sun.COM }
218*11963SAfshin.Ardakani@Sun.COM
219*11963SAfshin.Ardakani@Sun.COM return (0);
220*11963SAfshin.Ardakani@Sun.COM }
221*11963SAfshin.Ardakani@Sun.COM
222*11963SAfshin.Ardakani@Sun.COM /*
223*11963SAfshin.Ardakani@Sun.COM * Frees given nvlist
224*11963SAfshin.Ardakani@Sun.COM */
225*11963SAfshin.Ardakani@Sun.COM static void
smb_reparse_free(nvlist_t * nvl)226*11963SAfshin.Ardakani@Sun.COM smb_reparse_free(nvlist_t *nvl)
227*11963SAfshin.Ardakani@Sun.COM {
228*11963SAfshin.Ardakani@Sun.COM reparse_free(nvl);
229*11963SAfshin.Ardakani@Sun.COM }
230*11963SAfshin.Ardakani@Sun.COM
231*11963SAfshin.Ardakani@Sun.COM /*
232*11963SAfshin.Ardakani@Sun.COM * Create a reparse point with given services in the passed
233*11963SAfshin.Ardakani@Sun.COM * nvlist. If the reparse point already exists, it will be
234*11963SAfshin.Ardakani@Sun.COM * deleted and a new one with the given data is created.
235*11963SAfshin.Ardakani@Sun.COM */
236*11963SAfshin.Ardakani@Sun.COM static int
smb_reparse_set(const char * path,nvlist_t * nvl)237*11963SAfshin.Ardakani@Sun.COM smb_reparse_set(const char *path, nvlist_t *nvl)
238*11963SAfshin.Ardakani@Sun.COM {
239*11963SAfshin.Ardakani@Sun.COM char *rp_data;
240*11963SAfshin.Ardakani@Sun.COM int rc;
241*11963SAfshin.Ardakani@Sun.COM
242*11963SAfshin.Ardakani@Sun.COM if ((rc = reparse_unparse(nvl, &rp_data)) != 0)
243*11963SAfshin.Ardakani@Sun.COM return (rc);
244*11963SAfshin.Ardakani@Sun.COM
245*11963SAfshin.Ardakani@Sun.COM rc = reparse_delete(path);
246*11963SAfshin.Ardakani@Sun.COM if ((rc != 0) && (rc != ENOENT)) {
247*11963SAfshin.Ardakani@Sun.COM free(rp_data);
248*11963SAfshin.Ardakani@Sun.COM return (rc);
249*11963SAfshin.Ardakani@Sun.COM }
250*11963SAfshin.Ardakani@Sun.COM
251*11963SAfshin.Ardakani@Sun.COM rc = reparse_create(path, rp_data);
252*11963SAfshin.Ardakani@Sun.COM free(rp_data);
253*11963SAfshin.Ardakani@Sun.COM
254*11963SAfshin.Ardakani@Sun.COM return (rc);
255*11963SAfshin.Ardakani@Sun.COM }
256