Back to index

glibc  2.9
readdir.c
Go to the documentation of this file.
00001 /* Copyright (C) 1993,94,95,96,97,2002 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003 
00004    The GNU C Library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Lesser General Public
00006    License as published by the Free Software Foundation; either
00007    version 2.1 of the License, or (at your option) any later version.
00008 
00009    The GNU C Library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Lesser General Public License for more details.
00013 
00014    You should have received a copy of the GNU Lesser General Public
00015    License along with the GNU C Library; if not, write to the Free
00016    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00017    02111-1307 USA.  */
00018 
00019 #include <errno.h>
00020 #include <stddef.h>
00021 #include <dirent.h>
00022 #include <unistd.h>
00023 #include <endian.h>
00024 #include <assert.h>
00025 
00026 /* Read a directory entry from DIRP.  */
00027 struct dirent *
00028 __readdir (DIR *dirp)
00029 {
00030   struct dirent64 *entry64 = __readdir64 (dirp);
00031 
00032   if (sizeof (struct dirent64) == sizeof (struct dirent))
00033     /* We should in fact just be an alias to readdir64 on this machine.  */
00034     return (struct dirent *) entry64;
00035 
00036   /* These are all compile-time constants.  We know that d_ino is the first
00037      member and that the layout of the following members matches exactly in
00038      both structures.  */
00039   assert (offsetof (struct dirent, d_ino) == 0);
00040   assert (offsetof (struct dirent64, d_ino) == 0);
00041 # define MATCH(memb)                                                 \
00042   assert (offsetof (struct dirent64, memb) - sizeof (entry64->d_ino)        \
00043          == offsetof (struct dirent, memb) - sizeof (ino_t))
00044   MATCH (d_reclen);
00045   MATCH (d_type);
00046   MATCH (d_namlen);
00047 # undef MATCH
00048 
00049   if (entry64 == NULL)
00050     return NULL;
00051 
00052   struct dirent *const entry = ((void *) (&entry64->d_ino + 1)
00053                             - sizeof entry->d_ino);
00054   const ino_t d_ino = entry64->d_ino;
00055   if (d_ino != entry64->d_ino)
00056     {
00057       __set_errno (EOVERFLOW);
00058       return NULL;
00059     }
00060 # if BYTE_ORDER != BIG_ENDIAN      /* We just skipped over the zero high word.  */
00061   entry->d_ino = d_ino;     /* ... or the nonzero low word, swap it.  */
00062 # endif
00063   entry->d_reclen -= sizeof entry64->d_ino - sizeof entry->d_ino;
00064   return entry;
00065 }
00066 
00067 weak_alias (__readdir, readdir)