Пример #1
0
posix_errno_t efile_open(const efile_path_t *path, enum efile_modes_t modes,
        ErlNifResourceType *nif_type, efile_data_t **d) {

    DWORD attributes, access_flags, open_mode;
    HANDLE handle;

    ASSERT_PATH_FORMAT(path);

    access_flags = 0;
    open_mode = 0;

    if(modes & EFILE_MODE_READ && !(modes & EFILE_MODE_WRITE)) {
        access_flags = GENERIC_READ;
        open_mode = OPEN_EXISTING;
    } else if(modes & EFILE_MODE_WRITE && !(modes & EFILE_MODE_READ)) {
        access_flags = GENERIC_WRITE;
        open_mode = CREATE_ALWAYS;
    } else if(modes & EFILE_MODE_READ_WRITE) {
        access_flags = GENERIC_READ | GENERIC_WRITE;
        open_mode = OPEN_ALWAYS;
    } else {
        return EINVAL;
    }

    if(modes & EFILE_MODE_APPEND) {
        access_flags |= FILE_APPEND_DATA;
        open_mode = OPEN_ALWAYS;
    }

    if(modes & EFILE_MODE_EXCLUSIVE) {
        open_mode = CREATE_NEW;
    }

    if(modes & EFILE_MODE_SYNC) {
        attributes = FILE_FLAG_WRITE_THROUGH;
    } else {
        attributes = FILE_ATTRIBUTE_NORMAL;
    }

    handle = CreateFileW((WCHAR*)path->data, access_flags,
        FILE_SHARE_FLAGS, NULL, open_mode, attributes, NULL);

    if(handle != INVALID_HANDLE_VALUE) {
        efile_win_t *w;

        w = (efile_win_t*)enif_alloc_resource(nif_type, sizeof(efile_win_t));
        w->handle = handle;

        EFILE_INIT_RESOURCE(&w->common, modes);
        (*d) = &w->common;

        return 0;
    } else {
        DWORD last_error = GetLastError();

        /* Rewrite all failures on directories to EISDIR to match the old
         * driver. */
        if(has_file_attributes(path, FILE_ATTRIBUTE_DIRECTORY)) {
            return EISDIR;
        }

        return windows_to_posix_errno(last_error);
    }
}
Пример #2
0
posix_errno_t efile_open(const efile_path_t *path, enum efile_modes_t modes,
        ErlNifResourceType *nif_type, efile_data_t **d) {

    int flags, fd;

    flags = 0;

    if(modes & EFILE_MODE_READ && !(modes & EFILE_MODE_WRITE)) {
        flags |= O_RDONLY;
    } else if(modes & EFILE_MODE_WRITE && !(modes & EFILE_MODE_READ)) {
        if(!(modes & EFILE_MODE_NO_TRUNCATE)) {
            flags |= O_TRUNC;
        }

        flags |= O_WRONLY | O_CREAT;
    } else if(modes & EFILE_MODE_READ_WRITE) {
        flags |= O_RDWR | O_CREAT;
    } else {
        return EINVAL;
    }

    if(modes & EFILE_MODE_APPEND) {
        flags &= ~O_TRUNC;
        flags |= O_APPEND;
    }

    if(modes & EFILE_MODE_EXCLUSIVE) {
        flags |= O_EXCL;
    }

    if(modes & EFILE_MODE_SYNC) {
#ifndef O_SYNC
        return ENOTSUP;
#else
        flags |= O_SYNC;
#endif
    }

    do {
        fd = open((const char*)path->data, flags, FILE_MODE);
    } while(fd == -1 && errno == EINTR);

    if(fd != -1) {
        efile_unix_t *u;

        if(!(modes & EFILE_MODE_SKIP_TYPE_CHECK) && !open_file_type_check(path, fd)) {
            close(fd);

            /* This is blatantly incorrect, but we're documented as returning
             * this for everything that isn't a file. */
            return EISDIR;
        }

        u = (efile_unix_t*)enif_alloc_resource(nif_type, sizeof(efile_unix_t));
        u->fd = fd;

        EFILE_INIT_RESOURCE(&u->common, modes);
        (*d) = &u->common;

        return 0;
    }

    (*d) = NULL;
    return errno;
}