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