~ubuntu-branches/ubuntu/precise/gzip/precise

« back to all changes in this revision

Viewing changes to lib/openat-proc.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2011-10-19 11:42:42 UTC
  • mfrom: (4.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20111019114242-d8wiiu8kbvdtgmgj
Tags: 1.4-1ubuntu1
* Merge with Debian testing.  Remaining Ubuntu changes:
  - debian/{control,rules}: Remove the Win32 build and mingw64
    build-dependency, since mingw is in universe, and will remain so for
    the forseeable future.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Create /proc/self/fd-related names for subfiles of open directories.
 
2
 
 
3
   Copyright (C) 2006, 2009-2010 Free Software Foundation, Inc.
 
4
 
 
5
   This program is free software: you can redistribute it and/or modify
 
6
   it under the terms of the GNU General Public License as published by
 
7
   the Free Software Foundation; either version 3 of the License, or
 
8
   (at your option) any later version.
 
9
 
 
10
   This program is distributed in the hope that it will be useful,
 
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
   GNU General Public License for more details.
 
14
 
 
15
   You should have received a copy of the GNU General Public License
 
16
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
17
 
 
18
/* Written by Paul Eggert.  */
 
19
 
 
20
#include <config.h>
 
21
 
 
22
#include "openat-priv.h"
 
23
 
 
24
#include <sys/types.h>
 
25
#include <sys/stat.h>
 
26
#include <fcntl.h>
 
27
 
 
28
#include <stdio.h>
 
29
#include <string.h>
 
30
#include <unistd.h>
 
31
 
 
32
#include "dirname.h"
 
33
#include "intprops.h"
 
34
#include "same-inode.h"
 
35
#include "xalloc.h"
 
36
 
 
37
/* The results of open() in this file are not used with fchdir,
 
38
   and we do not leak fds to any single-threaded code that could use stdio,
 
39
   therefore save some unnecessary work in fchdir.c.
 
40
   FIXME - if the kernel ever adds support for multi-thread safety for
 
41
   avoiding standard fds, then we should use open_safer.  */
 
42
#undef open
 
43
#undef close
 
44
 
 
45
#define PROC_SELF_FD_FORMAT "/proc/self/fd/%d/%s"
 
46
 
 
47
#define PROC_SELF_FD_NAME_SIZE_BOUND(len) \
 
48
  (sizeof PROC_SELF_FD_FORMAT - sizeof "%d%s" \
 
49
   + INT_STRLEN_BOUND (int) + (len) + 1)
 
50
 
 
51
 
 
52
/* Set BUF to the expansion of PROC_SELF_FD_FORMAT, using FD and FILE
 
53
   respectively for %d and %s.  If successful, return BUF if the
 
54
   result fits in BUF, dynamically allocated memory otherwise.  But
 
55
   return NULL if /proc is not reliable.  */
 
56
char *
 
57
openat_proc_name (char buf[OPENAT_BUFFER_SIZE], int fd, char const *file)
 
58
{
 
59
  static int proc_status = 0;
 
60
 
 
61
  /* Make sure the caller gets ENOENT when appropriate.  */
 
62
  if (!*file)
 
63
    {
 
64
      buf[0] = '\0';
 
65
      return buf;
 
66
    }
 
67
 
 
68
  if (! proc_status)
 
69
    {
 
70
      /* Set PROC_STATUS to a positive value if /proc/self/fd is
 
71
         reliable, and a negative value otherwise.  Solaris 10
 
72
         /proc/self/fd mishandles "..", and any file name might expand
 
73
         to ".." after symbolic link expansion, so avoid /proc/self/fd
 
74
         if it mishandles "..".  Solaris 10 has openat, but this
 
75
         problem is exhibited on code that built on Solaris 8 and
 
76
         running on Solaris 10.  */
 
77
 
 
78
      int proc_self_fd = open ("/proc/self/fd", O_RDONLY);
 
79
      if (proc_self_fd < 0)
 
80
        proc_status = -1;
 
81
      else
 
82
        {
 
83
          struct stat proc_self_fd_dotdot_st;
 
84
          struct stat proc_self_st;
 
85
          char dotdot_buf[PROC_SELF_FD_NAME_SIZE_BOUND (sizeof ".." - 1)];
 
86
          sprintf (dotdot_buf, PROC_SELF_FD_FORMAT, proc_self_fd, "..");
 
87
          proc_status =
 
88
            ((stat (dotdot_buf, &proc_self_fd_dotdot_st) == 0
 
89
              && stat ("/proc/self", &proc_self_st) == 0
 
90
              && SAME_INODE (proc_self_fd_dotdot_st, proc_self_st))
 
91
             ? 1 : -1);
 
92
          close (proc_self_fd);
 
93
        }
 
94
    }
 
95
 
 
96
  if (proc_status < 0)
 
97
    return NULL;
 
98
  else
 
99
    {
 
100
      size_t bufsize = PROC_SELF_FD_NAME_SIZE_BOUND (strlen (file));
 
101
      char *result = (bufsize < OPENAT_BUFFER_SIZE ? buf : xmalloc (bufsize));
 
102
      sprintf (result, PROC_SELF_FD_FORMAT, fd, file);
 
103
      return result;
 
104
    }
 
105
}