netkite.cpp
来自「包含客户和服务器的升级程序,在linux下可以运行的.」· C++ 代码 · 共 879 行 · 第 1/2 页
CPP
879 行
/* * Copyright (C) 2006, Binary Ma * Licence: GNU GPL 1991 - version 2 * Bug report: binary@eniak.org*/#include <fcntl.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/vfs.h>#include <stdlib.h>#include <sys/time.h>#include <dirent.h>#include <ftw.h>#include <sys/wait.h>#include <sys/mman.h>#include <sys/mount.h>#include <syslog.h>#include <search.h>#include <libgen.h>#include <errno.h>#include "binary.h"#include "connect.h"#include "mdc.h"#include "sharemem.h"#include "hash.h"#include "logger.h"#include "rule.h"#include "calmd5.h"#include "init.h"#include "version.h"const char* PROTOCOL = "PRO_2";const char* XXX = "XXXXXX";const int SUCCESS = 1;const int LOG_PRI = LOG_DAEMON | LOG_DEBUG;const int SIZE_NAME = 256;const int SIZE_PATH = 1024;const int SIZE_INFO = 4096;char g_module_path[SIZE_PATH];char g_module_name[SIZE_NAME];const char* timestr(){ time_t tm; char* ctm; tm = time( NULL ); ctm = ctime( &tm ); if( NULL != ctm ) { int len = strlen( ctm ) - 1; if( '\n' == ctm[len] ) ctm[len] = 0; } else { ctm = "unknown date"; } return ctm;}void log_client( int retval, const char* info, const struct filemap* fmap ){ if( NULL == info || NULL == fmap ) return; const char* strtime = timestr(); const char* state = "success"; char l = '[', r = ']'; if( ACT_REMOVE == fmap->act ) { l = '<', r = '>'; } if( 0 != retval ) state = strerror( errno ); const char* name = fmap->name; char dev[strlen( fmap->device ) + strlen( fmap->name ) + 8]; if( 0 != *fmap->device ) { sprintf( dev, "%s->%s", fmap->device, fmap->name ); name = dev; } syslog( LOG_PRI, "%s %i %s %s %c%s%c", strtime, retval, state, info, l, name, r );}void log_server( int retval, const char* addr, const char* file ){ if( NULL == addr || NULL == file ) return; const char* strtime = timestr(); const char* state = "success"; if( 0 != retval ) state = strerror( errno ); syslog( LOG_PRI, "%s %i %s %s [%s] %s", strtime, retval, state, addr, g_module_name, file );}void log_finish( int order ){ const char* strtime = timestr(); const char* state = "success"; if( ORD_FINISH != order ) state = "break"; syslog( LOG_PRI, "%s %i %s finish", strtime, order, state );}void startlog( const char* info ){ if( NULL == info ) return; const char* strtime = timestr(); syslog( LOG_PRI, "%s %s", strtime, info );}int rmtree( const char* file ){ if( NULL == file ) return -__LINE__; // for safe, i dont provide recursive method return remove( file );}int automount( const char* s, const char* d ){ char* fstype[] = { "ext3", "ext2", "jfs", "reiserfs", "vfat", "msdos" }; int retval = -__LINE__; int loop = sizeof( fstype ) / sizeof( *fstype ); for( int i = 0; i < loop && 0 != retval; i++ ) retval = mount( s, d, fstype[i], MS_NOATIME, NULL ); return retval;}// found the last exist path in transfer stringconst char* existpath( const char* file ){ if( NULL == file ) return NULL; static char exist[SIZE_PATH]; bzero( exist, sizeof( exist ) ); strncpy( exist, file, sizeof( exist ) - 1 ); char* dir = exist; while( 0 != access( dir, F_OK ) ) { dir = dirname( exist ); } return dir;}/* check whether need upgrade return: 0: need upgrade !0: needless upgrade */int isrequired( const char* localfile, const struct filemap* fmap ){ if( NULL == localfile || NULL == fmap ) return -__LINE__; struct stat st; if( 0 == lstat( localfile, &st ) ) { if( ACT_REMOVE == fmap->act ) { int retval = rmtree( localfile ); log_client( retval, "remove", fmap ); return 1; } if( ACT_UNIQUE == fmap->act ) return 1; } else { if( ACT_REMOVE == fmap->act ) return 1; if( ACT_UPDATE == fmap->act ) return 1; // act = create or unique return 0; } // act = create or update, but file exist already bool mode_change = false; if( st.st_uid != fmap->st.st_uid || st.st_gid != fmap->st.st_gid ) { mode_change = true; lchown( localfile, fmap->st.st_uid, fmap->st.st_gid ); } if( st.st_mode != fmap->st.st_mode ) { mode_change = true; chmod( localfile, fmap->st.st_mode ); // mode changed, obtain again lstat( localfile, &st ); } // check whether same file type int retval = 0; if( st.st_mode == fmap->st.st_mode ) { const char* md5 = calculate_md5( localfile ); if( NULL == md5 ) return -__LINE__; retval = !strcmp( md5, fmap->md5 ); } // chmod or chown made the consistent if( 0 != retval && mode_change ) log_client( 0, "change", fmap ); return retval;}// rename file s to d// if d is a directory, remove firstint s_rename( const char* s, const char* d ){ if( NULL == s || NULL == d ) return -__LINE__; struct stat st; if( 0 == lstat( d, &st ) && S_ISDIR( st.st_mode ) ) rmtree( d ); return rename( s, d );} /* clean dest file or create dest valid path */int cleanclog( const char* dest ){ if( NULL == dest ) return -__LINE__; // dont use access function, the dest maybe // invalid symbol link, access will faild struct stat st; int retval = 0; if( 0 == lstat( dest, &st ) ) retval = rmtree( dest ); else retval = createtree( dest ); return retval;}int upgrade_node( const char* dest, const struct filemap* fmap ){ if( NULL == dest || NULL == fmap || 0 == *dest ) return -__LINE__; if( 0 != cleanclog( dest ) ) return -__LINE__; if( S_ISDIR( fmap->st.st_mode ) ) { mkdir( dest, fmap->st.st_mode ); } else { mknod( dest, fmap->st.st_mode, fmap->st.st_rdev ); } return chown( dest, fmap->st.st_uid, fmap->st.st_gid );}int upgrade_link( const char* dest, const char* link, const struct filemap* fmap ){ if( NULL == dest || NULL == link || NULL == fmap || 0 == *dest ) return -__LINE__; if( 0 != cleanclog( dest ) ) return -__LINE__; symlink( link, dest ); return lchown( dest, fmap->st.st_uid, fmap->st.st_gid );}int upgrade_file( const char* src, const char* dest, const struct filemap* fmap ){ if( NULL == src || NULL == dest || NULL == fmap || 0 == *dest ) return -__LINE__; const char* check = existpath( dest ); if( NULL == check ) return -__LINE__; // check free space struct statfs fst; if( -1 == statfs( check, &fst ) ) return -__LINE__; if( (long long)fst.f_bavail * fst.f_bsize < fmap->st.st_size ) return -__LINE__; struct stat st; if( 0 != lstat( dest, &st ) ) createtree( dest ); char tmpfile[strlen( dest ) + strlen( XXX ) + 8]; snprintf( tmpfile, sizeof( tmpfile ), "%s.%s", dest, XXX ); int tmpfd = mkstemp( tmpfile ); if( -1 == tmpfd ) return -__LINE__; close( tmpfd ); memmap map_s( src ); memmap map_t( tmpfile, map_s.size() ); if( MAP_FAILED == map_s.map || MAP_FAILED == map_t.map ) { if( 0 == access( tmpfile, F_OK ) ) remove( tmpfile ); return -__LINE__; } memcpy( map_t.map, map_s.map, map_t.size() ); /* the step is mandatory, because the system's calling page layout * sync is latter than the loop, if no explicite msync calling is * implemented, when the next mmap is called, the statfs will report * that there is enough space to store new data; however, in fact, * there isn't enough space since the most data is stored in page layout */ msync( map_t.map, map_t.size(), MS_SYNC ); mdmethod mdc_s( MDC_MD5 ); mdmethod mdc_t( MDC_MD5 ); const char* md5_s = (char*)mdc_s.sum_file( src ); const char* md5_t = (char*)mdc_t.sum_file( tmpfile ); if( NULL == md5_s || NULL == md5_t || 0 != strcmp( md5_s, md5_t ) ) { remove( tmpfile ); return -__LINE__; } if( 0 != s_rename( tmpfile, dest ) ) { remove( tmpfile ); return -__LINE__; } int retval = 0; if( 0 != chmod( dest, fmap->st.st_mode ) ) retval = -__LINE__; if( 0 != chown( dest, fmap->st.st_uid, fmap->st.st_gid ) ) retval = -__LINE__; return retval;}// if device mode, return device mount point// if non device mode, return ""const char* mkroot( const char* tmppath, const char* device ){ if( NULL == tmppath || NULL == device ) return NULL; // not appear dev segment at rule file if( 0 == *device ) return ""; static char devmnt[SIZE_PATH]; snprintf( devmnt, sizeof( devmnt ), "%s/mnt.%s", tmppath, XXX ); if( NULL == mkdtemp( devmnt ) ) return NULL; if( 0 != automount( device, devmnt ) ) { rmdir( devmnt ); return NULL; } return devmnt;}// search the package position, save to g_module_pathint search( const char* path, const struct stat*, int flag, struct FTW* ){ if( NULL == path ) return -__LINE__; int retval = 0; const char* name = NULL; if( FTW_D == flag ) { char copy[strlen( path ) + 1]; strcpy( copy, path ); name = basename( copy ); if( 0 == strcmp( name, g_module_name ) ) { bzero( g_module_path, sizeof( g_module_path ) ); strncpy( g_module_path, path, sizeof( g_module_path ) - 1 ); retval = SUCCESS; } } return retval;}int send_order( tcpbase* sock, int ORDER ){ if( NULL == sock ) return -__LINE__; int retval = 0; char order = '0' + ORDER; if( sock->send( &order, 1 ) < 0 ) retval = -__LINE__; return retval;}int receive_order( tcpbase* sock ){ if( NULL == sock ) return -__LINE__; char respond[8]; bzero( respond, sizeof( respond ) ); if( sock->recv( respond, sizeof( respond ) - 1 ) < 0 )
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?