Ejemplo n.º 1
0
tb_size_t tb_directory_temporary(tb_char_t* path, tb_size_t maxn)
{
    // check
    tb_assert_and_check_return_val(path && maxn > 4, 0);

    // the temporary directory
    return tb_strlcpy(path, "/tmp", maxn);
}
Ejemplo n.º 2
0
tb_char_t const* tb_addrinfo_name(tb_ipaddr_ref_t addr, tb_char_t* name, tb_size_t maxn)
{
    // check
    tb_assert_and_check_return_val(addr && name && maxn, tb_null);

#if defined(TB_CONFIG_POSIX_HAVE_GETNAMEINFO)
    // load socket address
    struct sockaddr_storage saddr;
    socklen_t saddrlen = (socklen_t)tb_sockaddr_load(&saddr, addr);
    tb_assert_and_check_return_val(saddrlen, tb_null);

    // get host name from address
    return !getnameinfo((struct sockaddr const*)&saddr, saddrlen, name, maxn, tb_null, 0, NI_NAMEREQD)? name : tb_null;
#elif defined(TB_CONFIG_POSIX_HAVE_GETHOSTBYNAME)

    // done
    struct hostent* hostaddr = tb_null;
    switch (tb_ipaddr_family(addr))
    {
    case TB_IPADDR_FAMILY_IPV4:
        {
            // init ip address
            struct in_addr ipaddr = {0};
            ipaddr.s_addr = tb_ipaddr_ip_is_any(addr)? INADDR_ANY : addr->u.ipv4.u32;

            // get host name from address
            hostaddr = gethostbyaddr((tb_char_t const*)&ipaddr, sizeof(ipaddr), AF_INET);
        }
        break;
    case TB_IPADDR_FAMILY_IPV6:
        {
            // init ip address
            struct in6_addr ipaddr;
            tb_memset(&ipaddr, 0, sizeof(ipaddr));

            // save ipv6
            if (tb_ipaddr_ip_is_any(addr)) ipaddr = in6addr_any;
            else tb_memcpy(ipaddr.s6_addr, addr->u.ipv6.addr.u8, sizeof(ipaddr.s6_addr));

            // get host name from address
            hostaddr = gethostbyaddr((tb_char_t const*)&ipaddr, sizeof(ipaddr), AF_INET6);
        }
        break;
    default:
        break;
    }
    tb_check_return_val(hostaddr && hostaddr->h_name, tb_null);

    // save name
    tb_strlcpy(name, hostaddr->h_name, maxn);

    // ok?
    return name;
#else
    tb_trace_noimpl();
    return tb_null;
#endif
}
Ejemplo n.º 3
0
Archivo: true.c Proyecto: luxuan/tbox
static tb_char_t const* tb_element_true_cstr(tb_element_ref_t element, tb_cpointer_t data, tb_char_t* cstr, tb_size_t maxn)
{
    // check
    tb_assert_and_check_return_val(element && cstr && maxn, "");

    // format string
    tb_strlcpy(cstr, "true", maxn - 1); cstr[maxn - 1] = '\0';

    // ok?
    return (tb_char_t const*)cstr;
}
Ejemplo n.º 4
0
static tb_void_t tb_test_strncpy(tb_char_t const* s2, tb_size_t size)
{
    __tb_volatile__ tb_int_t    n = 1000000;
    tb_char_t s1[4096];
    tb_hong_t t = tb_mclock();
    while (n--)
    {
        tb_strlcpy(s1, s2, size);
    }
    t = tb_mclock() - t;
    tb_printf("%lld ms, tb_test_strncpy(%s, %d) = %s\n", t, s2, size, s1);
}
Ejemplo n.º 5
0
tb_size_t tb_directory_temp(tb_char_t* path, tb_size_t maxn)
{
    // check
    tb_assert_and_check_return_val(path && maxn > 4, 0);

    // the temporary directory
    tb_strlcpy(path, "/tmp", maxn - 1);
    path[4] = '\0';

    // ok
    return 4;
}
Ejemplo n.º 6
0
Archivo: str.c Proyecto: luxuan/tbox
static tb_void_t tb_element_str_repl(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data)
{
    // check
    tb_assert_and_check_return(element && element->dupl && buff);

#if 0
    // free it
    if (element->free) element->free(element, buff);

    // dupl it
    element->dupl(element, buff, data);
#else
    // replace it
    tb_pointer_t cstr = *((tb_pointer_t*)buff);
    if (cstr && data)
    {
        // attempt to replace it
        tb_char_t*          p = (tb_char_t*)cstr;
        tb_char_t const*    q = (tb_char_t const*)data;
        while (*p && *q) *p++ = *q++;

        // not enough space?
        if (!*p && *q)
        {
            // the left size
            tb_size_t left = tb_strlen(q);
            tb_assert_abort(left);

            // the copy size
            tb_size_t copy = p - (tb_char_t*)cstr;

            // grow size
            cstr = tb_ralloc(cstr, copy + left + 1);
            tb_assert_abort(cstr);

            // copy the left data
            tb_strlcpy((tb_char_t*)cstr + copy, q, left + 1); 

            // update the cstr
            *((tb_pointer_t*)buff) = cstr;
        }
        // end
        else *p = '\0';
    }
    // duplicate it
    else if (data) element->dupl(element, buff, data);
    // free it
    else if (element->free) element->free(element, buff);
    // clear it
    else *((tb_char_t const**)buff) = tb_null;
#endif
}
Ejemplo n.º 7
0
static tb_void_t tb_directory_walk_impl(tb_char_t const* path, tb_bool_t recursion, tb_bool_t prefix, tb_directory_walk_func_t func, tb_cpointer_t priv)
{
    // check
    tb_assert_and_check_return(path && func);

    // last
    tb_long_t       last = tb_strlen(path) - 1;
    tb_assert_and_check_return(last >= 0);

    // init info
    tb_char_t       temp[4096] = {0};
    DIR*            directory = tb_null;
    if ((directory = opendir(path)))
    {
        // walk
        struct dirent* item = tb_null;
        while ((item = readdir(directory)))
        {
            // check
            tb_assert_and_check_continue(item->d_name && item->d_reclen);

            // the item name
            tb_char_t name[1024] = {0};
            tb_strlcpy(name, item->d_name, tb_min(item->d_reclen, 1023));
            if (tb_strcmp(name, ".") && tb_strcmp(name, ".."))
            {
                // the temp path
                tb_long_t n = tb_snprintf(temp, 4095, "%s%s%s", path, path[last] == '/'? "" : "/", name);
                if (n >= 0) temp[n] = '\0';

                // the file info
                tb_file_info_t info = {0};
                if (tb_file_info(temp, &info))
                {
                    // do callback
                    if (prefix) func(temp, &info, priv);

                    // walk to the next directory
                    if (info.type == TB_FILE_TYPE_DIRECTORY && recursion) tb_directory_walk_impl(temp, recursion, prefix, func, priv);
    
                    // do callback
                    if (!prefix) func(temp, &info, priv);
                }
            }
        }

        // exit directory
        closedir(directory);
    }
}
Ejemplo n.º 8
0
tb_size_t tb_environment_get(tb_char_t const* name, tb_char_t* values, tb_size_t maxn)
{
    // check
    tb_assert_and_check_return_val(name && values && maxn, 0);

    // init values
    tb_string_t valuestrs;
    if (!tb_string_init(&valuestrs)) return 0;

    // init environment
    tb_environment_ref_t environment = tb_environment_init();
    if (environment)
    {
        // load variable
        if (tb_environment_load(environment, name))
        {
            // make values
            tb_bool_t is_first = tb_true;
            tb_for_all_if (tb_char_t const*, value, environment, value)
            {
                // append separator
                if (!is_first) tb_string_chrcat(&valuestrs, TM_ENVIRONMENT_SEP);
                else is_first = tb_false;

                // append value
                tb_string_cstrcat(&valuestrs, value);
            }
        }

        // exit environment
        tb_environment_exit(environment);
    }

    // save result
    tb_size_t           size = tb_string_size(&valuestrs);
    tb_char_t const*    cstr = tb_string_cstr(&valuestrs);
    if (size && cstr) 
    {
        // copy it
        size = tb_strlcpy(values, cstr, maxn);
        tb_assert(size < maxn);
    }

    // exit values
    tb_string_exit(&valuestrs);

    // ok?
    return size;
}
Ejemplo n.º 9
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * main
 */ 
tb_int_t tb_demo_coroutine_http_server_main(tb_int_t argc, tb_char_t** argv)
{
    // done
    tb_socket_ref_t sock = tb_null;
    do
    {
        // init socket
        sock = tb_socket_init(TB_SOCKET_TYPE_TCP, TB_IPADDR_FAMILY_IPV4);
        tb_assert_and_check_break(sock);

        // bind socket
        tb_ipaddr_t addr;
        tb_ipaddr_set(&addr, tb_null, TB_DEMO_PORT, TB_IPADDR_FAMILY_IPV4);
        if (!tb_socket_bind(sock, &addr)) break;

        // listen socket
        if (!tb_socket_listen(sock, 1000)) break;

        // init the root directory
        if (argv[1]) tb_strlcpy(g_rootdir, argv[1], sizeof(g_rootdir));
        else tb_directory_current(g_rootdir, sizeof(g_rootdir));

        // only data?
        if (!tb_file_info(g_rootdir, tb_null)) g_onlydata = tb_true;

        // trace
        tb_trace_i("%s: %s", g_onlydata? "data" : "rootdir", g_rootdir);

#if TB_DEMO_CPU > 1
        // start workers for multi-threads
        tb_size_t count = TB_DEMO_CPU - 1;
        while (count--) tb_thread_init(tb_null, tb_demo_coroutine_worker, sock, 0);
#endif

        // start worker
        tb_demo_coroutine_worker(sock);

    } while (0);

    // exit socket
    if (sock) tb_socket_exit(sock);
    sock = tb_null;

    // ok
    return 0;
}
Ejemplo n.º 10
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * implementation
 */
tb_int_t xm_path_translate(lua_State* lua)
{
    // check
    tb_assert_and_check_return_val(lua, 0);

    // get the path 
    tb_char_t const* path = luaL_checkstring(lua, 1);
    tb_check_return_val(path, 0);

    // copy path
    tb_char_t data[TB_PATH_MAXN];
    tb_strlcpy(data, path, sizeof(data));

    // done path:translate() 
    lua_pushstring(lua, tb_path_translate(data, 0, sizeof(data) - 1)? data : tb_null);

    // ok
    return 1;
}
Ejemplo n.º 11
0
Archivo: option.c Proyecto: waruqi/tbox
/* //////////////////////////////////////////////////////////////////////////////////////
 * implementation
 */
tb_option_ref_t tb_option_init(tb_char_t const* name, tb_char_t const* help, tb_option_item_t const* opts)
{
    // check
    tb_assert_and_check_return_val(name && opts, tb_null);

    // done
    tb_bool_t           ok = tb_false;
    tb_option_impl_t*   impl = tb_null;
    do
    {
        // make option
        impl = tb_malloc0_type(tb_option_impl_t);
        tb_assert_and_check_break(impl);

        // init option
        impl->opts = opts;
        impl->list = tb_oc_dictionary_init(TB_OC_DICTIONARY_SIZE_MICRO, tb_false);
        tb_assert_and_check_break(impl->list);

        // init name
        tb_strlcpy(impl->name, name, sizeof(impl->name));

        // init help
        if (!tb_string_init(&impl->help)) break;
        if (help) tb_string_cstrcpy(&impl->help, help);

        // ok
        ok = tb_true;

    } while (0);

    // failed?
    if (!ok)
    {
        // exit it
        if (impl) tb_option_exit((tb_option_ref_t)impl);
        impl = tb_null;
    }

    // ok?
    return (tb_option_ref_t)impl;
}
Ejemplo n.º 12
0
static tb_void_t tb_ifaddrs_interface_done_hwaddr(tb_list_ref_t interfaces, tb_hash_map_ref_t names, struct nlmsghdr* response)
{
    // check
    tb_assert_and_check_return(interfaces && names && response);

    // the info
    struct ifaddrmsg* info = (struct ifaddrmsg *)NLMSG_DATA(response);

    // attempt to find the interface name
    tb_bool_t   owner = tb_false;
    tb_char_t*  name = (tb_char_t*)tb_hash_map_get(names, tb_u2p(info->ifa_index));
    if (!name)
    {
        // get the interface name
        struct rtattr*  rta = tb_null;
        tb_size_t       rta_size = NLMSG_PAYLOAD(response, sizeof(struct ifaddrmsg));
        for(rta = IFLA_RTA(info); RTA_OK(rta, rta_size); rta = RTA_NEXT(rta, rta_size))
        {
            // done
            tb_pointer_t    rta_data = RTA_DATA(rta);
            tb_size_t       rta_data_size = RTA_PAYLOAD(rta);
            switch(rta->rta_type)
            {
                case IFLA_IFNAME:
                    {
                        // make name
                        name = (tb_char_t*)tb_ralloc(name, rta_data_size + 1);
                        tb_assert_and_check_break(name);

                        // copy name
                        tb_strlcpy(name, rta_data, rta_data_size + 1);

                        // save name
                        tb_hash_map_insert(names, tb_u2p(info->ifa_index), name);
                        owner = tb_true;
                    }
                    break;
                default:
                    break;
            }
        }
    }

    // check
    tb_check_return(name);

    // done
    struct rtattr*  rta = tb_null;
    tb_size_t       rta_size = NLMSG_PAYLOAD(response, sizeof(struct ifaddrmsg));
    for(rta = IFLA_RTA(info); RTA_OK(rta, rta_size); rta = RTA_NEXT(rta, rta_size))
    {
        /* attempt to get the interface from the cached interfaces
         * and make a new interface if no the cached interface
         */
        tb_ifaddrs_interface_t      interface_new = {0};
        tb_ifaddrs_interface_ref_t  interface = tb_ifaddrs_interface_find((tb_iterator_ref_t)interfaces, name);
        if (!interface) interface = &interface_new;

        // check
        tb_assert(interface == &interface_new || interface->name);

        // done
        tb_pointer_t    rta_data = RTA_DATA(rta);
        tb_size_t       rta_data_size = RTA_PAYLOAD(rta);
        switch(rta->rta_type)
        {
            case IFLA_ADDRESS:
                {
                    // no hwaddr?
                    if (!(interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR))
                    {
                        // check
                        tb_check_break(rta_data_size == sizeof(interface->hwaddr.u8));

                        // save flags
                        interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR;
                        if (info->ifa_flags & IFF_LOOPBACK) interface->flags |= TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK;

                        // save hwaddr
                        tb_memcpy(interface->hwaddr.u8, rta_data, sizeof(interface->hwaddr.u8));

                        // trace
                        tb_trace_d("name: %s, hwaddr: %{hwaddr}", name, &interface->hwaddr);

                        // new interface? save it
                        if (interface == &interface_new)
                        {
                            // save interface name
                            interface->name = tb_strdup(name);
                            tb_assert(interface->name);

                            // save interface
                            tb_list_insert_tail(interfaces, interface);
                        }
                    }
                }
                break;
            case IFLA_IFNAME:
            case IFLA_BROADCAST:
            case IFLA_STATS:
                break;
            default:
                break;
        }
    }

    // exit name
    if (name && owner) tb_free(name);
    name = tb_null;
}
Ejemplo n.º 13
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * implementation
 */
tb_size_t tb_directory_temporary(tb_char_t* path, tb_size_t maxn)
{
    // check
    tb_assert_and_check_return_val(path && maxn > 4, 0);

    // the jvm
    JavaVM* jvm = tb_android_jvm();
    tb_assert_and_check_return_val(jvm, 0);

    // attempt to get jni environment first
    JNIEnv*     jenv = tb_null; 
    tb_bool_t   jattached = tb_false;
    if ((*jvm)->GetEnv(jvm, (tb_pointer_t*)&jenv, JNI_VERSION_1_4) != JNI_OK) 
    {
        // bind jni environment
        if ((*jvm)->AttachCurrentThread(jvm, &jenv, tb_null) != JNI_OK) return 0;

        // attach ok
        jattached = tb_true;
    }
    tb_assert_and_check_return_val(jenv, 0);

    // enter
    if ((*jenv)->PushLocalFrame(jenv, 10) < 0) return 0;

    // done
    tb_size_t   size = 0;
    jboolean    error = tb_false;
    do
    {
        // get the environment class
        jclass environment = (*jenv)->FindClass(jenv, "android/os/Environment");
        tb_assert_and_check_break(!(error = (*jenv)->ExceptionCheck(jenv)) && environment);

        // get the getDownloadCacheDirectory func
        jmethodID getDownloadCacheDirectory_func = (*jenv)->GetStaticMethodID(jenv, environment, "getDownloadCacheDirectory", "()Ljava/io/File;");
        tb_assert_and_check_break(getDownloadCacheDirectory_func);

        // get the download cache directory 
        jobject directory = (*jenv)->CallStaticObjectMethod(jenv, environment, getDownloadCacheDirectory_func);
        tb_assert_and_check_break(!(error = (*jenv)->ExceptionCheck(jenv)) && directory);

        // get file class
        jclass file_class = (*jenv)->GetObjectClass(jenv, directory);
        tb_assert_and_check_break(!(error = (*jenv)->ExceptionCheck(jenv)) && file_class);

        // get the getPath func
        jmethodID getPath_func = (*jenv)->GetMethodID(jenv, file_class, "getPath", "()Ljava/lang/String;");
        tb_assert_and_check_break(getPath_func);

        // get the directory path
        jstring path_jstr = (jstring)(*jenv)->CallObjectMethod(jenv, directory, getPath_func);
        tb_assert_and_check_break(!(error = (*jenv)->ExceptionCheck(jenv)) && path_jstr);

        // get the path string length
        size = (tb_size_t)(*jenv)->GetStringLength(jenv, path_jstr);
        tb_assert_and_check_break(size);

        // get the path string
        tb_char_t const* path_cstr = (*jenv)->GetStringUTFChars(jenv, path_jstr, tb_null);
        tb_assert_and_check_break(path_cstr);

        // trace
        tb_trace_d("temp: %s", path_cstr);

        // copy it
        tb_size_t need = tb_min(size + 1, maxn);
        tb_strlcpy(path, path_cstr, need);

        // exit the path string
        (*jenv)->ReleaseStringUTFChars(jenv, path_jstr, path_cstr);

    } while (0);

    // exception? clear it
    if (error) (*jenv)->ExceptionClear(jenv);

    // leave
    (*jenv)->PopLocalFrame(jenv, tb_null);

    // detach it?
    if (jattached)
    {
        // detach jni environment
        if ((*jvm)->DetachCurrentThread(jvm) == JNI_OK)
            jattached = tb_false;
    }

    // ok?
    return size;
}
Ejemplo n.º 14
0
Archivo: path.c Proyecto: richwu/tbox
tb_char_t const* tb_path_relative_to(tb_char_t const* root, tb_char_t const* path, tb_char_t* data, tb_size_t maxn)
{
    // check
    tb_assert_and_check_return_val(path && data && maxn, tb_null);

    // trace
    tb_trace_d("path: %s", path);

    // the root is the current and the path is absolute? return path directly
    if (!root && !tb_path_is_absolute(path))
    {
        // copy it
        tb_strlcpy(data, path, maxn);

        // translate it
        return tb_path_translate(data, 0, maxn)? data : tb_null;
    }

    // get the absolute path
    tb_size_t path_size = 0;
    tb_char_t path_absolute[TB_PATH_MAXN];
    tb_size_t path_maxn = sizeof(path_absolute);
    path        = tb_path_absolute(path, path_absolute, path_maxn);
    path_size   = tb_strlen(path);
    tb_assert_and_check_return_val(path && path_size && path_size < path_maxn, tb_null);

    // trace
    tb_trace_d("path_absolute: %s", path);

    // get the absolute root
    tb_size_t root_size = 0;
    tb_char_t root_absolute[TB_PATH_MAXN];
    tb_size_t root_maxn = sizeof(root_absolute);
    if (root) 
    {
        // get the absolute root
        root        = tb_path_absolute(root, root_absolute, root_maxn);
        root_size   = tb_strlen(root);
    }
    else
    {
        // get the current directory
        if (!(root_size = tb_directory_current(root_absolute, root_maxn))) return tb_null;

        // translate it
        if (!(root_size = tb_path_translate(root_absolute, root_size, root_maxn))) return tb_null;
        root = root_absolute;
    }
    tb_assert_and_check_return_val(root && root_size && root_size < root_maxn, tb_null);

    // trace
    tb_trace_d("root_absolute: %s", root);

    // same directory? return "."
    if (path_size == root_size && !tb_strncmp(path, root, root_size)) 
    {
        // check
        tb_assert_and_check_return_val(maxn >= 2, ".");

        // return "."
        data[0] = '.';
        data[1] = '\0';
        return data;
    }

    // append separator
    if (path_size + 1 < path_maxn)
    {
        path_absolute[path_size++] = TB_PATH_SEPARATOR;
        path_absolute[path_size] = '\0';
    }
    if (root_size + 1 < root_maxn) 
    {
        root_absolute[root_size++] = TB_PATH_SEPARATOR;
        root_absolute[root_size] = '\0';
    }

    // find the common leading directory
    tb_char_t const*    p = path;
    tb_char_t const*    q = root;
    tb_long_t           last = -1;
    for (; *p && *q && *p == *q; q++, p++)
    {
        // save the last separator
        if (*p == TB_PATH_SEPARATOR) last = q - root;
    }

    // is different directory or outside the windows drive root? using the absolute path
    if (last <= 0 || (last == 2 && root[1] == ':'))
    {
        // the path size
        tb_size_t size = tb_min(path_size - 1, maxn);

        // copy it
        tb_strncpy(data, path, size);
        data[size] = '\0';
    }
    // exists same root?
    else
    {
        // count the remaining levels in root
        tb_size_t count = 0;
        tb_char_t const* l = root + last + 1;
        for (; *l; l++)
        {
            if (*l == TB_PATH_SEPARATOR) count++;
        }

        // append "../" or "..\\"
        tb_char_t* d = data;
        tb_char_t* e = data + maxn;
        while (count--)
        {
            if (d + 3 < e)
            {
                d[0] = '.';
                d[1] = '.';
                d[2] = TB_PATH_SEPARATOR;
                d += 3;
            }
        }

        // append the left path
        l = path + last + 1;
        while (*l && d < e) *d++ = *l++;

        // remove the last separator
        if (d > data) d--;

        // end
        *d = '\0';
    }

    // trace    
    tb_trace_d("relative: %s", data);
    
    // ok?
    return data;
}
Ejemplo n.º 15
0
Archivo: path.c Proyecto: richwu/tbox
tb_char_t const* tb_path_absolute_to(tb_char_t const* root, tb_char_t const* path, tb_char_t* data, tb_size_t maxn)
{
    // check
    tb_assert_and_check_return_val(path && data && maxn, tb_null);

    // trace
    tb_trace_d("path: %s", path);

    // the path is absolute?
    if (tb_path_is_absolute(path))
    {
        // copy it
        tb_strlcpy(data, path, maxn);

        // translate it
        return tb_path_translate(data, 0, maxn)? data : tb_null;
    }

    // get the root directory
    tb_size_t size = 0;
    if (root)
    {
        // copy it
        size = tb_strlcpy(data, root, maxn);
        tb_assert_and_check_return_val(size < maxn, tb_null);
    }
    else
    {
        // get the current directory
        if (!(size = tb_directory_current(data, maxn))) return tb_null;
    }

    // translate the root directory
    size = tb_path_translate(data, size, maxn);

    // trace
    tb_trace_d("root: %s, size: %lu", data, size);

    // is windows path? skip the drive prefix
    tb_char_t* absolute = data;
    if (size > 2 && tb_isalpha(absolute[0]) && absolute[1] == ':' && absolute[2] == TB_PATH_SEPARATOR)
    {
        // skip it
        absolute    += 2;
        size        -= 2;
    }

    // path => data
    tb_char_t const*    p = path;
    tb_char_t const*    t = p;
    tb_char_t*          q = absolute + size;
    tb_char_t const*    e = absolute + maxn - 1;
    while (1)
    {
        if (tb_path_is_separator(*p) || !*p)
        {
            // the item size
            tb_size_t n = p - t;

            // ..? remove item
            if (n == 2 && t[0] == '.' && t[1] == '.')
            {
                // find the last separator
                for (; q > absolute && *q != TB_PATH_SEPARATOR; q--) ;

                // strip it
                *q = '\0';
            }
            // .? continue it
            else if (n == 1 && t[0] == '.') ;
            // append item
            else if (n && q + 1 + n < e)
            {
                *q++ = TB_PATH_SEPARATOR;
                tb_strncpy(q, t, n);
                q += n;
            }
            // empty item? remove repeat
            else if (!n) ;
            // too small?
            else 
            {
                // trace
                tb_trace_e("the data path is too small for %s", path);
                return tb_null;
            }

            // break
            tb_check_break(*p);

            // next
            t = p + 1;
        }

        // next
        p++;
    }

    // end
    if (q > absolute) *q = '\0';
    // root?
    else
    {
        *q++ = TB_PATH_SEPARATOR;
        *q = '\0';
    }

    // trace    
    tb_trace_d("absolute: %s", data);
    
    // ok?
    return data;
}
Ejemplo n.º 16
0
static tb_void_t tb_ifaddrs_interface_done_ipaddr(tb_list_ref_t interfaces, tb_hash_map_ref_t names, struct nlmsghdr* response)
{
    // check
    tb_assert_and_check_return(interfaces && names && response);

    // the info
    struct ifaddrmsg* info = (struct ifaddrmsg *)NLMSG_DATA(response);

    // must be not link 
    tb_assert_and_check_return(info->ifa_family != AF_PACKET);

    // attempt to find the interface name
    tb_bool_t   owner = tb_false;
    tb_char_t*  name = (tb_char_t*)tb_hash_map_get(names, tb_u2p(info->ifa_index));
    if (!name)
    {
        // get the interface name
        struct rtattr*  rta = tb_null;
        tb_size_t       rta_size = NLMSG_PAYLOAD(response, sizeof(struct ifaddrmsg));
        for(rta = IFA_RTA(info); RTA_OK(rta, rta_size); rta = RTA_NEXT(rta, rta_size))
        {
            // done
            tb_pointer_t    rta_data = RTA_DATA(rta);
            tb_size_t       rta_data_size = RTA_PAYLOAD(rta);
            switch(rta->rta_type)
            {
                case IFA_LABEL:
                    {
                        // make name
                        name = (tb_char_t*)tb_ralloc(name, rta_data_size + 1);
                        tb_assert_and_check_break(name);

                        // copy name
                        tb_strlcpy(name, rta_data, rta_data_size + 1);

                        // save name
                        tb_hash_map_insert(names, tb_u2p(info->ifa_index), name);
                        owner = tb_true;
                    }
                    break;
                default:
                    break;
            }
        }
    }

    // check
    tb_check_return(name);

    // done
    struct rtattr*  rta = tb_null;
    tb_size_t       rta_size = NLMSG_PAYLOAD(response, sizeof(struct ifaddrmsg));
    for(rta = IFA_RTA(info); RTA_OK(rta, rta_size); rta = RTA_NEXT(rta, rta_size))
    {
        /* attempt to get the interface from the cached interfaces
         * and make a new interface if no the cached interface
         */
        tb_ifaddrs_interface_t      interface_new = {0};
        tb_ifaddrs_interface_ref_t  interface = tb_ifaddrs_interface_find((tb_iterator_ref_t)interfaces, name);
        if (!interface) interface = &interface_new;

        // check
        tb_assert(interface == &interface_new || interface->name);

        // done
        tb_pointer_t rta_data = RTA_DATA(rta);
        switch(rta->rta_type)
        {
            case IFA_LOCAL:
            case IFA_ADDRESS:
                {
                    // make ipaddr
                    tb_ipaddr_t ipaddr;
                    if (!tb_ifaddrs_netlink_ipaddr_save(&ipaddr, info->ifa_family, info->ifa_index, rta_data)) break;

                    // save flags
                    if ((info->ifa_flags & IFF_LOOPBACK) || tb_ipaddr_ip_is_loopback(&ipaddr)) 
                        interface->flags |= TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK;

                    // save ipaddr
                    switch (tb_ipaddr_family(&ipaddr))
                    {
                    case TB_IPADDR_FAMILY_IPV4:
                        {
                            interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR4;
                            interface->ipaddr4 = ipaddr.u.ipv4;
                        }
                        break;
                    case TB_IPADDR_FAMILY_IPV6:
                        {
                            interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR6;
                            interface->ipaddr6 = ipaddr.u.ipv6;
                        }
                        break;
                    default:
                        break;
                    }

                    // trace
                    tb_trace_d("name: %s, ipaddr: %{ipaddr}", name, &ipaddr);

                    // new interface? save it
                    if (tb_ipaddr_family(&ipaddr) && interface == &interface_new)
                    {
                        // save interface name
                        interface->name = tb_strdup(name);
                        tb_assert(interface->name);

                        // save interface
                        tb_list_insert_tail(interfaces, interface);
                    }
                }
                break;
            case IFA_LABEL:
            case IFA_BROADCAST:
                break;
            default:
                break;
        }
    }

    // exit name
    if (name && owner) tb_free(name);
    name = tb_null;
}
Ejemplo n.º 17
0
tb_bool_t tb_aicp_dns_done(tb_aicp_dns_ref_t dns, tb_char_t const* host, tb_long_t timeout, tb_aicp_dns_done_func_t func, tb_cpointer_t priv)
{
    // check
    tb_aicp_dns_impl_t* impl = (tb_aicp_dns_impl_t*)dns;
    tb_assert_and_check_return_val(impl && func && host && host[0], tb_false);
    
    // trace
    tb_trace_d("done: aico: %p, host: %s: ..", impl->aico, host);

    // init func
    impl->done.func = func;
    impl->done.priv = priv;

    // save host
    tb_strlcpy(impl->host, host, sizeof(impl->host));
 
    // only address? ok
    tb_ipaddr_t addr = {0};
    if (tb_ipaddr_ip_cstr_set(&addr, impl->host, TB_IPADDR_FAMILY_NONE))
    {
        impl->done.func(dns, impl->host, &addr, impl->done.priv);
        return tb_true;
    }

    // try to lookup it from cache first
    if (tb_dns_cache_get(impl->host, &addr))
    {
        impl->done.func(dns, impl->host, &addr, impl->done.priv);
        return tb_true;
    }

    // init server list
    if (!impl->size) impl->size = tb_dns_server_get(impl->list);
    tb_check_return_val(impl->size, tb_false);

    // get the server 
    tb_ipaddr_ref_t server = &impl->list[impl->indx = 0];
    tb_assert_and_check_return_val(!tb_ipaddr_is_empty(server), tb_false);

    // init reqt
    tb_size_t size = tb_aicp_dns_reqt_init(impl);
    tb_assert_and_check_return_val(size, tb_false);

    // init it first if no aico
    if (!impl->aico)
    {
        // init aico
        impl->aico = tb_aico_init(impl->aicp);
        tb_assert_and_check_return_val(impl->aico, tb_false);

        // open aico
        if (!tb_aico_open_sock_from_type(impl->aico, TB_SOCKET_TYPE_UDP, tb_ipaddr_family(server))) return tb_false;

        // init timeout
        tb_aico_timeout_set(impl->aico, TB_AICO_TIMEOUT_SEND, timeout);
        tb_aico_timeout_set(impl->aico, TB_AICO_TIMEOUT_RECV, timeout);
    }

    // post reqt
    return tb_aico_usend(impl->aico, server, impl->data, size, tb_aicp_dns_reqt_func, (tb_pointer_t)impl);
}
Ejemplo n.º 18
0
static tb_bool_t tb_demo_spider_init(tb_demo_spider_t* spider, tb_int_t argc, tb_char_t** argv)
{
    // check
    tb_assert_and_check_return_val(spider && argc && argv, tb_false);

    // done
    tb_bool_t ok = tb_false;
    do
    {
#ifdef TB_CONFIG_MODULE_HAVE_OBJECT
        // init option
        spider->option = tb_option_init("spider", "the spider demo", g_options);
        tb_assert_and_check_break(spider->option);
 
        // done option
        if (!tb_option_done(spider->option, argc - 1, &argv[1])) break;

        // check
        tb_assert_and_check_break(tb_option_find(spider->option, "home"));

        // init home
        if (!tb_url_init(&spider->home)) break;
        tb_url_set(&spider->home, tb_option_item_cstr(spider->option, "home"));
        tb_trace_d("home: %s", tb_url_get(&spider->home));

        // init only home?
        if (tb_option_find(spider->option, "only"))
            spider->home_only = tb_option_item_bool(spider->option, "only");

        // init root
        tb_char_t const* root = tb_option_item_cstr(spider->option, "directory");

        // init user agent
        spider->user_agent = tb_option_item_cstr(spider->option, "agent");

        // init timeout
        if (tb_option_find(spider->option, "timeout"))
            spider->timeout = tb_option_item_sint32(spider->option, "timeout");

        // init limited rate
        if (tb_option_find(spider->option, "rate"))
            spider->limited_rate = tb_option_item_uint32(spider->option, "rate");
#else

        // check
        tb_assert_and_check_break(argv[1]);

        // init home
        if (!tb_url_init(&spider->home)) break;
        spider->home = argv[1]? argv[1] : tb_null;
        tb_trace_d("home: %s", tb_url_get(&spider->home));

        // init root
        tb_char_t const* root = argv[2];
#endif

        // the home host
        tb_char_t const* host = tb_url_host_get(&spider->home);
        tb_assert_and_check_break(host);

        // init home domain
        tb_char_t const* domain = tb_strchr(host, '.');
        if (domain)
        {
            tb_strlcpy(spider->home_domain, domain, sizeof(spider->home_domain) - 1);
            spider->home_domain[sizeof(spider->home_domain) - 1] = '\0';
        }

        // using the default root
        if (root) tb_strlcpy(spider->root, root, sizeof(spider->root) - 1);
        else 
        {
            // the temporary root
            tb_directory_temp(spider->root, sizeof(spider->root) - 1);

            // append spider
            tb_strcat(spider->root, "/spider");
        }
        tb_trace_d("root: %s", spider->root);

        // using the default user agent
        if (!spider->user_agent) spider->user_agent = TB_DEMO_SPIDER_USER_AGENT;

        // using the default timeout
        if (!spider->timeout) spider->timeout = TB_DEMO_SPIDER_TASK_TIMEOUT;

        // using the default rate
        if (!spider->limited_rate) spider->limited_rate = TB_DEMO_SPIDER_TASK_RATE;

        // strip root tail: '/' or '\\'
        tb_size_t size = tb_strlen(spider->root);
        if (size && (spider->root[size - 1] == '/' || spider->root[size - 1] == '\\')) spider->root[size - 1] = '\0';

        // init state
        spider->state = TB_STATE_OK;

        // init lock
        if (!tb_spinlock_init(&spider->lock)) break;

        // init pool
        spider->pool = tb_fixed_pool_init(tb_null, TB_DEMO_SPIDER_TASK_MAXN >> 2, sizeof(tb_demo_spider_task_t), tb_null, tb_null, tb_null);
        tb_assert_and_check_break(spider->pool);

        // init filter
        spider->filter = tb_bloom_filter_init(TB_BLOOM_FILTER_PROBABILITY_0_001, 3, TB_DEMO_SPIDER_FILTER_MAXN, tb_item_func_str(tb_true));
        tb_assert_and_check_break(spider->filter);

        // register lock profiler
#ifdef TB_LOCK_PROFILER_ENABLE
        tb_lock_profiler_register(tb_lock_profiler(), (tb_pointer_t)&spider->lock, "spider");
#endif

        // ok
        ok = tb_true;

    } while (0);

    // failed? help it
#ifdef TB_CONFIG_MODULE_HAVE_OBJECT
    if (!ok && spider->option) tb_option_help(spider->option);
#endif

    // ok?
    return ok;
}
Ejemplo n.º 19
0
static tb_bool_t tb_demo_spider_task_done(tb_demo_spider_t* spider, tb_char_t const* iurl, tb_bool_t* full)
{
    // check
    tb_assert_and_check_return_val(spider && iurl, tb_false);

    // killed?
    tb_check_return_val(TB_STATE_OK == tb_atomic_get(&spider->state), tb_false);

    // only for home?
    if (spider->home_only && !tb_stristr(iurl, spider->home_domain)) 
    {
        // trace
        tb_trace_d("task: done: %s: skip", iurl);
        return tb_true;
    }

    // enter
    tb_spinlock_enter(&spider->lock);

    // done
    tb_bool_t               ok = tb_false;
    tb_size_t               size = 0;
    tb_demo_spider_task_t*  task = tb_null;
    tb_bool_t               repeat = tb_false;
    do
    {
        // check
        tb_assert_and_check_break(spider->filter && spider->pool);

        // the task count
        size = tb_fixed_pool_size(spider->pool);
        
        // make the output url
        if (!tb_demo_spider_make_ourl(spider, iurl, spider->ourl, sizeof(spider->ourl) - 1)) break;

        // have been done already?
        if (!tb_bloom_filter_set(spider->filter, spider->ourl)) 
        {
            // trace
            tb_trace_d("task: size: %lu, done: %s: repeat", size, iurl);

            // ok
            ok = tb_true;
            repeat = tb_true;
            break;
        }

        // trace
        tb_trace_d("task: size: %lu, done: %s: ..", size, iurl);

        // full?
        tb_check_break(size < TB_DEMO_SPIDER_TASK_MAXN);

        // make task
        task = (tb_demo_spider_task_t*)tb_fixed_pool_malloc0(spider->pool);
        tb_assert_and_check_break(task);

        // init task
        task->spider = spider;
        tb_strlcpy(task->iurl, iurl, sizeof(task->iurl) - 1);
        tb_strlcpy(task->ourl, spider->ourl, sizeof(task->ourl) - 1);
           
        // ok 
        ok = tb_true;

    } while (0);

    // leave
    tb_spinlock_leave(&spider->lock);

    // ok?
    if (ok && !repeat)
    {
        // done
        ok = tb_false;
        do
        {
            // check
            tb_assert_and_check_break(task);

            // killed?
            tb_check_break(TB_STATE_OK == tb_atomic_get(&spider->state));

            // repeat?
            if (tb_file_info(task->ourl, tb_null))
            {
                // trace
                tb_trace_d("task: size: %lu, done: %s: repeat", size, iurl);

                // ok
                ok = tb_true;
                repeat = tb_true;
                break;
            }

            // done task
            ok = tb_transfer_pool_done(tb_transfer_pool(), task->iurl, task->ourl, 0, spider->limited_rate, tb_demo_spider_task_save, tb_demo_spider_task_ctrl, task);
            tb_assert_and_check_break(ok);

        } while (0);
    }

    // repeat or failed?
    if (repeat || !ok)
    {
        // exit task
        if (task) tb_demo_spider_task_exit(task);
        task = tb_null;

        // failed?
        if (!full && !ok)
        {
            // trace
            tb_trace_e("task: size: %lu, done: %s: post failed", size, iurl);
        }

        // save full
        if (full) *full = size < TB_DEMO_SPIDER_TASK_MAXN? tb_false : tb_true;
    }

    // ok?
    return ok;
}