diff options
Diffstat (limited to 'contrib/cvs/src/hardlink.c')
-rw-r--r-- | contrib/cvs/src/hardlink.c | 298 |
1 files changed, 0 insertions, 298 deletions
diff --git a/contrib/cvs/src/hardlink.c b/contrib/cvs/src/hardlink.c deleted file mode 100644 index 51bd2a60567b2..0000000000000 --- a/contrib/cvs/src/hardlink.c +++ /dev/null @@ -1,298 +0,0 @@ -/* This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. */ - -/* Collect and manage hardlink info associated with a particular file. */ - -#include "cvs.h" -#include "hardlink.h" - -/* The structure currently used to manage hardlink info is a list. - Therefore, most of the functions which manipulate hardlink data - are walklist procedures. This is not a very efficient implementation; - if someone decides to use a real hash table (for instance), then - much of this code can be rewritten to be a little less arcane. - - Each element of `hardlist' represents an inode. It is keyed on the - inode number, and points to a list of files. This is to make it - easy to find out what files are linked to a given file FOO: find - FOO's inode, look it up in hardlist, and retrieve the list of files - associated with that inode. - - Each file node, in turn, is represented by a `hardlink_info' struct, - which includes `status' and `links' fields. The `status' field should - be used by a procedure like commit_fileproc or update_fileproc to - record each file's status; that way, after all file links have been - recorded, CVS can check the linkage of files which are in doubt - (i.e. T_NEEDS_MERGE files). - - TODO: a diagram of an example hardlist would help here. */ - -/* TODO: change this to something with a marginal degree of - efficiency, like maybe a hash table. Yeah. */ - -List *hardlist; /* Record hardlink information for working files */ -char *working_dir; /* The top-level working directory, used for - constructing full pathnames. */ - -/* For check_link_proc: list all of the files named in an inode list. */ -static int -list_files_proc (node, vstrp) - Node *node; - void *vstrp; -{ - char **strp, *file; - int len; - - /* Get the file's basename. This is because -- VERY IMPORTANT -- - the `hardlinks' field is presently defined only to include links - within a directory. So the hardlinks field might be `foo' or - `mumble grump flink', but not `foo bar com/baz' or `wham ../bam - ../thank/you'. Someday it would be nice to extend this to - permit cross-directory links, but the issues involved are - hideous. */ - - file = strrchr (node->key, '/'); - if (file) - ++file; - else - file = node->key; - - /* Is it safe to cast vstrp to (char **) here, and then play with - the contents? I think so, since vstrp will have started out - a char ** to begin with, so we should not have alignment bugs. */ - strp = (char **) vstrp; - len = (*strp == NULL ? 0 : strlen (*strp)); - *strp = (char *) xrealloc (*strp, len + strlen (file) + 2); - if (*strp == NULL) - { - error (0, errno, "could not allocate memory"); - return 1; - } - if (sprintf (*strp + len, "%s ", file) < 0) - { - error (0, errno, "could not compile file list"); - return 1; - } - - return 0; -} - -/* Set the link field of each hardlink_info node to `data', which is a - list of linked files. */ -static int -set_hardlink_field_proc (node, data) - Node *node; - void *data; -{ - struct hardlink_info *hlinfo = (struct hardlink_info *) node->data; - hlinfo->links = xstrdup ((char *) data); - - return 0; -} - -/* For each file being checked in, compile a list of the files linked - to it, and cache the list in the file's hardlink_info field. */ -int -cache_hardlinks_proc (node, data) - Node *node; - void *data; -{ - List *inode_links; - char *p, *linked_files = NULL; - int err; - - inode_links = (List *) node->data; - - /* inode->data is a list of hardlink_info structures: all the - files linked to this inode. We compile a string of each file - named in this list, in alphabetical order, separated by spaces. - Then store this string in the `links' field of each - hardlink_info structure, so that RCS_checkin can easily add - it to the `hardlinks' field of a new delta node. */ - - sortlist (inode_links, fsortcmp); - err = walklist (inode_links, list_files_proc, &linked_files); - if (err) - return err; - - /* Trim trailing whitespace. */ - p = linked_files + strlen(linked_files) - 1; - while (p > linked_files && isspace (*p)) - *p-- = '\0'; - - err = walklist (inode_links, set_hardlink_field_proc, linked_files); - return err; -} - -/* Return a pointer to FILEPATH's node in the hardlist. This means - looking up its inode, retrieving the list of files linked to that - inode, and then looking up FILE in that list. If the file doesn't - seem to exist, return NULL. */ -Node * -lookup_file_by_inode (filepath) - const char *filepath; -{ - char *inodestr, *file; - struct stat sb; - Node *hp, *p; - - /* Get file's basename, so that we can stat it. */ - file = strrchr (filepath, '/'); - if (file) - ++file; - else - file = (char *) filepath; - - /* inodestr contains the hexadecimal representation of an - inode, so it requires two bytes of text to represent - each byte of the inode number. */ - inodestr = (char *) xmalloc (2*sizeof(ino_t)*sizeof(char) + 1); - if (stat (file, &sb) < 0) - { - if (errno == ENOENT) - { - /* The file doesn't exist; we may be doing an update on a - file that's been removed. A nonexistent file has no - link information, so return without changing hardlist. */ - free (inodestr); - return NULL; - } - error (1, errno, "cannot stat %s", file); - } - - sprintf (inodestr, "%lx", (unsigned long) sb.st_ino); - - /* Find out if this inode is already in the hardlist, adding - a new entry to the list if not. */ - hp = findnode (hardlist, inodestr); - if (hp == NULL) - { - hp = getnode (); - hp->type = UNKNOWN; - hp->key = inodestr; - hp->data = (char *) getlist(); - hp->delproc = dellist; - (void) addnode (hardlist, hp); - } - else - { - free (inodestr); - } - - p = findnode ((List *) hp->data, filepath); - if (p == NULL) - { - p = getnode(); - p->type = UNKNOWN; - p->key = xstrdup (filepath); - p->data = NULL; - (void) addnode ((List *) hp->data, p); - } - - return p; -} - -/* After a file has been checked out, add a node for it to the hardlist - (if necessary) and mark it as checked out. */ -void -update_hardlink_info (file) - const char *file; -{ - char *path; - Node *n; - struct hardlink_info *hlinfo; - - if (file[0] == '/') - { - path = xstrdup (file); - } - else - { - /* file is a relative pathname; assume it's from the current - working directory. */ - char *dir = xgetwd(); - path = xmalloc (sizeof(char) * (strlen(dir) + strlen(file) + 2)); - sprintf (path, "%s/%s", dir, file); - free (dir); - } - - n = lookup_file_by_inode (path); - if (n == NULL) - { - /* Something is *really* wrong if the file doesn't exist here; - update_hardlink_info should be called only when a file has - just been checked out to a working directory. */ - error (1, 0, "lost hardlink info for %s", file); - } - - if (n->data == NULL) - n->data = (char *) xmalloc (sizeof (struct hardlink_info)); - hlinfo = (struct hardlink_info *) n->data; - hlinfo->status = T_UPTODATE; - hlinfo->checked_out = 1; - hlinfo->links = NULL; -} - -/* Return a string listing all the files known to be linked to FILE in - the working directory. Used by special_file_mismatch, to determine - whether it is safe to merge two files. */ -char * -list_files_linked_to (file) - const char *file; -{ - char *inodestr, *filelist, *path; - struct stat sb; - Node *n; - int err; - - /* If hardlist is NULL, we have not been doing an operation that - would permit us to know anything about the file's hardlinks - (cvs update, cvs commit, etc). Return an empty string. */ - if (hardlist == NULL) - return xstrdup (""); - - /* Get the full pathname of file (assuming the working directory) */ - if (file[0] == '/') - path = xstrdup (file); - else - { - char *dir = xgetwd(); - path = (char *) xmalloc (sizeof(char) * - (strlen(dir) + strlen(file) + 2)); - sprintf (path, "%s/%s", dir, file); - free (dir); - } - - /* We do an extra lookup_file here just to make sure that there - is a node for `path' in the hardlist. If that were not so, - comparing the working directory linkage against the repository - linkage for a file would always fail. */ - (void) lookup_file_by_inode (path); - - if (stat (path, &sb) < 0) - error (1, errno, "cannot stat %s", file); - /* inodestr contains the hexadecimal representation of an - inode, so it requires two bytes of text to represent - each byte of the inode number. */ - inodestr = (char *) xmalloc (2*sizeof(ino_t)*sizeof(char) + 1); - sprintf (inodestr, "%lx", (unsigned long) sb.st_ino); - - /* Make sure the files linked to this inode are sorted. */ - n = findnode (hardlist, inodestr); - sortlist ((List *) n->data, fsortcmp); - - filelist = NULL; - err = walklist ((List *) n->data, list_files_proc, &filelist); - if (err) - error (1, 0, "cannot get list of hardlinks for %s", file); - - free (inodestr); - return filelist; -} |