1 /*
2    sitecopy, for managing remote web sites.
3    Copyright (C) 1999-2005, Joe Orton <joe@manyfish.co.uk>
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9 
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 
20 #ifndef SITESI_H
21 #define SITESI_H
22 
23 #include <sys/stat.h>
24 
25 #include "common.h"
26 #include "sites.h"
27 #include "frontend.h" /* for fe_*_abort */
28 
29 #include "ne_md5.h" /* for ne_md5_* */
30 
31 /* Internal sites code handling */
32 
33 void file_uploaded(struct site_file *file, struct site *site);
34 void file_downloaded(struct site_file *file, struct site *site);
35 
36 int file_contents_changed(struct site_file *file, struct site *site);
37 int file_perms_changed(struct site_file *file, struct site *site);
38 
39 #define DEBUG_GIVE_DIFF(diff)					\
40        diff==file_new?"new":(					\
41 	   diff==file_changed?"changed":(			\
42 	       diff==file_unchanged?"unchanged":(		\
43 		   diff==file_deleted?"deleted":"moved")))
44 
45 /* Macro, used mainly internally to the sites code to dump a file. */
46 #define DEBUG_DUMP_FILE(ch, file)			\
47 NE_DEBUG(ch, "%s: local=%s stored=%s, %s%s\n",		\
48        (file->type==file_file)?"File":(			\
49 	   file->type==file_dir?"Dir":"Link"),		\
50        file->local.filename?file->local.filename:".",	\
51        file->stored.filename?file->stored.filename:".",	\
52        DEBUG_GIVE_DIFF(file->diff),			\
53        file->ignore?" (ignored)":"")
54 
55 #define DEBUG_DUMP_FILE_PROPS(ch, file, site)			\
56 DEBUG_DUMP_FILE(ch, file);					\
57 if (site->state_method == state_timesize) {			\
58     NE_DEBUG(ch, "Time: %ld/%ld Size: %" NE_FMT_OFF_T "/%" NE_FMT_OFF_T, \
59        file->local.time, file->stored.time,			\
60        file->local.size, file->stored.size);			\
61 } else {							\
62     char l[33], s[33];						\
63     ne_md5_to_ascii(file->local.checksum, l);			\
64     ne_md5_to_ascii(file->stored.checksum, s);			\
65     NE_DEBUG(ch, "Checksum: %32s/%32s\n", l, s);			\
66 }								\
67 NE_DEBUG(ch, "ASCII:%c/%c Perms:%03o/%03o\n",			\
68        file->local.ascii?'y':'n', file->stored.ascii?'y':'n',	\
69        file->local.mode, file->stored.mode   );			\
70 if (file->server.exists) {					\
71     NE_DEBUG(ch, "Server: %ld\n", file->server.time);		\
72 }
73 
74 /* Use to iterate over a files list. */
75 #define for_each_file(file, site) \
76 for (file = site->files; file != NULL; file = file->next)
77 
78 
79 /* Remove a file from the files list */
80 void file_delete(struct site *site, struct site_file *item);
81 
82 /* Destroys a file state */
83 void file_state_destroy(struct file_state *state);
84 /* Copies a file state from src to dest */
85 void file_state_copy(struct file_state *dest, const struct file_state *src,
86 		      struct site *site);
87 
88 /* This *MUST* be called after you change the local or stored state
89  * of a file. It sets the ->diff appropriately, and updates the
90  * site's num* and total* fields. */
91 void file_set_diff(struct site_file *file, struct site *site);
92 
93 struct site_file *
94 file_find(struct site *site, const char *fname, enum file_type type);
95 
96 struct site_file *
97 file_set_stored(enum file_type type, struct file_state *state,
98 		struct site *site);
99 
100 struct site_file *
101 file_set_local(enum file_type type, struct file_state *state,
102 	       struct site *site);
103 
104 static inline void
105 site_stats_increase(const struct site_file *file, struct site *site);
106 
107 static inline void
108 site_stats_decrease(const struct site_file *file, struct site *site);
109 
110 void site_stats_update(struct site *site);
111 
112 static inline void
site_stats_increase(const struct site_file * file,struct site * site)113 site_stats_increase(const struct site_file *file, struct site *site) {
114     switch (file->diff) {
115     case file_unchanged:
116 	site->numunchanged++;
117 	break;
118     case file_changed:
119 	if (file->ignore) {
120 	    site->numignored++;
121 	} else {
122 	    site->numchanged++;
123 	    site->totalchanged += file->local.size;
124 	}
125 	break;
126     case file_new:
127 	site->numnew++;
128 	site->totalnew += file->local.size;
129 	break;
130     case file_moved:
131 	site->nummoved++;
132 	break;
133     case file_deleted:
134 	site->numdeleted++;
135 	break;
136     default:
137 	/* Do nothing */
138 	break;
139     }
140 }
141 
142 static inline void
site_stats_decrease(const struct site_file * file,struct site * site)143 site_stats_decrease(const struct site_file *file, struct site *site) {
144     switch (file->diff) {
145     case file_unchanged:
146 	site->numunchanged--;
147 	break;
148     case file_changed:
149 	if (file->ignore) {
150 	    site->numignored--;
151 	} else {
152 	    site->numchanged--;
153 	    site->totalchanged -= file->local.size;
154 	}
155 	break;
156     case file_new:
157 	site->numnew--;
158 	site->totalnew -= file->local.size;
159 	break;
160     case file_moved:
161 	site->nummoved--;
162 	break;
163     case file_deleted:
164 	site->numdeleted--;
165 	break;
166     default:
167 	/* Do nothing */
168 	break;
169     }
170 }
171 
172 /* Returns the difference between the local and stored state of the
173  * given file in the given state.
174  * Returns:
175  *   file_changed    if changed
176  *   file_unchanged  otherwise
177  */
178 enum file_diff inline static
file_compare(const enum file_type type,const struct file_state * first,const struct file_state * second,const struct site * site)179 file_compare(const enum file_type type,
180 	     const struct file_state *first, const struct file_state *second,
181 	     const struct site *site) {
182 
183     /* Handle the special cases */
184     if (!first->exists)
185 	return file_deleted;
186     if (!second->exists)
187 	return file_new;
188 
189     /* They're both there... compare them properly */
190     switch (type) {
191     case file_dir:
192         if (site->dirperms) {
193             return (first->mode != second->mode ?
194                     file_changed : file_unchanged);
195         }
196 	break;
197 
198     case file_link:
199 	if (strcmp(first->linktarget, second->linktarget) != 0) {
200 	    return file_changed;
201 	}
202 	break;
203 
204     case file_file:
205 	switch (site->state_method) {
206 	case state_timesize:
207 	    if ((first->time != second->time)
208 		|| (first->size!=second->size)) {
209 		return file_changed;
210 	    }
211 	    break;
212 	case state_checksum:
213 	    if (memcmp(first->checksum, second->checksum, 16) != 0) {
214 		return file_changed;
215 	    }
216 	    break;
217 	}
218 	/* Check permissions and ASCIIness.
219 	 * There's a twist for permissions: if EITHER local or
220 	 * remote file has an EXEC bit set, then in 'perms exec' mode,
221 	 * perms are compared. */
222 	if (first->ascii != second->ascii) {
223 	    return file_changed;
224 	} else if (((site->perms == sitep_all) ||
225 		    (((first->mode & S_IXUSR) || (second->mode & S_IXUSR)) &&
226 		     (site->perms == sitep_exec)))
227 		   && (first->mode != second->mode)) {
228 	    return file_changed;
229 	}
230 	if (site->checkmoved && strcmp(first->filename, second->filename)) {
231 	    return file_moved;
232 	}
233 	break;
234     }
235     return file_unchanged;
236 }
237 
238 /* Places the checksum of the given filename in the given file state.
239  * The checksum algorithm may in the future be determined from the
240  * site. Returns 0 on success or -1 on error.
241  */
242 int file_checksum(const char *fname, struct file_state *state, struct site *s);
243 
244 /* Returns whether a file of given name is exclude from the given site */
245 int file_isexcluded(const char *filename, struct site *site);
246 /* Returns whether a file is ASCII text or binary */
247 int file_isascii(const char *filename, struct site *site);
248 /* Returns whether a file is ignored or not */
249 int file_isignored(const char *filename, struct site *site);
250 
251 #endif /* SITESI_H */
252