void cfg_dealloc( conf_t *cfg ) { if( cfg->dbdir ){ pdealloc( cfg->dbdir ); } pdealloc( cfg ); }
static void test_static_exec( const testdata_t data[], size_t len, const char *delim ) { usher_t *u = usher_alloc( delim, NULL ); usher_error_t err; usher_glob_t glob; const testdata_t *item; size_t i, j, vlen; char *sval; for( i = 0; i < len; i++ ){ do_insert( u, i, data ); } for( i = 0; i < len; i++ ) { item = &data[i]; glob.nitems = 0; glob.items = NULL; err = usher_exec( u, item->key, &glob ); if( err ){ printf( "\nEXEC ERR[%zu]: %s -> %s\n", i, item->path, usher_strerror( err ) ); assert(0); } else if( glob.nitems != item->globs.nitems ){ printf( "\nEXEC ERR[%zu]: %s -> number of catch param should be %zu but %zu\n", i, item->path, item->globs.nitems, glob.nitems ); printf( "key: %s\n", item->key ); assert(0); } for( j = 0; j < glob.nitems; j++ ){ assert( strcmp( (const char*)glob.items[j].name, (const char*)item->globs.items[j].name ) == 0 ); vlen = glob.items[j].tail - glob.items[j].head; sval = pnalloc( vlen + 1, char ); memcpy( sval, glob.items[j].head, vlen ); sval[vlen] = 0; assert( strcmp( sval, (const char*)item->globs.items[j].head ) == 0 ); pdealloc( sval ); } usher_glob_dealloc( &glob ); } usher_dealloc( u ); }
conf_t *cfg_alloc( int argc, const char *argv[] ) { conf_t *cfg = palloc( conf_t ); char *val = rindex( argv[0], '/' ); int pagesize = getpagesize(); size_t mbytes = 1048576 / pagesize; *val = 0; if( !cfg ){ pfelog( malloc ); exit( EXIT_FAILURE ); } else if( !val ){ pdealloc( cfg ); pfelog( rindex ); exit( EXIT_FAILURE ); } *val = 0; // set default configration if( !( cfg->dbdir = realpath( argv[0], NULL ) ) ){ pfelog( realpath, "%s", val ); exit( EXIT_FAILURE ); } cfg->addr = DEFAULT_ADDR; cfg->nch = DEFAULT_NCHILD; cfg->bktsize = pagesize; cfg->mapsize = DEFAULT_DBMAPSIZE * mbytes * pagesize; cfg->flgs = DEFAULT_DBFLAGS; cfg->perm = DEFAULT_DBPERM; if( argc > 1 ) { char *opt; char *needle; int i = 1; for(; i < argc; i++ ) { // listen-address if( i + 1 == argc ){ cfg->addr = argv[i]; } else { opt = (char*)argv[i]; val = (char*)argv[++i]; // check opt-type if( *opt != '-' || !isalpha( opt[1] ) || opt[2] ){ config_eexit( opt, "invalid option" ); } else if( !val ){ config_eexit( opt, "undefined value" ); } // check opt val errno = 0; opt++; switch( *opt ) { // mapsize case 'm': cfg->mapsize = buf_strudec2u16( val, needle ); // invalid argument if( errno ){ config_eexit( opt, "%s -- %s", val, strerror(errno) ); } else if( *needle ){ config_eexit( opt, "%s -- %s", val, strerror(EINVAL) ); } else if( !cfg->mapsize ){ cfg->mapsize = mbytes * pagesize; } else { cfg->mapsize = cfg->mapsize * mbytes * pagesize; } break; // db dir case 'd': // remove default-dbdir pdealloc( cfg->dbdir ); cfg->dbdir = realpath( val, NULL ); if( !cfg->dbdir ){ pfelog( realpath ); usage(); } break; // flags case 'f': cfg->flgs = parse_flgs( val ); break; // perm case 'p': cfg->perm = buf_stroct2u16( val, needle ); if( errno ){ config_eexit( opt, "%s -- %s", val, strerror(errno) ); } else if( *needle ){ config_eexit( opt, "%s -- %s", val, strerror(EINVAL) ); } else if( !cfg->perm || cfg->perm > 4095 ){ config_eexit( opt, "0 < |%d| < 4095", cfg->perm ); } break; // thread case 't': cfg->nch = buf_strudec2u8( val, needle ); if( errno ){ config_eexit( opt, "%s -- %s", val, strerror(errno) ); } else if( *needle ){ config_eexit( opt, "%s -- %s", val, strerror(EINVAL) ); } else if( !cfg->nch ){ cfg->nch = DEFAULT_NCHILD; } break; // bucket-size case 'b': cfg->bktsize = buf_strudec2u16( val, needle ); if( errno ){ config_eexit( opt, "%s -- %s", val, strerror(errno) ); exit( EXIT_FAILURE ); } else if( *needle ){ config_eexit( opt, "%s -- %s", val, strerror(EINVAL) ); } else if( !cfg->bktsize ){ cfg->bktsize = pagesize; } break; default: config_eexit( opt, "%s", strerror(EINVAL) ); } } } } return cfg; }
static afd_sock_t *_afd_sock_alloc_inet( int type, const char *addr, size_t len ) { if( len < ASYNCSOCK_INETPATH_MAX ) { // find port separator char *port = memchr( addr, ':', len ); ptrdiff_t hlen = len; ptrdiff_t plen = 0; if( port ) { // port-number undefined if( !port[1] ) { errno = EINVAL; return NULL; } // calc host and port length hlen = (uintptr_t)port - (uintptr_t)addr; plen = len - hlen - 1; port++; } // cannot use wildcard ip-address if port number unspecified else if( *addr == '*' ) { errno = EINVAL; return NULL; } // valid host and port length if( hlen < ASYNCSOCK_FQDN_LEN && plen < ASYNCSOCK_PORT_LEN ) { const struct addrinfo hints = { // AI_PASSIVE:bind socket if node is null .ai_flags = AI_PASSIVE, // AF_INET:ipv4 | AF_INET6:ipv6 .ai_family = AF_UNSPEC, // SOCK_STREAM:tcp | SOCK_DGRAM:udp | SOCK_SEQPACKET .ai_socktype = type, // IPPROTO_TCP:tcp | IPPROTO_UDP:udp | 0:automatic .ai_protocol = 0, // initialize .ai_addrlen = 0, .ai_canonname = NULL, .ai_addr = NULL, .ai_next = NULL }; struct addrinfo *res = NULL; int rc = 0; // getaddrinfo is better than inet_pton. // i wonder that can be ignore an overhead of creating socket // descriptor when i simply want to confirm correct address? // wildcard ip-address if( *addr == '*' ) { rc = getaddrinfo( NULL, port, &hints, &res ); } else { char host[hlen]; memcpy( host, addr, hlen ); host[hlen] = 0; rc = getaddrinfo( host, port, &hints, &res ); } if( rc == 0 ) { afd_sock_t *as = NULL; struct addrinfo *ptr = res; int fd = 0; errno = 0; do { // try to create socket descriptor for find valid address if( ( fd = socket( ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol ) ) != -1 ) { // init socket descriptor if( afd_sockfd_init( fd ) ) { struct sockaddr_in *inaddr = palloc( struct sockaddr_in ); if( inaddr && ( as = palloc( afd_sock_t ) ) ) { as->fd = fd; as->family = ptr->ai_family; as->type = ptr->ai_socktype; as->proto = ptr->ai_protocol; as->addrlen = ptr->ai_addrlen; as->addr = (void*)inaddr; // copy struct sockaddr memcpy( (void*)inaddr, (void*)ptr->ai_addr, (size_t)ptr->ai_addrlen ); break; } else if( inaddr ) { pdealloc( inaddr ); } } close( fd ); break; } } while( ( ptr = ptr->ai_next ) ); // remove address-list freeaddrinfo( res ); return as; } return NULL; } }