"Fossies" - the Fresh Open Source Software Archive

Member "parted-3.2/m4/o-direct.m4" (15 Jun 2014, 6696 Bytes) of archive /linux/misc/parted-3.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 #serial 2
    2 # Find a directory in which a disk-simulating file is usable by parted.
    3 # The problem is that on systems supporting O_DIRECT, open with O_DIRECT
    4 # fails for some file system types (e.g., tmpfs on linux-2.6.21).
    5 
    6 # Copyright (C) 2007-2014 Free Software Foundation, Inc.
    7 # This file is free software; the Free Software Foundation
    8 # gives unlimited permission to copy and/or distribute it,
    9 # with or without modifications, as long as this notice is preserved.
   10 
   11 # From Jim Meyering.
   12 
   13 # Set PARTED_USABLE_TEST_DIR to the name of the first usable directory
   14 # from the list below.  If none is usable, set it to the empty string.
   15 # Consider $TMPDIR only if it specifies an absolute name, and that
   16 # name contains no shell meta-character.  Likewise for $HOME.
   17 
   18 # This code is pretty picky.  The chosen partition must support aligned reads
   19 # and writes in blocks of size 512B and 4KB to a file descriptor opened with
   20 # O_RDWR|O_DIRECT.  Reiserfs doesn't support 512-byte reads.  On tmpfs,
   21 # the open fails.
   22 
   23 # The candidate directories:
   24 #   . $HOME $TMPDIR /tmp /var/tmp /dev/shm
   25 AC_DEFUN([parted_FIND_USABLE_TEST_DIR],
   26 [
   27   AC_CACHE_CHECK([for a usable (O_DIRECT-supporting) temporary dir],
   28     [parted_cv_func_open_O_DIRECT_temp_dir],
   29     [
   30       # First of all, if there is no O_DIRECT definition, use ".",
   31       # and skip the run-test.
   32       AC_EGREP_CPP([frobnozzle], [
   33 #include <fcntl.h>
   34 #ifdef O_DIRECT
   35 frobnozzle
   36 #endif
   37           ], pe_have_O_DIRECT=yes, pe_have_O_DIRECT=no)
   38       if test $pe_have_O_DIRECT = no; then
   39       # With no O_DIRECT definition, "." is fine.
   40       pe_cand_dirs=.
   41       else
   42       pe_cand_dirs=.
   43       for pe_dir in "$HOME" "$TMPDIR"; do
   44           case $pe_dir in
   45           /tmp) ;;
   46           /var/tmp) ;;
   47           /dev/shm) ;;
   48           /*) case $pe_dir in
   49           # Accept $HOME or $TMP only if the value is nice and boring.
   50           *[^/a-zA-Z0-9_.-]*) ;;
   51           *) pe_cand_dirs="$pe_cand_dirs $pe_dir";;
   52           esac
   53           esac
   54       done
   55 
   56       case $PARTED_TMPDIR in
   57           *[^/a-zA-Z0-9_.-]*) ;;
   58           *) pe_cand_dirs="$PARTED_TMPDIR $pe_cand_dirs";;
   59       esac
   60 
   61       # This is the list of candidate directories.
   62       pe_cand_dirs="$pe_cand_dirs /tmp /var/tmp /dev/shm"
   63 
   64       PARTED_CANDIDATE_DIRS=$pe_cand_dirs
   65       export PARTED_CANDIDATE_DIRS
   66 
   67       AC_RUN_IFELSE(
   68         [AC_LANG_SOURCE(
   69           [[
   70 #include <sys/types.h>
   71 #include <sys/stat.h>
   72 #include <fcntl.h>
   73 #include <unistd.h>
   74 #include <stdlib.h>
   75 #include <string.h>
   76 
   77 #define MAX_LOGICAL_BLOCK_SIZE 4096
   78 static char g_buf[2 * MAX_LOGICAL_BLOCK_SIZE];
   79 
   80 static inline void *
   81 ptr_align (void const *ptr, size_t alignment)
   82 {
   83   char const *p0 = ptr;
   84   char const *p1 = p0 + alignment - 1;
   85   return (void *) (p1 - (size_t) p1 % alignment);
   86 }
   87 
   88 static int
   89 create_input_file (char const *file, char const *buf, size_t n_bytes)
   90 {
   91   int fd = open (file, O_CREAT | O_WRONLY, 0600);
   92   if (fd < 0)
   93     return 1;
   94   if (write (fd, buf, n_bytes) != n_bytes)
   95     {
   96       close (fd);
   97       return 1;
   98     }
   99   return !! close (fd);
  100 }
  101 
  102 static int
  103 try_o_direct (char const *file, size_t block_size)
  104 {
  105   char *p = ptr_align (g_buf, MAX_LOGICAL_BLOCK_SIZE);
  106   int fd;
  107 
  108   if (!(p + block_size < g_buf + sizeof g_buf))
  109     return 4;
  110 
  111   fd = open (file, O_RDWR | O_DIRECT);
  112   if (fd < 0)
  113     return 1;
  114 
  115   if (write (fd, p, block_size) != block_size)
  116     return 1;
  117 
  118   if (lseek (fd, 0, SEEK_SET) != 0)
  119     return 1;
  120 
  121   if (read (fd, p, block_size) != block_size)
  122     return 1;
  123 
  124   return !! close (fd);
  125 }
  126 
  127 #undef stpcpy
  128 #define stpcpy(a, b) my_stpcpy (a, b)
  129 static char *
  130 my_stpcpy (char *dest, const char *src)
  131 {
  132   char *d = dest;
  133   const char *s = src;
  134   do *d++ = *s; while (*s++ != '\0');
  135   return d - 1;
  136 }
  137 
  138 /* The base name of the file we'll create in the mkdtemp-returned
  139    temporary directory.  */
  140 #define BASENAME "x"
  141 
  142 /* Return 0 upon failure, else the 1-based index of the first
  143    useful directory name from PARTED_CANDIDATE_DIRS.  */
  144 int
  145 main ()
  146 {
  147   char const *env_dirs;
  148   char *dirs;
  149   char *dir;
  150   unsigned int n;
  151   int found = 0;
  152   size_t dirs_len;
  153 
  154   if ((env_dirs = getenv ("PARTED_CANDIDATE_DIRS")) == NULL)
  155     return 0;
  156 
  157   dirs_len = strlen (env_dirs);
  158   if ((dirs = strndup (env_dirs, dirs_len)) == NULL)
  159     return 0;
  160   dir = dirs;
  161 
  162   for (n = 1; ; n++)
  163     {
  164       size_t dirname_len;
  165       char *space;
  166 
  167       /* Skip any leading spaces.  */
  168       while (*dir == ' ')
  169     ++dir;
  170 
  171       space = strchr (dir, ' ');
  172       if (space)
  173     {
  174       *space = '\0';
  175       dirname_len = space - dir;
  176     }
  177       else
  178     {
  179       dirname_len = strlen (dir);
  180     }
  181 
  182       if (dirname_len != 0)
  183     {
  184       /* Create an mkdtemp template starting with dir.  */
  185       char *tmp;
  186       char *endp;
  187       char const *base = "partedOD.XXXXXX";
  188       /* Allocate enough space not just for the dir name, but
  189          also for the name of the file to create within it.  */
  190       char *template = malloc (dirname_len + 1 + strlen (base)
  191                    + 1 + strlen (BASENAME) + 1);
  192       if (template != NULL
  193           && (endp = stpcpy (stpcpy (stpcpy (template, dir), "/"), base))
  194           && (tmp = mkdtemp (template)) != NULL)
  195         {
  196           /* Append "/BASENAME" to create the file name.  */
  197           stpcpy (stpcpy (endp, "/"), BASENAME);
  198 
  199           if (create_input_file (tmp, g_buf, sizeof g_buf) == 0
  200           && try_o_direct (tmp, 512) == 0
  201           && try_o_direct (tmp, MAX_LOGICAL_BLOCK_SIZE) == 0)
  202         found = 1;
  203 
  204           unlink (tmp); /* ignore failure */
  205           *endp = '\0';
  206           rmdir (tmp); /* ignore failure */
  207         }
  208       free (template);
  209     }
  210 
  211       if (found)
  212     break;
  213 
  214       dir += dirname_len + 1;
  215       if (dirs + dirs_len < dir)
  216     {
  217       n = 0;
  218       break;
  219     }
  220     }
  221   free (dirs);
  222 
  223   return n;
  224 }
  225           ]])],
  226         # If the above program exits with status 0, then
  227         # there it found no useful directory.  Use ".".
  228         [parted_cv_func_open_O_DIRECT_temp_dir=.],
  229 
  230         # It found one.  The exit status is an index into the list.
  231         # We also run this code when the program fails to compile or
  232         # to link, as will happen on systems without a mkdtemp function.
  233         [pe_err=$?; set _ $pe_cand_dirs; shift
  234           eval parted_cv_func_open_O_DIRECT_temp_dir='$'$pe_err],
  235 
  236         # When cross-compiling, use ".".
  237         [parted_cv_func_open_O_DIRECT_temp_dir=.]
  238         )
  239       fi
  240     ])
  241   PARTED_USABLE_TEST_DIR=$parted_cv_func_open_O_DIRECT_temp_dir
  242   AC_SUBST([PARTED_USABLE_TEST_DIR])
  243 
  244   # If the result is ".", don't cache it.  The next user of
  245   # the cache may well be running from a different file system.
  246   dnl Here, I'm using "$as_unset", which is a non-published (i.e., internal)
  247   dnl part of autoconf, but we don't expect its name to change any time soon.
  248   dnl and by then, it'll probably be ok to use "unset" all by itself.
  249   if test "$parted_cv_func_open_O_DIRECT_temp_dir" = .; then
  250     $as_unset parted_cv_func_open_O_DIRECT_temp_dir
  251   fi
  252 ])