2 Copyright (C) Andrew Tridgell 1996
3 Copyright (C) Paul Mackerras 1996
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.
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.
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.
20 /* generate and receive file lists */
26 extern int always_checksum;
27 extern off_t total_size;
29 extern int cvs_exclude;
31 extern int one_file_system;
32 extern int make_backups;
33 extern int preserve_links;
34 extern int preserve_perms;
35 extern int preserve_devices;
36 extern int preserve_uid;
37 extern int preserve_gid;
38 extern int preserve_times;
40 static char **local_exclude_list = NULL;
42 static void clean_fname(char *name);
46 This function is used to check if a file should be included/excluded
47 from the list of files based on its name and type etc
49 static int match_file_name(char *fname,struct stat *st)
51 if (check_exclude(fname,local_exclude_list)) {
53 fprintf(stderr,"excluding file %s\n",fname);
59 /* used by the one_file_system code */
60 static dev_t filesystem_dev;
62 static void set_filesystem(char *fname)
65 if (lstat(fname,&st) != 0) return;
66 filesystem_dev = st.st_dev;
70 static void send_directory(int f,struct file_list *flist,char *dir);
72 static char *flist_dir = NULL;
74 static void send_file_entry(struct file_struct *file,int f)
78 write_int(f,strlen(file->name));
79 write_buf(f,file->name,strlen(file->name));
80 write_int(f,(int)file->modtime);
81 write_int(f,(int)file->length);
82 write_int(f,(int)file->mode);
84 write_int(f,(int)file->uid);
86 write_int(f,(int)file->gid);
87 if (preserve_devices) {
89 fprintf(stderr,"dev=0x%x\n",(int)file->dev);
90 write_int(f,(int)file->dev);
94 if (preserve_links && S_ISLNK(file->mode)) {
95 write_int(f,strlen(file->link));
96 write_buf(f,file->link,strlen(file->link));
100 if (always_checksum) {
101 write_buf(f,file->sum,SUM_LENGTH);
106 static struct file_struct *make_file(int recurse,char *fname)
108 static struct file_struct file;
110 char sum[SUM_LENGTH];
112 bzero(sum,SUM_LENGTH);
114 if (lstat(fname,&st) != 0) {
115 fprintf(stderr,"%s: %s\n",
116 fname,strerror(errno));
120 if (S_ISDIR(st.st_mode) && !recurse) {
121 fprintf(stderr,"skipping directory %s\n",fname);
125 if (one_file_system && st.st_dev != filesystem_dev)
128 if (!match_file_name(fname,&st))
132 fprintf(stderr,"make_file(%s)\n",fname);
134 file.name = strdup(fname);
135 file.modtime = st.st_mtime;
136 file.length = st.st_size;
137 file.mode = st.st_mode;
138 file.uid = st.st_uid;
139 file.gid = st.st_gid;
141 file.dev = st.st_rdev;
145 if (S_ISLNK(st.st_mode)) {
147 char lnk[MAXPATHLEN];
148 if ((l=readlink(fname,lnk,MAXPATHLEN-1)) == -1) {
149 fprintf(stderr,"readlink %s : %s\n",fname,strerror(errno));
153 file.link = strdup(lnk);
157 if (always_checksum && S_ISREG(st.st_mode)) {
158 file_checksum(fname,file.sum,st.st_size);
162 file.dir = strdup(flist_dir);
166 if (!S_ISDIR(st.st_mode))
167 total_size += st.st_size;
174 static void send_file_name(int f,struct file_list *flist,
175 int recurse,char *fname)
177 struct file_struct *file;
179 file = make_file(recurse,fname);
183 if (flist->count >= flist->malloced) {
184 flist->malloced += 100;
185 flist->files = (struct file_struct *)realloc(flist->files,
186 sizeof(flist->files[0])*
189 out_of_memory("send_file_name");
192 if (strcmp(file->name,".") && strcmp(file->name,"/")) {
193 flist->files[flist->count++] = *file;
194 send_file_entry(file,f);
197 if (S_ISDIR(file->mode) && recurse) {
198 char **last_exclude_list = local_exclude_list;
199 send_directory(f,flist,file->name);
200 local_exclude_list = last_exclude_list;
207 static void send_directory(int f,struct file_list *flist,char *dir)
211 char fname[MAXPATHLEN];
217 fprintf(stderr,"%s: %s\n",
218 dir,strerror(errno));
224 if (fname[l-1] != '/')
226 p = fname + strlen(fname);
229 strcpy(p,".cvsignore");
230 local_exclude_list = make_exclude_list(fname,NULL,0);
233 for (di=readdir(d); di; di=readdir(d)) {
234 if (strcmp(di->d_name,".")==0 ||
235 strcmp(di->d_name,"..")==0)
237 strcpy(p,di->d_name);
238 send_file_name(f,flist,1,fname);
246 struct file_list *send_file_list(int f,int recurse,int argc,char *argv[])
251 char dbuf[MAXPATHLEN];
252 struct file_list *flist;
254 if (verbose && recurse) {
255 fprintf(am_server?stderr:stdout,"building file list ... ");
256 fflush(am_server?stderr:stdout);
259 flist = (struct file_list *)malloc(sizeof(flist[0]));
260 if (!flist) out_of_memory("send_file_list");
263 flist->malloced = 100;
264 flist->files = (struct file_struct *)malloc(sizeof(flist->files[0])*
266 if (!flist->files) out_of_memory("send_file_list");
268 for (i=0;i<argc;i++) {
269 char fname2[MAXPATHLEN];
270 char *fname = fname2;
272 strcpy(fname,argv[i]);
275 if (l != 1 && fname[l-1] == '/') {
279 if (lstat(fname,&st) != 0) {
280 fprintf(stderr,"%s : %s\n",fname,strerror(errno));
284 if (S_ISDIR(st.st_mode) && !recurse) {
285 fprintf(stderr,"skipping directory %s\n",fname);
290 p = strrchr(fname,'/');
300 if (getcwd(dbuf,MAXPATHLEN-1) == NULL) {
301 fprintf(stderr,"getwd : %s\n",strerror(errno));
304 if (chdir(dir) != 0) {
305 fprintf(stderr,"chdir %s : %s\n",dir,strerror(errno));
310 set_filesystem(fname);
311 send_file_name(f,flist,recurse,fname);
313 if (chdir(dbuf) != 0) {
314 fprintf(stderr,"chdir %s : %s\n",dbuf,strerror(errno));
321 set_filesystem(fname);
322 send_file_name(f,flist,recurse,fname);
332 if (verbose && recurse)
333 fprintf(am_server?stderr:stdout,"done\n");
339 struct file_list *recv_file_list(int f)
342 struct file_list *flist;
345 fprintf(stderr,"recv_file_list starting\n");
347 flist = (struct file_list *)malloc(sizeof(flist[0]));
353 flist->files = (struct file_struct *)malloc(sizeof(flist->files[0])*
359 for (l=read_int(f); l; l=read_int(f)) {
360 int i = flist->count;
362 if (i >= flist->malloced) {
363 flist->malloced += 100;
364 flist->files =(struct file_struct *)realloc(flist->files,
365 sizeof(flist->files[0])*
371 flist->files[i].name = (char *)malloc(l+1);
372 if (!flist->files[i].name)
375 read_buf(f,flist->files[i].name,l);
376 flist->files[i].name[l] = 0;
377 flist->files[i].modtime = (time_t)read_int(f);
378 flist->files[i].length = (off_t)read_int(f);
379 flist->files[i].mode = (mode_t)read_int(f);
381 flist->files[i].uid = (uid_t)read_int(f);
383 flist->files[i].gid = (gid_t)read_int(f);
384 if (preserve_devices)
385 flist->files[i].dev = (dev_t)read_int(f);
388 if (preserve_links && S_ISLNK(flist->files[i].mode)) {
390 flist->files[i].link = (char *)malloc(l+1);
391 read_buf(f,flist->files[i].link,l);
392 flist->files[i].link[l] = 0;
397 read_buf(f,flist->files[i].sum,SUM_LENGTH);
399 if (S_ISREG(flist->files[i].mode))
400 total_size += flist->files[i].length;
405 fprintf(stderr,"recv_file_name(%s)\n",flist->files[i].name);
410 fprintf(stderr,"received %d names\n",flist->count);
417 out_of_memory("recv_file_list");
418 return NULL; /* not reached */
422 static int flist_compare(struct file_struct *f1,struct file_struct *f2)
424 if (!f1->name && !f2->name) return 0;
425 if (!f1->name) return -1;
426 if (!f2->name) return 1;
427 return strcmp(f1->name,f2->name);
431 int flist_find(struct file_list *flist,struct file_struct *f)
433 int low=0,high=flist->count;
435 while (low != high) {
436 int mid = (low+high)/2;
437 int ret = flist_compare(&flist->files[mid],f);
438 if (ret == 0) return mid;
444 if (flist_compare(&flist->files[low],f) == 0)
450 static void clean_fname(char *name)
461 if ((p=strstr(name,"/./"))) {
469 if ((p=strstr(name,"//"))) {
477 if (strncmp(p=name,"./",2) == 0) {
486 if (l > 1 && p[l-1] == '/') {
495 * This routine ensures we don't have any duplicate names in our file list.
496 * duplicate names can cause corruption because of the pipelining
498 void clean_flist(struct file_list *flist)
502 if (!flist || flist->count == 0)
505 for (i=0;i<flist->count;i++) {
506 clean_fname(flist->files[i].name);
509 qsort(flist->files,flist->count,
510 sizeof(flist->files[0]),
511 (int (*)())flist_compare);
513 for (i=1;i<flist->count;i++) {
514 if (flist->files[i].name &&
515 strcmp(flist->files[i].name,flist->files[i-1].name) == 0) {
516 if (verbose > 1 && !am_server)
517 fprintf(stderr,"removing duplicate name %s from file list\n",
518 flist->files[i].name);
519 free(flist->files[i-1].name);
520 flist->files[i-1].name = NULL;