1*4dcde513Sjoris /* $OpenBSD: edit.c,v 1.53 2017/06/01 08:08:24 joris Exp $ */
25a31a4e8Sxsa /*
34aab05f0Sxsa * Copyright (c) 2006, 2007 Xavier Santolaria <xsa@openbsd.org>
45a31a4e8Sxsa *
55a31a4e8Sxsa * Permission to use, copy, modify, and distribute this software for any
65a31a4e8Sxsa * purpose with or without fee is hereby granted, provided that the above
75a31a4e8Sxsa * copyright notice and this permission notice appear in all copies.
85a31a4e8Sxsa *
95a31a4e8Sxsa * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
105a31a4e8Sxsa * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
115a31a4e8Sxsa * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
125a31a4e8Sxsa * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
135a31a4e8Sxsa * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
145a31a4e8Sxsa * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
155a31a4e8Sxsa * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
165a31a4e8Sxsa */
175a31a4e8Sxsa
181f8531bdSotto #include <sys/stat.h>
191f8531bdSotto
201f8531bdSotto #include <errno.h>
21397ddb8aSnicm #include <stdlib.h>
221f8531bdSotto #include <string.h>
236534056aStobias #include <time.h>
241f8531bdSotto #include <unistd.h>
255a31a4e8Sxsa
265a31a4e8Sxsa #include "cvs.h"
275a31a4e8Sxsa #include "remote.h"
285a31a4e8Sxsa
2933c4ed80Sxsa #define E_COMMIT 0x01
3033c4ed80Sxsa #define E_EDIT 0x02
3133c4ed80Sxsa #define E_UNEDIT 0x04
3233c4ed80Sxsa #define E_ALL (E_EDIT|E_COMMIT|E_UNEDIT)
3333c4ed80Sxsa
34de08069bSxsa #define BASE_ADD 0x01
35de08069bSxsa #define BASE_GET 0x02
36de08069bSxsa #define BASE_REMOVE 0x04
37de08069bSxsa
3833c4ed80Sxsa static void cvs_edit_local(struct cvs_file *);
395a31a4e8Sxsa static void cvs_editors_local(struct cvs_file *);
404aab05f0Sxsa static void cvs_unedit_local(struct cvs_file *);
415a31a4e8Sxsa
42de08069bSxsa static RCSNUM *cvs_base_handle(struct cvs_file *, int);
43de08069bSxsa
4433c4ed80Sxsa static int edit_aflags = 0;
4533c4ed80Sxsa
4633c4ed80Sxsa struct cvs_cmd cvs_cmd_edit = {
47f331ff59Stobias CVS_OP_EDIT, CVS_USE_WDIR, "edit",
487eeb4908Sragge { { 0 }, { 0 } },
4933c4ed80Sxsa "Get ready to edit a watched file",
5033c4ed80Sxsa "[-lR] [-a action] [file ...]",
5133c4ed80Sxsa "a:lR",
5233c4ed80Sxsa NULL,
5333c4ed80Sxsa cvs_edit
5433c4ed80Sxsa };
5533c4ed80Sxsa
565a31a4e8Sxsa struct cvs_cmd cvs_cmd_editors = {
57f331ff59Stobias CVS_OP_EDITORS, CVS_USE_WDIR, "editors",
587eeb4908Sragge { { 0 }, { 0 } },
595a31a4e8Sxsa "See who is editing a watched file",
605a31a4e8Sxsa "[-lR] [file ...]",
615a31a4e8Sxsa "lR",
625a31a4e8Sxsa NULL,
635a31a4e8Sxsa cvs_editors
645a31a4e8Sxsa };
655a31a4e8Sxsa
664aab05f0Sxsa struct cvs_cmd cvs_cmd_unedit = {
67f331ff59Stobias CVS_OP_UNEDIT, CVS_USE_WDIR, "unedit",
687eeb4908Sragge { { 0 }, { 0 } },
694aab05f0Sxsa "Undo an edit command",
704aab05f0Sxsa "[-lR] [file ...]",
714aab05f0Sxsa "lR",
724aab05f0Sxsa NULL,
734aab05f0Sxsa cvs_unedit
744aab05f0Sxsa };
754aab05f0Sxsa
765a31a4e8Sxsa int
cvs_edit(int argc,char ** argv)7733c4ed80Sxsa cvs_edit(int argc, char **argv)
7833c4ed80Sxsa {
7933c4ed80Sxsa int ch;
8033c4ed80Sxsa int flags;
8133c4ed80Sxsa struct cvs_recursion cr;
8233c4ed80Sxsa
8333c4ed80Sxsa flags = CR_RECURSE_DIRS;
8433c4ed80Sxsa
8533c4ed80Sxsa while ((ch = getopt(argc, argv, cvs_cmd_edit.cmd_opts)) != -1) {
8633c4ed80Sxsa switch (ch) {
8733c4ed80Sxsa case 'a':
8833c4ed80Sxsa if (strcmp(optarg, "edit") == 0)
8933c4ed80Sxsa edit_aflags |= E_EDIT;
9033c4ed80Sxsa else if (strcmp(optarg, "unedit") == 0)
9133c4ed80Sxsa edit_aflags |= E_UNEDIT;
9233c4ed80Sxsa else if (strcmp(optarg, "commit") == 0)
9333c4ed80Sxsa edit_aflags |= E_COMMIT;
9433c4ed80Sxsa else if (strcmp(optarg, "all") == 0)
9533c4ed80Sxsa edit_aflags |= E_ALL;
9633c4ed80Sxsa else if (strcmp(optarg, "none") == 0)
9733c4ed80Sxsa edit_aflags &= ~E_ALL;
9833c4ed80Sxsa else
9933c4ed80Sxsa fatal("%s", cvs_cmd_edit.cmd_synopsis);
10033c4ed80Sxsa break;
10133c4ed80Sxsa case 'l':
10233c4ed80Sxsa flags &= ~CR_RECURSE_DIRS;
10333c4ed80Sxsa break;
10433c4ed80Sxsa case 'R':
105bcf22459Stobias flags |= CR_RECURSE_DIRS;
10633c4ed80Sxsa break;
10733c4ed80Sxsa default:
10833c4ed80Sxsa fatal("%s", cvs_cmd_edit.cmd_synopsis);
10933c4ed80Sxsa }
11033c4ed80Sxsa }
11133c4ed80Sxsa
11233c4ed80Sxsa argc -= optind;
11333c4ed80Sxsa argv += optind;
11433c4ed80Sxsa
11533c4ed80Sxsa if (argc == 0)
11633c4ed80Sxsa fatal("%s", cvs_cmd_edit.cmd_synopsis);
11733c4ed80Sxsa
11833c4ed80Sxsa if (edit_aflags == 0)
11933c4ed80Sxsa edit_aflags |= E_ALL;
12033c4ed80Sxsa
12133c4ed80Sxsa cr.enterdir = NULL;
12233c4ed80Sxsa cr.leavedir = NULL;
12333c4ed80Sxsa
124*4dcde513Sjoris if (cvsroot_is_remote()) {
12580f6ca9bSjoris cvs_client_connect_to_server();
12633c4ed80Sxsa cr.fileproc = cvs_client_sendfile;
12733c4ed80Sxsa
12833c4ed80Sxsa if (!(flags & CR_RECURSE_DIRS))
12933c4ed80Sxsa cvs_client_send_request("Argument -l");
13033c4ed80Sxsa } else {
13133c4ed80Sxsa cr.fileproc = cvs_edit_local;
13233c4ed80Sxsa }
13333c4ed80Sxsa
13433c4ed80Sxsa cr.flags = flags;
13533c4ed80Sxsa
13633c4ed80Sxsa cvs_file_run(argc, argv, &cr);
13733c4ed80Sxsa
138*4dcde513Sjoris if (cvsroot_is_remote()) {
13933c4ed80Sxsa cvs_client_send_files(argv, argc);
14033c4ed80Sxsa cvs_client_senddir(".");
14133c4ed80Sxsa cvs_client_send_request("edit");
14233c4ed80Sxsa cvs_client_get_responses();
14333c4ed80Sxsa }
14433c4ed80Sxsa
14533c4ed80Sxsa return (0);
14633c4ed80Sxsa }
14733c4ed80Sxsa
14833c4ed80Sxsa int
cvs_editors(int argc,char ** argv)1495a31a4e8Sxsa cvs_editors(int argc, char **argv)
1505a31a4e8Sxsa {
1515a31a4e8Sxsa int ch;
1525a31a4e8Sxsa int flags;
1535a31a4e8Sxsa struct cvs_recursion cr;
1545a31a4e8Sxsa
1555a31a4e8Sxsa flags = CR_RECURSE_DIRS;
1565a31a4e8Sxsa
1575a31a4e8Sxsa while ((ch = getopt(argc, argv, cvs_cmd_editors.cmd_opts)) != -1) {
1585a31a4e8Sxsa switch (ch) {
1595a31a4e8Sxsa case 'l':
1605a31a4e8Sxsa flags &= ~CR_RECURSE_DIRS;
1615a31a4e8Sxsa break;
1625a31a4e8Sxsa case 'R':
163bcf22459Stobias flags |= CR_RECURSE_DIRS;
1645a31a4e8Sxsa break;
1655a31a4e8Sxsa default:
1665a31a4e8Sxsa fatal("%s", cvs_cmd_editors.cmd_synopsis);
1675a31a4e8Sxsa }
1685a31a4e8Sxsa }
1695a31a4e8Sxsa
1705a31a4e8Sxsa argc -= optind;
1715a31a4e8Sxsa argv += optind;
1725a31a4e8Sxsa
1735a31a4e8Sxsa if (argc == 0)
1745a31a4e8Sxsa fatal("%s", cvs_cmd_editors.cmd_synopsis);
1755a31a4e8Sxsa
1765a31a4e8Sxsa cr.enterdir = NULL;
1775a31a4e8Sxsa cr.leavedir = NULL;
1785a31a4e8Sxsa
179*4dcde513Sjoris if (cvsroot_is_remote()) {
18080f6ca9bSjoris cvs_client_connect_to_server();
1815a31a4e8Sxsa cr.fileproc = cvs_client_sendfile;
1825a31a4e8Sxsa
1835a31a4e8Sxsa if (!(flags & CR_RECURSE_DIRS))
1845a31a4e8Sxsa cvs_client_send_request("Argument -l");
1855a31a4e8Sxsa } else {
1865a31a4e8Sxsa cr.fileproc = cvs_editors_local;
1875a31a4e8Sxsa }
1885a31a4e8Sxsa
1895a31a4e8Sxsa cr.flags = flags;
1905a31a4e8Sxsa
1915a31a4e8Sxsa cvs_file_run(argc, argv, &cr);
1925a31a4e8Sxsa
193*4dcde513Sjoris if (cvsroot_is_remote()) {
1945a31a4e8Sxsa cvs_client_send_files(argv, argc);
1955a31a4e8Sxsa cvs_client_senddir(".");
1965a31a4e8Sxsa cvs_client_send_request("editors");
1975a31a4e8Sxsa cvs_client_get_responses();
1985a31a4e8Sxsa }
1995a31a4e8Sxsa
2005a31a4e8Sxsa return (0);
2015a31a4e8Sxsa }
2025a31a4e8Sxsa
2034aab05f0Sxsa int
cvs_unedit(int argc,char ** argv)2044aab05f0Sxsa cvs_unedit(int argc, char **argv)
2054aab05f0Sxsa {
2064aab05f0Sxsa int ch;
2074aab05f0Sxsa int flags;
2084aab05f0Sxsa struct cvs_recursion cr;
2094aab05f0Sxsa
2104aab05f0Sxsa flags = CR_RECURSE_DIRS;
2114aab05f0Sxsa
2124aab05f0Sxsa while ((ch = getopt(argc, argv, cvs_cmd_unedit.cmd_opts)) != -1) {
2134aab05f0Sxsa switch (ch) {
2144aab05f0Sxsa case 'l':
2154aab05f0Sxsa flags &= ~CR_RECURSE_DIRS;
2164aab05f0Sxsa break;
2174aab05f0Sxsa case 'R':
218bcf22459Stobias flags |= CR_RECURSE_DIRS;
2194aab05f0Sxsa break;
2204aab05f0Sxsa default:
2214aab05f0Sxsa fatal("%s", cvs_cmd_unedit.cmd_synopsis);
2224aab05f0Sxsa }
2234aab05f0Sxsa }
2244aab05f0Sxsa
2254aab05f0Sxsa argc -= optind;
2264aab05f0Sxsa argv += optind;
2274aab05f0Sxsa
2284aab05f0Sxsa if (argc == 0)
2294aab05f0Sxsa fatal("%s", cvs_cmd_unedit.cmd_synopsis);
2304aab05f0Sxsa
2314aab05f0Sxsa cr.enterdir = NULL;
2324aab05f0Sxsa cr.leavedir = NULL;
2334aab05f0Sxsa
234*4dcde513Sjoris if (cvsroot_is_remote()) {
23575010b66Sxsa cvs_client_connect_to_server();
2364aab05f0Sxsa cr.fileproc = cvs_client_sendfile;
2374aab05f0Sxsa
2384aab05f0Sxsa if (!(flags & CR_RECURSE_DIRS))
2394aab05f0Sxsa cvs_client_send_request("Argument -l");
2404aab05f0Sxsa } else {
2414aab05f0Sxsa cr.fileproc = cvs_unedit_local;
2424aab05f0Sxsa }
2434aab05f0Sxsa
2444aab05f0Sxsa cr.flags = flags;
2454aab05f0Sxsa
2464aab05f0Sxsa cvs_file_run(argc, argv, &cr);
2474aab05f0Sxsa
248*4dcde513Sjoris if (cvsroot_is_remote()) {
2494aab05f0Sxsa cvs_client_send_files(argv, argc);
2504aab05f0Sxsa cvs_client_senddir(".");
2514aab05f0Sxsa cvs_client_send_request("unedit");
2524aab05f0Sxsa cvs_client_get_responses();
2534aab05f0Sxsa }
2544aab05f0Sxsa
2554aab05f0Sxsa return (0);
2564aab05f0Sxsa }
2574aab05f0Sxsa
2585a31a4e8Sxsa static void
cvs_edit_local(struct cvs_file * cf)25933c4ed80Sxsa cvs_edit_local(struct cvs_file *cf)
26033c4ed80Sxsa {
26133c4ed80Sxsa FILE *fp;
2626534056aStobias struct tm t;
26333c4ed80Sxsa time_t now;
264b9fc9a72Sderaadt char timebuf[CVS_TIME_BUFSZ], thishost[HOST_NAME_MAX+1];
265b9fc9a72Sderaadt char bfpath[PATH_MAX], wdir[PATH_MAX];
26633c4ed80Sxsa
26733c4ed80Sxsa if (cvs_noexec == 1)
26833c4ed80Sxsa return;
26933c4ed80Sxsa
270b7b86dcdSxsa cvs_log(LP_TRACE, "cvs_edit_local(%s)", cf->file_path);
271b7b86dcdSxsa
27251ef6581Sjoris cvs_file_classify(cf, cvs_directory_tag);
273de08069bSxsa
27433c4ed80Sxsa if ((fp = fopen(CVS_PATH_NOTIFY, "a")) == NULL)
27533c4ed80Sxsa fatal("cvs_edit_local: fopen: `%s': %s",
27633c4ed80Sxsa CVS_PATH_NOTIFY, strerror(errno));
27733c4ed80Sxsa
27833c4ed80Sxsa (void)time(&now);
2796534056aStobias gmtime_r(&now, &t);
2806534056aStobias asctime_r(&t, timebuf);
2812820b891Stobias timebuf[strcspn(timebuf, "\n")] = '\0';
28233c4ed80Sxsa
28302b07ef5Sxsa if (gethostname(thishost, sizeof(thishost)) == -1)
28402b07ef5Sxsa fatal("gethostname failed");
28502b07ef5Sxsa
286b6798006Sxsa if (getcwd(wdir, sizeof(wdir)) == NULL)
287b6798006Sxsa fatal("getcwd failed");
288b6798006Sxsa
28957e637ffSxsa (void)fprintf(fp, "E%s\t%s GMT\t%s\t%s\t",
290b6798006Sxsa cf->file_name, timebuf, thishost, wdir);
29133c4ed80Sxsa
29233c4ed80Sxsa if (edit_aflags & E_EDIT)
29333c4ed80Sxsa (void)fprintf(fp, "E");
29433c4ed80Sxsa if (edit_aflags & E_UNEDIT)
29533c4ed80Sxsa (void)fprintf(fp, "U");
29633c4ed80Sxsa if (edit_aflags & E_COMMIT)
29733c4ed80Sxsa (void)fprintf(fp, "C");
29833c4ed80Sxsa
29933c4ed80Sxsa (void)fprintf(fp, "\n");
30033c4ed80Sxsa
30133c4ed80Sxsa (void)fclose(fp);
30233c4ed80Sxsa
30333c4ed80Sxsa if (fchmod(cf->fd, 0644) == -1)
30433c4ed80Sxsa fatal("cvs_edit_local: fchmod %s", strerror(errno));
30533c4ed80Sxsa
306b9fc9a72Sderaadt (void)xsnprintf(bfpath, PATH_MAX, "%s/%s",
307e40de241Sxsa CVS_PATH_BASEDIR, cf->file_name);
30833c4ed80Sxsa
309158dfd40Sxsa if (mkdir(CVS_PATH_BASEDIR, 0755) == -1 && errno != EEXIST)
310158dfd40Sxsa fatal("cvs_edit_local: `%s': %s", CVS_PATH_BASEDIR,
311158dfd40Sxsa strerror(errno));
312158dfd40Sxsa
3130b10fb85Sxsa if (cvs_file_copy(cf->file_path, bfpath) == -1)
3140b10fb85Sxsa fatal("cvs_edit_local: cvs_file_copy failed");
31533c4ed80Sxsa
316de08069bSxsa (void)cvs_base_handle(cf, BASE_ADD);
31733c4ed80Sxsa }
31833c4ed80Sxsa
31933c4ed80Sxsa static void
cvs_editors_local(struct cvs_file * cf)3205a31a4e8Sxsa cvs_editors_local(struct cvs_file *cf)
3215a31a4e8Sxsa {
3225a31a4e8Sxsa }
3234aab05f0Sxsa
3244aab05f0Sxsa static void
cvs_unedit_local(struct cvs_file * cf)3254aab05f0Sxsa cvs_unedit_local(struct cvs_file *cf)
3264aab05f0Sxsa {
3274aab05f0Sxsa FILE *fp;
3284aab05f0Sxsa struct stat st;
3296534056aStobias struct tm t;
3304aab05f0Sxsa time_t now;
331b9fc9a72Sderaadt char bfpath[PATH_MAX], timebuf[64], thishost[HOST_NAME_MAX+1];
332b9fc9a72Sderaadt char wdir[PATH_MAX], sticky[CVS_ENT_MAXLINELEN];
333b7b86dcdSxsa RCSNUM *ba_rev;
3344aab05f0Sxsa
33578cab6d5Szinovik cvs_log(LP_TRACE, "cvs_unedit_local(%s)", cf->file_path);
33678cab6d5Szinovik
3374aab05f0Sxsa if (cvs_noexec == 1)
3384aab05f0Sxsa return;
3394aab05f0Sxsa
3405a1806edSjoris cvs_file_classify(cf, cvs_directory_tag);
341de08069bSxsa
342b9fc9a72Sderaadt (void)xsnprintf(bfpath, PATH_MAX, "%s/%s",
343e40de241Sxsa CVS_PATH_BASEDIR, cf->file_name);
3444aab05f0Sxsa
345ba7b4b60Sotto if (stat(bfpath, &st) == -1)
3464aab05f0Sxsa return;
3474aab05f0Sxsa
34893c88394Sxsa if (cvs_file_cmp(cf->file_path, bfpath) != 0) {
34993c88394Sxsa cvs_printf("%s has been modified; revert changes? ",
35093c88394Sxsa cf->file_name);
35193c88394Sxsa
352ba7b4b60Sotto if (cvs_yesno() == -1)
35393c88394Sxsa return;
35493c88394Sxsa }
3554aab05f0Sxsa
3564aab05f0Sxsa cvs_rename(bfpath, cf->file_path);
3574aab05f0Sxsa
3584aab05f0Sxsa if ((fp = fopen(CVS_PATH_NOTIFY, "a")) == NULL)
3594aab05f0Sxsa fatal("cvs_unedit_local: fopen: `%s': %s",
3604aab05f0Sxsa CVS_PATH_NOTIFY, strerror(errno));
3614aab05f0Sxsa
3624aab05f0Sxsa (void)time(&now);
3636534056aStobias gmtime_r(&now, &t);
3646534056aStobias asctime_r(&t, timebuf);
3652820b891Stobias timebuf[strcspn(timebuf, "\n")] = '\0';
3664aab05f0Sxsa
36702b07ef5Sxsa if (gethostname(thishost, sizeof(thishost)) == -1)
36802b07ef5Sxsa fatal("gethostname failed");
36902b07ef5Sxsa
370b6798006Sxsa if (getcwd(wdir, sizeof(wdir)) == NULL)
371b6798006Sxsa fatal("getcwd failed");
372de08069bSxsa
3734aab05f0Sxsa (void)fprintf(fp, "U%s\t%s GMT\t%s\t%s\t\n",
374b6798006Sxsa cf->file_name, timebuf, thishost, wdir);
3754aab05f0Sxsa
3764aab05f0Sxsa (void)fclose(fp);
3774aab05f0Sxsa
378b7b86dcdSxsa if ((ba_rev = cvs_base_handle(cf, BASE_GET)) == NULL) {
379b7b86dcdSxsa cvs_log(LP_ERR, "%s not mentioned in %s",
380b7b86dcdSxsa cf->file_name, CVS_PATH_BASEREV);
381b7b86dcdSxsa return;
382b7b86dcdSxsa }
383a0486c11Sxsa
384a0486c11Sxsa if (cf->file_ent != NULL) {
385a0486c11Sxsa CVSENTRIES *entlist;
386a0486c11Sxsa struct cvs_ent *ent;
3870a7da307Sxsa char *entry, rbuf[CVS_REV_BUFSZ];
388a0486c11Sxsa
389a0486c11Sxsa entlist = cvs_ent_open(cf->file_wd);
390a0486c11Sxsa
391a0486c11Sxsa if ((ent = cvs_ent_get(entlist, cf->file_name)) == NULL)
3928a8a62cbSxsa fatal("cvs_unedit_local: cvs_ent_get failed");
393a0486c11Sxsa
394a0486c11Sxsa (void)rcsnum_tostr(ba_rev, rbuf, sizeof(rbuf));
395a0486c11Sxsa
396a0486c11Sxsa memset(timebuf, 0, sizeof(timebuf));
397a0486c11Sxsa ctime_r(&cf->file_ent->ce_mtime, timebuf);
3982820b891Stobias timebuf[strcspn(timebuf, "\n")] = '\0';
399a0486c11Sxsa
400b0b4b42cStobias sticky[0] = '\0';
401b0b4b42cStobias if (cf->file_ent->ce_tag != NULL)
402b0b4b42cStobias (void)xsnprintf(sticky, sizeof(sticky), "T%s",
403b0b4b42cStobias cf->file_ent->ce_tag);
404b0b4b42cStobias
405a0486c11Sxsa (void)xasprintf(&entry, "/%s/%s/%s/%s/%s",
4067eeb4908Sragge cf->file_name, rbuf, timebuf, cf->file_ent->ce_opts ?
4077eeb4908Sragge cf->file_ent->ce_opts : "", sticky);
408a0486c11Sxsa
409a0486c11Sxsa cvs_ent_add(entlist, entry);
410a0486c11Sxsa
411a0486c11Sxsa cvs_ent_free(ent);
412a0486c11Sxsa
413397ddb8aSnicm free(entry);
414b7b86dcdSxsa }
415b7b86dcdSxsa
41653ce2177Sfcambus free(ba_rev);
417a0486c11Sxsa
418b7b86dcdSxsa (void)cvs_base_handle(cf, BASE_REMOVE);
4192b484273Sxsa
4202b484273Sxsa if (fchmod(cf->fd, 0644) == -1)
4212b484273Sxsa fatal("cvs_unedit_local: fchmod %s", strerror(errno));
4224aab05f0Sxsa }
423de08069bSxsa
424de08069bSxsa static RCSNUM *
cvs_base_handle(struct cvs_file * cf,int flags)425de08069bSxsa cvs_base_handle(struct cvs_file *cf, int flags)
426de08069bSxsa {
427de08069bSxsa FILE *fp, *tfp;
428de08069bSxsa RCSNUM *ba_rev;
429b7b86dcdSxsa int i;
430b7b86dcdSxsa char *dp, *sp;
431b9fc9a72Sderaadt char buf[PATH_MAX], *fields[2], rbuf[CVS_REV_BUFSZ];
432de08069bSxsa
433de08069bSxsa cvs_log(LP_TRACE, "cvs_base_handle(%s)", cf->file_path);
434de08069bSxsa
435de08069bSxsa tfp = NULL;
436de08069bSxsa ba_rev = NULL;
437de08069bSxsa
438b7b86dcdSxsa if (((fp = fopen(CVS_PATH_BASEREV, "r")) == NULL) && errno != ENOENT) {
439de08069bSxsa cvs_log(LP_ERRNO, "%s", CVS_PATH_BASEREV);
440de08069bSxsa goto out;
441de08069bSxsa }
442de08069bSxsa
443de08069bSxsa if (flags & (BASE_ADD|BASE_REMOVE)) {
444de08069bSxsa if ((tfp = fopen(CVS_PATH_BASEREVTMP, "w")) == NULL) {
445de08069bSxsa cvs_log(LP_ERRNO, "%s", CVS_PATH_BASEREVTMP);
446de08069bSxsa goto out;
447de08069bSxsa }
448de08069bSxsa }
449de08069bSxsa
450b7b86dcdSxsa if (fp != NULL) {
451de08069bSxsa while (fgets(buf, sizeof(buf), fp)) {
452b625fa02Sgilles buf[strcspn(buf, "\n")] = '\0';
453de08069bSxsa
454de08069bSxsa if (buf[0] != 'B')
455de08069bSxsa continue;
456de08069bSxsa
457b7b86dcdSxsa sp = buf + 1;
458b7b86dcdSxsa i = 0;
459b7b86dcdSxsa do {
460b7b86dcdSxsa if ((dp = strchr(sp, '/')) != NULL)
461b7b86dcdSxsa *(dp++) = '\0';
462b7b86dcdSxsa fields[i++] = sp;
463b7b86dcdSxsa sp = dp;
464b7b86dcdSxsa } while (dp != NULL && i < 2);
465de08069bSxsa
466b7b86dcdSxsa if (cvs_file_cmpname(fields[0], cf->file_path) == 0) {
467de08069bSxsa if (flags & BASE_GET) {
468b7b86dcdSxsa ba_rev = rcsnum_parse(fields[1]);
469b7b86dcdSxsa if (ba_rev == NULL)
470b7b86dcdSxsa fatal("cvs_base_handle: "
471b7b86dcdSxsa "rcsnum_parse");
472de08069bSxsa goto got_rev;
473de08069bSxsa }
474de08069bSxsa } else {
475de08069bSxsa if (flags & (BASE_ADD|BASE_REMOVE))
476de08069bSxsa (void)fprintf(tfp, "%s\n", buf);
477de08069bSxsa }
478de08069bSxsa }
479b7b86dcdSxsa }
480de08069bSxsa
481de08069bSxsa got_rev:
482de08069bSxsa if (flags & (BASE_ADD)) {
483de08069bSxsa (void)rcsnum_tostr(cf->file_ent->ce_rev, rbuf, sizeof(rbuf));
484de08069bSxsa (void)fprintf(tfp, "B%s/%s/\n", cf->file_path, rbuf);
485de08069bSxsa }
486de08069bSxsa
487de08069bSxsa out:
488de08069bSxsa if (fp != NULL)
489de08069bSxsa (void)fclose(fp);
490de08069bSxsa
491de08069bSxsa if (tfp != NULL) {
492de08069bSxsa (void)fclose(tfp);
493de08069bSxsa (void)cvs_rename(CVS_PATH_BASEREVTMP, CVS_PATH_BASEREV);
494de08069bSxsa }
495de08069bSxsa
496de08069bSxsa return (ba_rev);
497de08069bSxsa }
498