157 lines
4.8 KiB
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;
|
||
|
}
|