This is entries.c in view mode; [Download] [Up]
/* * Copyright (c) 1992, Brian Berliner and Jeff Polk * Copyright (c) 1989-1992, Brian Berliner * * You may distribute under the terms of the GNU General Public License as * specified in the README file that comes with the CVS 1.4 kit. * * Entries file to Files file * * Creates the file Files containing the names that comprise the project, from * the Entries file. */ #include "cvs.h" #ifndef lint static const char rcsid[] = "$CVSid: @(#)entries.c 1.44 94/10/07 $"; USE(rcsid) #endif static Node *AddEntryNode PROTO((List * list, char *name, char *version, char *timestamp, char *options, char *tag, char *date, char *conflict)); static FILE *entfile; static char *entfilename; /* for error messages */ /* * Write out the line associated with a node of an entries file */ static int write_ent_proc PROTO ((Node *, void *)); static int write_ent_proc (node, closure) Node *node; void *closure; { Entnode *p; p = (Entnode *) node->data; if (fprintf (entfile, "/%s/%s/%s", node->key, p->version, p->timestamp) == EOF) error (1, errno, "cannot write %s", entfilename); if (p->conflict) { if (fprintf (entfile, "+%s", p->conflict) < 0) error (1, errno, "cannot write %s", entfilename); } if (fprintf (entfile, "/%s/", p->options) < 0) error (1, errno, "cannot write %s", entfilename); if (p->tag) { if (fprintf (entfile, "T%s\n", p->tag) < 0) error (1, errno, "cannot write %s", entfilename); } else if (p->date) { if (fprintf (entfile, "D%s\n", p->date) < 0) error (1, errno, "cannot write %s", entfilename); } else if (fprintf (entfile, "\n") < 0) error (1, errno, "cannot write %s", entfilename); return (0); } /* * write out the current entries file given a list, making a backup copy * first of course */ static void write_entries (list) List *list; { /* open the new one and walk the list writing entries */ entfilename = CVSADM_ENTBAK; entfile = open_file (entfilename, "w+"); (void) walklist (list, write_ent_proc, NULL); if (fclose (entfile) == EOF) error (1, errno, "error closing %s", entfilename); /* now, atomically (on systems that support it) rename it */ rename_file (entfilename, CVSADM_ENT); /* now, remove the log file */ unlink_file (CVSADM_ENTLOG); } /* * Removes the argument file from the Entries file if necessary. */ void Scratch_Entry (list, fname) List *list; char *fname; { Node *node; if (trace) #ifdef SERVER_SUPPORT (void) fprintf (stderr, "%c-> Scratch_Entry(%s)\n", (server_active) ? 'S' : ' ', fname); #else (void) fprintf (stderr, "-> Scratch_Entry(%s)\n", fname); #endif /* hashlookup to see if it is there */ if ((node = findnode (list, fname)) != NULL) { delnode (node); /* delete the node */ #ifdef SERVER_SUPPORT if (server_active) server_scratch (fname); #endif if (!noexec) write_entries (list); /* re-write the file */ } } /* * Enters the given file name/version/time-stamp into the Entries file, * removing the old entry first, if necessary. */ void Register (list, fname, vn, ts, options, tag, date, ts_conflict) List *list; char *fname; char *vn; char *ts; char *options; char *tag; char *date; char *ts_conflict; { Node *node; #ifdef SERVER_SUPPORT if (server_active) { server_register (fname, vn, ts, options, tag, date, ts_conflict); } #endif if (trace) { #ifdef SERVER_SUPPORT (void) fprintf (stderr, "%c-> Register(%s, %s, %s%s%s, %s, %s %s)\n", (server_active) ? 'S' : ' ', fname, vn, ts ? ts : "", ts_conflict ? "+" : "", ts_conflict ? ts_conflict : "", options, tag ? tag : "", date ? date : ""); #else (void) fprintf (stderr, "-> Register(%s, %s, %s%s%s, %s, %s %s)\n", fname, vn, ts ? ts : "", ts_conflict ? "+" : "", ts_conflict ? ts_conflict : "", options, tag ? tag : "", date ? date : ""); #endif } node = AddEntryNode (list, fname, vn, ts, options, tag, date, ts_conflict); if (!noexec) { entfile = open_file (CVSADM_ENTLOG, "a"); write_ent_proc (node, NULL); if (fclose (entfile) == EOF) error (1, errno, "error closing %s", CVSADM_ENTLOG); } } /* * Node delete procedure for list-private sticky dir tag/date info */ static void freesdt (p) Node *p; { struct stickydirtag *sdtp; sdtp = (struct stickydirtag *) p->data; if (sdtp->tag) free (sdtp->tag); if (sdtp->date) free (sdtp->date); if (sdtp->options) free (sdtp->options); free ((char *) sdtp); } struct entent { char *user; char *vn; char *ts; char *options; char *tag; char *date; char *ts_conflict; }; struct entent * fgetentent(fpin) FILE *fpin; { static struct entent ent; static char line[MAXLINELEN]; register char *cp; char *user, *vn, *ts, *options; char *tag_or_date, *tag, *date, *ts_conflict; while (fgets (line, sizeof (line), fpin) != NULL) { if (line[0] != '/') continue; user = line + 1; if ((cp = strchr (user, '/')) == NULL) continue; *cp++ = '\0'; vn = cp; if ((cp = strchr (vn, '/')) == NULL) continue; *cp++ = '\0'; ts = cp; if ((cp = strchr (ts, '/')) == NULL) continue; *cp++ = '\0'; options = cp; if ((cp = strchr (options, '/')) == NULL) continue; *cp++ = '\0'; tag_or_date = cp; if ((cp = strchr (tag_or_date, '\n')) == NULL) continue; *cp = '\0'; tag = (char *) NULL; date = (char *) NULL; if (*tag_or_date == 'T') tag = tag_or_date + 1; else if (*tag_or_date == 'D') date = tag_or_date + 1; if ((ts_conflict = strchr (ts, '+'))) *ts_conflict++ = '\0'; /* * XXX - Convert timestamp from old format to new format. * * If the timestamp doesn't match the file's current * mtime, we'd have to generate a string that doesn't * match anyways, so cheat and base it on the existing * string; it doesn't have to match the same mod time. * * For an unmodified file, write the correct timestamp. */ { struct stat sb; if (strlen (ts) > 30 && stat (user, &sb) == 0) { extern char *ctime (); char *c = ctime (&sb.st_mtime); if (!strncmp (ts + 25, c, 24)) ts = time_stamp (user); else { ts += 24; ts[0] = '*'; } } } ent.user = user; ent.vn = vn; ent.ts = ts; ent.options = options; ent.tag = tag; ent.date = date; ent.ts_conflict = ts_conflict; return &ent; } return NULL; } /* * Read the entries file into a list, hashing on the file name. */ List * Entries_Open (aflag) int aflag; { List *entries; struct entent *ent; char *dirtag, *dirdate; int do_rewrite = 0; FILE *fpin; /* get a fresh list... */ entries = getlist (); /* * Parse the CVS/Tag file, to get any default tag/date settings. Use * list-private storage to tuck them away for Version_TS(). */ ParseTag (&dirtag, &dirdate); if (aflag || dirtag || dirdate) { struct stickydirtag *sdtp; sdtp = (struct stickydirtag *) xmalloc (sizeof (*sdtp)); memset ((char *) sdtp, 0, sizeof (*sdtp)); sdtp->aflag = aflag; sdtp->tag = xstrdup (dirtag); sdtp->date = xstrdup (dirdate); /* feed it into the list-private area */ entries->list->data = (char *) sdtp; entries->list->delproc = freesdt; } fpin = fopen (CVSADM_ENT, "r"); if (fpin == NULL) error (0, errno, "cannot open %s for reading", CVSADM_ENT); else { while ((ent = fgetentent (fpin)) != NULL) { (void) AddEntryNode (entries, ent->user, ent->vn, ent->ts, ent->options, ent->tag, ent->date, ent->ts_conflict); } fclose (fpin); } fpin = fopen (CVSADM_ENTLOG, "r"); if (fpin != NULL) { while ((ent = fgetentent (fpin)) != NULL) { (void) AddEntryNode (entries, ent->user, ent->vn, ent->ts, ent->options, ent->tag, ent->date, ent->ts_conflict); } do_rewrite = 1; fclose (fpin); } if (do_rewrite && !noexec) write_entries (entries); /* clean up and return */ if (fpin) (void) fclose (fpin); if (dirtag) free (dirtag); if (dirdate) free (dirdate); return (entries); } void Entries_Close(list) List *list; { if (list) { if (!noexec) { if (isfile (CVSADM_ENTLOG)) write_entries (list); } dellist(&list); } } /* * Free up the memory associated with the data section of an ENTRIES type * node */ static void Entries_delproc (node) Node *node; { Entnode *p; p = (Entnode *) node->data; free (p->version); free (p->timestamp); free (p->options); if (p->tag) free (p->tag); if (p->date) free (p->date); if (p->conflict) free (p->conflict); free ((char *) p); } /* * Get an Entries file list node, initialize it, and add it to the specified * list */ static Node * AddEntryNode (list, name, version, timestamp, options, tag, date, conflict) List *list; char *name; char *version; char *timestamp; char *options; char *tag; char *date; char *conflict; { Node *p; Entnode *entdata; /* was it already there? */ if ((p = findnode (list, name)) != NULL) { /* take it out */ delnode (p); } /* get a node and fill in the regular stuff */ p = getnode (); p->type = ENTRIES; p->delproc = Entries_delproc; /* this one gets a key of the name for hashing */ p->key = xstrdup (name); /* malloc the data parts and fill them in */ p->data = xmalloc (sizeof (Entnode)); entdata = (Entnode *) p->data; entdata->version = xstrdup (version); entdata->timestamp = xstrdup (timestamp); if (entdata->timestamp == NULL) entdata->timestamp = xstrdup ("");/* must be non-NULL */ entdata->options = xstrdup (options); if (entdata->options == NULL) entdata->options = xstrdup ("");/* must be non-NULL */ entdata->conflict = xstrdup (conflict); entdata->tag = xstrdup (tag); entdata->date = xstrdup (date); /* put the node into the list */ addnode (list, p); return (p); } /* * Write out/Clear the CVS/Tag file. */ void WriteTag (dir, tag, date) char *dir; char *tag; char *date; { FILE *fout; char tmp[PATH_MAX]; if (noexec) return; if (dir == NULL) (void) strcpy (tmp, CVSADM_TAG); else (void) sprintf (tmp, "%s/%s", dir, CVSADM_TAG); if (tag || date) { fout = open_file (tmp, "w+"); if (tag) { if (fprintf (fout, "T%s\n", tag) < 0) error (1, errno, "write to %s failed", tmp); } else { if (fprintf (fout, "D%s\n", date) < 0) error (1, errno, "write to %s failed", tmp); } if (fclose (fout) == EOF) error (1, errno, "cannot close %s", tmp); } else if (unlink_file (tmp) < 0 && errno != ENOENT) error (1, errno, "cannot remove %s", tmp); } /* * Parse the CVS/Tag file for the current directory. */ void ParseTag (tagp, datep) char **tagp; char **datep; { FILE *fp; char line[MAXLINELEN]; char *cp; if (tagp) *tagp = (char *) NULL; if (datep) *datep = (char *) NULL; fp = fopen (CVSADM_TAG, "r"); if (fp) { if (fgets (line, sizeof (line), fp) != NULL) { if ((cp = strrchr (line, '\n')) != NULL) *cp = '\0'; if (*line == 'T' && tagp) *tagp = xstrdup (line + 1); else if (*line == 'D' && datep) *datep = xstrdup (line + 1); } (void) fclose (fp); } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.