xref: /illumos-gate/usr/src/cmd/bnu/cpmv.c (revision afab0816ecb604f0099a09ad8ee398f0d7b77b1c)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * 	Copyright (c) 1999 by Sun Microsystems, Inc.
24  * 	All rights reserved.
25  */
26 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
27 /*	  All Rights Reserved  	*/
28 
29 
30 #ident	"%Z%%M%	%I%	%E% SMI"	/* from SVR4 bnu:cpmv.c	2.13 */
31 
32 #include "uucp.h"
33 
34 /*
35  * copy f1 to f2 locally
36  *	f1	-> source file name
37  *	f2	-> destination file name
38  * return:
39  *	0	-> ok
40  *	FAIL	-> failed
41  */
42 
43 static int
44 xcp(f1, f2)
45 char *f1, *f2;
46 {
47 	register int	fd1, fd2;
48 	register int	nr, nw;
49 	char buf[BUFSIZ];
50 	char *temp_p, temp[MAXFULLNAME];
51 
52 	if ((fd1 = open(f1, O_RDONLY)) == -1)
53 		return (FAIL);
54 
55 	if (DIRECTORY(f2)) {
56 		(void) strcat(f2, "/");
57 		(void) strcat(f2, BASENAME(f1, '/'));
58 	}
59 	DEBUG(4, "file name is %s\n", f2);
60 
61 	(void) strcpy(temp, f2);
62 	if ((temp_p = strrchr(temp, '/')) == NULL)
63 	    temp_p = temp;
64 	else
65 	    temp_p++;
66 	(void) strcpy(temp_p, ".TM.XXXXXX");
67 	temp_p = temp;
68 	DEBUG(4, "temp name is %s\n", temp_p);
69 
70 	if ((fd2 = mkstemp(temp_p)) == -1) {
71 		/* open of temp may fail if called from uidxcp() */
72 		/* in this case, try f2 since it is pre-created */
73 		temp_p = f2;
74 		if ((fd2 = open(temp_p, O_CREAT | O_TRUNC | O_WRONLY,
75 		    PUB_FILEMODE)) == -1) {
76 			DEBUG(5, "open of file returned errno %d\n", errno);
77 			(void) close(fd1);
78 			return (FAIL);
79 		}
80 		DEBUG(4, "using file name directly.%s\n", "");
81 	}
82 	(void) chmod(temp_p, PUB_FILEMODE);
83 
84 	/*	copy, looking for read or write failures */
85 	while ((nr = read(fd1, buf, sizeof (buf))) > 0 &&
86 		(nw = write(fd2, buf, nr)) == nr)
87 		;
88 
89 	close(fd1);
90 	close(fd2);
91 
92 	if (nr != 0 || nw == -1) {
93 		(void) unlink(temp_p);
94 		return (FAIL);
95 	}
96 	if (temp_p != f2) {
97 	    if (rename(temp_p, f2) != 0) {
98 		DEBUG(5, "rename failed: errno %d\n", errno);
99 		(void) unlink(temp_p);
100 		return (FAIL);
101 	    }
102 	}
103 	return (0);
104 }
105 
106 
107 /*
108  * move f1 to f2 locally
109  * returns:
110  *	0	-> ok
111  *	FAIL	-> failed
112  */
113 
114 int
115 xmv(f1, f2)
116 register char *f1, *f2;
117 {
118 	register int do_unlink, ret;
119 	struct stat sbuf;
120 
121 	if (stat(f2, &sbuf) == 0)
122 		do_unlink = ((sbuf.st_mode & S_IFMT) == S_IFREG);
123 	else
124 		do_unlink = 1;
125 
126 	if (do_unlink)
127 		(void) unlink(f2);	/* i'm convinced this is the right */
128 					/* thing to do */
129 	if ((ret = link(f1, f2)) < 0) {
130 	    /* copy file */
131 	    ret = xcp(f1, f2);
132 	}
133 
134 	if (ret == 0)
135 	    (void) unlink(f1);
136 	return (ret);
137 }
138 
139 /*
140  * toCorrupt - move file to CORRUPTDIR
141  * return - none
142  */
143 
144 void
145 toCorrupt(file)
146 char *file;
147 {
148 	char corrupt[MAXFULLNAME];
149 
150 	(void) sprintf(corrupt, "%s/%s", CORRUPTDIR, BASENAME(file, '/'));
151 	(void) link(file, corrupt);
152 	ASSERT(unlink(file) == 0, Ct_UNLINK, file, errno);
153 }
154 
155 /*
156  * append f1 to f2
157  *	f1	-> source FILE pointer
158  *	f2	-> destination FILE pointer
159  * return:
160  *	SUCCESS	-> ok
161  *	FAIL	-> failed
162  *
163  * to avoid confusing mail, turn lines with just "." into "..".
164  */
165 int
166 xfappend(fp1, fp2)
167 register FILE	*fp1, *fp2;
168 {
169 	char	buf[BUFSIZ];
170 
171 	while (fgets(buf, sizeof (buf), fp1) != NULL) {
172 		if (buf[0] == '.' && buf[1] == '\n')
173 			strcpy(buf, "..\n");
174 		fputs(buf, fp2);
175 	}
176 
177 	return (ferror(fp1) || ferror(fp2) ? FAIL : SUCCESS);
178 }
179 
180 
181 /*
182  * copy f1 to f2 locally under uid of uid argument
183  *	f1	-> source file name
184  *	f2	-> destination file name
185  *	Uid and Euid are global
186  * return:
187  *	0	-> ok
188  *	FAIL	-> failed
189  * NOTES:
190  *  for V7 systems, flip-flop between real and effective uid is
191  *  not allowed, so fork must be done.  This code will not
192  *  work correctly when realuid is root on System 5 because of
193  *  a bug in setuid.
194  */
195 
196 int
197 uidxcp(f1, f2)
198 char *f1, *f2;
199 {
200 	int status;
201 	char full[MAXFULLNAME];
202 
203 	(void) strcpy(full, f2);
204 	if (DIRECTORY(f2)) {
205 	    (void) strcat(full, "/");
206 	    (void) strcat(full, BASENAME(f1, '/'));
207 	}
208 
209 	/* create full owned by uucp */
210 	(void) close(creat(full, PUB_FILEMODE));
211 	(void) chmod(full, PUB_FILEMODE);
212 
213 	/* do file copy as read uid */
214 #ifndef V7
215 	(void) setuid(Uid);
216 	status = xcp(f1, full);
217 	(void) setuid(Euid);
218 	return (status);
219 
220 #else /* V7 */
221 
222 	if (vfork() == 0) {
223 	    setuid(Uid);
224 	    _exit(xcp(f1, full));
225 	}
226 	wait(&status);
227 	return (status);
228 #endif
229 }
230 
231 /*
232  * put file in public place
233  * if successful, filename is modified
234  * returns:
235  *	0	-> success
236  *	FAIL	-> failure
237  */
238 int
239 putinpub(file, tmp, user)
240 char *file, *user, *tmp;
241 {
242 	int status;
243 	char fullname[MAXFULLNAME];
244 
245 	(void) sprintf(fullname, "%s/%s/", Pubdir, user);
246 	if (mkdirs(fullname, PUBMASK) != 0) {
247 		/* cannot make directories */
248 		return (FAIL);
249 	}
250 	(void) strcat(fullname, BASENAME(file, '/'));
251 	status = xmv(tmp, fullname);
252 	if (status == 0) {
253 		(void) strcpy(file, fullname);
254 		(void) chmod(fullname, PUB_FILEMODE);
255 	}
256 	return (status);
257 }
258