Back to index

glibc  2.9
posix_fallocate.c
Go to the documentation of this file.
00001 /* Copyright (C) 2000, 2003, 2005 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 <fcntl.h>
00021 #include <unistd.h>
00022 #include <sys/stat.h>
00023 #include <sys/statfs.h>
00024 
00025 /* Reserve storage for the data of the file associated with FD.  */
00026 
00027 int
00028 posix_fallocate (int fd, __off_t offset, __off_t len)
00029 {
00030   struct stat64 st;
00031   struct statfs f;
00032 
00033   /* `off_t' is a signed type.  Therefore we can determine whether
00034      OFFSET + LEN is too large if it is a negative value.  */
00035   if (offset < 0 || len < 0)
00036     return EINVAL;
00037   if (offset + len < 0)
00038     return EFBIG;
00039 
00040   /* First thing we have to make sure is that this is really a regular
00041      file.  */
00042   if (__fxstat64 (_STAT_VER, fd, &st) != 0)
00043     return EBADF;
00044   if (S_ISFIFO (st.st_mode))
00045     return ESPIPE;
00046   if (! S_ISREG (st.st_mode))
00047     return ENODEV;
00048 
00049   if (len == 0)
00050     {
00051       if (st.st_size < offset)
00052        {
00053          int ret = __ftruncate (fd, offset);
00054 
00055          if (ret != 0)
00056            ret = errno;
00057          return ret;
00058        }
00059       return 0;
00060     }
00061 
00062   /* We have to know the block size of the filesystem to get at least some
00063      sort of performance.  */
00064   if (__fstatfs (fd, &f) != 0)
00065     return errno;
00066 
00067   /* Try to play safe.  */
00068   if (f.f_bsize == 0)
00069     f.f_bsize = 512;
00070 
00071   /* Write something to every block.  */
00072   for (offset += (len - 1) % f.f_bsize; len > 0; offset += f.f_bsize)
00073     {
00074       len -= f.f_bsize;
00075 
00076       if (offset < st.st_size)
00077        {
00078          unsigned char c;
00079          ssize_t rsize = __pread (fd, &c, 1, offset);
00080 
00081          if (rsize < 0)
00082            return errno;
00083          /* If there is a non-zero byte, the block must have been
00084             allocated already.  */
00085          else if (rsize == 1 && c != 0)
00086            continue;
00087        }
00088 
00089       if (__pwrite (fd, "", 1, offset) != 1)
00090        return errno;
00091     }
00092 
00093   return 0;
00094 }