- repo_rpmdb: read in RPMTAG_SHA1HEADER
[platform/upstream/libsolv.git] / ext / repo_releasefile_products.c
1 /*
2  * repo_products.c
3  *
4  * Parses all files below 'proddir'
5  * See http://en.opensuse.org/Product_Management/Code11
6  *
7  *
8  * Copyright (c) 2008, Novell Inc.
9  *
10  * This program is licensed under the BSD license, read LICENSE.BSD
11  * for further information
12  */
13
14 #include <sys/types.h>
15 #include <unistd.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <assert.h>
20 #include <dirent.h>
21 #include <ctype.h>
22
23 #include "pool.h"
24 #include "repo.h"
25 #include "util.h"
26 #define DISABLE_SPLIT
27 #include "tools_util.h"
28 #include "repo_releasefile_products.h"
29
30 #define BUFF_SIZE 8192
31
32 struct parsedata {
33   Repo *repo;
34   struct joindata jd;
35 };
36
37 static void
38 add_releasefile_product(struct parsedata *pd, FILE *fp)
39 {
40   Repo *repo = pd->repo;
41   Pool *pool = repo->pool;
42   char buf[BUFF_SIZE];
43   Id name = 0;
44   Id arch = 0;
45   Id version = 0;
46   int lnum = 0; /* line number */
47   char *ptr, *ptr1;
48
49   /* parse /etc/<xyz>-release file */
50   while (fgets(buf, sizeof(buf), fp))
51     {
52       /* remove trailing \n */
53       int l = strlen(buf);
54       if (l && buf[l - 1] == '\n')
55         buf[--l] = 0;
56       ++lnum;
57
58       if (lnum == 1)
59         {
60           /* 1st line, <name> [(<arch>)] */
61           ptr = strchr(buf, '(');
62           if (ptr)
63             {
64               ptr1 = ptr - 1;
65               *ptr++ = 0;
66             }
67           else
68             ptr1 = buf + l - 1;
69
70           /* track back until non-blank, non-digit */
71           while (ptr1 > buf
72                  && (*ptr1 == ' ' || isdigit(*ptr1) || *ptr1 == '.'))
73             --ptr1;
74           *(++ptr1) = 0;
75           name = pool_str2id(pool, join2(&pd->jd, "product", ":", buf), 1);
76
77           if (ptr)
78             {
79               /* have arch */
80               char *ptr1 = strchr(ptr, ')');
81               if (ptr1)
82                 {
83                   *ptr1 = 0;
84                   /* downcase arch */
85                   ptr1 = ptr;
86                   while (*ptr1)
87                     {
88                       if (isupper(*ptr1))
89                          *ptr1 = tolower(*ptr1);
90                       ++ptr1;
91                     }
92                   arch = pool_str2id(pool, ptr, 1);
93                 }
94             }
95         }
96       else if (strncmp(buf, "VERSION", 7) == 0)
97         {
98           ptr = strchr(buf + 7, '=');
99           if (ptr)
100             {
101               while (*++ptr == ' ')
102                 ;
103               version = makeevr(pool, ptr);
104             }
105         }
106     }
107   if (name)
108     {
109       Solvable *s = pool_id2solvable(pool, repo_add_solvable(repo));
110       s->name = name;
111       s->evr = version ? version : ID_EMPTY;
112       s->arch = arch ? arch : ARCH_NOARCH;
113       if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
114         s->provides = repo_addid_dep(repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
115     }
116 }
117
118
119 int
120 repo_add_releasefile_products(Repo *repo, const char *dirpath, int flags)
121 {
122   DIR *dir;
123   struct dirent *entry;
124   FILE *fp;
125   char *fullpath;
126   struct parsedata pd;
127
128   dir = opendir(dirpath);
129   if (!dir)
130     return 0;
131
132   memset(&pd, 0, sizeof(pd));
133   pd.repo = repo;
134   while ((entry = readdir(dir)))
135     {
136       int len = strlen(entry->d_name);
137       if (len > 8 && !strcmp(entry->d_name + len - 8, "-release"))
138         {
139           /* skip /etc/lsb-release, thats not a product per-se */
140           if (strcmp(entry->d_name, "lsb-release") == 0)
141             continue;
142           fullpath = join2(&pd.jd, dirpath, "/", entry->d_name);
143           if ((fp = fopen(fullpath, "r")) == 0)
144             {
145               perror(fullpath);
146               continue;
147             }
148           add_releasefile_product(&pd, fp);
149           fclose(fp);
150         }
151     }
152   closedir(dir);
153   join_freemem(&pd.jd);
154
155   if (!(flags & REPO_NO_INTERNALIZE) && (flags & REPO_REUSE_REPODATA) != 0)
156     repodata_internalize(repo_last_repodata(repo));
157   return 0;
158 }
159