<commit_before>#include "nfsping.h"
#include "rpc.h"


void usage() {
    printf("Usage: nfsls [options] [filehandle...]\n\
    -T   use TCP (default UDP)\n"); 

    exit(3);
}


entryplus3 *do_readdirplus(CLIENT *client, fsroots_t *dir) {
    READDIRPLUS3res *res;
    entryplus3 *entry, *current, dummy;
    READDIRPLUS3args args = {
        .dir = dir->fsroot,
        .cookie = 0,
        .dircount = 512,
        .maxcount = 8192,
    };
    int i;
    struct rpc_err clnt_err;

    /* the RPC call */
    res = nfsproc3_readdirplus_3(&args, client);

    dummy.nextentry = NULL;
    current = &dummy;

    if (res) {
        /* loop through results, might take multiple calls for the whole directory */
        while (res) {
            if (res->status == NFS3_OK) {
                entry = res->READDIRPLUS3res_u.resok.reply.entries;
                while (entry) {
                    current = malloc(sizeof(entryplus3));
                    current->nextentry = NULL;
                    current = memcpy(current, entry, sizeof(entryplus3));

                    printf("%s:%s", dir->host, dir->path);
                    /* if the path doesn't already end in /, print one now */
                    if (dir->path[strlen(dir->path) - 1] != '/')
                        printf("/");
                    /* the filename */
                    printf("%s", entry->name);
                    /* if it's a directory print a trailing slash */
                    /* TODO this seems to be 0 sometimes */
                    if (entry->name_attributes.post_op_attr_u.attributes.type == NF3DIR)
                        printf("/");
                    printf(":");

                    /* print the filehandle in hex */
                    for (i = 0; i < entry->name_handle.post_op_fh3_u.handle.data.data_len; i++) {
                        printf("%02hhx", entry->name_handle.post_op_fh3_u.handle.data.data_val[i]);
                    }
                    printf("\n");

                    args.cookie = entry->cookie;

                    entry = entry->nextentry;
                    current = current->nextentry;
                }
                if (res->READDIRPLUS3res_u.resok.reply.eof) {
                    break;
                } else {
                    memcpy(args.cookieverf, res->READDIRPLUS3res_u.resok.cookieverf, NFS3_COOKIEVERFSIZE);
                    res = nfsproc3_readdirplus_3(&args, client);
                }
            } else {
                fprintf(stderr, "%s:%s: ", dir->host, dir->path);
                clnt_geterr(client, &clnt_err);
                if (clnt_err.re_status)
                    clnt_perror(client, "nfsproc3_readdirplus_3");
                else
                    nfs_perror(res->status);
                break;
            }
        }
    } else {
        clnt_perror(client, "nfsproc3_readdirplus_3");
    }  

    return dummy.nextentry;
}


int main(int argc, char **argv) {
    int ch;
    int all = 0;
    char input_fh[FHMAX];
    fsroots_t *current, *tail, dummy;
    struct addrinfo hints = {
        .ai_family = AF_INET,
        /* default to UDP */
        .ai_socktype = SOCK_DGRAM,
    };
    CLIENT *client = NULL;
    struct sockaddr_in clnt_info;
    unsigned long version = 3;
    struct timeval timeout = NFS_TIMEOUT;
    entryplus3 *entry;

    while ((ch = getopt(argc, argv, "ahT")) != -1) {
        switch(ch) {
            /* list hidden files */
            case 'a':
                all = 1;
                break;
            /* use TCP */
            case 'T':
                hints.ai_socktype = SOCK_STREAM;
                break;
            case 'h':
            default:
                usage();
        }
    }

    dummy.next = NULL;
    tail = &dummy;

    while (fgets(input_fh, FHMAX, stdin)) {
        tail->next = malloc(sizeof(fsroots_t));
        tail = tail->next;
        tail->next = NULL;

        parse_fh(input_fh, tail);

        tail->client_sock->sin_family = AF_INET;
        tail->client_sock->sin_port = htons(NFS_PORT);
    }

    /* skip the first empty struct */
    current = dummy.next;

    /* loop through the list of targets */
    while (current) {
        /* check if we can use the same client connection as the previous target */
        while (client && current) {
            /* get the server address out of the client */
            clnt_control(client, CLGET_SERVER_ADDR, (char *)&clnt_info);
            while (current) {
                if (clnt_info.sin_addr.s_addr == current->client_sock->sin_addr.s_addr) {
                    entry = do_readdirplus(client, current);
                    current = current->next;
                } else {
                    client = destroy_rpc_client(client);
                    break;
                }
            }
        }
        if (current) {
            /* connect to server */
            client = create_rpc_client(current->client_sock, &hints, NFS_PROGRAM, version, timeout);
            client->cl_auth = authunix_create_default();
        }
    }
}
<commit_msg>move the printing code out of do_readdirplus<commit_after>#include "nfsping.h"
#include "rpc.h"


void usage() {
    printf("Usage: nfsls [options] [filehandle...]\n\
    -T   use TCP (default UDP)\n"); 

    exit(3);
}


/* do readdirplus calls to get a full list of directory entries */
entryplus3 *do_readdirplus(CLIENT *client, fsroots_t *dir) {
    READDIRPLUS3res *res;
    entryplus3 *entry, *current, dummy;
    READDIRPLUS3args args = {
        .dir = dir->fsroot,
        .cookie = 0,
        .dircount = 512,
        .maxcount = 8192,
    };
    struct rpc_err clnt_err;

    /* the RPC call */
    res = nfsproc3_readdirplus_3(&args, client);

    dummy.nextentry = NULL;
    current = &dummy;

    if (res) {
        /* loop through results, might take multiple calls for the whole directory */
        while (res) {
            if (res->status == NFS3_OK) {
                entry = res->READDIRPLUS3res_u.resok.reply.entries;
                while (entry) {
                    current->nextentry = malloc(sizeof(entryplus3));
                    current = current->nextentry;
                    current->nextentry = NULL;
                    current = memcpy(current, entry, sizeof(entryplus3));

                    args.cookie = entry->cookie;

                    entry = entry->nextentry;
                }
                if (res->READDIRPLUS3res_u.resok.reply.eof) {
                    break;
                } else {
                    memcpy(args.cookieverf, res->READDIRPLUS3res_u.resok.cookieverf, NFS3_COOKIEVERFSIZE);
                    res = nfsproc3_readdirplus_3(&args, client);
                }
            } else {
                fprintf(stderr, "%s:%s: ", dir->host, dir->path);
                clnt_geterr(client, &clnt_err);
                if (clnt_err.re_status)
                    clnt_perror(client, "nfsproc3_readdirplus_3");
                else
                    nfs_perror(res->status);
                break;
            }
        }
    } else {
        clnt_perror(client, "nfsproc3_readdirplus_3");
    }  

    return dummy.nextentry;
}


int main(int argc, char **argv) {
    int ch;
    int all = 0;
    char input_fh[FHMAX];
    fsroots_t *current, *tail, dummy;
    struct addrinfo hints = {
        .ai_family = AF_INET,
        /* default to UDP */
        .ai_socktype = SOCK_DGRAM,
    };
    CLIENT *client = NULL;
    struct sockaddr_in clnt_info;
    unsigned long version = 3;
    struct timeval timeout = NFS_TIMEOUT;
    entryplus3 *entry;
    int i;

    while ((ch = getopt(argc, argv, "ahT")) != -1) {
        switch(ch) {
            /* list hidden files */
            case 'a':
                all = 1;
                break;
            /* use TCP */
            case 'T':
                hints.ai_socktype = SOCK_STREAM;
                break;
            case 'h':
            default:
                usage();
        }
    }

    dummy.next = NULL;
    tail = &dummy;

    while (fgets(input_fh, FHMAX, stdin)) {
        tail->next = malloc(sizeof(fsroots_t));
        tail = tail->next;
        tail->next = NULL;

        parse_fh(input_fh, tail);

        tail->client_sock->sin_family = AF_INET;
        tail->client_sock->sin_port = htons(NFS_PORT);
    }

    /* skip the first empty struct */
    current = dummy.next;

    /* loop through the list of targets */
    while (current) {
        /* check if we can use the same client connection as the previous target */
        while (client && current) {
            /* get the server address out of the client */
            clnt_control(client, CLGET_SERVER_ADDR, (char *)&clnt_info);
            while (current) {
                if (clnt_info.sin_addr.s_addr == current->client_sock->sin_addr.s_addr) {
                    entry = do_readdirplus(client, current);
                    while (entry) {
                        printf("%s:%s", current->host, current->path);
                        /* if the path doesn't already end in /, print one now */
                        if (current->path[strlen(current->path) - 1] != '/')
                            printf("/");
                        /* the filename */
                        printf("%s", entry->name);
                        /* if it's a directory print a trailing slash */
                        /* TODO this seems to be 0 sometimes */
                        if (entry->name_attributes.post_op_attr_u.attributes.type == NF3DIR)
                            printf("/");
                        printf(":");

                        /* print the filehandle in hex */
                        for (i = 0; i < entry->name_handle.post_op_fh3_u.handle.data.data_len; i++) {
                            printf("%02hhx", entry->name_handle.post_op_fh3_u.handle.data.data_val[i]);
                        }
                        printf("\n");

                        entry = entry->nextentry;
                    }
                    current = current->next;
                } else {
                    client = destroy_rpc_client(client);
                    break;
                }
            }
        }
        if (current) {
            /* connect to server */
            client = create_rpc_client(current->client_sock, &hints, NFS_PROGRAM, version, timeout);
            client->cl_auth = authunix_create_default();
        }
    }
}

{'fraction_non_alphanumeric': 0.11443408020001923, 'fraction_numerical': 0.007885373593614771, 'mean_word_length': 1.4146737868586023, 'pattern_counts': {'":': 2, '<': 5, '<?xml version=': 0, '>': 69, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '151784', 'n_tokens_mistral': 3159, 'n_tokens_neox': 2959, 'n_words': 681}