update.c
1 /*- 2 * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org> 3 * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org> 4 * Copyright (c) 2011-2012 Marin Atanasov Nikolov <dnaeon@gmail.com> 5 * Copyright (c) 2014 Matthew Seaman <matthew@FreeBSD.org> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer 13 * in this position and unchanged. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <sys/stat.h> 31 #include <sys/param.h> 32 33 #include <err.h> 34 #include <getopt.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <unistd.h> 39 40 #include <pkg.h> 41 42 #include "pkgcli.h" 43 44 static bool 45 _find_repo(c_charv_t *reponames, const char *name) 46 { 47 vec_foreach(*reponames, i) { 48 if (STREQ(name, reponames->d[i])) 49 return (true); 50 } 51 return(false); 52 } 53 54 /** 55 * Fetch repository calalogues. 56 */ 57 int 58 pkgcli_update(bool force, bool strict, c_charv_t *reponames) 59 { 60 int retcode = EPKG_FATAL, update_count = 0, total_count = 0; 61 struct pkg_repo *r = NULL; 62 63 /* Only auto update if the user has write access. */ 64 if (pkgdb_access2(PKGDB_MODE_READ|PKGDB_MODE_WRITE|PKGDB_MODE_CREATE, 65 PKGDB_DB_REPO, reponames) == EPKG_ENOACCESS) 66 return (EPKG_OK); 67 68 if (pkg_repos_total_count() == 0) { 69 fprintf(stderr, "No active remote repositories configured.\n"); 70 return (EPKG_FATAL); 71 } 72 73 while (pkg_repos(&r) == EPKG_OK) { 74 if (reponames->len > 0 ) { 75 if (!_find_repo(reponames, pkg_repo_name(r))) 76 continue; 77 } else { 78 if (!pkg_repo_enabled(r)) 79 continue; 80 } 81 82 if (!quiet) 83 printf("Updating %s repository catalogue...\n", 84 pkg_repo_name(r)); 85 86 retcode = pkg_update(r, force); 87 88 if (retcode == EPKG_UPTODATE) { 89 retcode = EPKG_OK; 90 if (!quiet) { 91 printf("%s repository is up to date.\n", 92 pkg_repo_name(r)); 93 } 94 } 95 else if (retcode != EPKG_OK && strict) 96 retcode = EPKG_FATAL; 97 98 if (retcode == EPKG_OK) { 99 update_count++; 100 } 101 102 total_count ++; 103 } 104 105 if (total_count == 0) { 106 retcode = EPKG_FATAL; 107 if (!quiet) { 108 printf("No repositories are enabled.\n"); 109 } 110 } 111 else if (update_count == total_count) { 112 if (!quiet) { 113 if (reponames == NULL || reponames->len == 0) 114 printf("All repositories are up to date.\n"); 115 else { 116 vec_foreach(*reponames, i) 117 printf("%s%s", i == 0 ? "" : ", ", reponames->d[i]); 118 printf(" %s up to date.\n", reponames->len == 1 ? "is" : "are"); 119 } 120 } 121 } 122 else if (total_count == 1) { 123 if (!quiet) { 124 printf("Error updating repositories!\n"); 125 } 126 } 127 else { 128 if (!quiet) { 129 printf("Error updating repositories!\n"); 130 } 131 if (strict) { 132 retcode = EPKG_FATAL; 133 } 134 } 135 136 return (retcode); 137 } 138 139 140 void 141 usage_update(void) 142 { 143 fprintf(stderr, "Usage: pkg update [-fq] [-r reponame]\n\n"); 144 fprintf(stderr, "For more information, see 'pkg help update'.\n"); 145 } 146 147 int 148 exec_update(int argc, char **argv) 149 { 150 int ret; 151 int ch; 152 c_charv_t reponames = vec_init(); 153 154 struct option longopts[] = { 155 { "force", no_argument, NULL, 'f' }, 156 { "quiet", no_argument, NULL, 'q' }, 157 { "repository", required_argument, NULL, 'r' }, 158 { NULL, 0, NULL, 0 }, 159 }; 160 161 while ((ch = getopt_long(argc, argv, "+fqr:", longopts, NULL)) != -1) { 162 switch (ch) { 163 case 'f': 164 force = true; 165 break; 166 case 'q': 167 quiet = true; 168 break; 169 case 'r': 170 vec_push(&reponames, optarg); 171 break; 172 default: 173 usage_update(); 174 return (EXIT_FAILURE); 175 } 176 } 177 argc -= optind; 178 179 if (argc != 0) { 180 usage_update(); 181 return (EXIT_FAILURE); 182 } 183 184 ret = pkgdb_access2(PKGDB_MODE_WRITE|PKGDB_MODE_CREATE, 185 PKGDB_DB_REPO, &reponames); 186 if (ret == EPKG_ENOACCESS) { 187 warnx("Insufficient privileges to update the repository " 188 "catalogue."); 189 return (EXIT_FAILURE); 190 } else if (ret != EPKG_OK) 191 return (EXIT_FAILURE); 192 193 /* For pkg-update update op is strict */ 194 ret = pkgcli_update(force, true, &reponames); 195 196 return ((ret == EPKG_OK) ? EXIT_SUCCESS : EXIT_FAILURE); 197 }