Add fcntl(F_DUPFD)
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1995 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
e68c54fea0
commit
297cb5e256
37
fs/fs_dup.c
37
fs/fs_dup.c
@ -47,15 +47,8 @@
|
|||||||
#include <nuttx/fs.h>
|
#include <nuttx/fs.h>
|
||||||
#include "fs_internal.h"
|
#include "fs_internal.h"
|
||||||
|
|
||||||
/* This logic in this applies only when both socket and file descriptors are
|
|
||||||
* in that case, this function descriminates which type of dup is being
|
|
||||||
* performed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Definitions
|
* Pre-processor Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -76,34 +69,40 @@
|
|||||||
|
|
||||||
int dup(int fildes)
|
int dup(int fildes)
|
||||||
{
|
{
|
||||||
|
int ret = OK;
|
||||||
|
|
||||||
/* Check the range of the descriptor to see if we got a file or a socket
|
/* Check the range of the descriptor to see if we got a file or a socket
|
||||||
* descriptor. */
|
* descriptor. */
|
||||||
|
|
||||||
if ((unsigned int)fildes >= CONFIG_NFILE_DESCRIPTORS)
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
|
if ((unsigned int)fildes < CONFIG_NFILE_DESCRIPTORS)
|
||||||
|
{
|
||||||
|
/* Its a valid file descriptor.. dup the file descriptor using any
|
||||||
|
* other file descriptor*/
|
||||||
|
|
||||||
|
ret = file_dup(fildes, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
/* Not a vailid file descriptor. Did we get a valid socket descriptor? */
|
/* Not a vailid file descriptor. Did we get a valid socket descriptor? */
|
||||||
|
|
||||||
|
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
|
||||||
if ((unsigned int)fildes < (CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS))
|
if ((unsigned int)fildes < (CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS))
|
||||||
{
|
{
|
||||||
/* Yes.. dup the socket descriptor */
|
/* Yes.. dup the socket descriptor */
|
||||||
|
|
||||||
return net_dup(fildes);
|
ret = net_dup(fildes, CONFIG_NFILE_DESCRIPTORS);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
/* No.. then it is a bad descriptor number */
|
/* No.. then it is a bad descriptor number */
|
||||||
|
|
||||||
errno = EBADF;
|
errno = EBADF;
|
||||||
return ERROR;
|
ret = ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
return ret;
|
||||||
{
|
|
||||||
/* Its a valid file descriptor.. dup the file descriptor */
|
|
||||||
|
|
||||||
return file_dup(fildes);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_NFILE_DESCRIPTORS > 0 ... */
|
|
||||||
|
|
||||||
|
@ -94,6 +94,11 @@ static inline int file_vfcntl(int fildes, int cmd, va_list ap)
|
|||||||
* exec functions.
|
* exec functions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
{
|
||||||
|
ret = file_dup(fildes, va_arg(ap, int));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case F_GETFD:
|
case F_GETFD:
|
||||||
/* Get the file descriptor flags defined in <fcntl.h> that are associated
|
/* Get the file descriptor flags defined in <fcntl.h> that are associated
|
||||||
* with the file descriptor fildes. File descriptor flags are associated
|
* with the file descriptor fildes. File descriptor flags are associated
|
||||||
|
@ -40,7 +40,6 @@
|
|||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
@ -76,11 +75,7 @@
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
|
int file_dup(int fildes, int minfd)
|
||||||
int file_dup(int fildes)
|
|
||||||
#else
|
|
||||||
int dup(int fildes)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
FAR struct filelist *list;
|
FAR struct filelist *list;
|
||||||
int fildes2;
|
int fildes2;
|
||||||
@ -110,7 +105,8 @@ int dup(int fildes)
|
|||||||
|
|
||||||
fildes2 = files_allocate(list->fl_files[fildes].f_inode,
|
fildes2 = files_allocate(list->fl_files[fildes].f_inode,
|
||||||
list->fl_files[fildes].f_oflags,
|
list->fl_files[fildes].f_oflags,
|
||||||
list->fl_files[fildes].f_pos);
|
list->fl_files[fildes].f_pos,
|
||||||
|
minfd);
|
||||||
if (fildes2 < 0)
|
if (fildes2 < 0)
|
||||||
{
|
{
|
||||||
errno = EMFILE;
|
errno = EMFILE;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* fs/fs_files.c
|
* fs/fs_files.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -361,7 +361,8 @@ errout:
|
|||||||
* Returns the file descriptor == index into the files array.
|
* Returns the file descriptor == index into the files array.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
int files_allocate(FAR struct inode *inode, int oflags, off_t pos)
|
|
||||||
|
int files_allocate(FAR struct inode *inode, int oflags, off_t pos, int minfd)
|
||||||
{
|
{
|
||||||
FAR struct filelist *list;
|
FAR struct filelist *list;
|
||||||
int i;
|
int i;
|
||||||
@ -370,7 +371,7 @@ int files_allocate(FAR struct inode *inode, int oflags, off_t pos)
|
|||||||
if (list)
|
if (list)
|
||||||
{
|
{
|
||||||
_files_semtake(list);
|
_files_semtake(list);
|
||||||
for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++)
|
for (i = minfd; i < CONFIG_NFILE_DESCRIPTORS; i++)
|
||||||
{
|
{
|
||||||
if (!list->fl_files[i].f_inode)
|
if (!list->fl_files[i].f_inode)
|
||||||
{
|
{
|
||||||
|
@ -225,7 +225,7 @@ EXTERN void inode_release(FAR struct inode *inode);
|
|||||||
/* fs_files.c ****************************************************************/
|
/* fs_files.c ****************************************************************/
|
||||||
|
|
||||||
EXTERN void weak_function files_initialize(void);
|
EXTERN void weak_function files_initialize(void);
|
||||||
EXTERN int files_allocate(FAR struct inode *inode, int oflags, off_t pos);
|
EXTERN int files_allocate(FAR struct inode *inode, int oflags, off_t pos, int minfd);
|
||||||
EXTERN int files_close(int filedes);
|
EXTERN int files_close(int filedes);
|
||||||
EXTERN void files_release(int filedes);
|
EXTERN void files_release(int filedes);
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ int open(const char *path, int oflags, ...)
|
|||||||
|
|
||||||
/* Associate the inode with a file structure */
|
/* Associate the inode with a file structure */
|
||||||
|
|
||||||
fd = files_allocate(inode, oflags, 0);
|
fd = files_allocate(inode, oflags, 0, 0);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
ret = EMFILE;
|
ret = EMFILE;
|
||||||
|
@ -344,15 +344,9 @@ EXTERN int files_dup(FAR struct file *filep1, FAR struct file *filep2);
|
|||||||
|
|
||||||
/* fs_filedup.c **************************************************************/
|
/* fs_filedup.c **************************************************************/
|
||||||
|
|
||||||
/* This alternative naming is used when dup could operate on both file and
|
/* Dupicate a file descriptor using any value greater than or equal to minfd */
|
||||||
* socket descritors to avoid drawing unused socket support into the link.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
|
EXTERN int file_dup(int fd, int minfd);
|
||||||
EXTERN int file_dup(int fd);
|
|
||||||
#else
|
|
||||||
# define file_dup(fd) dup(fd)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* fs_filedup2.c *************************************************************/
|
/* fs_filedup2.c *************************************************************/
|
||||||
|
|
||||||
|
@ -166,14 +166,10 @@ EXTERN int net_poll(int sockfd, struct pollfd *fds, boolean setup);
|
|||||||
|
|
||||||
/* net_dup.c *****************************************************************/
|
/* net_dup.c *****************************************************************/
|
||||||
/* The standard dup() operation redirects operations on socket descriptors to
|
/* The standard dup() operation redirects operations on socket descriptors to
|
||||||
* this function (when both file and socket descriptors are supported)
|
* this function
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTOR > 0
|
EXTERN int net_dup(int sockfd, int minsd);
|
||||||
EXTERN int net_dup(int sockfd);
|
|
||||||
#else
|
|
||||||
# define net_dup(sockfd) dup(sockfd)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* net_dup2.c ****************************************************************/
|
/* net_dup2.c ****************************************************************/
|
||||||
/* The standard dup2() operation redirects operations on socket descriptors to
|
/* The standard dup2() operation redirects operations on socket descriptors to
|
||||||
|
@ -318,7 +318,7 @@ int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
|
|||||||
* (so that it cannot fail later)
|
* (so that it cannot fail later)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
newfd = sockfd_allocate();
|
newfd = sockfd_allocate(0);
|
||||||
if (newfd < 0)
|
if (newfd < 0)
|
||||||
{
|
{
|
||||||
err = ENFILE;
|
err = ENFILE;
|
||||||
|
@ -49,12 +49,16 @@
|
|||||||
|
|
||||||
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
|
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Global Functions
|
* Global Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Function: net_dup OR dup
|
* Function: net_dup
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Clone a socket descriptor to an arbitray descriptor number. If file
|
* Clone a socket descriptor to an arbitray descriptor number. If file
|
||||||
@ -64,11 +68,7 @@
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTOR > 0
|
int net_dup(int sockfd, int minsd)
|
||||||
int net_dup(int sockfd)
|
|
||||||
#else
|
|
||||||
int dup(int sockfd)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
FAR struct socket *psock1 = sockfd_socket(sockfd);
|
FAR struct socket *psock1 = sockfd_socket(sockfd);
|
||||||
FAR struct socket *psock2;
|
FAR struct socket *psock2;
|
||||||
@ -76,6 +76,22 @@ int dup(int sockfd)
|
|||||||
int err;
|
int err;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
/* Make sure that the minimum socket descriptor is within the legal range.
|
||||||
|
* the minimum value we receive is relative to file descriptor 0; we need
|
||||||
|
* map it relative of the first socket descriptor.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
|
if (minsd >= CONFIG_NFILE_DESCRIPTORS)
|
||||||
|
{
|
||||||
|
minsd -= CONFIG_NFILE_DESCRIPTORS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
minsd = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Lock the scheduler throughout the following */
|
/* Lock the scheduler throughout the following */
|
||||||
|
|
||||||
sched_lock();
|
sched_lock();
|
||||||
@ -94,7 +110,7 @@ int dup(int sockfd)
|
|||||||
|
|
||||||
/* Allocate a new socket descriptor */
|
/* Allocate a new socket descriptor */
|
||||||
|
|
||||||
sockfd2 = sockfd_allocate();
|
sockfd2 = sockfd_allocate(minsd);
|
||||||
if (sockfd2 < 0)
|
if (sockfd2 < 0)
|
||||||
{
|
{
|
||||||
err = ENFILE;
|
err = ENFILE;
|
||||||
|
@ -144,7 +144,7 @@ extern "C" {
|
|||||||
|
|
||||||
/* net_sockets.c *************************************************************/
|
/* net_sockets.c *************************************************************/
|
||||||
|
|
||||||
EXTERN int sockfd_allocate(void);
|
EXTERN int sockfd_allocate(int minsd);
|
||||||
EXTERN void sockfd_release(int sockfd);
|
EXTERN void sockfd_release(int sockfd);
|
||||||
EXTERN FAR struct socket *sockfd_socket(int sockfd);
|
EXTERN FAR struct socket *sockfd_socket(int sockfd);
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* net_sockets.c
|
* net_sockets.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2007- 2009 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -192,7 +192,7 @@ int net_releaselist(FAR struct socketlist *list)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sockfd_allocate(void)
|
int sockfd_allocate(int minsd)
|
||||||
{
|
{
|
||||||
FAR struct socketlist *list;
|
FAR struct socketlist *list;
|
||||||
int i;
|
int i;
|
||||||
@ -205,14 +205,16 @@ int sockfd_allocate(void)
|
|||||||
/* Search for a socket structure with no references */
|
/* Search for a socket structure with no references */
|
||||||
|
|
||||||
_net_semtake(list);
|
_net_semtake(list);
|
||||||
for (i = 0; i < CONFIG_NSOCKET_DESCRIPTORS; i++)
|
for (i = minsd; i < CONFIG_NSOCKET_DESCRIPTORS; i++)
|
||||||
{
|
{
|
||||||
/* Are there references on this socket? */
|
/* Are there references on this socket? */
|
||||||
|
|
||||||
if (!list->sl_sockets[i].s_crefs)
|
if (!list->sl_sockets[i].s_crefs)
|
||||||
{
|
{
|
||||||
/* No take the reference and return the index + an offset
|
/* No take the reference and return the index + an offset
|
||||||
* as the socket descriptor.
|
* as the socket descriptor.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
memset(&list->sl_sockets[i], 0, sizeof(struct socket));
|
memset(&list->sl_sockets[i], 0, sizeof(struct socket));
|
||||||
list->sl_sockets[i].s_crefs = 1;
|
list->sl_sockets[i].s_crefs = 1;
|
||||||
_net_semgive(list);
|
_net_semgive(list);
|
||||||
|
@ -49,6 +49,10 @@
|
|||||||
|
|
||||||
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
|
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-Processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Global Functions
|
* Global Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -67,7 +71,7 @@ int net_vfcntl(int sockfd, int cmd, va_list ap)
|
|||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
#warning "fcntl() commands not yet implemented"
|
#warning "Most fcntl() commands not yet implemented"
|
||||||
switch (cmd)
|
switch (cmd)
|
||||||
{
|
{
|
||||||
case F_DUPFD:
|
case F_DUPFD:
|
||||||
@ -81,6 +85,11 @@ int net_vfcntl(int sockfd, int cmd, va_list ap)
|
|||||||
* exec functions.
|
* exec functions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
{
|
||||||
|
ret = net_dup(sockfd, va_arg(ap, int));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case F_GETFD:
|
case F_GETFD:
|
||||||
/* Get the file descriptor flags defined in <fcntl.h> that are associated
|
/* Get the file descriptor flags defined in <fcntl.h> that are associated
|
||||||
* with the file descriptor fildes. File descriptor flags are associated
|
* with the file descriptor fildes. File descriptor flags are associated
|
||||||
|
@ -126,7 +126,7 @@ int socket(int domain, int type, int protocol)
|
|||||||
|
|
||||||
/* Everything looks good. Allocate a socket descriptor */
|
/* Everything looks good. Allocate a socket descriptor */
|
||||||
|
|
||||||
sockfd = sockfd_allocate();
|
sockfd = sockfd_allocate(0);
|
||||||
if (sockfd < 0)
|
if (sockfd < 0)
|
||||||
{
|
{
|
||||||
err = ENFILE;
|
err = ENFILE;
|
||||||
|
Loading…
Reference in New Issue
Block a user