#include "cvs.h"
static int find_dirs PROTO((char *dir, List * list, int checkadm,
List *entries));
static int find_rcs PROTO((char *dir, List * list));
static int add_subdir_proc PROTO((Node *, void *));
static int register_subdir_proc PROTO((Node *, void *));
static List *filelist;
static int add_entries_proc PROTO((Node *, void *));
static int
add_entries_proc (node, closure)
Node *node;
void *closure;
{
Entnode *entnode;
Node *fnode;
entnode = (Entnode *) node->data;
if (entnode->type != ENT_FILE)
return (0);
fnode = getnode ();
fnode->type = FILES;
fnode->key = xstrdup (node->key);
if (addnode (filelist, fnode) != 0)
freenode (fnode);
return (0);
}
List *
Find_Names (repository, which, aflag, optentries)
char *repository;
int which;
int aflag;
List **optentries;
{
List *entries;
List *files;
files = filelist = getlist ();
if (which & W_LOCAL)
{
entries = Entries_Open (aflag, NULL);
if (entries != NULL)
{
(void) walklist (entries, add_entries_proc, NULL);
if (optentries != NULL)
*optentries = entries;
else
Entries_Close (entries);
}
}
if ((which & W_REPOS) && repository && !isreadable (CVSADM_ENTSTAT))
{
if (find_rcs (repository, files) != 0)
error (1, errno, "cannot open directory %s", repository);
if (which & W_ATTIC)
{
char *dir;
dir = xmalloc (strlen (repository) + sizeof (CVSATTIC) + 10);
(void) sprintf (dir, "%s/%s", repository, CVSATTIC);
(void) find_rcs (dir, files);
free (dir);
}
}
sortlist (files, fsortcmp);
return (files);
}
static int
add_subdir_proc (p, closure)
Node *p;
void *closure;
{
List *dirlist = (List *) closure;
Entnode *entnode;
Node *dnode;
entnode = (Entnode *) p->data;
if (entnode->type != ENT_SUBDIR)
return 0;
dnode = getnode ();
dnode->type = DIRS;
dnode->key = xstrdup (entnode->user);
if (addnode (dirlist, dnode) != 0)
freenode (dnode);
return 0;
}
static int
register_subdir_proc (p, closure)
Node *p;
void *closure;
{
List *entries = (List *) closure;
Subdir_Register (entries, (char *) NULL, p->key);
return 0;
}
List *
Find_Directories (repository, which, entries)
char *repository;
int which;
List *entries;
{
List *dirlist;
dirlist = getlist ();
if (which & W_LOCAL)
{
List *tmpentries;
struct stickydirtag *sdtp;
if (entries != NULL)
tmpentries = entries;
else if (isfile (CVSADM_ENT))
tmpentries = Entries_Open (0, NULL);
else
tmpentries = NULL;
if (tmpentries != NULL)
sdtp = (struct stickydirtag *) tmpentries->list->data;
if (tmpentries != NULL && (sdtp == NULL || sdtp->subdirs))
walklist (tmpentries, add_subdir_proc, (void *) dirlist);
else
{
if (find_dirs (".", dirlist, 1, tmpentries) != 0)
error (1, errno, "cannot open current directory");
if (tmpentries != NULL)
{
if (! list_isempty (dirlist))
walklist (dirlist, register_subdir_proc,
(void *) tmpentries);
else
Subdirs_Known (tmpentries);
}
}
if (entries == NULL && tmpentries != NULL)
Entries_Close (tmpentries);
}
if ((which & W_REPOS) && repository)
{
if (find_dirs (repository, dirlist, 0, entries) != 0)
error (1, errno, "cannot open directory %s", repository);
}
sortlist (dirlist, fsortcmp);
return (dirlist);
}
static int
find_rcs (dir, list)
char *dir;
List *list;
{
Node *p;
struct dirent *dp;
DIR *dirp;
if ((dirp = CVS_OPENDIR (dir)) == NULL)
return (1);
while ((dp = readdir (dirp)) != NULL)
{
if (CVS_FNMATCH (RCSPAT, dp->d_name, 0) == 0)
{
char *comma;
comma = strrchr (dp->d_name, ',');
*comma = '\0';
p = getnode ();
p->type = FILES;
p->key = xstrdup (dp->d_name);
if (addnode (list, p) != 0)
freenode (p);
}
}
(void) closedir (dirp);
return (0);
}
static int
find_dirs (dir, list, checkadm, entries)
char *dir;
List *list;
int checkadm;
List *entries;
{
Node *p;
char *tmp = NULL;
size_t tmp_size = 0;
struct dirent *dp;
DIR *dirp;
int skip_emptydir = 0;
if (isabsolute (dir)
&& strncmp (dir, CVSroot_directory, strlen (CVSroot_directory)) == 0
&& ISDIRSEP (dir[strlen (CVSroot_directory)])
&& strcmp (dir + strlen (CVSroot_directory) + 1, CVSROOTADM) == 0)
skip_emptydir = 1;
if ((dirp = CVS_OPENDIR (dir)) == NULL)
return (1);
while ((dp = readdir (dirp)) != NULL)
{
if (strcmp (dp->d_name, ".") == 0 ||
strcmp (dp->d_name, "..") == 0 ||
strcmp (dp->d_name, CVSATTIC) == 0 ||
strcmp (dp->d_name, CVSLCK) == 0 ||
strcmp (dp->d_name, CVSREP) == 0)
continue;
if (entries != NULL && findnode (entries, dp->d_name) != NULL)
continue;
if (skip_emptydir
&& strcmp (dp->d_name, CVSNULLREPOS) == 0)
continue;
#ifdef DT_DIR
if (dp->d_type != DT_DIR)
{
if (dp->d_type != DT_UNKNOWN && dp->d_type != DT_LNK)
continue;
#endif
if (CVS_FNMATCH (RCSPAT, dp->d_name, 0) == 0)
continue;
expand_string (&tmp,
&tmp_size,
strlen (dir) + strlen (dp->d_name) + 10);
sprintf (tmp, "%s/%s", dir, dp->d_name);
if (!isdir (tmp))
continue;
#ifdef DT_DIR
}
#endif
if (checkadm)
{
#ifdef DT_DIR
if (dp->d_type != DT_DIR)
{
if (dp->d_type == DT_LNK)
continue;
#endif
if (islink (tmp))
continue;
#ifdef DT_DIR
}
#endif
expand_string (&tmp,
&tmp_size,
(strlen (dir) + strlen (dp->d_name)
+ sizeof (CVSADM) + 10));
(void) sprintf (tmp, "%s/%s/%s", dir, dp->d_name, CVSADM);
if (!isdir (tmp))
continue;
}
p = getnode ();
p->type = DIRS;
p->key = xstrdup (dp->d_name);
if (addnode (list, p) != 0)
freenode (p);
}
(void) closedir (dirp);
if (tmp != NULL)
free (tmp);
return (0);
}