XBPS Library API  0.19
The X Binary Package System
rindex_sync.c
1 /*-
2  * Copyright (c) 2009-2012 Juan Romero Pardines.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <errno.h>
30 
31 #include "xbps_api_impl.h"
32 #include "fetch.h"
33 
34 char HIDDEN *
35 xbps_get_remote_repo_string(const char *uri)
36 {
37  struct url *url;
38  size_t i;
39  char *p;
40 
41  if ((url = fetchParseURL(uri)) == NULL)
42  return NULL;
43 
44  /*
45  * Replace '.' ':' and '/' characters with underscores, so that
46  * provided URL:
47  *
48  * http://nocturno.local:8080/repo/x86_64
49  *
50  * becomes:
51  *
52  * http___nocturno_local_8080_repo_x86_64
53  */
54  if (url->port != 0)
55  p = xbps_xasprintf("%s://%s:%u%s", url->scheme,
56  url->host, url->port, url->doc);
57  else
58  p = xbps_xasprintf("%s://%s%s", url->scheme,
59  url->host, url->doc);
60 
61  fetchFreeURL(url);
62  for (i = 0; i < strlen(p); i++) {
63  if (p[i] == '.' || p[i] == '/' || p[i] == ':')
64  p[i] = '_';
65  }
66 
67  return p;
68 }
69 
70 /*
71  * Returns -1 on error, 0 if transfer was not necessary (local/remote
72  * size and/or mtime match) and 1 if downloaded successfully.
73  */
74 int HIDDEN
75 xbps_rindex_sync(struct xbps_handle *xhp, const char *uri, const char *plistf)
76 {
77  prop_dictionary_t repod;
78  const char *fetchstr = NULL;
79  char *rpidx, *lrepodir, *uri_fixedp, *lrepofile;
80  int rv = 0;
81 
82  assert(uri != NULL);
83  rpidx = uri_fixedp = lrepodir = lrepofile = NULL;
84 
85  /* ignore non remote repositories */
86  if (!xbps_repository_is_remote(uri))
87  return 0;
88 
89  uri_fixedp = xbps_get_remote_repo_string(uri);
90  if (uri_fixedp == NULL)
91  return -1;
92  /*
93  * Remote repository plist index full URL.
94  */
95  rpidx = xbps_xasprintf("%s/%s-%s", uri, xhp->un_machine, plistf);
96  /*
97  * Full path to repository directory to store the plist
98  * index file.
99  */
100  lrepodir = xbps_xasprintf("%s/%s", xhp->metadir, uri_fixedp);
101  /*
102  * Full path to the local repository index file.
103  */
104  lrepofile = xbps_xasprintf("%s/%s-%s", lrepodir,
105  xhp->un_machine, plistf);
106  /*
107  * Create repodir in metadir.
108  */
109  if (access(lrepodir, R_OK|X_OK|W_OK) == -1) {
110  if ((rv = xbps_mkpath(lrepodir, 0755)) == -1) {
111  xbps_set_cb_state(xhp, XBPS_STATE_REPOSYNC_FAIL,
112  errno, NULL, NULL,
113  "[reposync] failed to create repodir `%s': %s",
114  lrepodir, strerror(errno));
115  goto out;
116  }
117  }
118  if (chdir(lrepodir) == -1) {
119  xbps_set_cb_state(xhp, XBPS_STATE_REPOSYNC_FAIL,
120  errno, NULL, NULL,
121  "[reposync] failed to change dir to repodir `%s': %s",
122  lrepodir, strerror(errno));
123  rv = -1;
124  goto out;
125  }
126 
127  /* reposync start cb */
128  xbps_set_cb_state(xhp, XBPS_STATE_REPOSYNC, 0, uri, plistf, NULL);
129  /*
130  * Download plist index file from repository.
131  */
132  if ((rv = xbps_fetch_file(xhp, rpidx, NULL)) == -1) {
133  /* reposync error cb */
134  fetchstr = xbps_fetch_error_string();
135  xbps_set_cb_state(xhp, XBPS_STATE_REPOSYNC_FAIL,
136  fetchLastErrCode != 0 ? fetchLastErrCode : errno,
137  NULL, NULL,
138  "[reposync] failed to fetch file `%s': %s",
139  rpidx, fetchstr ? fetchstr : strerror(errno));
140  goto out;
141  } else if (rv == 0) {
142  goto out;
143  } else {
144  rv = 0;
145  }
146  /*
147  * Make sure that downloaded plist file can be internalized, i.e
148  * some HTTP servers don't return proper errors and sometimes
149  * you get an HTML ASCII file :-)
150  */
151  repod = prop_dictionary_internalize_from_zfile(lrepofile);
152  if (repod == NULL) {
153  xbps_set_cb_state(xhp, XBPS_STATE_REPOSYNC_FAIL, 0, NULL, NULL,
154  "[reposync] downloaded file `%s' is not valid.", rpidx);
155  (void)unlink(lrepofile);
156  (void)remove(lrepodir);
157  rv = -1;
158  goto out;
159  }
160  prop_object_release(repod);
161 
162 out:
163  if (rpidx)
164  free(rpidx);
165  if (lrepodir)
166  free(lrepodir);
167  if (lrepofile)
168  free(lrepofile);
169  if (uri_fixedp)
170  free(uri_fixedp);
171 
172  return rv;
173 }