Представим ситуацию, когда вам надо использовать в своей программе кусок кода из опенсорсного проекта. В отдельных случаях удастся этот кусок локализовать и просто скопировать не заботясь о зависимости от других библиотек того самого опенсорсного проекта. Я рассмотрю более общий случай, когда зависимости (типы данных или функции) приходится тащить с собой.
В качестве примера будет функционал httpd, который создает хешированную строку фиксированной длины по исходной строке. В httpd так в частности создается путь для кеширования страницы исходя из ее URL. В результате вы сможете с помощью своего достаточно легковесного бинарника проверять есть ли в кеше определенная страница.
#include <stdio.h> #include <apr_md5.h> static void doHash(const char* it, char* val, int nlength, int ndepth) { apr_md5_ctx_t context; unsigned char digest[16]; char tmp[22]; int i, k, d; unsigned int x; static const char enc_table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_@"; apr_md5_init(&context); apr_md5_update(&context, (const unsigned char *) it, strlen(it)); apr_md5_final(digest, &context); /* encode 128 bits as 22 characters, using a modified uuencoding * the encoding is 3 bytes -> 4 characters* i.e. 128 bits is * 5 x 3 bytes + 1 byte -> 5 * 4 characters + 2 characters */ for (i = 0, k = 0; i < 15; i += 3) { x = (digest[i] << 16) | (digest[i + 1] << 8) | digest[i + 2]; tmp[k++] = enc_table[x >> 18]; tmp[k++] = enc_table[(x >> 12) & 0x3f]; tmp[k++] = enc_table[(x >> 6) & 0x3f]; tmp[k++] = enc_table[x & 0x3f]; } /* one byte left */ x = digest[15]; tmp[k++] = enc_table[x >> 2]; /* use up 6 bits */ tmp[k++] = enc_table[(x << 4) & 0x3f]; /* now split into directory levels */ for (i = k = d = 0; d < ndepth; ++d) { memcpy(&val[i], &tmp[k], nlength); k += nlength; val[i + nlength] = '/'; i += nlength + 1; } memcpy(&val[i], &tmp[k], 22 - k); val[i + 22 - k] = '\0'; } int main(int argc, char *argv[]) { // mandatory parameters char* url; if (argc == 2 || argc == 4) // 4 if length and depth were specified { url = argv[1]; } else { printf("\nUsage: HashDir url <length> <depth>\n"); return 1; } // optional parameters int nlength = 3; // my own default values int ndepth = 5; if (argc == 4) { nlength = atoi(argv[2]); ndepth = atoi(argv[3]); } char hash1[66]; char str1[256] = {""}; strcat(str1, url); strcat(str1, "?"); doHash(str1, hash1, nlength, ndepth); char hash2[66]; char str2[512] = {""}; // can't recall what happens here in vanilla httpd, probably something // appended to str2 via strcat() strcat(str2, str1); doHash(str2, hash2, nlength, ndepth); char output[256]; output[0] = '\0'; // sometimes there are junk characters in the beginning, so need to set null length explicitly strcat(output, hash1); strcat(output, ".header.vary/"); strcat(output, hash2); strcat(output, ".data"); printf("\nurl[%s]\nhashed path[%s]\n", url, output); return 0; } |
Сборка осуществляется так:
gcc -m32 -D_GNU_SOURCE -I/apache/include -Llib -laprutil-1 -lapr-1 -lexpat Hasher.c -o Hasher |
(поставьте свой путь к хедерам, нужен apr_md5.h)
Запускается программа с помощью скрипта, который создает необходимое окружение:
#!/bin/sh LD_LIBRARY_PATH=./lib ./Hasher $@ |
В папке lib надо иметь те библиотеки, которые были использованы при сборке: libaprutil-1 libapr-1 libexpat.
Запуск:
./run.sh rrrr 4 3 |
После запуска получается примерно такая строка:
xNQ/QC2/IbV/aZc/r23/tg3kj2Q.header.vary/ZIy/ZJr/5og/jP0/qK6/0c7t4ZA.data