]> pd.if.org Git - zpackage/blob - zpm-findpkg.c
3fd608c56327f5ed1653fb6fbbbef31811b18c79
[zpackage] / zpm-findpkg.c
1 #define _POSIX_C_SOURCE 2 
2
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <ctype.h>
6 #include <unistd.h>
7
8 #include "zpm.h"
9
10 static int found = 0;
11
12 void usage(void) {
13         fprintf(stderr, "zpm-findpkg [-I] [-s <status> ...] [-S <status>] [package]\n");
14 }
15
16 static int prow(void *f, int ncols, char **vals, char **cols) {
17         FILE *out = f;
18         int i;
19
20         if (cols == 0) {
21                 fprintf(stderr, "sqlite can't get column names\n");
22         }
23         for (i=3;i<ncols;i++) {
24                 if (i>3) fprintf(out, "\t");
25                 fprintf(out, "%s", vals[i]);
26         }
27         fprintf(out, "\n");
28         found++;
29         return 0;
30 }
31
32 void parse_package(char *pstr, char *name, char *ver, int *rel) {
33         if (name) *name = 0;
34         if (ver) *ver = 0;
35         if (rel) *rel = -1;
36
37         /* string - ver - rel */
38         /* rel is all digits */
39         /* possible forms:
40          * ^(.+)-([0-9][^-]*)-([\d+])$
41          * ^(.+)-([0-9][^-]*)$
42          * ^(.+)$
43          * The main problem in parsing is that the package name itself
44          * can contain a '-', so you can't just split on '-'
45          * Also, the version can be just digits.
46          */
47
48         /* everything up to the first '-' is in the name */
49         while (*pstr) {
50                 if (*pstr == '-' && isdigit(*(pstr+1))) {
51                         break;
52                 }
53                 if (name) {
54                         *name++ = *pstr;
55                 }
56                 pstr++;
57         }
58         if (name) *name = 0;
59         if (*pstr == '-') {
60                 pstr++;
61         }
62         while (*pstr && *pstr != '-') {
63                 if (ver) {
64                         *ver++ = *pstr;
65                 }
66                 pstr++;
67         }
68         if (ver) *ver = 0;
69         if (*pstr == '-') {
70                 pstr++;
71         }
72         if (rel && *pstr) {
73                 *rel = atoi(pstr);
74         }
75 }
76
77 int main(int ac, char **av){
78         int opt;
79         struct zpm pkg;
80         char *dbfile, *pkgstr;
81         char *select = "select package, version, release, package||'-'||version||'-'||release as pkgid from packages";
82         char *group = "group by package having max( version||'-'||release collate vercmp) order by length(package), package, version||'-'||release collate vercmp";
83
84         char *sql;
85         sqlite3_str *include;
86         sqlite3_str *exclude;
87         sqlite3_str *query;
88
89         dbfile = getenv("ZPMDB");
90
91         query = sqlite3_str_new(NULL);
92         include = sqlite3_str_new(NULL);
93         exclude = sqlite3_str_new(NULL);
94
95         while ((opt = getopt(ac, av, "f:s:S:I")) != -1) {
96                 switch (opt) {
97                         case 'f': dbfile = optarg; break;
98                         case 's': sqlite3_str_appendf(include,",%Q", optarg);
99                                   break;
100                         case 'S': sqlite3_str_appendf(exclude,",%Q", optarg);
101                                   break;
102                         case 'I': sqlite3_str_appendall(include,",'installed'");
103                                   break;
104                         default:
105                                   usage();
106                                   exit(EXIT_FAILURE);
107                                   break;
108                 }
109         }
110         int argn = optind;
111
112         if (!dbfile) {
113                 fprintf(stderr, "must specify db\n");
114                 return 1;
115         }
116
117         /* given a package name, get the packages */
118         /* no package name, get all */
119
120 #ifdef DEBUG
121         fprintf(stderr, "opening db %s\n", dbfile);
122 #endif
123
124         if (zpm_open(&pkg, dbfile)) {
125                 char *errmsg;
126                 char *excludes, *includes;
127
128                 excludes = sqlite3_str_value(exclude);
129                 includes = sqlite3_str_value(include);
130
131                 sqlite3_str_appendall(query, " ");
132                 sqlite3_str_appendall(query, select);
133                 sqlite3_str_appendall(query, " where true");
134
135                 if (includes) {
136                         sqlite3_str_appendf(query, " and status in (%s)", includes+1);
137                 }
138                 if (excludes) {
139                         sqlite3_str_appendf(query, " and status not in (%s)", excludes+1);
140                 }
141
142                 if (ac >= argn) {
143                         int release;
144                         char version[32];
145                         char package[32];
146
147                         pkgstr = av[argn];
148
149                         parse_package(pkgstr, package, version, &release);
150                         if (*package != 0) {
151                                 sqlite3_str_appendf(query, " and package = %Q",
152                                                 package);
153                         }
154                         if (*version != 0) {
155                                 sqlite3_str_appendf(query, " and version = %Q",
156                                                 version);
157                         }
158                         if (release != -1) {
159                                 sqlite3_str_appendf(query, " and release = %d",
160                                                 release);
161                         }
162                 }
163
164                 sqlite3_str_appendall(query, " ");
165                 sqlite3_str_appendall(query, group);
166                 sqlite3_str_appendall(query, ";");
167
168                 sql = sqlite3_str_value(query);
169                 if (sql) {
170 #ifdef DEBUG
171                         fprintf(stderr, "q: %s\n", sql);
172 #endif
173                         zpm_exec(&pkg, sql, prow, stdout, &errmsg);
174                 } else {
175                         fprintf(stderr, "unable to form database query\n");
176                 }
177         }
178         zpm_close(&pkg);
179         return found ? 0 : 1;
180 }