Mail Archives: djgpp-workers/1999/05/27/21:32:08
Hello,
Bash uses fcntl with F_GETFD to check if a file descriptor is valid. To
support this in a future port, I enhanced fcntl to check if the descriptor is
valid. While I was at it, I made a go a implementing the rest of the
commands using the online Unix spec as my reference.
Corrections, suggestions, and criticisms are welcome.
/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
#include <libc/stubs.h>
#include <dpmi.h>
#include <errno.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/fsext.h>
#include <sys/movedata.h>
static int
is_used_fd(int fd)
{
__dpmi_regs regs;
regs.x.ax = 0x4400;
regs.x.bx = fd;
__dpmi_int(0x21, ®s);
if (regs.x.flags & 1)
return 0;
return 1;
}
static int get_sft_entry(int fd, char sft_entry[])
{
__dpmi_regs regs;
unsigned char index;
/* Get JFT entry address. */
regs.x.ax = 0x1220;
regs.x.bx = fd;
__dpmi_int (0x2f, ®s);
if (regs.x.flags & 1)
return -1;
/* First byte is the SFT entry number. */
dosmemget(regs.x.es * 16 + regs.x.di, 1, &index);
/* Get the SFT entry for the handle. */
regs.x.ax = 0x1216;
regs.x.bx = index;
__dpmi_int (0x2f, ®s);
if (regs.x.flags & 1)
return -1;
dosmemget(regs.x.es * 16 + regs.x.di, 63, sft_entry);
return 0;
}
static void
make_lock_args (int fd, struct flock *lck, off_t *_start, off_t *_len)
{
off_t cur_pos = lseek (fd, 0, SEEK_CUR);
off_t lock_pos = lseek (fd, lck->l_start, lck->l_whence);
off_t len = lck->l_len;
/* If l_len is zero, then lock is to be set from l_start
until the end-of-file. */
if (len == 0)
{
len = filelength(fd) - cur_pos;
if (len <= 0)
len = 1;
}
lseek (fd, cur_pos, SEEK_SET);
/* If l_len is positive, the area to lock is to be set from l_start to
l_start + l_len - 1. If l_len is negative, the area to lock is
from l_start + len to l_start - 1. */
if (lck->l_len > 0)
{
*_start = lock_pos;
*_len = lck->l_len;
}
else
{
*_start = lock_pos + lck->l_len;
*_len = -lck->l_len;
}
}
int
fcntl(int fd, int cmd, ...)
{
int tofd, open_max;
va_list ap;
__FSEXT_Function *func = __FSEXT_get_function(fd);
/* Before proceeding, verify the descriptor is valid. */
if (!is_used_fd(fd))
{
errno = EINVAL;
return -1;
}
if (func)
{
int rv;
if (func(__FSEXT_fcntl, &rv, &fd))
return rv;
}
switch (cmd)
{
case F_DUPFD:
{
va_start(ap, cmd);
tofd = va_arg(ap, int);
va_end(ap);
open_max = getdtablesize();
while (tofd < open_max)
{
if (! is_used_fd(tofd))
break;
tofd++;
}
if (tofd >= open_max)
{
errno = EMFILE;
return -1;
}
return dup2(fd, tofd);
}
case F_SETFD:
{
int flag;
/* Return error if any descriptor flags are passed, since
DOS doesn't support them. */
va_start (ap, cmd);
flag = va_arg(ap, int);
va_end(ap);
return (flag ? -1 : 0);
}
case F_GETFD:
/* DOS does not support FD_CLOEXEC or any other descriptor
flags,
so there are no flags to return. */
return 0;
case F_GETFL:
{
char sft_entry[64];
if (get_sft_entry(fd, sft_entry) < 0)
return -1;
/* Return the file access mode associated with the descriptor. */
return sft_entry[2];
}
case F_SETFL:
return 0;
case F_GETLK:
case F_SETLK:
case F_SETLKW:
{
struct flock *lock_req = va_arg(lock_req, struct flock *);
int ret = -1;
off_t pos, len;
make_lock_args(fd, lock_req, &pos, &len);
/* Ignore read locks because DOS/Windows support only write locks
for record locking. */
if (lock_req->l_type == F_UNLCK)
{
ret = _dos_unlock(fd, pos, len);
}
else if (lock_req->l_type == F_WRLCK)
{
ret = _dos_lock(fd, pos, len);
if (ret == 0 && cmd == F_GETLK)
_dos_unlock(fd, pos, len);
}
return ret;
}
}
return -1;
}
---
Mark Elbrecht, snowball3 AT bigfoot DOT com
http://snowball.frogspace.net/
- Raw text -