Merge branch 'vendor/OPENSSL'
[dragonfly.git] / contrib / amd / libamu / util.c
1 /*
2  * Copyright (c) 1997-1999 Erez Zadok
3  * Copyright (c) 1990 Jan-Simon Pendry
4  * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
5  * Copyright (c) 1990 The Regents of the University of California.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * Jan-Simon Pendry at Imperial College, London.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgment:
21  *      This product includes software developed by the University of
22  *      California, Berkeley and its contributors.
23  * 4. Neither the name of the University nor the names of its contributors
24  *    may be used to endorse or promote products derived from this software
25  *    without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37  * SUCH DAMAGE.
38  *
39  *      %W% (Berkeley) %G%
40  *
41  * $Id: util.c,v 1.2 1999/01/10 21:54:39 ezk Exp $
42  *
43  */
44
45 /*
46  * General Utilities.
47  */
48
49 #ifdef HAVE_CONFIG_H
50 # include <config.h>
51 #endif /* HAVE_CONFIG_H */
52 #include <am_defs.h>
53 #include <amu.h>
54
55
56 char *
57 strnsave(const char *str, int len)
58 {
59   char *sp = (char *) xmalloc(len + 1);
60   memmove(sp, str, len);
61   sp[len] = 0;
62
63   return sp;
64 }
65
66
67 /*
68  * Concatenate three strings and store in buffer pointed to
69  * by p, making p large enough to hold the strings
70  */
71 char *
72 str3cat(char *p, char *s1, char *s2, char *s3)
73 {
74   int l1 = strlen(s1);
75   int l2 = strlen(s2);
76   int l3 = strlen(s3);
77
78   p = (char *) xrealloc(p, l1 + l2 + l3 + 1);
79   memmove(p, s1, l1);
80   memmove(p + l1, s2, l2);
81   memmove(p + l1 + l2, s3, l3 + 1);
82   return p;
83 }
84
85
86 /*
87  * Make all the directories in the path.
88  */
89 int
90 mkdirs(char *path, int mode)
91 {
92   /*
93    * take a copy in case path is in readonly store
94    */
95   char *p2 = strdup(path);
96   char *sp = p2;
97   struct stat stb;
98   int error_so_far = 0;
99
100   /*
101    * Skip through the string make the directories.
102    * Mostly ignore errors - the result is tested at the end.
103    *
104    * This assumes we are root so that we can do mkdir in a
105    * mode 555 directory...
106    */
107   while ((sp = strchr(sp + 1, '/'))) {
108     *sp = '\0';
109     if (mkdir(p2, mode) < 0) {
110       error_so_far = errno;
111     } else {
112 #ifdef DEBUG
113       dlog("mkdir(%s)", p2);
114 #endif /* DEBUG */
115     }
116     *sp = '/';
117   }
118
119   if (mkdir(p2, mode) < 0) {
120     error_so_far = errno;
121   } else {
122 #ifdef DEBUG
123     dlog("mkdir(%s)", p2);
124 #endif /* DEBUG */
125   }
126
127   XFREE(p2);
128
129   return stat(path, &stb) == 0 &&
130     (stb.st_mode & S_IFMT) == S_IFDIR ? 0 : error_so_far;
131 }
132
133
134 /*
135  * Remove as many directories in the path as possible.
136  * Give up if the directory doesn't appear to have
137  * been created by Amd (not mode dr-x) or an rmdir
138  * fails for any reason.
139  */
140 void
141 rmdirs(char *dir)
142 {
143   char *xdp = strdup(dir);
144   char *dp;
145
146   do {
147     struct stat stb;
148     /*
149      * Try to find out whether this was
150      * created by amd.  Do this by checking
151      * for owner write permission.
152      */
153     if (stat(xdp, &stb) == 0 && (stb.st_mode & 0200) == 0) {
154       if (rmdir(xdp) < 0) {
155         if (errno != ENOTEMPTY &&
156             errno != EBUSY &&
157             errno != EEXIST &&
158             errno != EINVAL)
159           plog(XLOG_ERROR, "rmdir(%s): %m", xdp);
160         break;
161       } else {
162 #ifdef DEBUG
163         dlog("rmdir(%s)", xdp);
164 #endif /* DEBUG */
165       }
166     } else {
167       break;
168     }
169
170     dp = strrchr(xdp, '/');
171     if (dp)
172       *dp = '\0';
173   } while (dp && dp > xdp);
174
175   XFREE(xdp);
176 }