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