Add %_i18ndomains configuration.
[tools/librpm-tizen.git] / lib / formats.c
1 #include "system.h"
2
3 #include <rpmlib.h>
4 #include <rpmmacro.h>   /* XXX for %_i18ndomains */
5 #include "misc.h"
6
7 static char * permsString(int mode)
8 {
9     char * perms = xmalloc(11);
10
11     strcpy(perms, "-----------");
12    
13     if (mode & S_ISVTX) perms[10] = 't';
14
15     /*@-unrecog@*/
16     if (mode & S_IRUSR) perms[1] = 'r';
17     if (mode & S_IWUSR) perms[2] = 'w';
18     if (mode & S_IXUSR) perms[3] = 'x';
19  
20     if (mode & S_IRGRP) perms[4] = 'r';
21     if (mode & S_IWGRP) perms[5] = 'w';
22     if (mode & S_IXGRP) perms[6] = 'x';
23
24     if (mode & S_IROTH) perms[7] = 'r';
25     if (mode & S_IWOTH) perms[8] = 'w';
26     if (mode & S_IXOTH) perms[9] = 'x';
27     /*@=unrecog@*/
28
29     if (mode & S_ISUID) {
30         if (mode & S_IXUSR) 
31             perms[3] = 's'; 
32         else
33             perms[3] = 'S'; 
34     }
35
36     if (mode & S_ISGID) {
37         if (mode & S_IXGRP) 
38             perms[6] = 's'; 
39         else
40             perms[6] = 'S'; 
41     }
42
43     if (S_ISDIR(mode)) 
44         perms[0] = 'd';
45     else if (S_ISLNK(mode)) {
46         perms[0] = 'l';
47     }
48     else if (S_ISFIFO(mode)) 
49         perms[0] = 'p';
50     else if (S_ISSOCK(mode)) 
51         perms[0] = 'l';
52     else if (S_ISCHR(mode)) {
53         perms[0] = 'c';
54     } else if (S_ISBLK(mode)) {
55         perms[0] = 'b';
56     }
57
58     return perms;
59 }
60
61 static char * triggertypeFormat(int_32 type, const void * data, 
62         /*@unused@*/ char * formatPrefix, /*@unused@*/ int padding,
63         /*@unused@*/ int element)
64 {
65     const int_32 * item = data;
66     char * val;
67
68     if (type != RPM_INT32_TYPE) {
69         val = xstrdup(_("(not a number)"));
70     } else if (*item & RPMSENSE_TRIGGERIN) {
71         val = xstrdup("in");
72     } else {
73         val = xstrdup("un");
74     }
75
76     return val;
77 }
78
79 static char * permsFormat(int_32 type, const void * data, 
80                 char * formatPrefix, int padding, /*@unused@*/ int element)
81 {
82     char * val;
83     char * buf;
84
85     if (type != RPM_INT32_TYPE) {
86         val = xstrdup(_("(not a number)"));
87     } else {
88         val = xmalloc(15 + padding);
89         strcat(formatPrefix, "s");
90         buf = permsString(*((int_32 *) data));
91         sprintf(val, formatPrefix, buf);
92         free(buf);
93     }
94
95     return val;
96 }
97
98 static char * fflagsFormat(int_32 type, const void * data, 
99                 char * formatPrefix, int padding, /*@unused@*/ int element)
100 {
101     char * val;
102     char buf[15];
103     int anint = *((int_32 *) data);
104
105     if (type != RPM_INT32_TYPE) {
106         val = xstrdup(_("(not a number)"));
107     } else {
108         buf[0] = '\0';
109         if (anint & RPMFILE_DOC)
110             strcat(buf, "d");
111         if (anint & RPMFILE_CONFIG)
112             strcat(buf, "c");
113         if (anint & RPMFILE_SPECFILE)
114             strcat(buf, "s");
115         if (anint & RPMFILE_MISSINGOK)
116             strcat(buf, "m");
117         if (anint & RPMFILE_NOREPLACE)
118             strcat(buf, "n");
119         if (anint & RPMFILE_GHOST)
120             strcat(buf, "g");
121
122         val = xmalloc(5 + padding);
123         strcat(formatPrefix, "s");
124         sprintf(val, formatPrefix, buf);
125     }
126
127     return val;
128 }
129
130 static char * depflagsFormat(int_32 type, const void * data, 
131                 char * formatPrefix, int padding, /*@unused@*/ int element)
132 {
133     char * val;
134     char buf[10];
135     int anint = *((int_32 *) data);
136
137     if (type != RPM_INT32_TYPE) {
138         val = xstrdup(_("(not a number)"));
139     } else {
140         buf[0] = '\0';
141
142         if (anint & RPMSENSE_LESS) 
143             strcat(buf, "<");
144         if (anint & RPMSENSE_GREATER)
145             strcat(buf, ">");
146         if (anint & RPMSENSE_EQUAL)
147             strcat(buf, "=");
148
149         val = xmalloc(5 + padding);
150         strcat(formatPrefix, "s");
151         sprintf(val, formatPrefix, buf);
152     }
153
154     return val;
155 }
156
157 static int fsnamesTag( /*@unused@*/ Header h, /*@out@*/ int_32 * type,
158         /*@out@*/ void ** data, /*@out@*/ int_32 * count,
159         /*@out@*/ int * freeData)
160 {
161     const char ** list;
162
163     if (rpmGetFilesystemList(&list, count)) {
164         return 1;
165     }
166
167     *type = RPM_STRING_ARRAY_TYPE;
168     *((const char ***) data) = list;
169
170     *freeData = 0;
171
172     return 0; 
173 }
174
175 static int instprefixTag(Header h, /*@out@*/ int_32 * type,
176         /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
177         /*@out@*/ int * freeData)
178 {
179     char ** array;
180
181     if (headerGetEntry(h, RPMTAG_INSTALLPREFIX, type, (void **)data, count)) {
182         *freeData = 0;
183         return 0;
184     } else if (headerGetEntry(h, RPMTAG_INSTPREFIXES, NULL, (void **) &array, 
185                               count)) {
186         *data = xstrdup(array[0]);
187         *freeData = 1;
188         *type = RPM_STRING_TYPE;
189         free(array);
190         return 0;
191     } 
192
193     return 1;
194 }
195
196 static int fssizesTag(Header h, /*@out@*/ int_32 * type,
197         /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
198         /*@out@*/ int * freeData)
199 {
200     const char ** filenames;
201     int_32 * filesizes;
202     uint_32 * usages;
203     int numFiles;
204
205     if (!headerGetEntry(h, RPMTAG_FILESIZES, NULL, (void **) &filesizes, 
206                        &numFiles)) {
207         filesizes = NULL;
208         numFiles = 0;
209         filenames = NULL;
210     } else {
211         rpmBuildFileList(h, &filenames, &numFiles);
212     }
213
214     if (rpmGetFilesystemList(NULL, count)) {
215         return 1;
216     }
217
218     *type = RPM_INT32_TYPE;
219     *freeData = 1;
220
221     if (filenames == NULL) {
222         usages = xcalloc((*count), sizeof(usages));
223         *data = usages;
224
225         return 0;
226     }
227
228     if (rpmGetFilesystemUsage(filenames, filesizes, numFiles, &usages, 0))      
229         return 1;
230
231     *data = usages;
232
233     if (filenames) free(filenames);
234
235     return 0;
236 }
237
238 static int triggercondsTag(Header h, /*@out@*/ int_32 * type,
239         /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
240         /*@out@*/ int * freeData)
241 {
242     int_32 * indices, * flags;
243     char ** names, ** versions;
244     int numNames, numScripts;
245     char ** conds, ** s;
246     char * item, * flagsStr;
247     char * chptr;
248     int i, j;
249     char buf[5];
250
251     if (!headerGetEntry(h, RPMTAG_TRIGGERNAME, NULL, (void **) &names, 
252                         &numNames)) {
253         *freeData = 0;
254         return 0;
255     }
256
257     headerGetEntry(h, RPMTAG_TRIGGERINDEX, NULL, (void **) &indices, NULL);
258     headerGetEntry(h, RPMTAG_TRIGGERFLAGS, NULL, (void **) &flags, NULL);
259     headerGetEntry(h, RPMTAG_TRIGGERVERSION, NULL, (void **) &versions, NULL);
260     headerGetEntry(h, RPMTAG_TRIGGERSCRIPTS, NULL, (void **) &s, &numScripts);
261     free(s);
262
263     *freeData = 1;
264     *data = conds = xmalloc(sizeof(char * ) * numScripts);
265     *count = numScripts;
266     *type = RPM_STRING_ARRAY_TYPE;
267     for (i = 0; i < numScripts; i++) {
268         chptr = xstrdup("");
269
270         for (j = 0; j < numNames; j++) {
271             if (indices[j] != i) continue;
272
273             item = xmalloc(strlen(names[j]) + strlen(versions[j]) + 20);
274             if (flags[j] & RPMSENSE_SENSEMASK) {
275                 buf[0] = '%', buf[1] = '\0';
276                 flagsStr = depflagsFormat(RPM_INT32_TYPE, flags, buf,
277                                           0, j);
278                 sprintf(item, "%s %s %s", names[j], flagsStr, versions[j]);
279                 free(flagsStr);
280             } else {
281                 strcpy(item, names[j]);
282             }
283
284             chptr = xrealloc(chptr, strlen(chptr) + strlen(item) + 5);
285             if (*chptr) strcat(chptr, ", ");
286             strcat(chptr, item);
287             free(item);
288         }
289
290         conds[i] = chptr;
291     }
292
293     free(names);
294     free(versions);
295
296     return 0;
297 }
298
299 static int triggertypeTag(Header h, /*@out@*/ int_32 * type,
300         /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
301         /*@out@*/ int * freeData)
302 {
303     int_32 * indices, * flags;
304     char ** conds, ** s;
305     int i, j;
306     int numScripts, numNames;
307
308     if (!headerGetEntry(h, RPMTAG_TRIGGERINDEX, NULL, (void **) &indices, 
309                         &numNames)) {
310         *freeData = 0;
311         return 1;
312     }
313
314     headerGetEntry(h, RPMTAG_TRIGGERFLAGS, NULL, (void **) &flags, NULL);
315
316     headerGetEntry(h, RPMTAG_TRIGGERSCRIPTS, NULL, (void **) &s, &numScripts);
317     free(s);
318
319     *freeData = 1;
320     *data = conds = xmalloc(sizeof(char * ) * numScripts);
321     *count = numScripts;
322     *type = RPM_STRING_ARRAY_TYPE;
323     for (i = 0; i < numScripts; i++) {
324         for (j = 0; j < numNames; j++) {
325             if (indices[j] != i) continue;
326
327             if (flags[j] & RPMSENSE_TRIGGERIN)
328                 conds[i] = xstrdup("in");
329             else if (flags[j] & RPMSENSE_TRIGGERUN)
330                 conds[i] = xstrdup("un");
331             else
332                 conds[i] = xstrdup("postun");
333             break;
334         }
335     }
336
337     return 0;
338 }
339
340 static int filenamesTag(Header h, /*@out@*/ int_32 * type,
341         /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
342         /*@out@*/ int * freeData)
343 {
344     *type = RPM_STRING_ARRAY_TYPE;
345
346     rpmBuildFileList(h, (const char ***) data, count);
347     *freeData = 1;
348
349     *freeData = 0;      /* XXX WTFO? */
350
351     return 0; 
352 }
353
354 /* I18N look aside diversions */
355
356 int _nl_msg_cat_cntr;   /* XXX GNU gettext voodoo */
357 static const char * language = "LANGUAGE";
358
359 static char * _macro_i18ndomains = "%{?_i18ndomains:%{_i18ndomains}}";
360
361 static int i18nTag(Header h, int_32 tag, /*@out@*/ int_32 * type,
362         /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
363         /*@out@*/ int * freeData)
364 {
365     char * dstring = rpmExpand(_macro_i18ndomains, NULL);
366     int rc;
367
368     *type = RPM_STRING_TYPE;
369     *data = NULL;
370     *count = 0;
371     *freeData = 0;
372
373     if (dstring && *dstring) {
374         char *domain, *de;
375         const char * langval;
376         const char * msgkey;
377         const char * msgid;
378
379         {   const char * tn = tagName(tag);
380             const char * n;
381             char * mk;
382             headerNVR(h, &n, NULL, NULL);
383             mk = alloca(strlen(n) + strlen(tn) + sizeof("()"));
384             sprintf(mk, "%s(%s)", n, tn);
385             msgkey = mk;
386         }
387
388         /* change to en_US for msgkey -> msgid resolution */
389         langval = getenv(language);
390         setenv(language, "en_US", 1);
391         ++_nl_msg_cat_cntr;
392
393         msgid = NULL;
394         for (domain = dstring; domain != NULL; domain = de) {
395             de = strchr(domain, ':');
396             if (de) *de++ = '\0';
397             msgid = /*@-unrecog@*/ dgettext(domain, msgkey) /*@=unrecog@*/;
398             if (msgid != msgkey) break;
399         }
400
401         /* restore previous environment for msgid -> msgstr resolution */
402         if (langval)
403             setenv(language, langval, 1);
404         else
405             unsetenv(language);
406         ++_nl_msg_cat_cntr;
407
408         if (domain && msgid) {
409             *data = xstrdup(/*@-unrecog@*/ dgettext(domain, msgid) /*@=unrecog@*/);
410             *count = 1;
411             *freeData = 1;
412         }
413         xfree(dstring); dstring = NULL;
414         if (*data) {
415             return 0;
416         }
417     }
418
419     if (dstring) xfree(dstring);
420
421     rc = headerGetEntry(h, tag, type, (void **)data, count);
422
423     if (rc) {
424         *data = xstrdup(*data);
425         *freeData = 1;
426         return 0;
427     }
428
429     *freeData = 0;
430     *data = NULL;
431     *count = 0;
432     return 1;
433 }
434
435 static int summaryTag(Header h, /*@out@*/ int_32 * type,
436         /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
437         /*@out@*/ int * freeData)
438 {
439     return i18nTag(h, RPMTAG_SUMMARY, type, data, count, freeData);
440 }
441
442 static int descriptionTag(Header h, /*@out@*/ int_32 * type,
443         /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
444         /*@out@*/ int * freeData)
445 {
446     return i18nTag(h, RPMTAG_DESCRIPTION, type, data, count, freeData);
447 }
448
449 static int groupTag(Header h, /*@out@*/ int_32 * type,
450         /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
451         /*@out@*/ int * freeData)
452 {
453     return i18nTag(h, RPMTAG_GROUP, type, data, count, freeData);
454 }
455
456 const struct headerSprintfExtension rpmHeaderFormats[] = {
457     { HEADER_EXT_TAG, "RPMTAG_GROUP", { groupTag } },
458     { HEADER_EXT_TAG, "RPMTAG_DESCRIPTION", { descriptionTag } },
459     { HEADER_EXT_TAG, "RPMTAG_SUMMARY", { summaryTag } },
460     { HEADER_EXT_TAG, "RPMTAG_FILENAMES", { filenamesTag } },
461     { HEADER_EXT_TAG, "RPMTAG_FSSIZES", { fssizesTag } },
462     { HEADER_EXT_TAG, "RPMTAG_FSNAMES", { fsnamesTag } },
463     { HEADER_EXT_TAG, "RPMTAG_INSTALLPREFIX", { instprefixTag } },
464     { HEADER_EXT_TAG, "RPMTAG_TRIGGERCONDS", { triggercondsTag } },
465     { HEADER_EXT_TAG, "RPMTAG_TRIGGERTYPE", { triggertypeTag } },
466     { HEADER_EXT_FORMAT, "depflags", { depflagsFormat } },
467     { HEADER_EXT_FORMAT, "fflags", { fflagsFormat } },
468     { HEADER_EXT_FORMAT, "perms", { permsFormat } },
469     { HEADER_EXT_FORMAT, "permissions", { permsFormat } },
470     { HEADER_EXT_FORMAT, "triggertype", { triggertypeFormat } },
471     { HEADER_EXT_MORE, NULL, { (void *) headerDefaultFormats } }
472 } ;