xref: /onnv-gate/usr/src/lib/libtsol/common/setflabel.c (revision 1676:37f4a3e2bd99)
1*1676Sjpk /*
2*1676Sjpk  * CDDL HEADER START
3*1676Sjpk  *
4*1676Sjpk  * The contents of this file are subject to the terms of the
5*1676Sjpk  * Common Development and Distribution License (the "License").
6*1676Sjpk  * You may not use this file except in compliance with the License.
7*1676Sjpk  *
8*1676Sjpk  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*1676Sjpk  * or http://www.opensolaris.org/os/licensing.
10*1676Sjpk  * See the License for the specific language governing permissions
11*1676Sjpk  * and limitations under the License.
12*1676Sjpk  *
13*1676Sjpk  * When distributing Covered Code, include this CDDL HEADER in each
14*1676Sjpk  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*1676Sjpk  * If applicable, add the following below this CDDL HEADER, with the
16*1676Sjpk  * fields enclosed by brackets "[]" replaced with your own identifying
17*1676Sjpk  * information: Portions Copyright [yyyy] [name of copyright owner]
18*1676Sjpk  *
19*1676Sjpk  * CDDL HEADER END
20*1676Sjpk  */
21*1676Sjpk /*
22*1676Sjpk  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23*1676Sjpk  * Use is subject to license terms.
24*1676Sjpk  */
25*1676Sjpk 
26*1676Sjpk #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*1676Sjpk 
28*1676Sjpk /*
29*1676Sjpk  *	Change the label of a file
30*1676Sjpk  */
31*1676Sjpk 
32*1676Sjpk #include <ctype.h>
33*1676Sjpk #include <locale.h>
34*1676Sjpk #include <stdio.h>
35*1676Sjpk #include <stdlib.h>
36*1676Sjpk #include <strings.h>
37*1676Sjpk #include <errno.h>
38*1676Sjpk 
39*1676Sjpk #include <tsol/label.h>
40*1676Sjpk 
41*1676Sjpk #include "labeld.h"
42*1676Sjpk #include <sys/tsol/label_macro.h>
43*1676Sjpk 
44*1676Sjpk #include <sys/types.h>
45*1676Sjpk 
46*1676Sjpk #include <zone.h>
47*1676Sjpk #include <sys/zone.h>
48*1676Sjpk #include <sys/param.h>
49*1676Sjpk #include <string.h>
50*1676Sjpk 
51*1676Sjpk static int abspath(char *, const char *, char *);
52*1676Sjpk 
53*1676Sjpk /*
54*1676Sjpk  * setflabel(3TSOL) - set file label
55*1676Sjpk  *
56*1676Sjpk  * This is the library interface to the door call.
57*1676Sjpk  */
58*1676Sjpk 
59*1676Sjpk #define	clcall callp->param.acall.cargs.setfbcl_arg
60*1676Sjpk #define	clret callp->param.aret.rvals.setfbcl_ret
61*1676Sjpk /*
62*1676Sjpk  *
63*1676Sjpk  *	Exit	error = If error reported, the error indicator,
64*1676Sjpk  *				-1, Unable to access label encodings file;
65*1676Sjpk  *				 0, Invalid binary label passed;
66*1676Sjpk  *				>0, Position after the first character in
67*1676Sjpk  *				    string of error, 1 indicates entire string.
68*1676Sjpk  *			Otherwise, unchanged.
69*1676Sjpk  *
70*1676Sjpk  *	Returns	0, If error.
71*1676Sjpk  *		1, If successful.
72*1676Sjpk  *
73*1676Sjpk  *	Calls	__call_labeld(SETFLABEL)
74*1676Sjpk  *
75*1676Sjpk  */
76*1676Sjpk 
77*1676Sjpk int
setflabel(const char * path,m_label_t * label)78*1676Sjpk setflabel(const char *path, m_label_t *label)
79*1676Sjpk {
80*1676Sjpk 	labeld_data_t	call;
81*1676Sjpk 	labeld_data_t	*callp = &call;
82*1676Sjpk 	size_t	bufsize = sizeof (labeld_data_t);
83*1676Sjpk 	size_t	datasize;
84*1676Sjpk 	size_t	path_len;
85*1676Sjpk 	static char	cwd[MAXPATHLEN];
86*1676Sjpk 	char		canon[MAXPATHLEN];
87*1676Sjpk 
88*1676Sjpk 
89*1676Sjpk 	/*
90*1676Sjpk 	 * If path is relative and we haven't already determined the current
91*1676Sjpk 	 * working directory, do so now.  Calculating the working directory
92*1676Sjpk 	 * here lets us do the work once, instead of (potentially) repeatedly
93*1676Sjpk 	 * in realpath().
94*1676Sjpk 	 */
95*1676Sjpk 	if (*path != '/' && cwd[0] == '\0') {
96*1676Sjpk 		if (getcwd(cwd, MAXPATHLEN) == NULL) {
97*1676Sjpk 			cwd[0] = '\0';
98*1676Sjpk 			return (-1);
99*1676Sjpk 		}
100*1676Sjpk 	}
101*1676Sjpk 	/*
102*1676Sjpk 	 * Find an absolute pathname in the native file system name space that
103*1676Sjpk 	 * corresponds to path, stuffing it into canon.
104*1676Sjpk 	 */
105*1676Sjpk 	if (abspath(cwd, path, canon) < 0)
106*1676Sjpk 		return (-1);
107*1676Sjpk 
108*1676Sjpk 	path_len = strlen(canon) + 1;
109*1676Sjpk 
110*1676Sjpk 	datasize = CALL_SIZE(setfbcl_call_t, path_len - BUFSIZE);
111*1676Sjpk 	datasize += 2; /* PAD */
112*1676Sjpk 
113*1676Sjpk 	if (datasize > bufsize) {
114*1676Sjpk 		if ((callp = (labeld_data_t *)malloc(datasize)) == NULL) {
115*1676Sjpk 			return (-1);
116*1676Sjpk 		}
117*1676Sjpk 		bufsize = datasize;
118*1676Sjpk 	}
119*1676Sjpk 
120*1676Sjpk 	callp->callop = SETFLABEL;
121*1676Sjpk 
122*1676Sjpk 	clcall.sl = *label;
123*1676Sjpk 	(void) strcpy(clcall.pathname, canon);
124*1676Sjpk 
125*1676Sjpk 	if (__call_labeld(&callp, &bufsize, &datasize) == SUCCESS) {
126*1676Sjpk 		int err = callp->reterr;
127*1676Sjpk 
128*1676Sjpk 		if (callp != &call) {
129*1676Sjpk 			/* free allocated buffer */
130*1676Sjpk 			free(callp);
131*1676Sjpk 		}
132*1676Sjpk 		/*
133*1676Sjpk 		 * reterr == 0, OK,
134*1676Sjpk 		 * reterr < 0, invalid binary label,
135*1676Sjpk 		 */
136*1676Sjpk 		if (err == 0) {
137*1676Sjpk 			if (clret.status > 0) {
138*1676Sjpk 				errno = clret.status;
139*1676Sjpk 				return (-1);
140*1676Sjpk 			} else {
141*1676Sjpk 				return (0);
142*1676Sjpk 			}
143*1676Sjpk 		} else if (err < 0) {
144*1676Sjpk 			err = 0;
145*1676Sjpk 		}
146*1676Sjpk 		errno = ECONNREFUSED;
147*1676Sjpk 		return (-1);
148*1676Sjpk 	} else {
149*1676Sjpk 		if (callp != &call) {
150*1676Sjpk 			/* free allocated buffer */
151*1676Sjpk 			free(callp);
152*1676Sjpk 		}
153*1676Sjpk 		/* server not present */
154*1676Sjpk 		errno = ECONNREFUSED;
155*1676Sjpk 		return (-1);
156*1676Sjpk 	}
157*1676Sjpk }  /* setflabel */
158*1676Sjpk 
159*1676Sjpk #undef	clcall
160*1676Sjpk #undef	clret
161*1676Sjpk 
162*1676Sjpk #define	clcall callp->param.acall.cargs.zcopy_arg
163*1676Sjpk #define	clret callp->param.aret.rvals.zcopy_ret
164*1676Sjpk /*
165*1676Sjpk  *
166*1676Sjpk  *	Exit	status = result of zone copy request
167*1676Sjpk  *				-1, Copy not confirmed
168*1676Sjpk  *			Otherwise, unchanged.
169*1676Sjpk  *
170*1676Sjpk  *	Returns	0, If error.
171*1676Sjpk  *		1, If successful.
172*1676Sjpk  *
173*1676Sjpk  *	Calls	__call_labeld(ZCOPY)
174*1676Sjpk  *
175*1676Sjpk  */
176*1676Sjpk int
zonecopy(m_label_t * src_win_sl,char * remote_dir,char * filename,char * local_dir,int transfer_mode)177*1676Sjpk zonecopy(m_label_t *src_win_sl, char *remote_dir, char *filename,
178*1676Sjpk     char *local_dir, int  transfer_mode)
179*1676Sjpk {
180*1676Sjpk 	labeld_data_t	call;
181*1676Sjpk 	labeld_data_t	*callp = &call;
182*1676Sjpk 	size_t		bufsize = sizeof (labeld_data_t);
183*1676Sjpk 	size_t		datasize;
184*1676Sjpk 	size_t		strings;
185*1676Sjpk 	size_t		remote_dir_len;
186*1676Sjpk 	size_t		filename_len;
187*1676Sjpk 	size_t		local_dir_len;
188*1676Sjpk 	size_t		display_len;
189*1676Sjpk 	char		*display;
190*1676Sjpk 
191*1676Sjpk 	remote_dir_len = strlen(remote_dir) + 1;
192*1676Sjpk 	filename_len = strlen(filename) + 1;
193*1676Sjpk 	local_dir_len = strlen(local_dir) + 1;
194*1676Sjpk 
195*1676Sjpk 	if ((display = getenv("DISPLAY")) == NULL)
196*1676Sjpk 		display = "";
197*1676Sjpk 	display_len = strlen(display) + 1;
198*1676Sjpk 
199*1676Sjpk 	strings = remote_dir_len + filename_len + local_dir_len + display_len;
200*1676Sjpk 
201*1676Sjpk 	datasize = CALL_SIZE(zcopy_call_t, strings - BUFSIZE);
202*1676Sjpk 
203*1676Sjpk 	datasize += 4; /* PAD */
204*1676Sjpk 
205*1676Sjpk 	if (datasize > bufsize) {
206*1676Sjpk 		if ((callp = (labeld_data_t *)malloc(datasize)) == NULL) {
207*1676Sjpk 			return (NULL);
208*1676Sjpk 		}
209*1676Sjpk 		bufsize = datasize;
210*1676Sjpk 	}
211*1676Sjpk 
212*1676Sjpk 	strings = 0;
213*1676Sjpk 	callp->callop = ZCOPY;
214*1676Sjpk 
215*1676Sjpk 	clcall.src_win_sl = *src_win_sl;
216*1676Sjpk 	clcall.transfer_mode = transfer_mode;
217*1676Sjpk 	clcall.remote_dir = strings;
218*1676Sjpk 	strings += remote_dir_len;
219*1676Sjpk 	clcall.filename = strings;
220*1676Sjpk 	strings += filename_len;
221*1676Sjpk 	clcall.local_dir = strings;
222*1676Sjpk 	strings += local_dir_len;
223*1676Sjpk 	clcall.display = strings;
224*1676Sjpk 
225*1676Sjpk 	(void) strcpy(&clcall.buf[clcall.remote_dir], remote_dir);
226*1676Sjpk 	(void) strcpy(&clcall.buf[clcall.filename], filename);
227*1676Sjpk 	(void) strcpy(&clcall.buf[clcall.local_dir], local_dir);
228*1676Sjpk 	(void) strcpy(&clcall.buf[clcall.display], display);
229*1676Sjpk 
230*1676Sjpk 	if (__call_labeld(&callp, &bufsize, &datasize) == SUCCESS) {
231*1676Sjpk 		int err = callp->reterr;
232*1676Sjpk 
233*1676Sjpk 		if (callp != &call) {
234*1676Sjpk 			/* free allocated buffer */
235*1676Sjpk 			free(callp);
236*1676Sjpk 		}
237*1676Sjpk 		/*
238*1676Sjpk 		 * reterr == 0, OK,
239*1676Sjpk 		 * reterr < 0, transer not confirmed
240*1676Sjpk 		 */
241*1676Sjpk 		if (err == 0) {
242*1676Sjpk 			return (clret.status);
243*1676Sjpk 		} else if (err < 0) {
244*1676Sjpk 			err = 0;
245*1676Sjpk 		}
246*1676Sjpk 		return (PIPEMSG_CANCEL);
247*1676Sjpk 	} else {
248*1676Sjpk 		if (callp != &call) {
249*1676Sjpk 			/* free allocated buffer */
250*1676Sjpk 			free(callp);
251*1676Sjpk 		}
252*1676Sjpk 		/* server not present */
253*1676Sjpk 		return (PIPEMSG_CANCEL);
254*1676Sjpk 	}
255*1676Sjpk }
256*1676Sjpk 
257*1676Sjpk /*
258*1676Sjpk  * Convert the path given in raw to canonical, absolute, symlink-free
259*1676Sjpk  * form, storing the result in the buffer named by canon, which must be
260*1676Sjpk  * at least MAXPATHLEN bytes long.  If wd is non-NULL, assume that it
261*1676Sjpk  * points to a path for the current working directory and use it instead
262*1676Sjpk  * of invoking getcwd; accepting this value as an argument lets our caller
263*1676Sjpk  * cache the value, so that realpath (called from this routine) doesn't have
264*1676Sjpk  * to recalculate it each time it's given a relative pathname.
265*1676Sjpk  *
266*1676Sjpk  * Return 0 on success, -1 on failure.
267*1676Sjpk  */
268*1676Sjpk int
abspath(char * wd,const char * raw,char * canon)269*1676Sjpk abspath(char *wd, const char *raw, char *canon)
270*1676Sjpk {
271*1676Sjpk 	char		absbuf[MAXPATHLEN];
272*1676Sjpk 
273*1676Sjpk 	/*
274*1676Sjpk 	 * Preliminary sanity check.
275*1676Sjpk 	 */
276*1676Sjpk 	if (raw == NULL || canon == NULL)
277*1676Sjpk 		return (-1);
278*1676Sjpk 
279*1676Sjpk 	/*
280*1676Sjpk 	 * If the path is relative, convert it to absolute form,
281*1676Sjpk 	 * using wd if it's been supplied.
282*1676Sjpk 	 */
283*1676Sjpk 	if (raw[0] != '/') {
284*1676Sjpk 		char	*limit = absbuf + sizeof (absbuf);
285*1676Sjpk 		char	*d;
286*1676Sjpk 
287*1676Sjpk 		/* Fill in working directory. */
288*1676Sjpk 		if (wd != NULL)
289*1676Sjpk 			(void) strncpy(absbuf, wd, sizeof (absbuf));
290*1676Sjpk 		else if (getcwd(absbuf, strlen(absbuf)) == NULL)
291*1676Sjpk 			return (-1);
292*1676Sjpk 
293*1676Sjpk 		/* Add separating slash. */
294*1676Sjpk 		d = absbuf + strlen(absbuf);
295*1676Sjpk 		if (d < limit)
296*1676Sjpk 			*d++ = '/';
297*1676Sjpk 
298*1676Sjpk 		/* Glue on the relative part of the path. */
299*1676Sjpk 		while (d < limit && (*d++ = *raw++))
300*1676Sjpk 			continue;
301*1676Sjpk 
302*1676Sjpk 		raw = absbuf;
303*1676Sjpk 	}
304*1676Sjpk 
305*1676Sjpk 	/*
306*1676Sjpk 	 * Call realpath to canonicalize and resolve symlinks.
307*1676Sjpk 	 */
308*1676Sjpk 	return (realpath(raw, canon) == NULL ? -1 : 0);
309*1676Sjpk }
310