Message-Id: <199905280131.BAA105100@out2.ibm.net> From: "Mark E." To: djgpp-workers AT delorie DOT com Date: Thu, 27 May 1999 21:32:22 -0400 MIME-Version: 1.0 Content-type: text/plain; charset=US-ASCII Content-transfer-encoding: 7BIT Subject: enhancements to fcntl.c X-mailer: Pegasus Mail for Win32 (v3.11) Reply-To: djgpp-workers AT delorie DOT com 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 #include #include #include #include #include #include #include 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/