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 + -
显示快捷键?