[BACK]Return to entries.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / cvs

Annotation of src/usr.bin/cvs/entries.c, Revision 1.2

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*
1.2     ! jfb        53: cvs_ent_open(const char *dir, int flags)
1.1       jfb        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: }