?? sites.c
字號:
/* sitecopy, for managing remote web sites. Copyright (C) 1998-99, Joe Orton <joe@orton.demon.co.uk> 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 of the License, 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. $Id: sites.c,v 1.34.2.17 1999/08/27 17:48:58 joe Exp $*//* This is the core functionality of sitecopy, performing updates * and checking files etc. */#include <config.h>#include <sys/types.h>#include <sys/stat.h>#include <errno.h>#include <dirent.h>#include <fnmatch.h>#include <fcntl.h>#include <stdio.h>#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif /* HAVE_STDLIB_H */#ifdef HAVE_UNISTD_H#include <unistd.h>#endif /* HAVE_UNISTD_H */#ifdef HAVE_STRING_H#include <string.h>#endif#ifdef HAVE_STRINGS_H#include <strings.h>#endif#include <time.h>#include <utime.h>#ifndef HAVE_SNPRINTF#include <snprintf.h>#endif /* !HAVE_SNPRINTF */#include <basename.h>#include "common.h"#include "dirname.h"#include "frontend.h"#include "protocol.h"#include "socket.h"#include "sites.h"#include "ftp.h"/* The protocol drivers */const struct proto_driver ftp_driver = { ftp_init, ftp_finish, ftp_move, ftp_put, ftp_get, ftp_delete, ftp_chmod, ftp_mkdir, ftp_rmdir, NULL, /* create link */ NULL, /* change link target */ NULL, /* delete link */ ftp_fetch, "ftp", /* service name */ 21, /* service number */ "FTP", ftp_error};#ifdef USE_DAV#include "httpdav.h"const struct proto_driver dav_driver = { http_init, /* Connect */ http_finish, /* Disconnect */ dav_move, /* File move */ http_put, /* File upload - HTTP PUT */ http_get, /* File download */ http_delete, /* File delete */ NULL, /* File chmod... this could be done using either * a) A special live property * b) The ACL extensions: draft-ietf-webdav-acl-??.txt */ dav_mkcol, /* Dir create */ dav_rmdir, /* Dir remove, same as file remove */ dav_mkref, /* Create link */ dav_chref, /* Change link */ dav_rmref, /* Remove link */ /* fetch listing */#ifdef HAVE_LIBEXPAT dav_fetch, #else NULL, #endif "http", /* Service name */ 80, /* server number */ "WebDAV", /* User-visible protocol name */ http_error};#endif/* This is the maximum number of directories which can be held in the queue * at one time - each entry is only a pointer, so the size is not too * much of a problem. */#define MAXDIRS 500/* This is the string used in the storage files to indicate the * line is a directory rather than a file */#define DIRWORD "dir"/* And this is used for links */#define LINKWORD "link"/* Shorthand for protocol driver methods */#define CALL( a ) (*the_site->driver->a)/* This holds ALL the sites defined in the rcfile */struct site_t *all_sites; bool fe_prompting;bool site_keepgoing;static int proto_init( struct site_t *the_site );/* Prototypes */static void site_checkmoved( struct site_t *any_site );static void site_destroyfile( struct site_file_t *file );static int site_synch_create_directories( struct site_t *the_site );static int site_synch_files( struct site_t *the_site );static int site_synch_remove_directories( struct site_t *the_site );static int site_update_create_directories( struct site_t *the_site, bool onlymarked );static int site_update_delete_directories( struct site_t *the_site, bool onlymarked );static int site_update_delete_files( struct site_t *the_site, bool onlymarked );static int site_update_files( struct site_t *the_site, bool onlymarked );static int site_update_links( struct site_t *the_site, bool onlymarked );static void site_fetch_walk( struct site_t *the_site, struct proto_file_t *files );static int site_readlocalfiles( struct site_t * );static int site_readremotefiles( struct site_t * );static void site_flatlist_items( FILE *f, struct site_t *the_site, const enum file_diff diff, const char *name );/* Assigns the _local and _remote filenames to the site file */static void site_assignnames( struct site_file_t *the_file, struct site_t *the_site );/* Functions for manipulating the doubly linked files list */static void file_delete( struct site_t *site, struct site_file_t *item );static struct site_file_t *file_prepend( struct site_t *site );static struct site_file_t *file_append( struct site_t *site );static struct site_file_t *file_create( void );/* Whether a file is excluded from the site or not */static bool file_isexcluded( const char *filename, const char *fullpath, struct site_t *site );/* Whether a file is ASCII text or binary */static bool file_isascii( char *filename, struct site_t *site );/* Creates and initializes a file. * Returns NULL if out-of-memory */inline struct site_file_t *file_create( void ) { struct site_file_t *file; file = malloc( sizeof(struct site_file_t) ); if( file!=NULL ) { /* Initialize */ memset( file, 0, sizeof(struct site_file_t) ); } return file;}/* Creates a file prepended on to the beginning of the site files list. * Returns NULL if the file could not be malloc'ed. */struct site_file_t *file_prepend( struct site_t *site ) { struct site_file_t *file; file = file_create(); if( file == NULL ) return NULL; if( site->files == NULL ) { /* Empty list */ site->files = file; site->files_tail = file; } else { /* Non-empty list... update pointers */ site->files->prev = file; file->next = site->files; site->files = file; } return file;}/* Deletes the given file from the given site */void file_delete( struct site_t *site, struct site_file_t *item ) { if( item->prev ) { /* Not first in list */ item->prev->next = item->next; } else { /* Not last in list */ site->files = item->next; } if( item->next ) { /* Not last in list */ item->next->prev = item->prev; } else { /* Last in list */ site->files_tail = item->prev; } /* Safety */ item->prev = NULL; item->next = NULL;}/* Creates a file added on to the end of the site files list. * Returns NULL if the file could not be malloc'ed. */struct site_file_t *file_append( struct site_t *site ) { struct site_file_t *file; file = file_create(); if( file == NULL ) return NULL; if( site->files_tail == NULL ) { /* Empty list */ site->files = file; site->files_tail = file; } else { /* Non-empty list... update pointers */ site->files_tail->next = file; file->prev = site->files_tail; site->files_tail = file; } return file;}/* Returns whether the given filename is excluded from the * given site */bool file_isexcluded( const char *filename, const char *fullpath, struct site_t *site ) { struct exclude_t *excl; DEBUG( DEBUG_FILES, "\nChecking excludes:\n" ); for( excl=site->excludes; excl != NULL; excl=excl->next ) { DEBUG( DEBUG_FILES, "%s ", excl->pattern ); if( excl->haspath ) { if( fnmatch( excl->pattern, fullpath, FNM_PATHNAME ) == 0 ) break; } else { if( fnmatch( excl->pattern, filename, 0 ) == 0 ) break; } } if( excl != NULL ) { /* excluded */ DEBUG( DEBUG_FILES, "- matched\n" ); return true; } else { DEBUG( DEBUG_FILES, "... not matched.\n" ); return false; }}bool file_isascii( char *filename, struct site_t *site ) { int n; DEBUG( DEBUG_FILES, "\nChecking ASCII list:\n" ); for( n=0; n != site->numascii; n++ ) { DEBUG( DEBUG_FILES, "%s ", site->ascii[n] ); if( fnmatch( site->ascii[n], filename, 0 ) == 0 ) break; } if( n < site->numascii ) { DEBUG( DEBUG_FILES, "- matched\n" ); return true; } else { DEBUG( DEBUG_FILES, "... not matched.\n" ); return false; }}struct site_t *site_find( const char *sitename ) { struct site_t *current; for( current = all_sites; current!=NULL; current=current->next ) { if( strcmp( current->name, sitename ) == 0 ) { /* We found it */ return current; } } return NULL;}static int site_synch_create_directories( struct site_t *the_site ) { struct site_file_t *current; int ret; ret = 0; for( current=the_site->files; current!=NULL; current=current->next ) { if( current->dir && current->diff==file_deleted ) { fe_synching( current ); if( mkdir( current->full_local, 0755 ) == 0 ) { fe_synched( current, true, NULL ); } else { ret = 1; fe_synched( current, false, strerror(errno) ); } } } return ret;}static int site_synch_files( struct site_t *the_site ) { struct site_file_t *current; struct utimbuf times; int ret; ret = 0; for( current = the_site->files; current!=NULL; current=current->next ) { if( current->dir ) continue; switch( current->diff ) { case file_changed: case file_deleted: fe_synching( current ); if( CALL(file_download)( current->full_local,current->full_remote, current->remotesize, current->isascii ) != PROTO_OK ) { fe_synched( current, false, the_site->driver->last_error ); ret = 2; } else { /* Change the modtime of the local file so it doesn't look * like it's changed already */ times.actime = current->remotetime; times.modtime = current->remotetime; if( utime( current->full_local, × ) < 0 ) { fe_synched( current, false, strerror(errno) ); ret = 2; } else { fe_synched( current, true, NULL ); } } break; case file_new: fe_synching( current ); if( unlink( current->full_local ) != 0 ) { fe_synched( current, false, strerror(errno) ); ret = 2; } else { fe_synched( current, true, NULL ); } break; case file_moved: fe_synching( current ); if( rename( current->full_local, current->old->full_local ) == 0 ) { fe_synched( current, true, NULL ); } else { fe_synched( current, false, strerror(errno) ); ret = 2; } default: break; } } return ret;}static int site_synch_remove_directories( struct site_t *the_site ) { struct site_file_t *current; int ret; ret = 0; for( current=the_site->files_tail; current!=NULL; current=current->prev ) { if( current->dir && (current->diff==file_new) ) { fe_synching( current ); if( rmdir( current->full_local ) == -1 ) { fe_synched( current, false, strerror(errno) ); ret = 3; } else { fe_synched( current, true, NULL ); } } } return ret;}/* Resyncs the LOCAL site with the REMOTE site. * This is site_update backwards, and is essentially the same in structure, * except with the logic reversed. */int site_synch( struct site_t *the_site ) { int ret; ret = proto_init( the_site );
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -