xref: /openbsd-src/usr.bin/cvs/remove.c (revision 4dcde51379711c241d4d9b93f9d4e9eae2d51f3d)
1*4dcde513Sjoris /*	$OpenBSD: remove.c,v 1.84 2017/06/01 08:08:24 joris Exp $	*/
227a8b24eSjoris /*
327a8b24eSjoris  * Copyright (c) 2005, 2006 Xavier Santolaria <xsa@openbsd.org>
427a8b24eSjoris  *
527a8b24eSjoris  * Permission to use, copy, modify, and distribute this software for any
627a8b24eSjoris  * purpose with or without fee is hereby granted, provided that the above
727a8b24eSjoris  * copyright notice and this permission notice appear in all copies.
827a8b24eSjoris  *
927a8b24eSjoris  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1027a8b24eSjoris  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1127a8b24eSjoris  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1227a8b24eSjoris  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1327a8b24eSjoris  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1427a8b24eSjoris  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1527a8b24eSjoris  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1627a8b24eSjoris  */
1727a8b24eSjoris 
181f8531bdSotto #include <errno.h>
19397ddb8aSnicm #include <stdlib.h>
201f8531bdSotto #include <string.h>
211f8531bdSotto #include <unistd.h>
2227a8b24eSjoris 
2327a8b24eSjoris #include "cvs.h"
2477a3e292Sxsa #include "remote.h"
2527a8b24eSjoris 
2627a8b24eSjoris extern char *__progname;
2727a8b24eSjoris 
284b41b6d2Sjoris void		cvs_remove_force(struct cvs_file *);
2927a8b24eSjoris 
3027a8b24eSjoris static int	removed = 0;
3127a8b24eSjoris static int	existing = 0;
3227a8b24eSjoris 
3327a8b24eSjoris struct cvs_cmd cvs_cmd_remove = {
34f331ff59Stobias 	CVS_OP_REMOVE, CVS_USE_WDIR, "remove",
3527a8b24eSjoris 	{ "rm", "delete" },
3627a8b24eSjoris 	"Remove an entry from the repository",
3727a8b24eSjoris 	"[-flR] [file ...]",
3827a8b24eSjoris 	"flR",
3927a8b24eSjoris 	NULL,
4027a8b24eSjoris 	cvs_remove
4127a8b24eSjoris };
4227a8b24eSjoris 
4327a8b24eSjoris int
cvs_remove(int argc,char ** argv)4427a8b24eSjoris cvs_remove(int argc, char **argv)
4527a8b24eSjoris {
4627a8b24eSjoris 	int ch;
4734def685Sjoris 	int flags;
4827a8b24eSjoris 	char *arg = ".";
4927a8b24eSjoris 	struct cvs_recursion cr;
5063c546bcSnicm 	int force_remove = 0;
5127a8b24eSjoris 
5234def685Sjoris 	flags = CR_RECURSE_DIRS;
531ecbe6adSxsa 	while ((ch = getopt(argc, argv, cvs_cmd_remove.cmd_opts)) != -1) {
5427a8b24eSjoris 		switch (ch) {
5527a8b24eSjoris 		case 'f':
5627a8b24eSjoris 			force_remove = 1;
5727a8b24eSjoris 			break;
5827a8b24eSjoris 		case 'l':
5934def685Sjoris 			flags &= ~CR_RECURSE_DIRS;
6027a8b24eSjoris 			break;
6127a8b24eSjoris 		case 'R':
62bcf22459Stobias 			flags |= CR_RECURSE_DIRS;
6327a8b24eSjoris 			break;
6427a8b24eSjoris 		default:
651ecbe6adSxsa 			fatal("%s", cvs_cmd_remove.cmd_synopsis);
6627a8b24eSjoris 		}
6727a8b24eSjoris 	}
6827a8b24eSjoris 
6927a8b24eSjoris 	argc -= optind;
7027a8b24eSjoris 	argv += optind;
7127a8b24eSjoris 
7227a8b24eSjoris 	cr.enterdir = NULL;
7327a8b24eSjoris 	cr.leavedir = NULL;
744b41b6d2Sjoris 	cr.flags = flags;
754b41b6d2Sjoris 
769d480df2Stobias 	if (force_remove == 1 && cvs_noexec == 0) {
774b41b6d2Sjoris 		cr.fileproc = cvs_remove_force;
784b41b6d2Sjoris 		if (argc > 0)
794b41b6d2Sjoris 			cvs_file_run(argc, argv, &cr);
804b41b6d2Sjoris 		else
814b41b6d2Sjoris 			cvs_file_run(1, &arg, &cr);
829d480df2Stobias 	}
8377a3e292Sxsa 
84*4dcde513Sjoris 	if (cvsroot_is_remote()) {
8580f6ca9bSjoris 		cvs_client_connect_to_server();
8677a3e292Sxsa 		cr.fileproc = cvs_client_sendfile;
8777a3e292Sxsa 
8877a3e292Sxsa 		if (!(flags & CR_RECURSE_DIRS))
8977a3e292Sxsa 			cvs_client_send_request("Argument -l");
9077a3e292Sxsa 	} else {
91bc5d89feSjoris 		cr.fileproc = cvs_remove_local;
9277a3e292Sxsa 	}
9377a3e292Sxsa 
9427a8b24eSjoris 	if (argc > 0)
9527a8b24eSjoris 		cvs_file_run(argc, argv, &cr);
9627a8b24eSjoris 	else
9727a8b24eSjoris 		cvs_file_run(1, &arg, &cr);
9827a8b24eSjoris 
99*4dcde513Sjoris 	if (cvsroot_is_remote()) {
10077a3e292Sxsa 		cvs_client_send_files(argv, argc);
10177a3e292Sxsa 		cvs_client_senddir(".");
10277a3e292Sxsa 		cvs_client_send_request("remove");
10377a3e292Sxsa 		cvs_client_get_responses();
10477a3e292Sxsa 	} else {
1053aabb136Sjoris 		if (existing != 0) {
10644660a68Sxsa 			cvs_log(LP_ERR, (existing == 1) ?
10744660a68Sxsa 			    "%d file exists; remove it first" :
10844660a68Sxsa 			    "%d files exist; remove them first", existing);
1093aabb136Sjoris 		}
1103aabb136Sjoris 
1113aabb136Sjoris 		if (removed != 0) {
112408908afSjoris 			if (verbosity > 0) {
11377a3e292Sxsa 				cvs_log(LP_NOTICE,
11477a3e292Sxsa 				    "use '%s commit' to remove %s "
1153aabb136Sjoris 				    "permanently", __progname, (removed > 1) ?
1163aabb136Sjoris 				    "these files" : "this file");
1173aabb136Sjoris 			}
11877a3e292Sxsa 		}
11977a3e292Sxsa 	}
1203aabb136Sjoris 
12127a8b24eSjoris 	return (0);
12227a8b24eSjoris }
12327a8b24eSjoris 
12427a8b24eSjoris void
cvs_remove_force(struct cvs_file * cf)1254b41b6d2Sjoris cvs_remove_force(struct cvs_file *cf)
1264b41b6d2Sjoris {
1274b41b6d2Sjoris 	if (cf->file_type != CVS_DIR) {
1285cf15c45Sjoris 		if (cf->file_flags & FILE_ON_DISK) {
1294b41b6d2Sjoris 			if (unlink(cf->file_path) == -1)
1304b41b6d2Sjoris 				fatal("cvs_remove_force: %s", strerror(errno));
1314b41b6d2Sjoris 			(void)close(cf->fd);
1324b41b6d2Sjoris 			cf->fd = -1;
1334b41b6d2Sjoris 		}
1344b41b6d2Sjoris 	}
1354b41b6d2Sjoris }
1364b41b6d2Sjoris 
1374b41b6d2Sjoris void
cvs_remove_local(struct cvs_file * cf)13827a8b24eSjoris cvs_remove_local(struct cvs_file *cf)
13927a8b24eSjoris {
14027a8b24eSjoris 	CVSENTRIES *entlist;
141b9fc9a72Sderaadt 	char *entry, buf[PATH_MAX], tbuf[CVS_TIME_BUFSZ], rbuf[CVS_REV_BUFSZ];
142b0b4b42cStobias 	char sticky[CVS_ENT_MAXLINELEN];
14327a8b24eSjoris 
14427a8b24eSjoris 	cvs_log(LP_TRACE, "cvs_remove_local(%s)", cf->file_path);
14527a8b24eSjoris 
14627a8b24eSjoris 	if (cf->file_type == CVS_DIR) {
14727a8b24eSjoris 		if (verbosity > 1)
14827a8b24eSjoris 			cvs_log(LP_NOTICE, "Removing %s", cf->file_path);
14927a8b24eSjoris 		return;
15027a8b24eSjoris 	}
15127a8b24eSjoris 
15225d391d7Sjoris 	if (cvs_cmdop != CVS_OP_CHECKOUT && cvs_cmdop != CVS_OP_UPDATE)
15351ef6581Sjoris 		cvs_file_classify(cf, cvs_directory_tag);
15427a8b24eSjoris 
15580707535Sjoris 	if (cf->file_status == FILE_UNKNOWN) {
15680707535Sjoris 		if (verbosity > 1)
15780707535Sjoris 			cvs_log(LP_NOTICE, "nothing known about '%s'",
15880707535Sjoris 			    cf->file_path);
15980707535Sjoris 		return;
16080707535Sjoris 	}
16180707535Sjoris 
1625cf15c45Sjoris 	if (cf->file_flags & FILE_ON_DISK) {
16327a8b24eSjoris 		if (verbosity > 1)
16427a8b24eSjoris 			cvs_log(LP_ERR, "file `%s' still in working directory",
16527a8b24eSjoris 			    cf->file_name);
16627a8b24eSjoris 		existing++;
16727a8b24eSjoris 	} else {
16827a8b24eSjoris 		switch (cf->file_status) {
169ef06f8f7Sjoris 		case FILE_REMOVE_ENTRY:
17027a8b24eSjoris 			entlist = cvs_ent_open(cf->file_wd);
17127a8b24eSjoris 			cvs_ent_remove(entlist, cf->file_name);
17227a8b24eSjoris 
173c486465dSxsa 			(void)xsnprintf(buf, sizeof(buf), "%s/%s/%s%s",
174c4d292c1Stobias 			    cf->file_wd, CVS_PATH_CVSDIR, cf->file_name,
17527a8b24eSjoris 			    CVS_DESCR_FILE_EXT);
17627a8b24eSjoris 
17727a8b24eSjoris 			(void)unlink(buf);
17827a8b24eSjoris 
17927a8b24eSjoris 			if (verbosity > 1) {
18027a8b24eSjoris 				cvs_log(LP_NOTICE, "removed `%s'",
18127a8b24eSjoris 				    cf->file_name);
18227a8b24eSjoris 			}
18327a8b24eSjoris 			return;
18427a8b24eSjoris 		case FILE_REMOVED:
185408908afSjoris 			if (verbosity > 0) {
18627a8b24eSjoris 				cvs_log(LP_ERR,
18727a8b24eSjoris 				    "file `%s' already scheduled for removal",
18827a8b24eSjoris 				    cf->file_name);
18927a8b24eSjoris 			}
19027a8b24eSjoris 			return;
191ec6c6427Sjoris 		case FILE_LOST:
19237fdff3fStobias 			rcsnum_tostr(cf->file_ent->ce_rev, rbuf, sizeof(rbuf));
19327a8b24eSjoris 
19427a8b24eSjoris 			ctime_r(&cf->file_ent->ce_mtime, tbuf);
1952820b891Stobias 			tbuf[strcspn(tbuf, "\n")] = '\0';
19627a8b24eSjoris 
197b0b4b42cStobias 			sticky[0] = '\0';
198b0b4b42cStobias 			if (cf->file_ent->ce_tag != NULL)
199b0b4b42cStobias 				(void)xsnprintf(sticky, sizeof(sticky), "T%s",
200b0b4b42cStobias 				    cf->file_ent->ce_tag);
201b0b4b42cStobias 
20227a8b24eSjoris 			entry = xmalloc(CVS_ENT_MAXLINELEN);
203ae83823aSxsa 			cvs_ent_line_str(cf->file_name, rbuf, tbuf,
2047eeb4908Sragge 			    cf->file_ent->ce_opts ?
2057eeb4908Sragge 			    cf->file_ent->ce_opts : "", sticky, 0, 1,
206ae83823aSxsa 			    entry, CVS_ENT_MAXLINELEN);
20727a8b24eSjoris 
208408908afSjoris 			if (cvs_server_active == 1) {
209408908afSjoris 				cvs_server_update_entry("Checked-in", cf);
210408908afSjoris 				cvs_remote_output(entry);
211408908afSjoris 			} else {
21227a8b24eSjoris 				entlist = cvs_ent_open(cf->file_wd);
21327a8b24eSjoris 				cvs_ent_add(entlist, entry);
214408908afSjoris 			}
21527a8b24eSjoris 
216397ddb8aSnicm 			free(entry);
21727a8b24eSjoris 
218408908afSjoris 			if (verbosity > 0) {
21927a8b24eSjoris 				cvs_log(LP_NOTICE,
22027a8b24eSjoris 				    "scheduling file `%s' for removal",
22127a8b24eSjoris 				    cf->file_name);
22227a8b24eSjoris 			}
22327a8b24eSjoris 
22427a8b24eSjoris 			cf->file_status = FILE_REMOVED;
22527a8b24eSjoris 			removed++;
22627a8b24eSjoris 			break;
22727a8b24eSjoris 		}
22827a8b24eSjoris 	}
22927a8b24eSjoris }
230