delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2000/08/18/14:35:19

Message-ID: <399D80E1.716E69CF@softhome.net>
Date: Fri, 18 Aug 2000 20:30:57 +0200
From: Laurynas Biveinis <lauras AT softhome DOT net>
X-Mailer: Mozilla 4.74 [en] (Win98; U)
X-Accept-Language: lt,en
MIME-Version: 1.0
To: djgpp-workers AT delorie DOT com
Subject: Re: Patch: __internal_readlink() v2
References: <399C2FC5 DOT A12ECAA3 AT softhome DOT net>
Reply-To: djgpp-workers AT delorie DOT com

During fstat() hacking, I've found few bugs in __internal_readlink(),
so I resubmit the patch.

Any comments?

Laurynas

Index: djgpp/include/libc/symlink.h
===================================================================
RCS file: /cvs/djgpp/djgpp/include/libc/symlink.h,v
retrieving revision 1.1
diff -u -r1.1 symlink.h
--- symlink.h	2000/08/14 08:51:28	1.1
+++ symlink.h	2000/08/18 18:32:04
@@ -17,6 +17,19 @@
 
 #ifndef _POSIX_SOURCE
 
+#include <sys/djtypes.h>
+
+__DJ_size_t
+#undef __DJ_size_t
+#define __DJ_size_t
+
+/* Semi-internal library function which reads symlink contents given  */
+/* either a file name or its handle.  Used by readlink(), fstat() and */
+/* user supplied (if any) file fstat handler.                         */
+
+int __internal_readlink(const char * __path, int __fhandle, char * __buf, 
+                        size_t  __max);
+
 /* A prototype for internal library function for fully resolving symlink   */
 /* chain. Standard function readlink() solves only one symlink level.      */
 /* If path name passed appears to be not a symlink, it is copied to result */
Index: djgpp/include/sys/fsext.h
===================================================================
RCS file: /cvs/djgpp/djgpp/include/sys/fsext.h,v
retrieving revision 1.5
diff -u -r1.5 fsext.h
--- fsext.h	2000/08/16 18:28:19	1.5
+++ fsext.h	2000/08/18 18:32:04
@@ -37,6 +37,8 @@
   __FSEXT_symlink
 } __FSEXT_Fnumber;
 
+#define __FSEXT_lstat __FSEXT_stat
+
 /* _ready gets passed a fd and should return a mask of these,
    as if we were emulating "int ready(int fd)" */
 #define __FSEXT_ready_read	1
Index: djgpp/src/docs/kb/wc204.txi
===================================================================
RCS file: /cvs/djgpp/djgpp/src/docs/kb/wc204.txi,v
retrieving revision 1.20
diff -u -r1.20 wc204.txi
--- wc204.txi	2000/08/17 08:46:09	1.20
+++ wc204.txi	2000/08/18 18:32:05
@@ -93,14 +93,16 @@
 as if @code{it_interval.tv_usec} were set to the system clock
 granularity (55 AT dmn{msec} by default).
 
+@findex __internal_readlink AT r{, added to the library}
 @findex __solve_symlinks AT r{, added to the library}
 @findex lstat AT r{, added to the library}
 @findex readlink AT r{, added to the library}
 @findex S_ISLNK AT r{, added to the library}
 @findex S_IFLNK AT r{, added to the library}
-UNIX-style symbolic links are fully emulated by library.  As a part of this,
-new functions @code{__solve_symlinks}, @code{lstat} and @code{readlink};
-new macros @code{S_ISLNK} and @code{S_IFLNK} have been added to library.
+UNIX-style symbolic links are fully emulated by library.  As a part of 
+this, new functions @code{__internal_readlink}, @code{__solve_symlinks}, 
+@code{lstat} and @code{readlink}; new macros @code{S_ISLNK} and 
+@code{S_IFLNK} have been added to library.
 
 @findex O_NOLINK AT r{, new flag accepted by @code{open}}
 @findex O_NOFOLLOW AT r{, new flag accepted by @code{open}}
Index: djgpp/src/libc/compat/unistd/_irdlink.c
===================================================================
RCS file: _irdlink.c
diff -N _irdlink.c
--- /dev/null	Tue May  5 16:32:27 1998
+++ _irdlink.c	Fri Aug 18 14:32:09 2000
@@ -0,0 +1,135 @@
+/* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */
+
+#include <libc/stubs.h>
+#include <libc/symlink.h>
+#include <sys/fsext.h>
+#include <dir.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <io.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "xsymlink.h"
+
+int __internal_readlink(const char * __path, int __fhandle, char * __buf, 
+                        size_t __max)
+{
+   ssize_t       bytes_read         = 0;
+   char          buf[_SYMLINK_FILE_LEN];
+   char        * data_buf;
+   int           fd;
+   int           ret;
+   off_t         old_pos = 0;
+   long          file_size;
+
+   /* Reject NULL and impossible arg combinations */
+   if (!__buf || (__path && __fhandle))
+   {
+      errno = EINVAL;
+      return -1;
+   }
+
+   /* Provide ability to hook symlink support */
+   if (__path)
+   {
+      if (__FSEXT_call_open_handlers(__FSEXT_readlink, &ret, &__path))
+         return ret;
+   }
+   else if (__fhandle)
+   {
+      __FSEXT_Function *func = __FSEXT_get_function(__fhandle);
+      if (func)
+      {
+         int rv;
+         if (func(__FSEXT_readlink, &rv, &__path))
+            return rv;
+      }
+   }
+   else
+   {
+      /* What the ?.. */
+      errno = EINVAL;
+      return -1;
+   }
+
+
+   /* Get file size */
+
+   if (__fhandle)
+      file_size = filelength(__fhandle);
+   else
+   {
+      /* We will check if file exists by the way */
+      struct ffblk  file_info;
+      if (findfirst(__path, &file_info, 0))
+      {
+         errno = ENOENT;
+         return -1;
+      }
+      file_size = file_info.ff_fsize;
+   }
+
+   /* Is symlink file size a fixed magic value? */
+   if (file_size != _SYMLINK_FILE_LEN)
+   {
+      errno = EINVAL; /* Sad but true */
+      return -1;
+   }
+
+   /* Now we check for special DJGPP symlink format */
+
+   /* If we have file handle */
+   if (__fhandle)
+   {
+      /* Remember old file pos */
+      old_pos = tell(__fhandle);
+      if (old_pos == -1)
+         return -1;
+      lseek(__fhandle, 0, SEEK_SET);
+      fd = __fhandle;
+   }
+   else
+   {
+      fd = _open(__path, O_RDONLY);
+      if (fd < 0)
+      {
+         /* Retry with DENY-NONE share bit set. It might help in some cases
+          * when symlink file is opened by another program. We don't try with
+          * DENY-NONE set in the first _open() call, because it might fail under
+          * some circumstances. For details, see Ralf Brown's Interrupt List,
+          * description of INT 0x21, function 0x3D.
+          */
+         fd = _open(__path, O_RDONLY | SH_DENYNO);
+         if (fd < 0)
+            return -1; /* errno from _open() call */
+      } 
+   }
+
+   bytes_read = read(fd, &buf, _SYMLINK_FILE_LEN);
+
+   if (__fhandle)
+      lseek(__fhandle, old_pos, SEEK_SET);
+   else
+      _close(fd);
+
+   if (bytes_read == -1)
+      return -1; /* Return errno set by _read() (_close() in worse case) */
+      
+   /* Check for symlink file header */
+   if (strncmp(buf, _SYMLINK_PREFIX, _SYMLINK_PREFIX_LEN))
+   {
+      close(fd);
+      errno = EINVAL;
+      return -1;
+   }
+   
+   data_buf = buf + _SYMLINK_PREFIX_LEN;
+   bytes_read = strchr(data_buf, '\n') - data_buf;
+   bytes_read = ((unsigned)bytes_read > __max) ? __max : bytes_read;
+   memcpy(__buf, data_buf, bytes_read);
+   return bytes_read;
+}
+
Index: djgpp/src/libc/compat/unistd/_irdlink.txh
===================================================================
RCS file: _irdlink.txh
diff -N _irdlink.txh
--- /dev/null	Tue May  5 16:32:27 1998
+++ _irdlink.txh	Fri Aug 18 14:32:10 2000
@@ -0,0 +1,38 @@
+@node __internal_readlink, io
+@subheading Syntax
+
+@example
+#include <libc/symlink.h>
+
+int __internal_readlink(const char * path, int fhandle, char * buf, size_t max)
+@end example
+
+@subheading Description
+In general applications shouldn't call this function; use @code{readlink} 
+instead (@pxref{readlink}).  However, there is one exception: if you have
+a @code{FSEXT} @code{fstat} file handler, and do not want do anything special
+about symlinks.  In this case you should call this function from your handler
+to set properly @code{S_IFLNK} bit in @code{st_mode}.  This function operates
+on either @var{path} @strong{or} @var{fhandle}. In any case, the other arg
+should be set to @code{NULL} or 0.
+
+@subheading Return Value
+
+Number of copied characters; value -1 is returned in case of
+error and @code{errno} is set.  When value returned is equal to 
+@var{size}, you cannot determine if there was enough room to 
+copy whole name.  So increase @var{size} and try again.
+
+@subheading Portability
+
+@portability !ansi, !posix
+
+@subheading Example
+
+@example
+char buf[FILENAME_MAX + 1];
+if (__internal_readlink(0, "/dev/env/DJDIR/bin/sh.exe", buf, FILENAME_MAX) == -1)
+   if (errno == EINVAL)
+      puts("/dev/env/DJDIR/bin/sh.exe is not a symbolic link.");
+@end example
+
Index: djgpp/src/libc/compat/unistd/makefile
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/compat/unistd/makefile,v
retrieving revision 1.6
diff -u -r1.6 makefile
--- makefile	2000/08/14 08:51:30	1.6
+++ makefile	2000/08/18 18:32:10
@@ -2,6 +2,7 @@
 # Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details
 TOP=../..
 
+SRC += _irdlink.c
 SRC += basename.c
 SRC += dirname.c
 SRC += fsync.c
Index: djgpp/src/libc/compat/unistd/readlink.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/compat/unistd/readlink.c,v
retrieving revision 1.3
diff -u -r1.3 readlink.c
--- readlink.c	2000/08/16 18:29:37	1.3
+++ readlink.c	2000/08/18 18:32:10
@@ -2,84 +2,13 @@
 /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */
 
 #include <libc/stubs.h>
-#include <sys/fsext.h>
-#include <dir.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <io.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
+#include <libc/symlink.h>
 #include <unistd.h>
 
 #include "xsymlink.h"
 
 int readlink(const char * filename, char * buffer, size_t size)
 {
-   ssize_t       bytes_read         = 0;
-   char          buf[_SYMLINK_FILE_LEN];
-   char        * data_buf;
-   int           fd;
-   struct ffblk  file_info;
-   int           ret;
-
-   /* Reject NULLs */
-   if (!filename || !buffer)
-   {
-      errno = EINVAL;
-      return -1;
-   }
-
-   /* Provide ability to hook symlink support */
-   if (__FSEXT_call_open_handlers(__FSEXT_readlink, &ret, &filename))
-      return ret;
-
-   /* Does symlink file exist at all? */
-   if (findfirst(filename, &file_info, 0))
-   {
-      errno = ENOENT;
-      return -1;
-   }
-
-   /* Is symlink file size a fixed magic value? */
-   if (file_info.ff_fsize != _SYMLINK_FILE_LEN)
-   {
-      errno = EINVAL; /* Sad but true */
-      return -1;
-   }
-
-   /* Now we check for special DJGPP symlink format */
-   fd = _open(filename, O_RDONLY);
-   if (fd < 0)
-   {
-      /* Retry with DENY-NONE share bit set. It might help in some cases
-       * when symlink file is opened by another program. We don't try with
-       * DENY-NONE set in the first _open() call, because it might fail under
-       * some circumstances. For details, see Ralf Brown's Interrupt List,
-       * description of INT 0x21, function 0x3D.
-       */
-      fd = _open(filename, O_RDONLY | SH_DENYNO);
-      if (fd < 0)
-         return -1; /* errno from open() call */
-   } 
-
-   bytes_read = read(fd, &buf, _SYMLINK_FILE_LEN);
-   _close(fd);
-   if (bytes_read == -1)
-      return -1; /* Return errno set by _read() (_close() in worse case) */
-      
-   /* Check for symlink file header */
-   if (strncmp(buf, _SYMLINK_PREFIX, _SYMLINK_PREFIX_LEN))
-   {
-      close(fd);
-      errno = EINVAL;
-      return -1;
-   }
-   
-   data_buf = buf + _SYMLINK_PREFIX_LEN;
-   bytes_read = strchr(data_buf, '\n') - data_buf;
-   bytes_read = ((unsigned)bytes_read > size) ? size : bytes_read;
-   memcpy(buffer, data_buf, bytes_read);
-   return bytes_read;
+   return __internal_readlink(filename, 0, buffer, size);
 }

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019