netkite.cpp

来自「包含客户和服务器的升级程序,在linux下可以运行的.」· C++ 代码 · 共 879 行 · 第 1/2 页

CPP
879
字号
        return -__LINE__;    return atoi( respond );}// transmit a file to clientint transmit( const char* file, const filemap* fmap, tcpserver* sock ){    if( NULL == file || NULL == fmap || NULL == sock )        return -__LINE__;    send_order( sock, ORD_UNFINISH );    int respond = receive_order( sock );    if( ORD_AFFIRM != respond )        return -__LINE__;        char info[SIZE_INFO];    snprintf( info, sizeof( info ),        "%lli%c%i%c%i%c%i%c%i%c%s%c%i%c%s%c",        (long long)fmap->st.st_size,    INFO_COMPART,        (int)fmap->st.st_mode,          INFO_COMPART,        (int)fmap->st.st_uid,           INFO_COMPART,        (int)fmap->st.st_gid,           INFO_COMPART,        (int)fmap->st.st_rdev,          INFO_COMPART,        fmap->device,                   INFO_COMPART,        fmap->act,                      INFO_COMPART,        fmap->md5,                      INFO_COMPART );    sock->send( info, strlen( info ) );    respond = receive_order( sock );    if( ORD_AFFIRM != respond )        return -__LINE__;    // the file name maybe contain INFO_COMPART,    // will make trouble for extmap, so, do it like this    sock->send( fmap->name, strlen( fmap->name ) );    respond = receive_order( sock );    if( respond < 0 )        return -__LINE__;        int retval = 0;    if( ORD_UPGRADE == respond )    {        if( S_ISREG( fmap->st.st_mode ) )        {            if( sock->sendfile( file ) < 0 )                retval = -__LINE__;        }        else        if( S_ISLNK( fmap->st.st_mode ) )        {            char buflink[SIZE_PATH];            bzero( buflink, sizeof( buflink ) );            readlink( file, buflink, sizeof( buflink ) - 1 );            if( sock->send( buflink, strlen( buflink ) ) < 0 )                retval = -__LINE__;        }        log_server( retval, sock->accept_addr(), file );    }        return retval;}void sigclient( int ){    return;}void siglock( bool lock ){    static sigset_t save;    static sigset_t block;    if( lock )    {        sigfillset( &block );        sigprocmask( SIG_BLOCK, &block, &save );    }    else    {        sigprocmask( SIG_SETMASK, &save, NULL );    }}int start_server( tcpserver* sock, const char* root ){    if( NULL == sock || NULL == root )        return -__LINE__;        // send or receive PROTOCOL first;    char auth[16];    bzero( auth, sizeof( auth ) );    sock->recv( auth, sizeof( auth ) - 1 );    if( 0 != strcmp( auth, PROTOCOL ) )        return 0;    send_order( sock, ORD_AFFIRM );    if( -1 == chroot( root ) || -1 == chdir( "/" ) )    {        ERROR();        return -__LINE__;    }    bzero( g_module_name, sizeof( g_module_name ) );    if( sock->recv( g_module_name, sizeof( g_module_name ) - 1 ) < 0 )        return -__LINE__;        if( SUCCESS == nftw( "/", search, 512, FTW_PHYS ) )    {        // if g_module_path == "/", meet root        while( 0 != strcmp( g_module_path, "/" ) )        {            DIR* dir = opendir( g_module_path );            if( NULL == dir )                return -__LINE__;                        struct dirent* ent = NULL;            chdir( g_module_path );            const filemap* fmap = NULL;            while( NULL != ( ent = readdir( dir ) ) )            {                if( 0 == isdir( ent->d_name ) )                    continue;                            fmap = fillmap( ent->d_name );                if( NULL == fmap || 0 == *fmap->name )                    continue;                if( 0 != transmit( ent->d_name, fmap, sock ) )                    break;            }                        closedir( dir );            dirname( g_module_path );        }    }	    send_order( sock, ORD_FINISH );    return 0;}// if zero can be continueint hash_check( hash* hs, const struct filemap* fmap ){    // overlap mode, shake head...    if( NULL == hs )        return 0;        int offset = 0;    if( '/' == *fmap->name )        offset = 1;    char key[strlen( fmap->device ) + strlen( fmap->name ) + 8];    sprintf( key, "%s:%s", fmap->device, fmap->name + offset );    ENTRY ent;    ent.key = key;    ent.data = NULL;    int retval = 1;    if( NULL == hs->search( ent.key ) )    {        retval = 0;        hs->insert( ent, 0 );    }    return retval;}int start_client( tcpclient* sock, const char* module, const char* tmppath, hash* hs ){    if( NULL == sock || NULL == module || NULL == tmppath )        return -__LINE__;        struct filemap fmap;    char info[SIZE_INFO];    int respond = 0;    sock->send( PROTOCOL, strlen( PROTOCOL ) );    respond = receive_order( sock );    if( ORD_AFFIRM != respond )    {        log_finish( respond );        return -__LINE__;    }    sock->send( module, strlen( module ) );        while( 1 )    {        respond = receive_order( sock );        if( respond < 0 )        {            ERROR();            return -__LINE__;        }        // not have suit upgrade file        // unique quit way        if( ORD_UNFINISH != respond )        {            log_finish( respond );            break;        }                send_order( sock, ORD_AFFIRM );        bzero( &fmap, sizeof( fmap ) );        bzero( info, sizeof( info ) );        if( sock->recv( info, sizeof( info ) - 1 ) < 0 )        {            ERROR();            return -__LINE__;        }        extmap( info, &fmap );        send_order( sock, ORD_AFFIRM );        if( sock->recv( fmap.name, sizeof( fmap.name ) - 1 ) < 0 )        {            ERROR();            return -__LINE__;        }        if( 0 != hash_check( hs, &fmap ) )        {            send_order( sock, ORD_NEXT );            continue;        }                const char* destroot = mkroot( tmppath, fmap.device );        respond = ORD_NEXT;        int len = 0;        if( NULL != destroot )            len = strlen( destroot );        char destfile[ strlen( fmap.name ) + len + 8];        if( NULL != destroot )        {            strcpy( destfile, destroot );            if( '/' != *fmap.name )                strcat( destfile, "/" );                        strcat( destfile, fmap.name );            if( 0 == isrequired( destfile, &fmap ) )                respond = ORD_UPGRADE;        }        else        {            // maybe without such device            log_client( -__LINE__, "error", &fmap );        }                send_order( sock, respond );        if( ORD_UPGRADE == respond )        {            int retval = 0;            if( S_ISREG( fmap.st.st_mode ) )            {                retval = -__LINE__;                char tmpfile[strlen( tmppath ) + strlen( XXX ) + 8];                snprintf( tmpfile, sizeof( tmpfile ), "%s/tmp.%s", tmppath, XXX );                int tmpfd = mkstemp( tmpfile );                if( -1 == tmpfd )                {                    ERROR();                    return -__LINE__;                }                                close( tmpfd );                sock->recvfile( tmpfile );                const char* cal = calculate_md5( tmpfile );                if( NULL != cal && 0 == strcmp( cal, fmap.md5 ) )                {                    // this time, block SIGTERM at least                    siglock( 1 );                    retval = upgrade_file( tmpfile, destfile, &fmap );                    siglock( 0 );                }                if( 0 == access( tmpfile, F_OK ) )                    remove( tmpfile );            }            else            if( S_ISLNK( fmap.st.st_mode ) )            {                retval = -__LINE__;                char link[SIZE_PATH];                bzero( link, sizeof( link ) );                if( sock->recv( link, sizeof( link ) - 1 ) > 0 )                {                    retval = -__LINE__;                    mdmethod mdc( MDC_MD5 );                    const char* cal = mdc.sum_data( link, strlen( link ) );                    if( NULL != cal && 0 == strcmp( cal, fmap.md5 ) )                    {                        siglock( 1 );                        retval = upgrade_link( destfile, link, &fmap );                        siglock( 0 );                    }                }            }            else            {                siglock( 1 );                retval = upgrade_node( destfile, &fmap );                siglock( 0 );            }            log_client( retval, "upgrade", &fmap );        }        if( NULL != destroot && 0 != *destroot )        {            umount( destroot );            rmdir( destroot );        }    }    return 0;}int main( int argc, char* argv[] ){    struct option opt;    init( &opt );    parse_option( argc, argv, &opt );    parse_config( &opt );    umask( 0 );    daemon( 0, 0 );    signal( SIGCHLD, SIG_IGN );    if( opt.log_enable )    {        char startinfo[512];        sprintf( startinfo, "netkite version: %s starting", VERSION );        const char* ident = "client";        if( opt.server_mode )            ident = "server";                duplog( ident, opt.log_file );        startlog( startinfo );        if( opt.server_mode )        {            snprintf( startinfo, sizeof( startinfo ), "server will change root to %s", opt.root );            startlog( startinfo );        }    }    if( opt.server_mode )    {        tcpserver sock( opt.host, opt.port, opt.timeout, opt.backlog );        if( 0 != sock.error() )        {            ERROR();            return -__LINE__;        }        while( 1 )        {            if( 0 != sock.accept() )            {                if( EINTR == errno )                {                    continue;                }                else                {                    ERROR();                    return -__LINE__;                }            }                pid_t pid = fork();            if( pid < 0 )            {                ERROR();                return -__LINE__;            }    	            if( 0 == pid )            {                setsid();                sock.close_listen();                break;            }    		            sock.close_sock();        }        start_server( &sock, opt.root );    }    else    {        sigset_t block;        sigset_t empty;        sigemptyset( &empty );        sigemptyset( &block );        sigaddset( &block, SIGALRM );        sigprocmask( SIG_BLOCK, &block, NULL );        regsignal( SIGALRM, sigclient );        while( 1 )        {            // still have running child process            // block waiting, release system resource            if( -1 != waitpid( -1, NULL, 0 ) )                continue;                        pid_t pid = fork();            if( pid < 0 )            {                ERROR();                return -1;            }                        if( 0 == pid )                break;                        // running once only            if( 0 == opt.idle )                _exit( 0 );                        alarm( opt.idle );            sigsuspend( &empty );        }        tcpclient sock( opt.host, opt.port, opt.timeout );        if( 0 != sock.error() )        {            ERROR();            return -1;        }        hash* hs = NULL;        if( !opt.overlap )            hs = new hash( 1024 * 64 );                start_client( &sock, opt.module, opt.tmp_path, hs );    }    return 0;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?