1 /* $Id: entryfuncs.c,v 2.6 2000/06/05 07:10:57 chip Exp $ */
2 
3 #include "config.h"
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <fcntl.h>
9 #include <errno.h>
10 #ifdef HAVE_UNISTD_H
11 # include <unistd.h>
12 #endif
13 #ifdef HAVE_STDLIB_H
14 # include <stdlib.h>
15 #endif
16 
17 #include "xtail.h"
18 
new_entry_list(int chunk)19 struct entry_list *new_entry_list(int chunk)
20 {
21     struct entry_list *listp;
22     listp = safe_malloc(sizeof(struct entry_list));
23     listp->list = safe_malloc(chunk * sizeof(struct entry_descrip *));
24     listp->num_entries = 0;
25     listp->max_entries = chunk;
26     listp->chunk = chunk;
27     return listp;
28 }
29 
30 
E_append(struct entry_list * listp,struct entry_descrip * entryp)31 static struct entry_descrip *E_append(struct entry_list *listp,
32 	struct entry_descrip *entryp)
33 {
34     if (listp->num_entries >= listp->max_entries) {
35 	listp->max_entries += listp->chunk;
36     	listp->list = safe_realloc(listp->list,
37 	    listp->max_entries * sizeof(struct entry_descrip *));
38     }
39     listp->list[listp->num_entries++] = entryp;
40     Sorted = FALSE;
41     return entryp;
42 }
43 
44 
E_remove(struct entry_list * listp,int entryno)45 static void E_remove(struct entry_list *listp, int entryno)
46 {
47     while (++entryno < listp->num_entries)
48 	listp->list[entryno-1] = listp->list[entryno];
49     --listp->num_entries;
50     Sorted = FALSE;
51 }
52 
53 
list_name(struct entry_list * listp)54 static char *list_name(struct entry_list *listp) /* for debug output only */
55 {
56     if (listp == List_file)	return "<file>";
57     if (listp == List_dir)	return "<dir>";
58     if (listp == List_zap)	return "<zap>";
59     return "?unknown?";
60 }
61 
62 
63 /*
64  * Create a new entry description and append it to a list.
65  */
new_entry(struct entry_list * listp,const char * name)66 struct entry_descrip *new_entry(struct entry_list *listp, const char *name)
67 {
68     struct entry_descrip *entryp;
69 
70     Dprintf(stderr, ">>> creating entry '%s' on %s list\n",
71 	name, list_name(listp));
72 
73     entryp = safe_malloc(sizeof(struct entry_descrip));
74     entryp->name = safe_strdup(name);
75     entryp->fd = 0;
76     entryp->size =  0;
77     entryp->mtime = 0;
78 
79     return E_append(listp,entryp);
80 }
81 
82 
83 /*
84  * Remove an entry from a list and free up its space.
85  */
rmv_entry(struct entry_list * listp,int entryno)86 void rmv_entry(struct entry_list *listp, int entryno)
87 {
88     struct entry_descrip *entryp = listp->list[entryno];
89 
90     Dprintf(stderr, ">>> removing entry '%s' from %s list\n",
91 	listp->list[entryno]->name, list_name(listp));
92     E_remove(listp,entryno);
93     if (entryp->fd > 0)
94 	(void) close(entryp->fd);
95     free((VOID *) entryp->name);
96     free((VOID *) entryp);
97 }
98 
99 
100 /*
101  * Move an entry from one list to another.
102  *	In addition we close up the entry if appropriate.
103  */
move_entry(struct entry_list * dst_listp,struct entry_list * src_listp,int src_entryno)104 void move_entry(struct entry_list *dst_listp, struct entry_list *src_listp,
105 	int src_entryno)
106 {
107     struct entry_descrip *entryp = src_listp->list[src_entryno];
108 
109     Dprintf(stderr, ">>> moving entry '%s' from %s list to %s list\n",
110 	src_listp->list[src_entryno]->name,
111 	list_name(src_listp), list_name(dst_listp));
112     if (entryp->fd > 0) {
113 	(void) close(entryp->fd);
114 	entryp->fd = 0;
115     }
116     E_remove(src_listp,src_entryno);
117     (void) E_append(dst_listp,entryp);
118     if (Reset_status) {
119 	entryp->size = 0;
120 	entryp->mtime = 0;
121     }
122 }
123 
124 
125 /*
126  * Get the inode status for an entry.
127  *	Returns code describing the status of the entry.
128  */
stat_entry(struct entry_list * listp,int entryno,struct stat * sbuf)129 int stat_entry(struct entry_list *listp, int entryno, struct stat *sbuf)
130 {
131     int status;
132     struct entry_descrip *entryp = listp->list[entryno];
133 
134     status =
135 	(entryp->fd > 0 ? fstat(entryp->fd,sbuf) : stat(entryp->name,sbuf));
136 
137     if (status != 0)
138 	return (errno == ENOENT ? ENTRY_ZAP : ENTRY_ERROR);
139 
140     switch (sbuf->st_mode & S_IFMT) {
141 	case S_IFREG:	return ENTRY_FILE;
142 	case S_IFDIR:	return ENTRY_DIR;
143 	default:	return ENTRY_SPECIAL;
144     }
145 
146     /*NOTREACHED*/
147 }
148 
149 
150 /*
151  * Open an entry.
152  *	Returns 0 if the open is successful, else returns errno.  In the case
153  *	of an error, an appropriate diagnostic will be printed, and the entry
154  *	will be moved or deleted as required.  If the entry is already opened,
155  *	then no action will occur and 0 will be returned.
156  */
open_entry(struct entry_list * listp,int entryno)157 int open_entry(struct entry_list *listp, int entryno)
158 {
159     struct entry_descrip *entryp = listp->list[entryno];
160 
161     if (entryp->fd > 0)
162 	return 0;
163 
164     Dprintf(stderr, ">>> opening entry '%s' on %s list\n",
165 	listp->list[entryno]->name, list_name(listp));
166     if ((entryp->fd = open(entryp->name, O_RDONLY)) > 0)
167 	return 0;
168 
169     if (errno == ENOENT) {
170 	message(MSSG_ZAPPED, entryp);
171 	move_entry(List_zap, listp, entryno);
172     } else {
173 	message(MSSG_OPEN, entryp);
174 	rmv_entry(listp, entryno);
175     }
176     return -1;
177 }
178 
179 
180 
181