Annotation of src/usr.bin/cvs/entries.c, Revision 1.1
1.1 ! jfb 1: /* $OpenBSD$ */
! 2: /*
! 3: * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
! 4: * All rights reserved.
! 5: *
! 6: * Redistribution and use in source and binary forms, with or without
! 7: * modification, are permitted provided that the following conditions
! 8: * are met:
! 9: *
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. The name of the author may not be used to endorse or promote products
! 13: * derived from this software without specific prior written permission.
! 14: *
! 15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
! 16: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
! 17: * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
! 18: * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
! 19: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
! 20: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
! 21: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
! 22: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
! 23: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
! 24: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 25: */
! 26:
! 27: #include <sys/param.h>
! 28: #include <sys/stat.h>
! 29:
! 30: #include <stdio.h>
! 31: #include <fcntl.h>
! 32: #include <stdlib.h>
! 33: #include <unistd.h>
! 34: #include <string.h>
! 35:
! 36: #include "log.h"
! 37: #include "cvs.h"
! 38:
! 39:
! 40: #define CVS_ENTRIES_NFIELDS 5
! 41: #define CVS_ENTRIES_DELIM '/'
! 42:
! 43:
! 44: /*
! 45: * cvs_ent_open()
! 46: *
! 47: * Open the CVS Entries file for the directory <dir>.
! 48: * Returns a pointer to the CVSENTRIES file structure on success, or NULL
! 49: * on failure.
! 50: */
! 51:
! 52: CVSENTRIES*
! 53: cvs_ent_open(const char *dir)
! 54: {
! 55: size_t len;
! 56: char entpath[MAXPATHLEN], ebuf[128];
! 57: FILE *fp;
! 58: struct cvs_ent *ent;
! 59: CVSENTRIES *ep;
! 60:
! 61: snprintf(entpath, sizeof(entpath), "%s/" CVS_PATH_ENTRIES, dir);
! 62: fp = fopen(entpath, "r");
! 63: if (fp == NULL) {
! 64: cvs_log(LP_ERRNO, "cannot open CVS/Entries for reading",
! 65: entpath);
! 66: return (NULL);
! 67: }
! 68:
! 69: ep = (CVSENTRIES *)malloc(sizeof(CVSENTRIES));
! 70: if (ep == NULL) {
! 71: cvs_log(LP_ERRNO, "failed to allocate Entries data");
! 72: (void)fclose(fp);
! 73: return (NULL);
! 74: }
! 75: ep->cef_path = strdup(dir);
! 76: if (ep->cef_path == NULL) {
! 77: cvs_log(LP_ERRNO, "failed to copy Entries path");
! 78: free(ep);
! 79: (void)fclose(fp);
! 80: return (NULL);
! 81: }
! 82:
! 83: ep->cef_nid = 0;
! 84: ep->cef_entries = NULL;
! 85: ep->cef_nbent = 0;
! 86:
! 87: while (fgets(ebuf, sizeof(ebuf), fp) != NULL) {
! 88: len = strlen(ebuf);
! 89: if ((len > 0) && (ebuf[len - 1] == '\n'))
! 90: ebuf[--len] = '\0';
! 91: ent = cvs_ent_parse(ebuf);
! 92: if (ent == NULL)
! 93: continue;
! 94:
! 95: if (cvs_ent_add(ep, ent) < 0) {
! 96: cvs_ent_close(ep);
! 97: ep = NULL;
! 98: break;
! 99: }
! 100: }
! 101:
! 102: (void)fclose(fp);
! 103: return (ep);
! 104: }
! 105:
! 106:
! 107: /*
! 108: * cvs_ent_close()
! 109: *
! 110: * Close the Entries file <ep>.
! 111: */
! 112:
! 113: void
! 114: cvs_ent_close(CVSENTRIES *ep)
! 115: {
! 116: free(ep);
! 117: }
! 118:
! 119:
! 120: /*
! 121: * cvs_ent_add()
! 122: *
! 123: * Add the entry <ent>
! 124: */
! 125:
! 126: int
! 127: cvs_ent_add(CVSENTRIES *ef, struct cvs_ent *ent)
! 128: {
! 129: void *tmp;
! 130: struct cvs_ent *entp;
! 131:
! 132: if (cvs_ent_get(ef, ent->ce_name) != NULL)
! 133: return (-1);
! 134:
! 135: entp = cvs_ent_parse(ent->ce_line);
! 136: if (entp == NULL) {
! 137: return (-1);
! 138: }
! 139:
! 140: tmp = realloc(ef->cef_entries, (ef->cef_nbent + 1) * sizeof(entp));
! 141: if (tmp == NULL) {
! 142: cvs_log(LP_ERRNO, "failed to resize entries buffer");
! 143: return (-1);
! 144: }
! 145:
! 146: ef->cef_entries = (struct cvs_ent **)tmp;
! 147: ef->cef_entries[ef->cef_nbent++] = entp;
! 148:
! 149: return (0);
! 150: }
! 151:
! 152:
! 153: /*
! 154: * cvs_ent_get()
! 155: *
! 156: * Get the CVS entry from the Entries file <ef> whose 'name' portion matches
! 157: * <file>.
! 158: * Returns a pointer to the cvs entry structure on success, or NULL on failure.
! 159: */
! 160:
! 161: struct cvs_ent*
! 162: cvs_ent_get(CVSENTRIES *ef, const char *file)
! 163: {
! 164: u_int i;
! 165:
! 166: for (i = 0; i < ef->cef_nbent; i++) {
! 167: if (strcmp(ef->cef_entries[i]->ce_name, file) == 0)
! 168: return ef->cef_entries[i];
! 169: }
! 170:
! 171: return (NULL);
! 172: }
! 173:
! 174:
! 175: /*
! 176: * cvs_ent_next()
! 177: *
! 178: * Returns a pointer to the cvs entry structure on success, or NULL on failure.
! 179: */
! 180:
! 181: struct cvs_ent*
! 182: cvs_ent_next(CVSENTRIES *ef)
! 183: {
! 184: if (ef->cef_nid >= ef->cef_nbent)
! 185: return (NULL);
! 186:
! 187: return (ef->cef_entries[ef->cef_nid++]);
! 188: }
! 189:
! 190:
! 191: /*
! 192: * cvs_ent_parse()
! 193: *
! 194: * Parse a single line from a CVS/Entries file and return a cvs_entry structure
! 195: * containing all the parsed information.
! 196: */
! 197:
! 198: struct cvs_ent*
! 199: cvs_ent_parse(const char *entry)
! 200: {
! 201: int i;
! 202: char *fields[CVS_ENTRIES_NFIELDS], *sp, *dp;
! 203: struct cvs_ent *entp;
! 204:
! 205: entp = (struct cvs_ent *)malloc(sizeof(*entp));
! 206: if (entp == NULL) {
! 207: cvs_log(LP_ERRNO, "failed to allocate CVS entry");
! 208: return (NULL);
! 209: }
! 210:
! 211: entp->ce_rev = rcsnum_alloc();
! 212: if (entp->ce_rev == NULL) {
! 213: free(entp);
! 214: return (NULL);
! 215: }
! 216:
! 217: entp->ce_line = strdup(entry);
! 218: if (entp->ce_line == NULL) {
! 219: free(entp);
! 220: return (NULL);
! 221: }
! 222:
! 223: entp->ce_buf = strdup(entry);
! 224: if (entp->ce_buf == NULL) {
! 225: free(entp->ce_line);
! 226: free(entp);
! 227: return (NULL);
! 228: }
! 229: sp = entp->ce_buf;
! 230:
! 231: if (*sp == CVS_ENTRIES_DELIM)
! 232: entp->ce_type = CVS_ENT_FILE;
! 233: else if (*sp == 'D') {
! 234: entp->ce_type = CVS_ENT_DIR;
! 235: sp++;
! 236: }
! 237: else {
! 238: /* unknown entry, ignore for future expansion */
! 239: entp->ce_type = CVS_ENT_NONE;
! 240: sp++;
! 241: }
! 242:
! 243: sp++;
! 244: i = 0;
! 245: do {
! 246: dp = strchr(sp, CVS_ENTRIES_DELIM);
! 247: if (dp != NULL)
! 248: *(dp++) = '\0';
! 249: fields[i++] = sp;
! 250: sp = dp;
! 251: } while ((dp != NULL) && (i < CVS_ENTRIES_NFIELDS));
! 252:
! 253: entp->ce_name = fields[0];
! 254:
! 255: if (entp->ce_type == CVS_ENT_FILE) {
! 256: rcsnum_aton(fields[1], NULL, entp->ce_rev);
! 257: entp->ce_timestamp = fields[2];
! 258: entp->ce_opts = fields[3];
! 259: entp->ce_tag = fields[4];
! 260: }
! 261:
! 262: return (entp);
! 263: }