Back to index

glibc  2.9
memmove_chk.c
Go to the documentation of this file.
00001 /* Copy memory to memory until the specified number of bytes
00002    has been copied with error checking.  Overlap is handled correctly.
00003    Copyright (C) 1991,1995,1996,1997,2003,2004 Free Software Foundation, Inc.
00004    This file is part of the GNU C Library.
00005    Contributed by Torbjorn Granlund (tege@sics.se).
00006 
00007    The GNU C Library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Lesser General Public
00009    License as published by the Free Software Foundation; either
00010    version 2.1 of the License, or (at your option) any later version.
00011 
00012    The GNU C Library is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    Lesser General Public License for more details.
00016 
00017    You should have received a copy of the GNU Lesser General Public
00018    License along with the GNU C Library; if not, write to the Free
00019    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00020    02111-1307 USA.  */
00021 
00022 #include <string.h>
00023 #include <memcopy.h>
00024 #include <pagecopy.h>
00025 
00026 void *
00027 __memmove_chk (dest, src, len, destlen)
00028      void *dest;
00029      const void *src;
00030      size_t len;
00031      size_t destlen;
00032 {
00033   if (__builtin_expect (destlen < len, 0))
00034     __chk_fail ();
00035 
00036   unsigned long int dstp = (long int) dest;
00037   unsigned long int srcp = (long int) src;
00038 
00039   /* This test makes the forward copying code be used whenever possible.
00040      Reduces the working set.  */
00041   if (dstp - srcp >= len)   /* *Unsigned* compare!  */
00042     {
00043       /* Copy from the beginning to the end.  */
00044 
00045       /* If there not too few bytes to copy, use word copy.  */
00046       if (len >= OP_T_THRES)
00047        {
00048          /* Copy just a few bytes to make DSTP aligned.  */
00049          len -= (-dstp) % OPSIZ;
00050          BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ);
00051 
00052          /* Copy whole pages from SRCP to DSTP by virtual address
00053             manipulation, as much as possible.  */
00054 
00055          PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len);
00056 
00057          /* Copy from SRCP to DSTP taking advantage of the known
00058             alignment of DSTP.  Number of bytes remaining is put
00059             in the third argument, i.e. in LEN.  This number may
00060             vary from machine to machine.  */
00061 
00062          WORD_COPY_FWD (dstp, srcp, len, len);
00063 
00064          /* Fall out and copy the tail.  */
00065        }
00066 
00067       /* There are just a few bytes to copy.  Use byte memory operations.  */
00068       BYTE_COPY_FWD (dstp, srcp, len);
00069     }
00070   else
00071     {
00072       /* Copy from the end to the beginning.  */
00073       srcp += len;
00074       dstp += len;
00075 
00076       /* If there not too few bytes to copy, use word copy.  */
00077       if (len >= OP_T_THRES)
00078        {
00079          /* Copy just a few bytes to make DSTP aligned.  */
00080          len -= dstp % OPSIZ;
00081          BYTE_COPY_BWD (dstp, srcp, dstp % OPSIZ);
00082 
00083          /* Copy from SRCP to DSTP taking advantage of the known
00084             alignment of DSTP.  Number of bytes remaining is put
00085             in the third argument, i.e. in LEN.  This number may
00086             vary from machine to machine.  */
00087 
00088          WORD_COPY_BWD (dstp, srcp, len, len);
00089 
00090          /* Fall out and copy the tail.  */
00091        }
00092 
00093       /* There are just a few bytes to copy.  Use byte memory operations.  */
00094       BYTE_COPY_BWD (dstp, srcp, len);
00095     }
00096 
00097   return dest;
00098 }