g_tree.c
来自「Non-Networked File System在几个非网络的(或慢网络的)U」· C语言 代码 · 共 580 行
C
580 行
/* NNFS: Non-Networked File System. * Copyright (C) 1995-2002 Thierry EXCOFFIER (exco@ligim.univ-lyon1.fr) * * 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. */#include "g_debug.h"#include "g_malloc.h"#include "g_nnfs.h"#include "g_file.h"#include "g_read.h"#include "g_tree.h"#include "g_dir.h"#include "g_secure.h"#include "g_copy.h"#include "g_dspbar.h"#include "g_report.h"#include "g_histo.h"#include "g_update.h"#include "g_filter.h"#if HAVE_UNISTD_H#include <unistd.h>#endif#if HAVE_ERRNO_H#include <errno.h>#endif#if HAVE_UTIME_H#include <utime.h>#endif/* * */void g_Tree_Travel1( g_NNFS *nnfs, g_File_Info *f, void (*fct)(g_NNFS *, g_File_Info*), void (*post)(g_NNFS *, g_File_Info*)){int i ;int cl, ml ;g_File_Info *dir ;int child, dir_len ;if ( fct ) (*fct)(nnfs, f) ;ml = 0 ;for(i=0;i<f->nb_children;i++) { cl = strlen(f->children[i]->name) ; if ( cl > ml ) ml = cl ; }cl = strlen(nnfs->state.name) ;if ( cl + ml + 2 > nnfs->state.max_file_name ) { nnfs->state.max_file_name = cl + ml + 2 ; nnfs->state.name = g_Realloc(nnfs->state.name, nnfs->state.max_file_name) ; }nnfs->state.name[cl] = G_CHAR_SEPARATOR ;dir = nnfs->state.dir ;child = nnfs->state.child ;dir_len = nnfs->state.dir_len ;nnfs->state.dir_len = cl ; /* Len without the last / */nnfs->state.dir = f ;for(i=0;i<f->nb_children;i++) { strcpy(&nnfs->state.name[cl+1], f->children[i]->name) ; nnfs->state.child = i ; g_Tree_Travel1(nnfs, f->children[i], fct, post) ; }nnfs->state.name[cl] = '\0' ;nnfs->state.dir = dir ;nnfs->state.child = child ;nnfs->state.dir_len = dir_len ;if ( post ) (*post)(nnfs, f) ;}void g_Tree_Travel( g_NNFS *nnfs, void (*fct)(g_NNFS *, g_File_Info*), void (*post)(g_NNFS *, g_File_Info*)){#ifdef __CHECKER__ nnfs->state.child = 0 ; nnfs->state.dir_len = 0 ;#endif nnfs->state.dir = nnfs->state.nnfs ; g_Tree_Travel1(nnfs, nnfs->state.nnfs, fct, post) ;}/* * */static int g_nb_files ;static void g_File_Count(g_NNFS *nnfs, g_File_Info *fi){g_nb_files++ ;}int g_Nb_Files(g_NNFS *nnfs){g_nb_files = 0 ;g_Tree_Travel(nnfs, g_File_Count, NULL) ;return(g_nb_files) ;}/* * */void g_Filter_A_File(g_NNFS *nnfs, g_File_Info *f){g_Display_Bar() ;if ( nnfs->state.name[1] ) /* Not the "." file */f->filtered = g_Eval_Filter(nnfs->state.name+2, &f->hosts[f->nnfs_to_local ? f->up_to_date : nnfs->header.nb_fs], nnfs->config.output) ;/* * Solve "tst/test29" problems */if ( nnfs->state.dir->to_delete && !f->to_delete ) f->to_delete = g_True ;/* * * All is done now for the file * Send stats to user interface * */if ( f->to_delete ) nnfs->state.nb_to_delete++ ;if ( f->local_to_nnfs && !f->filtered && !f->hosts[f->up_to_date].type != g_Is_A_Directory ) nnfs->state.nb_local_to_nnfs++ ;if ( f->nnfs_to_local && !f->to_delete && !f->hosts[f->up_to_date].type != g_Is_A_Directory ) nnfs->state.nb_nnfs_to_local++ ;if ( f->local_change ) nnfs->state.nb_local_change++ ;if ( f->nnfs_change ) nnfs->state.nb_nnfs_change++ ;if ( f->read_error ) nnfs->state.nb_read_error++ ;if ( f->conflict ) nnfs->state.nb_conflict++ ;if ( f->hosts[nnfs->header.nb_fs].type != g_Is_A_Deleted ) nnfs->state.nb_local_file++ ;if ( f->local_to_nnfs && !f->filtered && f->hosts[f->up_to_date].type != g_Is_A_Deleted && !(!f->nnfs_to_local && f->hosts[nnfs->header.nb_fs].type == g_Is_A_Deleted) ) nnfs->state.nb_byte += f->hosts[f->up_to_date].size ;if ( strcmp( nnfs->state.name, "." ) ){ if ( (f->conflict || f->to_delete || f->nnfs_to_local || f->local_to_nnfs) && !f->filtered ) g_Output_Binary2(G_FILE, f, sizeof(*f)+ nnfs->header.nb_fs * sizeof(g_File_On_Host), nnfs->state.name + nnfs->state.dir->to_delete ) ; if ( f->filtered && !f->conflict && !f->to_delete && f->hosts[f->up_to_date].type!=g_Is_Not_Supported ) { fprintf(nnfs->state.filteredlogfile, "%s\n", nnfs->state.name+2) ; return ; } if ( f->nnfs_to_local || f->local_to_nnfs || f->to_delete || f->conflict ) { fprintf(nnfs->state.logfile, "%c%c%c%c%c%c%c %s\n", f->nnfs_to_local ? 'R' : ' ', f->local_to_nnfs ? 'W' : ' ', f->to_delete ? 'D' : ' ', f->conflict ? 'C' : ' ', f->nnfs_filtered ? 'f' : ' ', f->filtered ? 'F' : ' ', f->to_historize ? 'H' : ' ', nnfs->state.name+2) ; fprintf(nnfs->state.logfile, g_other_file_info(nnfs->header.nb_fs, f,1)) ; }}return ;}/* * */void G_FUNCTION(g_Write_An_Nnfs_File, (g_NNFS *nnfs, g_File_Info *info))int i ;G_PF("File = %s\n", info->name) ;g_Display_Bar() ;g_fprintf(nnfs->state.output, "%s%c%d %d %x\n", info->name, '\0', /* On medium: should be same expression as in g_Write_A_File */ /* (info->local_to_nnfs && !info->filtered && !info->read_error)*//* To fix test47 the 13/12/2002 */ (info->local_to_nnfs && !info->filtered && ( !info->read_error || !info->nnfs_to_local) )/* 22/2/98 */ || ( info->hosts[info->up_to_date].type == g_Is_A_Directory ) , /* filtered and error */ (info->filtered || (info->nnfs_filtered&&!info->local_to_nnfs))+ /* (info->read_error?2:0) *//* To fix test47 the 13/12/2002 */ ((info->read_error && info->nnfs_to_local)?2:0) , info->nb_children) ;for(i=0;i<nnfs->header.nb_fs;i++) g_fprintf(nnfs->state.output,"%d %x %lx %lx %d %d"#ifdef ROOTNNFS " %x %x"#endif "\n" ,info->hosts[i].type ,info->hosts[i].mode ,info->hosts[i].date ,info->hosts[i].size ,info->hosts[i].up_to_date ,info->hosts[i].to_historize#ifdef ROOTNNFS ,info->hosts[i].uid ,info->hosts[i].gid#endif ) ;G_RETURN(;) ;}/* * */void G_FUNCTION(g_File_Changement,(g_NNFS *nnfs, g_File_Info *b))g_File_On_Host *a, after_info ;struct stat after ;a = &b->hosts[nnfs->header.fs_id] ;if ( lstat(nnfs->state.name, &after) ){ b->write_error = g_Error_Deleted ;}else { g_Stat_To_File_On_Host(&after, &after_info, &nnfs->config) ; if ( a->type != after_info.type ) b->write_error = g_Error_Type_Changed ; else#if HAVE_LINK_MTIME if ( a->date != after_info.date ) b->write_error = g_Error_Time_Changed ; else#endif if ( a->mode != after_info.mode ) b->write_error = g_Error_Mode_Changed ; else if ( a->size != after_info.size ) b->write_error = g_Error_Size_Changed ; }g_fprintf(nnfs->state.output, "%d\n", b->write_error != g_No_Error) ;G_RETURN(;) ;} /* * fs_id */void G_FUNCTION(g_Write_A_File,(g_NNFS *nnfs, g_File_Info *a))int size ;FILE *r ;int i ;char buf[G_LINE_CHUNK] ;/* old versionif ( a->local_to_nnfs && !a->filtered && !a->read_error)*//* To fix test47 the 13/12/2002 */G_PF("local2nnfs %d filtered %d readerr=%d nnfs2local %d\n", a->local_to_nnfs, a->filtered ,a->read_error,a->nnfs_to_local) ;if ( a->local_to_nnfs && !a->filtered && ( !a->read_error || !a->nnfs_to_local) ) { g_Display_Bar() ; G_PF("File = %s\n",nnfs->state.name) ; switch( a->hosts[nnfs->header.fs_id].type ) { case g_Is_A_File : r = fopen(nnfs->state.name,"r") ; G_PF("Open %s = %d\n", nnfs->state.name,(int)r) ; if ( r ) { if ( g_Copy_Stream(r, nnfs->state.output, a->hosts[nnfs->header.fs_id].size) ) { a->write_error = g_Error_Read ; G_PF("error copy\n") ; } if ( fclose(r) ) { a->error = ERROR_NUMBER ; a->write_error = g_Error_Close ; } } else {/* g_fprintf(nnfs->state.output, "11\ncan't read\n") ;*/ a->error = ERROR_NUMBER ; a->write_error = g_Error_Open ; strcpy(buf, nnfs->state.name) ; for(i=strlen(buf);i<G_LINE_CHUNK;i++) buf[i] = " Source File Can't be Read\n"[i%26]; i = a->hosts[nnfs->header.fs_id].size ; while( i>G_LINE_CHUNK ) { fwrite(buf, 1, G_LINE_CHUNK, nnfs->state.output) ; i -= G_LINE_CHUNK ; } fwrite(buf, 1, i, nnfs->state.output) ; } g_File_Changement(nnfs,a) ; break ; case g_Is_A_Directory : case g_Is_A_FIFO : case g_Is_A_Deleted : break ; case g_Is_A_Link : size = readlink(nnfs->state.name, buf, G_LINE_CHUNK) ; if ( size <= 0 ) { a->write_error = g_Error_Read_Link ; a->error = ERROR_NUMBER ; g_fprintf(nnfs->state.output, "1\n?") ; perror(nnfs->state.name) ; } else { g_fprintf(nnfs->state.output, "%d\n", size) ; fwrite(buf, 1, size, nnfs->state.output) ; } g_File_Changement(nnfs,a) ; break ; case g_Is_Not_Supported: G_PRINTF("Bug!") ; g_Display_File_Info(nnfs,a) ; G_EXIT(1) ; } }if ( a->write_error != g_No_Error ){fprintf(stderr, "NNFS: %s\nNNFS: Error ", nnfs->state.name) ;switch( a->write_error ){ case g_Error_Deleted: fprintf(stderr, "the file was deleted while NNFS was running\n") ; break ; case g_Error_Type_Changed : fprintf(stderr, "the file type changed while NNFS was running\n") ; break ; case g_Error_Mode_Changed: fprintf(stderr, "the file mode changed while NNFS was running\n") ; break ; case g_Error_Size_Changed: fprintf(stderr, "the file size changed while NNFS was running\n") ; break ; case g_Error_Read: fprintf(stderr, "while reading the file\n") ; break ; case g_Error_Close: fprintf(stderr, "closing the file\n") ; fprintf(stderr, "%s\n", sys_errlist[a->error]) ; break ; case g_Error_Open: fprintf(stderr, "opening the file\n") ; fprintf(stderr, "%s\n", sys_errlist[a->error]) ; break ; case g_Error_Read_Link: fprintf(stderr, "reading the symbolic link\n") ; fprintf(stderr, "%s\n", sys_errlist[a->error]) ; break ; case g_No_Error: fprintf(stderr, "BUG !\n") ; break ; default: fprintf(stderr, "unknown\n") ; break ;}}G_RETURN(;) ;}/* * */void G_FUNCTION(g_Always_Delete_A_File,(g_NNFS *nnfs, g_File_Info *a))g_Display_Bar() ;switch( a->hosts[nnfs->header.nb_fs].type ) { case g_Is_A_Directory : if ( rmdir(nnfs->state.name) ) { if ( errno!=ENOENT ) { g_Printf("I can't delete the directory ``%s''\n", nnfs->state.name) ; g_Printf("Delete the directory yourself\n"); g_Ask_User_To_Free_Disk_Space(nnfs,"free", nnfs->state.name) ; } } break ; case g_Is_A_Deleted : break ; default : g_Historize(nnfs,a) ; break ; }G_RETURN(;) ;}void G_FUNCTION(g_Delete_A_File,(g_NNFS *nnfs, g_File_Info *a))int i ;if ( a->to_delete ) g_Always_Delete_A_File(nnfs, a) ;/* 15/08/2001 Add the if */if ( ( !a->local_change && a->hosts[a->up_to_date].type != g_Is_A_Directory)|| ( a->local_change && a->hosts[nnfs->header.nb_fs].type != g_Is_A_Directory) ) G_RETURN(;) ; for(i=0;i<a->nb_children;i++) if ( a->children[i]->nnfs_to_local ) { a->need_time_stamp = g_True ; break ; }G_RETURN(;) ;}/* * */void G_FUNCTION(g_Time_Stamp_A_File,(g_NNFS *nnfs, g_File_Info *a))struct utimbuf t ;struct stat st ;int i ;G_PF("Time stamp %s\n", nnfs->state.name) ;g_Display_Bar() ;/* 17/4/1998if ( a->read_error ) a->filtered = g_True ;*/a->update_nnfs = a->local_change && !a->need_time_stamp ;/* if ( a->conflict ) a->update_nnfs = g_False ; */ /* 06/08/97 */a->need_time_stamp |= a->nnfs_to_local && a->hosts[a->up_to_date].type != g_Is_A_Link ;if ( a->hosts[a->up_to_date].type == g_Is_A_Deleted || a->read_error ) a->need_time_stamp = g_False ;a->read_file_info = a->nnfs_to_local && a->hosts[a->up_to_date].type == g_Is_A_Link && !a->read_error ;if ( a->nnfs_to_local && !a->read_error) { G_PF("Take up to date informations\n") ; a->hosts[nnfs->header.fs_id] = a->hosts[a->up_to_date] ; a->hosts[nnfs->header.fs_id].up_to_date = g_True ; }if ( a->need_time_stamp ) { t.actime = a->hosts[a->up_to_date].date ; t.modtime = a->hosts[a->up_to_date].date ; if ( utime(nnfs->state.name, &t) ) { perror(nnfs->state.name) ; fprintf(stderr, "NNFS: Error setting file date\n") ; a->error = ERROR_NUMBER ; a->read_error = g_Error_Get_Time ; } else { /* Directory case, date modified */ G_PF("Set file date informations: OK\n") ; a->hosts[nnfs->header.fs_id].date = a->hosts[a->up_to_date].date ; } }if ( a->read_file_info ) /* Only for Symbolics links */ { G_PF("Reread ALL file informations\n") ; if ( lstat( nnfs->state.name, &st ) ) { perror(nnfs->state.name) ; fprintf(stderr, "NNFS: Error reading file informations\n") ; a->read_error = g_Error_Lstat ; g_Time_Stamp_A_File(nnfs, a) ; G_RETURN(;) ; } else { g_File_On_Host n ; g_Stat_To_File_On_Host(&st, &n, &nnfs->config ) ; if ( n.type == a->hosts[nnfs->header.fs_id].type && n.size == a->hosts[nnfs->header.fs_id].size /* 18/08/2001 */ ) { a->hosts[nnfs->header.fs_id] = n ; a->hosts[nnfs->header.fs_id].up_to_date = g_True ; } else { perror(nnfs->state.name) ; fprintf(stderr, "NNFS: file type changed while reading\n") ; a->read_error = g_Error_Type_Change_While_Read ; g_Time_Stamp_A_File(nnfs, a) ; G_RETURN(;) ; } } }if ( a->update_nnfs ) { G_PF("Update nnfs informations\n") ; a->hosts[nnfs->header.fs_id] = a->hosts[nnfs->header.nb_fs] ; for(i=0;i<nnfs->header.nb_fs;i++) a->hosts[i].up_to_date = g_False ; a->hosts[nnfs->header.fs_id].up_to_date = g_True ; }for(i=0;i<nnfs->header.nb_fs;i++) if ( a->hosts[i].up_to_date ) G_RETURN(;) ;g_Display_File_Info(nnfs,a) ;G_EXIT(1) ;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?