=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/cvs/file.c,v retrieving revision 1.13 retrieving revision 1.14 diff -c -r1.13 -r1.14 *** src/usr.bin/cvs/file.c 2004/07/30 11:50:33 1.13 --- src/usr.bin/cvs/file.c 2004/07/30 17:39:27 1.14 *************** *** 1,4 **** ! /* $OpenBSD: file.c,v 1.13 2004/07/30 11:50:33 jfb Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau * All rights reserved. --- 1,4 ---- ! /* $OpenBSD: file.c,v 1.14 2004/07/30 17:39:27 jfb Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau * All rights reserved. *************** *** 40,55 **** #include "cvs.h" #include "log.h" #define CVS_IGN_STATIC 0x01 /* pattern is static, no need to glob */ - - #define CVS_CHAR_ISMETA(c) ((c == '*') || (c == '?') || (c == '[')) - /* ignore pattern */ struct cvs_ignpat { char ip_pat[MAXNAMLEN]; --- 40,53 ---- #include "cvs.h" #include "log.h" + #include "file.h" #define CVS_IGN_STATIC 0x01 /* pattern is static, no need to glob */ #define CVS_CHAR_ISMETA(c) ((c == '*') || (c == '?') || (c == '[')) /* ignore pattern */ struct cvs_ignpat { char ip_pat[MAXNAMLEN]; *************** *** 97,107 **** TAILQ_HEAD(, cvs_ignpat) cvs_ign_pats; ! static int cvs_file_getdir (struct cvs_file *, int); static void cvs_file_freedir (struct cvs_dir *); static int cvs_file_sort (struct cvs_flist *); static int cvs_file_cmp (const void *, const void *); static CVSFILE* cvs_file_alloc (const char *, u_int); --- 95,106 ---- TAILQ_HEAD(, cvs_ignpat) cvs_ign_pats; ! static int cvs_file_getdir (CVSFILE *, int); static void cvs_file_freedir (struct cvs_dir *); static int cvs_file_sort (struct cvs_flist *); static int cvs_file_cmp (const void *, const void *); static CVSFILE* cvs_file_alloc (const char *, u_int); + static CVSFILE* cvs_file_lget (const char *, int, CVSFILE *); *************** *** 272,361 **** * with cvs_file_free(). */ ! struct cvs_file* cvs_file_get(const char *path, int flags) { ! int cwd; ! size_t len; ! char buf[32]; ! struct stat st; ! struct tm lmtm; ! struct cvs_file *cfp; ! struct cvs_ent *ent; ! ! if (strcmp(path, ".") == 0) ! cwd = 1; ! else ! cwd = 0; ! ! if (stat(path, &st) == -1) { ! cvs_log(LP_ERRNO, "failed to stat %s", path); ! return (NULL); ! } ! ! cfp = cvs_file_alloc(path, IFTODT(st.st_mode)); ! if (cfp == NULL) { ! cvs_log(LP_ERRNO, "failed to allocate CVS file data"); ! return (NULL); ! } ! ! ent = cvs_ent_getent(path); ! if (ent == NULL) ! cfp->cf_cvstat = (cwd == 1) ? ! CVS_FST_UPTODATE : CVS_FST_UNKNOWN; ! else { ! /* always show directories as up-to-date */ ! if (ent->ce_type == CVS_ENT_DIR) ! cfp->cf_cvstat = CVS_FST_UPTODATE; ! else if (rcsnum_cmp(ent->ce_rev, cvs_addedrev, 2) == 0) ! cfp->cf_cvstat = CVS_FST_ADDED; ! else { ! /* check last modified time */ ! if ((gmtime_r((time_t *)&(st.st_mtime), &lmtm) == NULL) || ! (asctime_r(&lmtm, buf) == NULL)) { ! cvs_log(LP_ERR, ! "failed to generate file timestamp"); ! /* fake an up to date file */ ! strlcpy(buf, ent->ce_timestamp, sizeof(buf)); ! } ! len = strlen(buf); ! if ((len > 0) && (buf[len - 1] == '\n')) ! buf[--len] = '\0'; ! ! if (strcmp(buf, ent->ce_timestamp) == 0) ! cfp->cf_cvstat = CVS_FST_UPTODATE; ! else ! cfp->cf_cvstat = CVS_FST_MODIFIED; ! } ! ! cvs_ent_free(ent); ! } ! ! /* convert from stat mode to dirent values */ ! cfp->cf_type = IFTODT(st.st_mode); ! if ((cfp->cf_type == DT_DIR) && ((flags & CF_RECURSE) || cwd)) { ! if ((flags & CF_KNOWN) && (cfp->cf_cvstat == CVS_FST_UNKNOWN)) { ! free(cfp->cf_ddat); ! cfp->cf_ddat = NULL; ! } ! else if (cvs_file_getdir(cfp, flags) < 0) { ! cvs_file_free(cfp); ! return (NULL); ! } ! } ! ! if (flags & CF_STAT) { ! cfp->cf_stat = (struct stat *)malloc(sizeof(struct stat)); ! if (cfp->cf_stat == NULL) { ! cvs_log(LP_ERRNO, "failed to allocate stat structure"); ! cvs_file_free(cfp); ! return (NULL); ! } ! ! memcpy(cfp->cf_stat, &st, sizeof(struct stat)); ! } ! ! return (cfp); } --- 271,280 ---- * with cvs_file_free(). */ ! CVSFILE* cvs_file_get(const char *path, int flags) { ! return cvs_file_lget(path, flags, NULL); } *************** *** 373,379 **** { int i, c; char common[MAXPATHLEN]; ! struct cvs_file *cfp; /* first find the common subdir */ strlcpy(common, fspec[0], sizeof(common)); --- 292,298 ---- { int i, c; char common[MAXPATHLEN]; ! CVSFILE *cfp; /* first find the common subdir */ strlcpy(common, fspec[0], sizeof(common)); *************** *** 459,472 **** */ static int ! cvs_file_getdir(struct cvs_file *cf, int flags) { int ret, fd; long base; void *dp, *ep; char fbuf[2048], pbuf[MAXPATHLEN]; struct dirent *ent; ! struct cvs_file *cfp; struct cvs_dir *cdp; struct cvs_flist dirs; --- 378,391 ---- */ static int ! cvs_file_getdir(CVSFILE *cf, int flags) { int ret, fd; long base; void *dp, *ep; char fbuf[2048], pbuf[MAXPATHLEN]; struct dirent *ent; ! CVSFILE *cfp; struct cvs_dir *cdp; struct cvs_flist dirs; *************** *** 482,492 **** --- 401,417 ---- } cdp->cd_root = cvsroot_get(cf->cf_path); + printf("cvsroot = %s\n", cdp->cd_root->cr_str); if (cdp->cd_root == NULL) { cvs_file_freedir(cdp); return (-1); } + if (flags & CF_MKADMIN) + cvs_mkadmin(cf, 0755); + + cdp->cd_ent = cvs_ent_open(cf->cf_path, O_RDONLY); + fd = open(cf->cf_path, O_RDONLY); if (fd == -1) { cvs_log(LP_ERRNO, "failed to open `%s'", cf->cf_path); *************** *** 514,520 **** snprintf(pbuf, sizeof(pbuf), "%s/%s", cf->cf_path, ent->d_name); ! cfp = cvs_file_get(pbuf, flags); if (cfp != NULL) { cfp->cf_parent = cf; if (cfp->cf_type == DT_DIR) --- 439,445 ---- snprintf(pbuf, sizeof(pbuf), "%s/%s", cf->cf_path, ent->d_name); ! cfp = cvs_file_lget(pbuf, flags, cf); if (cfp != NULL) { cfp->cf_parent = cf; if (cfp->cf_type == DT_DIR) *************** *** 526,531 **** --- 451,462 ---- } } while (ret > 0); + /* we can now close our Entries file */ + if (cdp->cd_ent != NULL) { + cvs_ent_close(cdp->cd_ent); + cdp->cd_ent = NULL; + } + if (flags & CF_SORT) { cvs_file_sort(&(cdp->cd_files)); cvs_file_sort(&dirs); *************** *** 547,553 **** */ void ! cvs_file_free(struct cvs_file *cf) { if (cf->cf_path != NULL) free(cf->cf_path); --- 478,484 ---- */ void ! cvs_file_free(CVSFILE *cf) { if (cf->cf_path != NULL) free(cf->cf_path); *************** *** 571,577 **** cvs_file_examine(CVSFILE *cf, int (*exam)(CVSFILE *, void *), void *arg) { int ret; ! struct cvs_file *fp; if (cf->cf_type == DT_DIR) { ret = (*exam)(cf, arg); --- 502,508 ---- cvs_file_examine(CVSFILE *cf, int (*exam)(CVSFILE *, void *), void *arg) { int ret; ! CVSFILE *fp; if (cf->cf_type == DT_DIR) { ret = (*exam)(cf, arg); *************** *** 597,609 **** static void cvs_file_freedir(struct cvs_dir *cd) { ! struct cvs_file *cfp; if (cd->cd_root != NULL) cvsroot_free(cd->cd_root); if (cd->cd_repo != NULL) free(cd->cd_repo); while (!TAILQ_EMPTY(&(cd->cd_files))) { cfp = TAILQ_FIRST(&(cd->cd_files)); TAILQ_REMOVE(&(cd->cd_files), cfp, cf_list); --- 528,543 ---- static void cvs_file_freedir(struct cvs_dir *cd) { ! CVSFILE *cfp; if (cd->cd_root != NULL) cvsroot_free(cd->cd_root); if (cd->cd_repo != NULL) free(cd->cd_repo); + if (cd->cd_ent != NULL) + cvs_ent_close(cd->cd_ent); + while (!TAILQ_EMPTY(&(cd->cd_files))) { cfp = TAILQ_FIRST(&(cd->cd_files)); TAILQ_REMOVE(&(cd->cd_files), cfp, cf_list); *************** *** 623,634 **** { int i; size_t nb; ! struct cvs_file *cf, *cfvec[256]; i = 0; TAILQ_FOREACH(cf, flp, cf_list) { cfvec[i++] = cf; ! if (i == sizeof(cfvec)/sizeof(struct cvs_file *)) { cvs_log(LP_WARN, "too many files to sort"); return (-1); } --- 557,568 ---- { int i; size_t nb; ! CVSFILE *cf, *cfvec[256]; i = 0; TAILQ_FOREACH(cf, flp, cf_list) { cfvec[i++] = cf; ! if (i == sizeof(cfvec)/sizeof(CVSFILE *)) { cvs_log(LP_WARN, "too many files to sort"); return (-1); } *************** *** 656,664 **** static int cvs_file_cmp(const void *f1, const void *f2) { ! struct cvs_file *cf1, *cf2; ! cf1 = *(struct cvs_file **)f1; ! cf2 = *(struct cvs_file **)f2; return strcmp(cf1->cf_name, cf2->cf_name); } --- 590,598 ---- static int cvs_file_cmp(const void *f1, const void *f2) { ! CVSFILE *cf1, *cf2; ! cf1 = *(CVSFILE **)f1; ! cf2 = *(CVSFILE **)f2; return strcmp(cf1->cf_name, cf2->cf_name); } *************** *** 671,677 **** CVSFILE *cfp; struct cvs_dir *ddat; ! cfp = (struct cvs_file *)malloc(sizeof(*cfp)); if (cfp == NULL) { cvs_log(LP_ERRNO, "failed to allocate CVS file data"); return (NULL); --- 605,611 ---- CVSFILE *cfp; struct cvs_dir *ddat; ! cfp = (CVSFILE *)malloc(sizeof(*cfp)); if (cfp == NULL) { cvs_log(LP_ERRNO, "failed to allocate CVS file data"); return (NULL); *************** *** 711,713 **** --- 645,747 ---- } return (cfp); } + + + /* + * cvs_file_lget() + * + * Get the file and link it with the parent right away. + */ + + static CVSFILE* + cvs_file_lget(const char *path, int flags, CVSFILE *parent) + { + int cwd; + size_t len; + char buf[32]; + struct stat st; + struct tm lmtm; + CVSFILE *cfp; + struct cvs_ent *ent; + + ent = NULL; + + if (strcmp(path, ".") == 0) + cwd = 1; + else + cwd = 0; + + if (stat(path, &st) == -1) { + cvs_log(LP_ERRNO, "failed to stat %s", path); + return (NULL); + } + + cfp = cvs_file_alloc(path, IFTODT(st.st_mode)); + if (cfp == NULL) { + cvs_log(LP_ERRNO, "failed to allocate CVS file data"); + return (NULL); + } + cfp->cf_parent = parent; + + if ((parent != NULL) && (CVS_DIR_ENTRIES(parent) != NULL)) { + ent = cvs_ent_get(CVS_DIR_ENTRIES(parent), path); + } + + if (ent == NULL) + cfp->cf_cvstat = (cwd == 1) ? + CVS_FST_UPTODATE : CVS_FST_UNKNOWN; + else { + /* always show directories as up-to-date */ + if (ent->ce_type == CVS_ENT_DIR) + cfp->cf_cvstat = CVS_FST_UPTODATE; + else if (rcsnum_cmp(ent->ce_rev, cvs_addedrev, 2) == 0) + cfp->cf_cvstat = CVS_FST_ADDED; + else { + /* check last modified time */ + if ((gmtime_r((time_t *)&(st.st_mtime), + &lmtm) == NULL) || + (asctime_r(&lmtm, buf) == NULL)) { + cvs_log(LP_ERR, + "failed to generate file timestamp"); + /* fake an up to date file */ + strlcpy(buf, ent->ce_timestamp, sizeof(buf)); + } + len = strlen(buf); + if ((len > 0) && (buf[len - 1] == '\n')) + buf[--len] = '\0'; + + if (strcmp(buf, ent->ce_timestamp) == 0) + cfp->cf_cvstat = CVS_FST_UPTODATE; + else + cfp->cf_cvstat = CVS_FST_MODIFIED; + } + + cvs_ent_free(ent); + } + + if ((cfp->cf_type == DT_DIR) && ((flags & CF_RECURSE) || cwd)) { + if ((flags & CF_KNOWN) && (cfp->cf_cvstat == CVS_FST_UNKNOWN)) { + free(cfp->cf_ddat); + cfp->cf_ddat = NULL; + } + else if (cvs_file_getdir(cfp, flags) < 0) { + cvs_file_free(cfp); + return (NULL); + } + } + + if (flags & CF_STAT) { + cfp->cf_stat = (struct stat *)malloc(sizeof(struct stat)); + if (cfp->cf_stat == NULL) { + cvs_log(LP_ERRNO, "failed to allocate stat structure"); + cvs_file_free(cfp); + return (NULL); + } + + memcpy(cfp->cf_stat, &st, sizeof(struct stat)); + } + + return (cfp); + } + +