developer's diary

最近はc#のエントリが多いです

C初心者がmemcached-1.4.5を追いかける。(5)

C初心者がmemcached-1.4.5を追いかける。(4)の続き
ソースはコチラにてDLしました。

getoptで受け取ったパラメータによって処理を行っている部分を追いかける。

memcached.c(4313行目あたり)

        switch (c) {
        case 'a':
            /* access for unix domain socket, as octal mask (like chmod)*/
            settings.access= strtol(optarg,NULL,8);
            break;

strtol(3)関数で引数を8進数に変換。

ちなみにgetopt部分

    while (-1 != (c = getopt(argc, argv,
          "a:"  /* access mask for unix socket */


getoptの第3引数の:コロンはaのパラメータに引き数が必要であることを示している*1

memcashed -a 0700

等で実行した時に-aと一緒に渡されるパラメータをsettings.accessに設定している所か。


settings.accessは何?

struct settings {
    int access;  /* access mask (a la chmod) for unix domain socket */
};
static void settings_init(void) {
    settings.access = 0700;
}

翻訳してみる。

/* access for unix domain socket, as octal mask (like chmod)*/
エキサイト 翻訳
/* 8進マスクとしてのunixドメインソケット(chmodのような)のためのアクセス*/


/* access mask (a la chmod) for unix domain socket */
エキサイト 翻訳
/* unixドメインソケットのためのアクセスマスク(chmodのような) */

何を設定しているかわ分からないけどもchmodが関連するということは、権限関連か。デフォルトで0700*2が設定されている

ソース内で使用している所は↓の2箇所

/* 2429行目 */
static void process_stat_settings(ADD_STAT add_stats, void *c) {
    APPEND_STAT("umask", "%o", settings.access);

/* 4622行目 */
int main (int argc, char **argv) {
    /* create unix mode sockets after dropping privileges */
    if (settings.socketpath != NULL) {
        errno = 0;
        if (server_socket_unix(settings.socketpath,settings.access)) {
            vperror("failed to listen on UNIX socket: %s", settings.socketpath);
            exit(EX_OSERR);
        }
    }

2箇所といいつつserver_socket_unix関数に渡しているが。。


memcached.c(3946行目)

static int server_socket_unix(const char *path, int access_mask) {
    int sfd;
    struct linger ling = {0, 0};
    struct sockaddr_un addr;
    struct stat tstat;
    int flags =1;
    int old_umask;

    if (!path) {
        return 1;
    }

    if ((sfd = new_socket_unix()) == -1) {
        return 1;
    }

    /*
     * Clean up a previous socket file if we left it around
     */
    if (lstat(path, &tstat) == 0) {
        if (S_ISSOCK(tstat.st_mode))
            unlink(path);
    }

    setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags));
    setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags));
    setsockopt(sfd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));

    /*
     * the memset call clears nonstandard fields in some impementations
     * that otherwise mess things up.
     */
    memset(&addr, 0, sizeof(addr));

    addr.sun_family = AF_UNIX;
    strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
    assert(strcmp(addr.sun_path, path) == 0);
    old_umask = umask( ~(access_mask&0777));
    if (bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
        perror("bind()");
        close(sfd);
        umask(old_umask);
        return 1;
    }
    umask(old_umask);
    if (listen(sfd, settings.backlog) == -1) {
        perror("listen()");
        close(sfd);
        return 1;
    }
    if (!(listen_conn = conn_new(sfd, conn_listening,
                                 EV_READ | EV_PERSIST, 1,
                                 local_transport, main_base))) {
        fprintf(stderr, "failed to create listening connection\n");
        exit(EXIT_FAILURE);
    }

    return 0;
}

続きは↓
C初心者がmemcached-1.4.5を追いかける。(6){起動オプション -U}

*1:http://www.linux.or.jp/JM/html/LDP_man-pages/man3/getopt.3.htmlに書いてありました。

*2:所有者による読み取り、書き込み、実行 (検索) を許可します。