incubator-nuttx/libs/libc/stdio/lib_fopencookie.c

157 lines
4.8 KiB
C

/****************************************************************************
* libs/libc/stdio/lib_fopencookie.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <nuttx/tls.h>
#include "libc.h"
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: cookie_read_cb
****************************************************************************/
static ssize_t cookie_read_cb(FAR void *cookie, FAR char *buf, size_t size)
{
/* Per specification: if *read is a null pointer, then reads from the
* custom stream always return end of file.
*/
return 0;
}
/****************************************************************************
* Name: cookie_write_cb
****************************************************************************/
static ssize_t cookie_write_cb(FAR void *cookie, FAR const char *buf,
size_t size)
{
/* Per specification: if *write is a null pointer, then output to the
* stream is discarded.
*/
return size;
}
/****************************************************************************
* Name: cookie_seek_cb
****************************************************************************/
static off_t cookie_seek_cb(FAR void *cookie, FAR off_t *offset, int whence)
{
/* Per specification: if *seek is a null pointer, then it is not
* possible to perform seek operations on the stream.
*/
set_errno(ENOTSUP);
return -1;
}
/****************************************************************************
* Name: cookie_close_cb
****************************************************************************/
static int cookie_close_cb(FAR void *cookie)
{
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: fopencookie
****************************************************************************/
FAR FILE *fopencookie(FAR void *cookie, FAR const char *mode,
cookie_io_functions_t io_funcs)
{
FAR FILE *filep = NULL;
/* Call fdopen to initialize the stream. The function is called with
* first possible file descriptor (0-2 are reserved). This is only
* to pass the required checks, file descriptor is then rewritten to
* cookie.
*/
filep = fdopen(3, mode);
if (filep == NULL)
{
return NULL;
}
/* Assign cookie to file descriptor (fs_cookie) and assign user
* defined callbacks.
*/
filep->fs_cookie = cookie;
filep->fs_iofunc = io_funcs;
/* Fopencookie Linux specification allows cookie_io_functions_t to be
* filled only partially and thus some callbacks might be NULL and not
* used. For this reason we add internal callbacks that are assigned to
* prevent undefined behaviour and handle correct return value per
* fopencookie specification.
*/
if (filep->fs_iofunc.read == NULL)
{
filep->fs_iofunc.read = cookie_read_cb;
}
if (filep->fs_iofunc.write == NULL)
{
filep->fs_iofunc.write = cookie_write_cb;
}
if (filep->fs_iofunc.seek == NULL)
{
filep->fs_iofunc.seek = cookie_seek_cb;
}
if (filep->fs_iofunc.close == NULL)
{
filep->fs_iofunc.close = cookie_close_cb;
}
return filep;
}