Пример #1
0
fs_ptable *fs_ptable_open_filename(const char *fname, int flags)
{
    fs_ptable *pt = calloc(1, sizeof(fs_ptable));

    if (sizeof(struct ptable_header) != 512) {
        fs_error(LOG_CRIT, "ptable header size not 512 bytes");

        return NULL;
    }
    pt->fd = open(fname, FS_O_NOATIME | flags, FS_FILE_MODE);
    if (pt->fd == -1) {
        fs_error(LOG_CRIT, "failed to open ptable %s: %s", fname, strerror(errno));

        return NULL;
    }
    pt->filename = g_strdup(fname);
    pt->flags = flags;
    struct ptable_header header;
    lseek(pt->fd, 0, SEEK_SET);
    if (flags & O_TRUNC || read(pt->fd, &header, sizeof(header)) <= 0) {
        header.id = PTABLE_ID;
        header.size = 1024;
        header.length = 0;
        header.revision = PTABLE_REVISION;
    }
    if (header.id != PTABLE_ID) {
        fs_error(LOG_CRIT, "%s does not look like a ptable file", pt->filename);

        return NULL;
    }
    if (header.revision != PTABLE_REVISION) {
        fs_error(LOG_CRIT, "%s is wrong revision of ptable file", pt->filename);

        return NULL;
    }
    if (map_pt(pt, header.length, header.size)) {
        return NULL;
    }

    return pt;
}
Пример #2
0
fs_row_id fs_ptable_new_row(fs_ptable *pt)
{
    if (!pt->ptr) {
        fs_error(LOG_CRIT, "attempted to get row from unmapped ptable");

        return 0;
    }
    if (pt->header->length == 0) {
        pt->header->length = 1;
    }

    /* we can reuse a free'd row */
    if (pt->header->free_list) {
        fs_row_id newr = pt->header->free_list;
        row *r = &pt->data[newr];
        pt->header->free_list = r->cont;
        r->cont = 0;
        r->data[0] = 0;
        r->data[1] = 0;

        return newr;
    }
        
    if (pt->header->length >= pt->header->size) {
        int length = pt->header->length;
        int size = pt->header->size;
        unmap_pt(pt);
        map_pt(pt, length, size * 2);
    }

    row *r = &pt->data[pt->header->length];
    r->cont = 0;
    r->data[0] = 0;
    r->data[1] = 0;

    return (pt->header->length)++;
}
Пример #3
0
fs_ptable *fs_ptable_open_filename(const char *fname, int flags)
{
    fs_ptable *pt = calloc(1, sizeof(fs_ptable));

    if (sizeof(struct ptable_header) != 512) {
        fs_error(LOG_CRIT, "ptable header size not 512 bytes");
        free(pt);
        return NULL;
    }
    pt->fd = open(fname, FS_O_NOATIME | flags, FS_FILE_MODE);
    if (pt->fd == -1) {
        fs_error(LOG_CRIT, "failed to open ptable %s: %s", fname, strerror(errno));
        free(pt);
        return NULL;
    }
    pt->filename = g_strdup(fname);
    pt->flags = flags;

    if (flags & O_TRUNC && ftruncate(pt->fd, sizeof(struct ptable_header)))
        fs_error(LOG_CRIT, "ftruncate failed: %s", strerror(errno));

    int mflags = PROT_READ;
    if (flags & (O_RDWR | O_WRONLY)) mflags |= PROT_WRITE;
    if (flags & (O_TRUNC)) mflags |= PROT_WRITE;

    struct ptable_header *header = mmap(NULL, sizeof(struct ptable_header), mflags, MAP_FILE | MAP_SHARED, pt->fd, 0);
    if (header == MAP_FAILED || header == NULL) {
        fs_error(LOG_CRIT, "failed to mmap: %s", strerror(errno));
        return NULL;
    }

    if (flags & O_TRUNC) {
        header->id = PTABLE_ID;
        header->size = 1024;
        header->length = 0;
        header->revision = PTABLE_REVISION;

        if (msync(header, sizeof(*header), MS_SYNC)) {
            fs_error(LOG_CRIT, "could not msync %s: %s", pt->filename, strerror(errno));
            munmap(header, sizeof(*header));
            return NULL;
        }
    }
    if (header->id != PTABLE_ID) {
        fs_error(LOG_CRIT, "%s does not look like a ptable file", pt->filename);
        munmap(header, sizeof(*header));
        return NULL;
    }
    if (header->revision != PTABLE_REVISION) {
        fs_error(LOG_CRIT, "%s is wrong revision of ptable file", pt->filename);
        munmap(header, sizeof(*header));
        return NULL;
    }

    if (map_pt(pt, header->length, header->size))
        return NULL;

    if (munmap(header, sizeof(*header)))
        fs_error(LOG_ERR, "could not unmap %s: %s", pt->filename, strerror(errno));

    return pt;
}