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