?? sites.c
字號:
int site_readremotefiles( struct site_t *the_site ) { FILE *fp; char buf[BUFSIZ], /* for the line */ tmp[BUFSIZ], /* for the current field */ *pos, /* for the current position within buf */ *point, /* for the curpos within tmp */ *this_file = NULL; struct site_file_t *current; size_t dir_length; int state; /* Get the remote files from the storage file */ DEBUG( DEBUG_FILES, "Reading info file: %s\n", the_site->infofile ); fp = fopen( the_site->infofile, "r" ); if( fp == NULL ) { /* This is not an error condition, since the info file WILL NOT * exist until the site has been created, which is okay, just means * there are 'no' files on the remote site */ return 1; } /* The file exists, so read it. * Format: one item / line, tab-separated fields. * First field is filename of item. * Second field is 'dir' for directory items, or mtime for files * Third field (files only) is size of file */ current = NULL; while( fgets( buf, BUFSIZ, fp) != NULL ) { /* Create a new file item and lob it on the end of the linked * list */ current = file_append( the_site ); /* Make sure we have an end-of-buffer */ buf[BUFSIZ-1] = '\0'; this_file = NULL; /* Now parse the line. Simple DFA, states are: * 0: Reading filename, field 1 * 1: Reading date/time stamp or DIRWORD, field 2 * 2: Reading file size, field 3 (if file) * 3: Junk state - consume-all-crud-till-end-of-line. * * We read the current field into tmp char by char. * point is the current point within tmp. */ state = 0; point = tmp; for( pos = buf; *pos!='\0'; pos++ ) { if( *pos < 0 ) state = 5; switch( state ) { case 0: if( *pos == '\t' ) { /* End of the filename */ *point = '\0'; this_file = strdup( tmp ); point = tmp; state = 1; } else { /* Still in the filename */ *(point++) = *pos; } break; case 1: if( *pos == '\t' || *pos == '\n' ) { /* End of the second field */ *point = '\0'; if( strlen( tmp ) > 0 ) { if( strcmp( tmp, DIRWORD ) == 0 ) { /* It's a directory! */ current->dir = true; state = 3; /* that's all we need */ } else if( strcmp( tmp, LINKWORD ) == 0 ) { current->link = true; point = tmp; state = 4; /* read the link target */ } else { /* It's a file! - field 2 is the mtime */ current->dir = false; current->remotetime = atol( tmp ); point = tmp; state = 2; } } else { /* Corrupt line, we need at least two fields */ /* FIXME: Report this to the user. */ state = 5; } } else { /* Within the second field */ *(point++) = *pos; } break; case 2: if( *pos == '\n' ) { /* End of the size field */ *point = '\0'; current->remotesize = atol( tmp ); state = 3; } else { /* Within the file size field */ *(point++) = *pos; } break; case 3: /* junk state */ break; case 4: /* read the link name */ if( *pos == '\n' ) { /* End of the field */ *point = '\0'; current->remotelink = strdup( tmp ); state = 3; } else { *(point++) = *pos; } case 5: /* error state */ break; } } if( this_file==NULL || state == 5 ) { /* FIXME: Report this to the user */ DEBUG( DEBUG_FILES, "Corrupt line.\n" ); file_delete( the_site, current ); continue; } current->diff = file_deleted; current->filename = strdup( base_name( this_file ) ); /* we are going to chop the leading / of this_file */ if( strlen(current->filename) > strlen(this_file) ) { /* FIXME: Handle these errors properly */ DEBUG( DEBUG_FILES, "Very corrupt line.\n" ); free( current->filename ); file_delete( the_site, current ); continue; } dir_length = strlen(this_file) - strlen(current->filename ) - 1; current->directory = malloc( dir_length + 1 ); strncpy( current->directory, this_file + 1, dir_length ); *(current->directory+dir_length) = '\0'; /* null-term */ DEBUG( DEBUG_FILES, "Split %s is: Dir [%s], name [%s]\n", this_file, current->directory, current->filename ); the_site->numdeleted++; site_assignnames( current, the_site ); DEBUG( DEBUG_FILES, "Remote: [%s] - file: size: %ld time: %ld\n", current->filename, current->remotesize, current->remotetime ); DEBUG( DEBUG_FILES, "Directory: [%s] Filename: %s\n" "rel_local: %s rel_remote: %s\n" "full_local: %s full_remote: %s\n", current->directory, current->filename, current->rel_local, current->rel_remote, current->full_local, current->full_remote ); free( this_file ); } fclose( fp ); return 0;}/* Read the local site files... * A stack is used for directories within the site - this is not recursive. * Each item on the stack is a FULL PATH to the directory, i.e., including * the local site root. */int site_readlocalfiles( struct site_t *the_site ) { char *dirstack[MAXDIRS], *this; char *full = NULL, *fname, *temp; struct stat item; DIR *curdir; struct dirent *ent; int dirtop = 0; size_t dir_length; struct site_file_t *current; /* Push the root directory on to the stack */ dirstack[dirtop++] = strdup( the_site->local_root ); /* Now, for all items in the stack, process all the files, and * add the dirs to the stack. Everything we put on the stack is * temporary and gets freed eventually. */ while( dirtop > 0 ) { /* Pop the stack */ this = dirstack[--dirtop]; DEBUG( DEBUG_FILES, "Dir: %s\n", this ); curdir = opendir( this ); if( curdir == NULL ) { free( this ); continue; } /* Now read all the directory entries */ while( (ent = readdir( curdir )) != NULL ) { if( full != NULL ) free( full ); full = malloc( strlen( this ) + strlen( ent->d_name ) + 1 ); strcpy( full, this ); strcat( full, ent->d_name ); DEBUG( DEBUG_FILES, "Item: %s - ", ent->d_name );#ifndef __EMX__ if( lstat( full, &item ) == -1 ) {#else /* There are no symlinks under OS/2, use stat() instead */ if( stat( full, &item ) == -1 ) {#endif /* FIXME: FE warning here */ continue; }#ifndef __EMX__ /* Is this a symlink? */ if( S_ISLNK( item.st_mode ) ) { DEBUG( DEBUG_FILES, "symlink - " ); if( the_site->symlinks == sitesym_ignore ) { /* Just skip it */ DEBUG( DEBUG_FILES, "ignoring.\n" ); continue; } else if( the_site->symlinks == sitesym_follow ) { DEBUG( DEBUG_FILES, "followed - " ); /* Else, carry on as normal, stat the real file */ if( stat( full, &item ) == -1 ) { /* It's probably a broken link */ DEBUG( DEBUG_FILES, "broken.\n" ); continue; } } else { DEBUG( DEBUG_FILES, "maintained:\n" ); } }#endif /* __EMX__ */ /* Now process it */ /* This is the rel_local of this file - i.e., everything * apart from the local root */ fname = (char *)full+strlen(the_site->local_root)-1; /* Check for excludes */ if( file_isexcluded( ent->d_name, fname, the_site ) ) continue; for( current=the_site->files; current!=NULL; current=current->next ) { if( strcmp( current->rel_local, fname ) == 0 ) /* Match found! */ break;/* last = current; */ } if( S_ISREG( item.st_mode ) ) { DEBUG( DEBUG_FILES, "file - " ); if( current == NULL ) { /* This is a new local file... */ DEBUG( DEBUG_FILES, "new - " ); the_site->numnew++; /* Add a new file to the beginning of the list */ current = file_prepend( the_site ); current->filename = strdup( base_name( fname ) ); /* This is the length of the directory name... * fname = "/full/file/name.ext", filename = "name.ext" * we want directory = "full/file/"... do the maths */ dir_length = strlen(fname) - strlen(current->filename)-1; DEBUG( DEBUG_FILES, "dir_length = %ld\n", (long) dir_length ); current->directory = malloc( dir_length + 1 ); strncpy( current->directory, fname+1, dir_length ); *(current->directory+dir_length) = '\0'; /* nullterm */ DEBUG( DEBUG_FILES, "directory = %s\n", current->directory ); site_assignnames( current, the_site ); current->localtime = item.st_mtime; current->localsize = item.st_size; current->diff = file_new; current->mode = item.st_mode; current->dir = false; the_site->totalnew += item.st_size;/* DEBUG( DEBUG_FILES, "new; size: %ld, time: %ld\n", item.st_size, item.st_mtime ); */ } else { /* Match found... compare it */ current->localtime = item.st_mtime; current->localsize = item.st_size; the_site->numdeleted--; if( (current->localtime > current->remotetime) || (current->localsize != current->remotesize) ) { /* Changed file */ current->diff = file_changed; current->mode = item.st_mode; the_site->numchanged++; the_site->totalchanged += item.st_size; DEBUG( DEBUG_FILES, "changed (%ld -> %ld)\n", current->localtime, current->remotetime ); } else { current->diff = file_unchanged; current->updated = true; the_site->numunchanged++; DEBUG( DEBUG_FILES, "unchanged.\n" ); } /* The names will already have been assigned */ } /* Assign the ASCII type value */ current->isascii = file_isascii( fname, the_site ); } else if( S_ISDIR( item.st_mode ) ) { /* THIS IS A DIRECTORY! */ if( strcmp( ent->d_name, "." )==0 || strcmp( ent->d_name, ".." )==0 ) { DEBUG( DEBUG_FILES, "ignored.\n" ); continue; } DEBUG( DEBUG_FILES, "directory - " ); if( dirtop < MAXDIRS ) { temp = malloc( strlen( full ) + 2 ); strcpy( temp, full ); strcat( temp, "/" ); dirstack[dirtop++] = temp; } else { /* No more room in stack * FIXME: Report this to the user.*/ } if( current == NULL ) { /* New Directory */ the_site->numnew++; current = file_append( the_site ); current->filename = strdup( base_name( fname ) ); /* Work out the directory name */ dir_length = strlen(fname) - strlen(current->filename )-1; current->directory = malloc( dir_length + 1 ); strncpy( current->directory, fname+1, dir_length ); *(current->directory+dir_length) = '\0'; /* null-term */ site_assignnames( current, the_site ); current->dir = true; current->diff = file_new; current->mode = item.st_mode; current->localsize = item.st_size; DEBUG( DEBUG_FILES, "new.\n" ); } else { /* It's an existing directory */ the_site->numdeleted--; the_site->numunchanged++; current->diff = file_unchanged; current->updated = true; DEBUG( DEBUG_FILES, "existing.\n" ); } } #ifndef __EMX__ else if( S_ISLNK( item.st_mode ) ) { char tmp[BUFSIZ]; memset( tmp, 0, BUFSIZ ); DEBUG( DEBUG_FILES, "symlink being maintained.\n" ); if( readlink( full, tmp, BUFSIZ ) == -1 ) { DEBUG( DEBUG_FILES, "readlink failed: %s\n", strerror(errno) ); continue; } DEBUG( DEBUG_FILES, "Link target: %s\n", tmp ); if( current == NULL ) { /* New link */ the_site->numnew++; current = file_append( the_site ); current->filename = strdup( base_name( fname ) ); dir_length = strlen(fname) - strlen(current->filename)-1; DEBUG( DEBUG_FILES, "dir_length = %ld\n", (long) dir_length ); current->directory = malloc( dir_length + 1 ); strncpy( current->directory, fname+1, dir_length ); *(current->directory+dir_length) = '\0'; /* nullterm */ DEBUG( DEBUG_FILES, "directory = %s\n", current->directory ); current->locallink = strdup( tmp ); current->diff = file_new; current->link = true; site_assignnames( current, the_site ); } else { /* Existing link... compare */ the_site->numdeleted--; current->locallink = strdup( tmp ); if( strcmp( current->remotelink, tmp ) == 0 ) { /* Links match */ current->updated = true; current->diff = file_unchanged; the_site->numunchanged++; } else { current->diff = file_changed; the_site->numchanged++; } } }#endif /* __EMX__ */ else { DEBUG( DEBUG_FILES, "something else.\n" ); } } /* Close the open directory */ closedir( curdir ); /* And we're finished with this */ free( this ); } return 0;}static void site_checkmoved( struct site_t *the_site ) { /* Have any files been moved? * We look for new files, then see if we can find a deleted file * which matches filename, mod time, and size exactly. * * This is simplistic, and it is possible to get it wrong in some * (unusual) circumstances: * Old: /bar/file1.zip, /foo/file1.zip * New: /new/file1.zip. * If all the file1.zip's have the same size and mod time, it * IS NOT POSSIBLE to know which one has become /new/file1.zip without * storing remembering the contents of /bar/file1.zip somehow and * comparing, or using a filesystem which remembers stuff. In any case * it's pretty silly to try - so the whole shabang is optional. * * It would probably be better to search for DELETED files, then * check them against NEW files, since files are more often added * to sites then they are deleted. But hey, this is C, who'll notice? */ struct site_file_t *search, *current; /* char *bname, *tmp; */ /* First off, find the new files... */ DEBUG( DEBUG_FILES, "Checking for moved files...\n" );
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -