config.c revision 156230
1156230Smux/*- 2156230Smux * Copyright (c) 2003-2006, Maxime Henrion <mux@FreeBSD.org> 3156230Smux * All rights reserved. 4156230Smux * 5156230Smux * Redistribution and use in source and binary forms, with or without 6156230Smux * modification, are permitted provided that the following conditions 7156230Smux * are met: 8156230Smux * 1. Redistributions of source code must retain the above copyright 9156230Smux * notice, this list of conditions and the following disclaimer. 10156230Smux * 2. Redistributions in binary form must reproduce the above copyright 11156230Smux * notice, this list of conditions and the following disclaimer in the 12156230Smux * documentation and/or other materials provided with the distribution. 13156230Smux * 14156230Smux * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15156230Smux * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16156230Smux * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17156230Smux * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18156230Smux * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19156230Smux * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20156230Smux * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21156230Smux * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22156230Smux * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23156230Smux * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24156230Smux * SUCH DAMAGE. 25156230Smux * 26156230Smux * $FreeBSD: vendor/csup/dist/contrib/csup/config.c 156230 2006-03-03 04:11:29Z mux $ 27156230Smux */ 28156230Smux 29156230Smux#include <sys/types.h> 30156230Smux#include <sys/stat.h> 31156230Smux 32156230Smux#include <errno.h> 33156230Smux#include <fcntl.h> 34156230Smux#include <stdio.h> 35156230Smux#include <stdlib.h> 36156230Smux#include <string.h> 37156230Smux#include <unistd.h> 38156230Smux 39156230Smux#include "config.h" 40156230Smux#include "globtree.h" 41156230Smux#include "keyword.h" 42156230Smux#include "misc.h" 43156230Smux#include "parse.h" 44156230Smux#include "stream.h" 45156230Smux#include "token.h" 46156230Smux 47156230Smuxstatic int config_parse_refusefiles(struct coll *); 48156230Smuxstatic int config_parse_refusefile(struct coll *, char *); 49156230Smux 50156230Smuxextern FILE *yyin; 51156230Smux 52156230Smux/* These are globals because I can't think of a better way with yacc. */ 53156230Smuxstatic STAILQ_HEAD(, coll) colls; 54156230Smuxstatic struct coll *cur_coll; 55156230Smuxstatic struct coll *defaults; 56156230Smuxstatic const char *cfgfile; 57156230Smux 58156230Smux/* 59156230Smux * Extract all the configuration information from the config 60156230Smux * file and some command line parameters. 61156230Smux */ 62156230Smuxstruct config * 63156230Smuxconfig_init(const char *file, struct coll *override, int overridemask) 64156230Smux{ 65156230Smux struct config *config; 66156230Smux struct coll *coll; 67156230Smux size_t slen; 68156230Smux char *prefix; 69156230Smux int error; 70156230Smux mode_t mask; 71156230Smux 72156230Smux config = xmalloc(sizeof(struct config)); 73156230Smux memset(config, 0, sizeof(struct config)); 74156230Smux STAILQ_INIT(&colls); 75156230Smux 76156230Smux defaults = coll_new(NULL); 77156230Smux /* Set the default umask. */ 78156230Smux mask = umask(0); 79156230Smux umask(mask); 80156230Smux defaults->co_umask = mask; 81156230Smux 82156230Smux /* Extract a list of collections from the configuration file. */ 83156230Smux cur_coll = coll_new(defaults); 84156230Smux yyin = fopen(file, "r"); 85156230Smux if (yyin == NULL) { 86156230Smux lprintf(-1, "Cannot open \"%s\": %s\n", file, 87156230Smux strerror(errno)); 88156230Smux goto bad; 89156230Smux } 90156230Smux cfgfile = file; 91156230Smux error = yyparse(); 92156230Smux fclose(yyin); 93156230Smux if (error) 94156230Smux goto bad; 95156230Smux 96156230Smux memcpy(&config->colls, &colls, sizeof(colls)); 97156230Smux if (STAILQ_EMPTY(&config->colls)) { 98156230Smux lprintf(-1, "Empty supfile\n"); 99156230Smux goto bad; 100156230Smux } 101156230Smux 102156230Smux /* Fixup the list of collections. */ 103156230Smux STAILQ_FOREACH(coll, &config->colls, co_next) { 104156230Smux coll_override(coll, override, overridemask); 105156230Smux if (coll->co_base == NULL) 106156230Smux coll->co_base = xstrdup("/usr/local/etc/cvsup"); 107156230Smux if (coll->co_colldir == NULL) 108156230Smux coll->co_colldir = "sup"; 109156230Smux if (coll->co_prefix == NULL) { 110156230Smux coll->co_prefix = xstrdup(coll->co_base); 111156230Smux /* 112156230Smux * If prefix is not an absolute pathname, it is 113156230Smux * interpreted relative to base. 114156230Smux */ 115156230Smux } else if (coll->co_prefix[0] != '/') { 116156230Smux slen = strlen(coll->co_base); 117156230Smux if (slen > 0 && coll->co_base[slen - 1] != '/') 118156230Smux xasprintf(&prefix, "%s/%s", coll->co_base, 119156230Smux coll->co_prefix); 120156230Smux else 121156230Smux xasprintf(&prefix, "%s%s", coll->co_base, 122156230Smux coll->co_prefix); 123156230Smux free(coll->co_prefix); 124156230Smux coll->co_prefix = prefix; 125156230Smux } 126156230Smux coll->co_prefixlen = strlen(coll->co_prefix); 127156230Smux /* Determine whether to checksum RCS files or not. */ 128156230Smux if (coll->co_options & CO_EXACTRCS) 129156230Smux coll->co_options |= CO_CHECKRCS; 130156230Smux else 131156230Smux coll->co_options &= ~CO_CHECKRCS; 132156230Smux /* In recent versions, we always try to set the file modes. */ 133156230Smux coll->co_options |= CO_SETMODE; 134156230Smux /* XXX We don't support the rsync updating algorithm yet. */ 135156230Smux coll->co_options |= CO_NORSYNC; 136156230Smux error = config_parse_refusefiles(coll); 137156230Smux if (error) 138156230Smux goto bad; 139156230Smux } 140156230Smux 141156230Smux coll_free(cur_coll); 142156230Smux coll_free(defaults); 143156230Smux config->host = STAILQ_FIRST(&config->colls)->co_host; 144156230Smux return (config); 145156230Smuxbad: 146156230Smux coll_free(cur_coll); 147156230Smux coll_free(defaults); 148156230Smux config_free(config); 149156230Smux return (NULL); 150156230Smux} 151156230Smux 152156230Smuxint 153156230Smuxconfig_checkcolls(struct config *config) 154156230Smux{ 155156230Smux char linkname[4]; 156156230Smux struct stat sb; 157156230Smux struct coll *coll; 158156230Smux int error, numvalid, ret; 159156230Smux 160156230Smux numvalid = 0; 161156230Smux STAILQ_FOREACH(coll, &config->colls, co_next) { 162156230Smux error = stat(coll->co_prefix, &sb); 163156230Smux if (error || !S_ISDIR(sb.st_mode)) { 164156230Smux /* Skip this collection, and warn about it unless its 165156230Smux prefix is a symbolic link pointing to "SKIP". */ 166156230Smux coll->co_options |= CO_SKIP; 167156230Smux ret = readlink(coll->co_prefix, linkname, 168156230Smux sizeof(linkname)); 169156230Smux if (ret != 4 || memcmp(linkname, "SKIP", 4) != 0) { 170156230Smux lprintf(-1,"Nonexistent prefix \"%s\" for " 171156230Smux "%s/%s\n", coll->co_prefix, coll->co_name, 172156230Smux coll->co_release); 173156230Smux } 174156230Smux continue; 175156230Smux } 176156230Smux numvalid++; 177156230Smux } 178156230Smux return (numvalid); 179156230Smux} 180156230Smux 181156230Smuxstatic int 182156230Smuxconfig_parse_refusefiles(struct coll *coll) 183156230Smux{ 184156230Smux char *collstem, *suffix, *supdir, *path; 185156230Smux int error; 186156230Smux 187156230Smux if (coll->co_colldir[0] == '/') 188156230Smux supdir = xstrdup(coll->co_colldir); 189156230Smux else 190156230Smux xasprintf(&supdir, "%s/%s", coll->co_base, coll->co_colldir); 191156230Smux 192156230Smux /* First, the global refuse file that applies to all collections. */ 193156230Smux xasprintf(&path, "%s/refuse", supdir); 194156230Smux error = config_parse_refusefile(coll, path); 195156230Smux free(path); 196156230Smux if (error) { 197156230Smux free(supdir); 198156230Smux return (error); 199156230Smux } 200156230Smux 201156230Smux /* Next the per-collection refuse files that applies to all release/tag 202156230Smux combinations. */ 203156230Smux xasprintf(&collstem, "%s/%s/refuse", supdir, coll->co_name); 204156230Smux free(supdir); 205156230Smux error = config_parse_refusefile(coll, collstem); 206156230Smux if (error) { 207156230Smux free(collstem); 208156230Smux return (error); 209156230Smux } 210156230Smux 211156230Smux /* Finally, the per-release and per-tag refuse file. */ 212156230Smux suffix = coll_statussuffix(coll); 213156230Smux if (suffix != NULL) { 214156230Smux xasprintf(&path, "%s%s", collstem, suffix); 215156230Smux free(suffix); 216156230Smux error = config_parse_refusefile(coll, path); 217156230Smux free(path); 218156230Smux } 219156230Smux free(collstem); 220156230Smux return (error); 221156230Smux} 222156230Smux 223156230Smux/* 224156230Smux * Parses a "refuse" file, and records the relevant information in 225156230Smux * coll->co_refusals. If the file does not exist, it is silently 226156230Smux * ignored. 227156230Smux */ 228156230Smuxstatic int 229156230Smuxconfig_parse_refusefile(struct coll *coll, char *path) 230156230Smux{ 231156230Smux struct stream *rd; 232156230Smux char *line; 233156230Smux 234156230Smux rd = stream_open_file(path, O_RDONLY); 235156230Smux if (rd == NULL) 236156230Smux return (0); 237156230Smux while ((line = stream_getln(rd, NULL)) != NULL) 238156230Smux pattlist_add(coll->co_refusals, line); 239156230Smux if (!stream_eof(rd)) { 240156230Smux stream_close(rd); 241156230Smux lprintf(-1, "Read failure from \"%s\": %s\n", path, 242156230Smux strerror(errno)); 243156230Smux return (-1); 244156230Smux } 245156230Smux stream_close(rd); 246156230Smux return (0); 247156230Smux} 248156230Smux 249156230Smuxvoid 250156230Smuxconfig_free(struct config *config) 251156230Smux{ 252156230Smux struct coll *coll; 253156230Smux 254156230Smux while (!STAILQ_EMPTY(&config->colls)) { 255156230Smux coll = STAILQ_FIRST(&config->colls); 256156230Smux STAILQ_REMOVE_HEAD(&config->colls, co_next); 257156230Smux coll_free(coll); 258156230Smux } 259156230Smux if (config->server != NULL) 260156230Smux stream_close(config->server); 261156230Smux if (config->laddr != NULL) 262156230Smux free(config->laddr); 263156230Smux free(config); 264156230Smux} 265156230Smux 266156230Smux/* Create a new collection, inheriting options from the default collection. */ 267156230Smuxstruct coll * 268156230Smuxcoll_new(struct coll *def) 269156230Smux{ 270156230Smux struct coll *new; 271156230Smux 272156230Smux new = xmalloc(sizeof(struct coll)); 273156230Smux memset(new, 0, sizeof(struct coll)); 274156230Smux if (def != NULL) { 275156230Smux new->co_options = def->co_options; 276156230Smux new->co_umask = def->co_umask; 277156230Smux if (def->co_host != NULL) 278156230Smux new->co_host = xstrdup(def->co_host); 279156230Smux if (def->co_base != NULL) 280156230Smux new->co_base = xstrdup(def->co_base); 281156230Smux if (def->co_date != NULL) 282156230Smux new->co_date = xstrdup(def->co_date); 283156230Smux if (def->co_prefix != NULL) 284156230Smux new->co_prefix = xstrdup(def->co_prefix); 285156230Smux if (def->co_release != NULL) 286156230Smux new->co_release = xstrdup(def->co_release); 287156230Smux if (def->co_tag != NULL) 288156230Smux new->co_tag = xstrdup(def->co_tag); 289156230Smux if (def->co_listsuffix != NULL) 290156230Smux new->co_listsuffix = xstrdup(def->co_listsuffix); 291156230Smux } else { 292156230Smux new->co_tag = xstrdup("."); 293156230Smux new->co_date = xstrdup("."); 294156230Smux } 295156230Smux new->co_keyword = keyword_new(); 296156230Smux new->co_accepts = pattlist_new(); 297156230Smux new->co_refusals = pattlist_new(); 298156230Smux new->co_attrignore = FA_DEV | FA_INODE; 299156230Smux return (new); 300156230Smux} 301156230Smux 302156230Smuxvoid 303156230Smuxcoll_override(struct coll *coll, struct coll *from, int mask) 304156230Smux{ 305156230Smux size_t i; 306156230Smux int newoptions, oldoptions; 307156230Smux 308156230Smux newoptions = from->co_options & mask; 309156230Smux oldoptions = coll->co_options & (CO_MASK & ~mask); 310156230Smux 311156230Smux if (from->co_release != NULL) { 312156230Smux if (coll->co_release != NULL) 313156230Smux free(coll->co_release); 314156230Smux coll->co_release = xstrdup(from->co_release); 315156230Smux } 316156230Smux if (from->co_host != NULL) { 317156230Smux if (coll->co_host != NULL) 318156230Smux free(coll->co_host); 319156230Smux coll->co_host = xstrdup(from->co_host); 320156230Smux } 321156230Smux if (from->co_base != NULL) { 322156230Smux if (coll->co_base != NULL) 323156230Smux free(coll->co_base); 324156230Smux coll->co_base = xstrdup(from->co_base); 325156230Smux } 326156230Smux if (from->co_colldir != NULL) 327156230Smux coll->co_colldir = from->co_colldir; 328156230Smux if (from->co_prefix != NULL) { 329156230Smux if (coll->co_prefix != NULL) 330156230Smux free(coll->co_prefix); 331156230Smux coll->co_prefix = xstrdup(from->co_prefix); 332156230Smux } 333156230Smux if (newoptions & CO_CHECKOUTMODE) { 334156230Smux if (from->co_tag != NULL) { 335156230Smux if (coll->co_tag != NULL) 336156230Smux free(coll->co_tag); 337156230Smux coll->co_tag = xstrdup(from->co_tag); 338156230Smux } 339156230Smux if (from->co_date != NULL) { 340156230Smux if (coll->co_date != NULL) 341156230Smux free(coll->co_date); 342156230Smux coll->co_date = xstrdup(from->co_date); 343156230Smux } 344156230Smux } 345156230Smux if (from->co_listsuffix != NULL) { 346156230Smux if (coll->co_listsuffix != NULL) 347156230Smux free(coll->co_listsuffix); 348156230Smux coll->co_listsuffix = xstrdup(from->co_listsuffix); 349156230Smux } 350156230Smux for (i = 0; i < pattlist_size(from->co_accepts); i++) { 351156230Smux pattlist_add(coll->co_accepts, 352156230Smux pattlist_get(from->co_accepts, i)); 353156230Smux } 354156230Smux for (i = 0; i < pattlist_size(from->co_refusals); i++) { 355156230Smux pattlist_add(coll->co_refusals, 356156230Smux pattlist_get(from->co_refusals, i)); 357156230Smux } 358156230Smux coll->co_options = oldoptions | newoptions; 359156230Smux} 360156230Smux 361156230Smuxchar * 362156230Smuxcoll_statussuffix(struct coll *coll) 363156230Smux{ 364156230Smux const char *tag; 365156230Smux char *suffix; 366156230Smux 367156230Smux if (coll->co_listsuffix != NULL) { 368156230Smux xasprintf(&suffix, ".%s", coll->co_listsuffix); 369156230Smux } else if (coll->co_options & CO_USERELSUFFIX) { 370156230Smux if (coll->co_tag == NULL) 371156230Smux tag = "."; 372156230Smux else 373156230Smux tag = coll->co_tag; 374156230Smux if (coll->co_release != NULL) { 375156230Smux if (coll->co_options & CO_CHECKOUTMODE) { 376156230Smux xasprintf(&suffix, ".%s:%s", 377156230Smux coll->co_release, tag); 378156230Smux } else { 379156230Smux xasprintf(&suffix, ".%s", coll->co_release); 380156230Smux } 381156230Smux } else if (coll->co_options & CO_CHECKOUTMODE) { 382156230Smux xasprintf(&suffix, ":%s", tag); 383156230Smux } 384156230Smux } else 385156230Smux suffix = NULL; 386156230Smux return (suffix); 387156230Smux} 388156230Smux 389156230Smuxchar * 390156230Smuxcoll_statuspath(struct coll *coll) 391156230Smux{ 392156230Smux char *path, *suffix; 393156230Smux 394156230Smux suffix = coll_statussuffix(coll); 395156230Smux if (suffix != NULL) { 396156230Smux if (coll->co_colldir[0] == '/') 397156230Smux xasprintf(&path, "%s/%s/checkouts%s", coll->co_colldir, 398156230Smux coll->co_name, suffix); 399156230Smux else 400156230Smux xasprintf(&path, "%s/%s/%s/checkouts%s", coll->co_base, 401156230Smux coll->co_colldir, coll->co_name, suffix); 402156230Smux } else { 403156230Smux if (coll->co_colldir[0] == '/') 404156230Smux xasprintf(&path, "%s/%s/checkouts", coll->co_colldir, 405156230Smux coll->co_name); 406156230Smux else 407156230Smux xasprintf(&path, "%s/%s/%s/checkouts", coll->co_base, 408156230Smux coll->co_colldir, coll->co_name); 409156230Smux } 410156230Smux free(suffix); 411156230Smux return (path); 412156230Smux} 413156230Smux 414156230Smuxvoid 415156230Smuxcoll_add(char *name) 416156230Smux{ 417156230Smux struct coll *coll; 418156230Smux 419156230Smux cur_coll->co_name = name; 420156230Smux if (cur_coll->co_release == NULL) { 421156230Smux lprintf(-1, "Release not specified for collection " 422156230Smux "\"%s\"\n", cur_coll->co_name); 423156230Smux exit(1); 424156230Smux } 425156230Smux if (cur_coll->co_host == NULL) { 426156230Smux lprintf(-1, "Host not specified for collection " 427156230Smux "\"%s\"\n", cur_coll->co_name); 428156230Smux exit(1); 429156230Smux } 430156230Smux if (!(cur_coll->co_options & CO_CHECKOUTMODE)) { 431156230Smux lprintf(-1, "Client only supports checkout mode\n"); 432156230Smux exit(1); 433156230Smux } 434156230Smux if (!STAILQ_EMPTY(&colls)) { 435156230Smux coll = STAILQ_LAST(&colls, coll, co_next); 436156230Smux if (strcmp(coll->co_host, cur_coll->co_host) != 0) { 437156230Smux lprintf(-1, "All \"host\" fields in the supfile " 438156230Smux "must be the same\n"); 439156230Smux exit(1); 440156230Smux } 441156230Smux } 442156230Smux STAILQ_INSERT_TAIL(&colls, cur_coll, co_next); 443156230Smux cur_coll = coll_new(defaults); 444156230Smux} 445156230Smux 446156230Smuxvoid 447156230Smuxcoll_free(struct coll *coll) 448156230Smux{ 449156230Smux 450156230Smux if (coll == NULL) 451156230Smux return; 452156230Smux if (coll->co_host != NULL) 453156230Smux free(coll->co_host); 454156230Smux if (coll->co_base != NULL) 455156230Smux free(coll->co_base); 456156230Smux if (coll->co_date != NULL) 457156230Smux free(coll->co_date); 458156230Smux if (coll->co_prefix != NULL) 459156230Smux free(coll->co_prefix); 460156230Smux if (coll->co_release != NULL) 461156230Smux free(coll->co_release); 462156230Smux if (coll->co_tag != NULL) 463156230Smux free(coll->co_tag); 464156230Smux if (coll->co_cvsroot != NULL) 465156230Smux free(coll->co_cvsroot); 466156230Smux if (coll->co_name != NULL) 467156230Smux free(coll->co_name); 468156230Smux if (coll->co_listsuffix != NULL) 469156230Smux free(coll->co_listsuffix); 470156230Smux keyword_free(coll->co_keyword); 471156230Smux if (coll->co_dirfilter != NULL) 472156230Smux globtree_free(coll->co_dirfilter); 473156230Smux if (coll->co_dirfilter != NULL) 474156230Smux globtree_free(coll->co_filefilter); 475156230Smux if (coll->co_accepts != NULL) 476156230Smux pattlist_free(coll->co_accepts); 477156230Smux if (coll->co_refusals != NULL) 478156230Smux pattlist_free(coll->co_refusals); 479156230Smux free(coll); 480156230Smux} 481156230Smux 482156230Smuxvoid 483156230Smuxcoll_setopt(int opt, char *value) 484156230Smux{ 485156230Smux struct coll *coll; 486156230Smux 487156230Smux coll = cur_coll; 488156230Smux switch (opt) { 489156230Smux case PT_HOST: 490156230Smux if (coll->co_host != NULL) 491156230Smux free(coll->co_host); 492156230Smux coll->co_host = value; 493156230Smux break; 494156230Smux case PT_BASE: 495156230Smux if (coll->co_base != NULL) 496156230Smux free(coll->co_base); 497156230Smux coll->co_base = value; 498156230Smux break; 499156230Smux case PT_DATE: 500156230Smux if (coll->co_date != NULL) 501156230Smux free(coll->co_date); 502156230Smux coll->co_date = value; 503156230Smux coll->co_options |= CO_CHECKOUTMODE; 504156230Smux break; 505156230Smux case PT_PREFIX: 506156230Smux if (coll->co_prefix != NULL) 507156230Smux free(coll->co_prefix); 508156230Smux coll->co_prefix = value; 509156230Smux break; 510156230Smux case PT_RELEASE: 511156230Smux if (coll->co_release != NULL) 512156230Smux free(coll->co_release); 513156230Smux coll->co_release = value; 514156230Smux break; 515156230Smux case PT_TAG: 516156230Smux if (coll->co_tag != NULL) 517156230Smux free(coll->co_tag); 518156230Smux coll->co_tag = value; 519156230Smux coll->co_options |= CO_CHECKOUTMODE; 520156230Smux break; 521156230Smux case PT_LIST: 522156230Smux if (strchr(value, '/') != NULL) { 523156230Smux lprintf(-1, "Parse error in \"%s\": \"list\" suffix " 524156230Smux "must not contain slashes\n", cfgfile); 525156230Smux exit(1); 526156230Smux } 527156230Smux if (coll->co_listsuffix != NULL) 528156230Smux free(coll->co_listsuffix); 529156230Smux coll->co_listsuffix = value; 530156230Smux break; 531156230Smux case PT_UMASK: 532156230Smux errno = 0; 533156230Smux coll->co_umask = strtol(value, NULL, 8); 534156230Smux free(value); 535156230Smux if (errno) { 536156230Smux lprintf(-1, "Parse error in \"%s\": Invalid " 537156230Smux "umask value\n", cfgfile); 538156230Smux exit(1); 539156230Smux } 540156230Smux break; 541156230Smux case PT_USE_REL_SUFFIX: 542156230Smux coll->co_options |= CO_USERELSUFFIX; 543156230Smux break; 544156230Smux case PT_DELETE: 545156230Smux coll->co_options |= CO_DELETE | CO_EXACTRCS; 546156230Smux break; 547156230Smux case PT_COMPRESS: 548156230Smux coll->co_options |= CO_COMPRESS; 549156230Smux break; 550156230Smux } 551156230Smux} 552156230Smux 553156230Smux/* Set "coll" as being the default collection. */ 554156230Smuxvoid 555156230Smuxcoll_setdef(void) 556156230Smux{ 557156230Smux 558156230Smux coll_free(defaults); 559156230Smux defaults = cur_coll; 560156230Smux cur_coll = coll_new(defaults); 561156230Smux} 562