version 1.7, 2004/07/27 13:12:10 |
version 1.8, 2004/07/30 17:37:13 |
|
|
size_t len; |
size_t len; |
char entpath[MAXPATHLEN], ebuf[128], mode[4]; |
char entpath[MAXPATHLEN], ebuf[128], mode[4]; |
FILE *fp; |
FILE *fp; |
|
struct stat st; |
struct cvs_ent *ent; |
struct cvs_ent *ent; |
CVSENTRIES *ep; |
CVSENTRIES *ep; |
|
|
memset(mode, 0, sizeof(mode)); |
memset(mode, 0, sizeof(mode)); |
|
|
|
snprintf(entpath, sizeof(entpath), "%s/" CVS_PATH_ENTRIES, dir); |
|
|
switch (flags & O_ACCMODE) { |
switch (flags & O_ACCMODE) { |
|
case O_WRONLY: |
case O_RDWR: |
case O_RDWR: |
|
/* we have to use append otherwise the file gets truncated */ |
|
mode[0] = 'w'; |
mode[1] = '+'; |
mode[1] = '+'; |
/* fallthrough */ |
break; |
case O_RDONLY: |
case O_RDONLY: |
mode[0] = 'r'; |
mode[0] = 'r'; |
break; |
break; |
case O_WRONLY: |
|
mode[0] = 'a'; |
|
break; |
|
} |
} |
|
|
snprintf(entpath, sizeof(entpath), "%s/" CVS_PATH_ENTRIES, dir); |
/* we can use 'r' if the file already exists */ |
|
if (stat(entpath, &st) == 0) |
|
mode[0] = 'r'; |
|
|
|
|
fp = fopen(entpath, mode); |
fp = fopen(entpath, mode); |
if (fp == NULL) { |
if (fp == NULL) { |
cvs_log(LP_ERRNO, "cannot open CVS/Entries for reading", |
cvs_log(LP_ERRNO, "cannot open %s for %s", entpath, |
entpath); |
mode[1] == '+' ? "writing" : "reading"); |
return (NULL); |
return (NULL); |
} |
} |
|
|
|
|
ep->cef_cur = NULL; |
ep->cef_cur = NULL; |
TAILQ_INIT(&(ep->cef_ent)); |
TAILQ_INIT(&(ep->cef_ent)); |
|
|
|
rewind(fp); |
|
|
while (fgets(ebuf, sizeof(ebuf), fp) != NULL) { |
while (fgets(ebuf, sizeof(ebuf), fp) != NULL) { |
len = strlen(ebuf); |
len = strlen(ebuf); |
if ((len > 0) && (ebuf[len - 1] == '\n')) |
if ((len > 0) && (ebuf[len - 1] == '\n')) |
|
|
} |
} |
|
|
/* only keep a pointer to the open file if we're in writing mode */ |
/* only keep a pointer to the open file if we're in writing mode */ |
if ((flags & O_WRONLY) || (flags & O_RDWR)) |
if ((flags & O_WRONLY) || (flags & O_RDWR)) { |
|
ep->cef_flags |= CVS_ENTF_WR; |
ep->cef_file = fp; |
ep->cef_file = fp; |
|
} |
else |
else |
(void)fclose(fp); |
(void)fclose(fp); |
|
|
|
ep->cef_flags |= CVS_ENTF_SYNC; |
return (ep); |
return (ep); |
} |
} |
|
|
|
|
{ |
{ |
struct cvs_ent *ent; |
struct cvs_ent *ent; |
|
|
|
if ((ep->cef_flags & CVS_ENTF_WR) && |
|
!(ep->cef_flags & CVS_ENTF_SYNC)) { |
|
/* implicit sync with disk */ |
|
(void)cvs_ent_write(ep); |
|
} |
|
|
if (ep->cef_file != NULL) |
if (ep->cef_file != NULL) |
(void)fclose(ep->cef_file); |
(void)fclose(ep->cef_file); |
if (ep->cef_path != NULL) |
if (ep->cef_path != NULL) |
|
|
/* |
/* |
* cvs_ent_add() |
* cvs_ent_add() |
* |
* |
* Add the entry <ent> to the Entries file <ef>. |
* Add the entry <ent> to the Entries file <ef>. The disk contents are not |
|
* modified until a call to cvs_ent_write() is performed. This is done |
|
* implicitly on a call to cvs_ent_close() on an Entries file that has been |
|
* opened for writing. |
* Returns 0 on success, or -1 on failure. |
* Returns 0 on success, or -1 on failure. |
*/ |
*/ |
|
|
int |
int |
cvs_ent_add(CVSENTRIES *ef, struct cvs_ent *ent) |
cvs_ent_add(CVSENTRIES *ef, struct cvs_ent *ent) |
{ |
{ |
void *tmp; |
|
char nbuf[64]; |
|
|
|
if (ef->cef_file == NULL) { |
if (ef->cef_file == NULL) { |
cvs_log(LP_ERR, "Entries file is opened in read-only mode"); |
cvs_log(LP_ERR, "Entries file is opened in read-only mode"); |
return (-1); |
return (-1); |
|
|
if (cvs_ent_get(ef, ent->ce_name) != NULL) |
if (cvs_ent_get(ef, ent->ce_name) != NULL) |
return (-1); |
return (-1); |
|
|
if (fseek(ef->cef_file, (long)0, SEEK_END) == -1) { |
|
cvs_log(LP_ERRNO, "failed to seek to end of CVS/Entries file"); |
|
return (-1); |
|
} |
|
rcsnum_tostr(ent->ce_rev, nbuf, sizeof(nbuf)); |
|
fprintf(ef->cef_file, "/%s/%s/%s/%s/\n", ent->ce_name, nbuf, |
|
ent->ce_timestamp, ent->ce_opts); |
|
|
|
TAILQ_INSERT_TAIL(&(ef->cef_ent), ent, ce_list); |
TAILQ_INSERT_TAIL(&(ef->cef_ent), ent, ce_list); |
|
|
|
ef->cef_flags &= ~CVS_ENTF_SYNC; |
|
|
return (0); |
return (0); |
} |
} |
|
|
|
|
int |
int |
cvs_ent_addln(CVSENTRIES *ef, const char *line) |
cvs_ent_addln(CVSENTRIES *ef, const char *line) |
{ |
{ |
void *tmp; |
|
struct cvs_ent *ent; |
struct cvs_ent *ent; |
|
|
if (ef->cef_file == NULL) { |
if (ef->cef_file == NULL) { |
|
|
return (-1); |
return (-1); |
|
|
TAILQ_INSERT_TAIL(&(ef->cef_ent), ent, ce_list); |
TAILQ_INSERT_TAIL(&(ef->cef_ent), ent, ce_list); |
|
ef->cef_flags &= ~CVS_ENTF_SYNC; |
|
|
return (0); |
return (0); |
} |
} |
|
|
|
|
struct cvs_ent* |
struct cvs_ent* |
cvs_ent_get(CVSENTRIES *ef, const char *file) |
cvs_ent_get(CVSENTRIES *ef, const char *file) |
{ |
{ |
u_int i; |
|
struct cvs_ent *ep; |
struct cvs_ent *ep; |
|
|
TAILQ_FOREACH(ep, &(ef->cef_ent), ce_list) |
TAILQ_FOREACH(ep, &(ef->cef_ent), ce_list) |
|
|
|
|
cvs_ent_close(entf); |
cvs_ent_close(entf); |
return (ep); |
return (ep); |
|
} |
|
|
|
|
|
/* |
|
* cvs_ent_write() |
|
* |
|
* Explicitly write the contents of the Entries file <ef> to disk. |
|
* Returns 0 on success, or -1 on failure. |
|
*/ |
|
|
|
int |
|
cvs_ent_write(CVSENTRIES *ef) |
|
{ |
|
char revbuf[64]; |
|
struct cvs_ent *ent; |
|
|
|
if (ef->cef_file == NULL) |
|
return (-1); |
|
|
|
if (ef->cef_flags & CVS_ENTF_SYNC) |
|
return (0); |
|
|
|
/* reposition ourself at beginning of file */ |
|
rewind(ef->cef_file); |
|
TAILQ_FOREACH(ent, &(ef->cef_ent), ce_list) { |
|
if (ent->ce_type == CVS_ENT_DIR) |
|
putc('D', ef->cef_file); |
|
|
|
rcsnum_tostr(ent->ce_rev, revbuf, sizeof(revbuf)); |
|
fprintf(ef->cef_file, "/%s/%s/%s/%s/%s\n", ent->ce_name, |
|
revbuf, ent->ce_timestamp, "", ""); |
|
} |
|
|
|
/* terminating line */ |
|
fprintf(ef->cef_file, "D\n"); |
|
|
|
ef->cef_flags |= CVS_ENTF_SYNC; |
|
|
|
return (0); |
} |
} |