- permit globs in macrofiles: directive (#117217).
[platform/upstream/rpm.git] / lib / misc.c
1 /**
2  * \file lib/misc.c
3  */
4
5 #include "system.h"
6
7 /* just to put a marker in librpm.a */
8 const char * RPMVERSION = VERSION;
9
10 #include "rpmio_internal.h"
11 #include <rpmurl.h>
12 #include <rpmmacro.h>   /* XXX for rpmGetPath */
13 #include <rpmlib.h>
14 #include "legacy.h"
15 #include "misc.h"
16 #include "debug.h"
17
18 rpmRC rpmMkdirPath (const char * dpath, const char * dname)
19 {
20     struct stat st;
21     int rc;
22
23     if ((rc = Stat(dpath, &st)) < 0) {
24         int ut = urlPath(dpath, NULL);
25         switch (ut) {
26         case URL_IS_PATH:
27         case URL_IS_UNKNOWN:
28             if (errno != ENOENT)
29                 break;
30             /*@fallthrough@*/
31         case URL_IS_FTP:
32         case URL_IS_HTTP:
33             rc = Mkdir(dpath, 0755);
34             break;
35         case URL_IS_DASH:
36             break;
37         }
38         if (rc < 0) {
39             rpmError(RPMERR_CREATE, _("cannot create %%%s %s\n"), dname, dpath);
40             return RPMRC_FAIL;
41         }
42     }
43     if ((rc = Access(dpath, W_OK))) {
44         rpmError(RPMERR_CREATE, _("cannot write to %%%s %s\n"), dname, dpath);
45         return RPMRC_FAIL;
46     }
47     return RPMRC_OK;
48 }
49
50 /*@-bounds@*/
51 char ** splitString(const char * str, int length, char sep)
52 {
53     const char * source;
54     char * s, * dest;
55     char ** list;
56     int i;
57     int fields;
58
59     s = xmalloc(length + 1);
60
61     fields = 1;
62     for (source = str, dest = s, i = 0; i < length; i++, source++, dest++) {
63         *dest = *source;
64         if (*dest == sep) fields++;
65     }
66
67     *dest = '\0';
68
69     list = xmalloc(sizeof(*list) * (fields + 1));
70
71     dest = s;
72     list[0] = dest;
73     i = 1;
74     while (i < fields) {
75         if (*dest == sep) {
76             list[i++] = dest + 1;
77             *dest = 0;
78         }
79         dest++;
80     }
81
82     list[i] = NULL;
83
84 /*@-nullret@*/ /* FIX: list[i] is NULL */
85     return list;
86 /*@=nullret@*/
87 }
88 /*@=bounds@*/
89
90 void freeSplitString(char ** list)
91 {
92     /*@-unqualifiedtrans@*/
93     list[0] = _free(list[0]);
94     /*@=unqualifiedtrans@*/
95     list = _free(list);
96 }
97
98 int doputenv(const char *str)
99 {
100     char * a;
101
102     /* FIXME: this leaks memory! */
103     a = xmalloc(strlen(str) + 1);
104     strcpy(a, str);
105     return putenv(a);
106 }
107
108 int dosetenv(const char * name, const char * value, int overwrite)
109 {
110     char * a;
111
112     if (!overwrite && getenv(name)) return 0;
113
114     /* FIXME: this leaks memory! */
115     a = xmalloc(strlen(name) + strlen(value) + sizeof("="));
116     (void) stpcpy( stpcpy( stpcpy( a, name), "="), value);
117     return putenv(a);
118 }
119
120 int makeTempFile(const char * prefix, const char ** fnptr, FD_t * fdptr)
121 {
122     const char * tpmacro = "%{?_tmppath:%{_tmppath}}%{!?_tmppath:/var/tmp}";
123     const char * tempfn = NULL;
124     const char * tfn = NULL;
125     static int _initialized = 0;
126     int temput;
127     FD_t fd = NULL;
128     int ran;
129
130     /*@-branchstate@*/
131     if (!prefix) prefix = "";
132     /*@=branchstate@*/
133
134     /* Create the temp directory if it doesn't already exist. */
135     /*@-branchstate@*/
136     if (!_initialized) {
137         _initialized = 1;
138         tempfn = rpmGenPath(prefix, tpmacro, NULL);
139         if (rpmioMkpath(tempfn, 0755, (uid_t) -1, (gid_t) -1))
140             goto errxit;
141     }
142     /*@=branchstate@*/
143
144     /* XXX should probably use mkstemp here */
145     srand(time(NULL));
146     ran = rand() % 100000;
147
148     /* maybe this should use link/stat? */
149
150     do {
151         char tfnbuf[64];
152 #ifndef NOTYET
153         sprintf(tfnbuf, "rpm-tmp.%d", ran++);
154         tempfn = _free(tempfn);
155         tempfn = rpmGenPath(prefix, tpmacro, tfnbuf);
156 #else
157         strcpy(tfnbuf, "rpm-tmp.XXXXXX");
158         tempfn = _free(tempfn);
159         tempfn = rpmGenPath(prefix, tpmacro, mktemp(tfnbuf));
160 #endif
161
162         temput = urlPath(tempfn, &tfn);
163         if (*tfn == '\0') goto errxit;
164
165         switch (temput) {
166         case URL_IS_HTTP:
167         case URL_IS_DASH:
168             goto errxit;
169             /*@notreached@*/ /*@switchbreak@*/ break;
170         default:
171             /*@switchbreak@*/ break;
172         }
173
174         fd = Fopen(tempfn, "w+x.ufdio");
175         /* XXX FIXME: errno may not be correct for ufdio */
176     } while ((fd == NULL || Ferror(fd)) && errno == EEXIST);
177
178     if (fd == NULL || Ferror(fd))
179         goto errxit;
180
181     switch(temput) {
182     case URL_IS_PATH:
183     case URL_IS_UNKNOWN:
184       { struct stat sb, sb2;
185         if (!stat(tfn, &sb) && S_ISLNK(sb.st_mode)) {
186             rpmError(RPMERR_SCRIPT, _("error creating temporary file %s\n"), tfn);
187             goto errxit;
188         }
189
190         if (sb.st_nlink != 1) {
191             rpmError(RPMERR_SCRIPT, _("error creating temporary file %s\n"), tfn);
192             goto errxit;
193         }
194
195         if (fstat(Fileno(fd), &sb2) == 0) {
196             if (sb2.st_ino != sb.st_ino || sb2.st_dev != sb.st_dev) {
197                 rpmError(RPMERR_SCRIPT, _("error creating temporary file %s\n"), tfn);
198                 goto errxit;
199             }
200         }
201       } break;
202     default:
203         break;
204     }
205
206     /*@-branchstate@*/
207     if (fnptr)
208         *fnptr = tempfn;
209     else 
210         tempfn = _free(tempfn);
211     /*@=branchstate@*/
212     *fdptr = fd;
213
214     return 0;
215
216 errxit:
217     tempfn = _free(tempfn);
218     /*@-usereleased@*/
219     if (fd != NULL) (void) Fclose(fd);
220     /*@=usereleased@*/
221     return 1;
222 }
223
224 char * currentDirectory(void)
225 {
226     int currDirLen = 0;
227     char * currDir = NULL;
228
229     do {
230         currDirLen += 128;
231         currDir = xrealloc(currDir, currDirLen);
232         memset(currDir, 0, currDirLen);
233     } while (getcwd(currDir, currDirLen) == NULL && errno == ERANGE);
234
235     return currDir;
236 }
237
238 /*
239  * XXX This is a "dressed" entry to headerGetEntry to do:
240  *      1) DIRNAME/BASENAME/DIRINDICES -> FILENAMES tag conversions.
241  *      2) i18n lookaside (if enabled).
242  */
243 int rpmHeaderGetEntry(Header h, int_32 tag, int_32 *type,
244         void **p, int_32 *c)
245 {
246     switch (tag) {
247     case RPMTAG_OLDFILENAMES:
248     {   const char ** fl = NULL;
249         int count;
250         rpmfiBuildFNames(h, RPMTAG_BASENAMES, &fl, &count);
251         if (count > 0) {
252             *p = fl;
253             if (c)      *c = count;
254             if (type)   *type = RPM_STRING_ARRAY_TYPE;
255             return 1;
256         }
257         if (c)  *c = 0;
258         return 0;
259     }   /*@notreached@*/ break;
260
261     case RPMTAG_GROUP:
262     case RPMTAG_DESCRIPTION:
263     case RPMTAG_SUMMARY:
264     {   char fmt[128];
265         const char * msgstr;
266         const char * errstr;
267
268         fmt[0] = '\0';
269         (void) stpcpy( stpcpy( stpcpy( fmt, "%{"), tagName(tag)), "}\n");
270
271         /* XXX FIXME: memory leak. */
272         msgstr = headerSprintf(h, fmt, rpmTagTable, rpmHeaderFormats, &errstr);
273         if (msgstr) {
274             *p = (void *) msgstr;
275             if (type)   *type = RPM_STRING_TYPE;
276             if (c)      *c = 1;
277             return 1;
278         } else {
279             if (c)      *c = 0;
280             return 0;
281         }
282     }   /*@notreached@*/ break;
283
284     default:
285         return headerGetEntry(h, tag, type, p, c);
286         /*@notreached@*/ break;
287     }
288     /*@notreached@*/
289 }