summaryrefslogtreecommitdiff
path: root/usr.bin/cvs/repo.h
blob: 3b92b8af9495e12d4489a735b30306785564bb11 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*	$OpenBSD: repo.h,v 1.3 2005/08/08 11:47:53 xsa Exp $	*/
/*
 * Copyright (c) 2005 Jean-Francois Brousseau <jfb@openbsd.org>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef REPO_H
#define REPO_H

#include <sys/types.h>
#include <sys/queue.h>


#define CVS_MODULE_ISALIAS	0x01

typedef struct cvs_module {
	char	*cm_name;
	int	 cm_flags;
	char	*cm_path;	/* subpath for aliases, NULL otherwise */

	TAILQ_ENTRY(cvs_module)	cm_link;
} CVSMODULE;



#define CVS_RPENT_UNKNOWN	0
#define CVS_RPENT_DIR		1
#define CVS_RPENT_RCSFILE	2

typedef struct cvs_repoent CVSRPENT;

/*
 * Repository locks
 * ================
 *
 * OpenCVS derives from the standard CVS mechanism in the way it manages locks
 * on the repository.  GNU CVS uses files with 'rfl' and 'wfl' extensions for
 * read and write locks on particular directories.
 * Using the filesystem for locking semantics has one major drawback: a lock
 * can stay even after the process that created it is gone, if it didn't
 * perform the appropriate cleanup.  This stale lock problem has been known
 * to happen with GNU CVS and an intervention from one of the repository
 * administrators is required before anyone else can access parts of the
 * repository.
 * In OpenCVS, a child cvsd needing to access a particular part of the tree
 * must first request a lock on that part of the tree by issuing a
 * CVS_MSG_LOCK message with the appropriate path.  Although the code
 * supports locking at the file level, it should only be applied to the
 * directory level to avoid extra overhead.  Both read and write locks can be
 * obtained, though with different behaviour.  Multiple simultaneous read locks
 * can be obtained on the same entry, but there can only be one active write
 * lock.  In the case where the directory
 * is already locked by another child, a lock wait is added to that entry
 * and the child requesting the lock will get a CVSD_MSG_LOCKPEND reply,
 * meaning that the lock has not been obtained but the child should block
 * until it receives a CVSD_MSG_OK or CVSD_MSG_ERR telling it whether it
 * obtained the lock or not.  When a child is done modifying the locked portion
 * it should release its lock using the CVSD_MSG_UNLOCK request with the path.
 *
 * NOTES:
 *  * The current locking mechanism allows a lock to be obtained on a
 *    subportion of a part that has already been locked by another process.
 *  * A lock on a directory only allows the owner to modify RCS files found
 *    within that directory.  Any modifications on subdirectories require the
 *    process to lock those subdirectories as well.
 */

#define CVS_LOCK_READ	1
#define CVS_LOCK_WRITE	2


struct cvs_lock {
	pid_t		 lk_owner;
	int		 lk_type;
	CVSRPENT	*lk_ent;	/* backpointer to the entry */

	TAILQ_ENTRY(cvs_lock)	lk_link;
	TAILQ_ENTRY(cvs_lock)	lk_chlink;
};

TAILQ_HEAD(cvs_lklist, cvs_lock);

struct cvs_repoent {
	char		*cr_name;
	int		 cr_type;
	CVSRPENT	*cr_parent;

	union {
		TAILQ_HEAD(, cvs_repoent)	files;
	} cr_data;

	struct cvs_lock		*cr_wlock;	/* write lock, NULL if none */
	struct cvs_lklist	 cr_rlocks;	/* read locks */
	struct cvs_lklist	 cr_lkreq;	/* pending lock requests */

	TAILQ_ENTRY(cvs_repoent)	cr_link;
};

#define cr_files	cr_data.files



#define CVS_REPO_LOCKED		0x01
#define CVS_REPO_READONLY	0x02
#define CVS_REPO_CHKPERM	0x04

TAILQ_HEAD(cvs_modlist, cvs_module);

typedef struct cvs_repo {
	char		*cr_path;
	int		 cr_flags;
	CVSRPENT	*cr_tree;

	struct cvs_modlist	cr_modules;
	TAILQ_ENTRY(cvs_repo)	cr_link;
} CVSREPO;




CVSREPO		*cvs_repo_load(const char *, int);
void		 cvs_repo_free(CVSREPO *);
int		 cvs_repo_alias(CVSREPO *, const char *, const char *);
int		 cvs_repo_unalias(CVSREPO *, const char *);
int		 cvs_repo_lockdir(CVSREPO *, const char *, int, pid_t);
int		 cvs_repo_unlockdir(CVSREPO *, const char *, pid_t);
int		 cvs_repo_lockent(CVSRPENT *, int, pid_t);
int		 cvs_repo_unlockent(CVSRPENT *, pid_t);
void		 cvs_repo_entfree(CVSRPENT *);
void		 cvs_repo_modfree(CVSMODULE *);

CVSRPENT	*cvs_repo_find(CVSREPO *, const char *);


#endif	/* REPO_H */