FileSpec.cpp revision 49ce682dfa7993d31206cea19ce7006cd3f3077e
124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===-- FileSpec.cpp --------------------------------------------*- C++ -*-===//
224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//                     The LLVM Compiler Infrastructure
424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// This file is distributed under the University of Illinois Open Source
624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// License. See LICENSE.TXT for details.
724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===----------------------------------------------------------------------===//
924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <fcntl.h>
1224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <libgen.h>
1324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <stdlib.h>
1424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <sys/param.h>
1524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <sys/stat.h>
1624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <sys/types.h>
17a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham#include <pwd.h>
1824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <fstream>
2024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
21e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice#include "llvm/ADT/StringRef.h"
22e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice#include "llvm/System/Path.h"
23e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice#include "llvm/System/Program.h"
24e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice
2524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/FileSpec.h"
2624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/DataBufferHeap.h"
2724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/DataBufferMemoryMap.h"
2824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/Stream.h"
29eddffe93d2c9ebb575e7b03fe1c5e71f9ecaf9f1Caroline Tice#include "lldb/Host/Host.h"
3024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
3124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerusing namespace lldb;
3224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerusing namespace lldb_private;
3324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerusing namespace std;
3424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
3524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerstatic bool
3624943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerGetFileStats (const FileSpec *file_spec, struct stat *stats_ptr)
3724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
3824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    char resolved_path[PATH_MAX];
3924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (file_spec->GetPath(&resolved_path[0], sizeof(resolved_path)))
4024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return ::stat (resolved_path, stats_ptr) == 0;
4124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return false;
4224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
4324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
4424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerstatic const char*
4524943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerGetCachedGlobTildeSlash()
4624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
4724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    static std::string g_tilde;
4824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (g_tilde.empty())
4924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
50a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        struct passwd *user_entry;
51a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        user_entry = getpwuid(geteuid());
52a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        if (user_entry != NULL)
53a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham            g_tilde = user_entry->pw_dir;
54a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham
5524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (g_tilde.empty())
5624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            return NULL;
5724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
5824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return g_tilde.c_str();
5924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
6024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
61a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham// Resolves the username part of a path of the form ~user/other/directories, and
62a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham// writes the result into dst_path.
63a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham// Returns 0 if there WAS a ~ in the path but the username couldn't be resolved.
64a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham// Otherwise returns the number of characters copied into dst_path.  If the return
65a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham// is >= dst_len, then the resolved path is too long...
6654e7afa84d945f9137f9372ecde432f9e1a702fcGreg Claytonsize_t
67a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim InghamFileSpec::ResolveUsername (const char *src_path, char *dst_path, size_t dst_len)
68a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham{
69a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    char user_home[PATH_MAX];
70a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    const char *user_name;
71a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham
72a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    if (src_path == NULL || src_path[0] == '\0')
73a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        return 0;
74b1a9862ba1ceb219b6042ff3f8c6ff591867ae26Greg Clayton
75a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    // If there's no ~, then just copy src_path straight to dst_path (they may be the same string...)
76a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    if (src_path[0] != '~')
77a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    {
7854e7afa84d945f9137f9372ecde432f9e1a702fcGreg Clayton        size_t len = strlen (src_path);
79a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        if (len >= dst_len)
80a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        {
81b1a9862ba1ceb219b6042ff3f8c6ff591867ae26Greg Clayton            ::bcopy (src_path, dst_path, dst_len - 1);
82b1a9862ba1ceb219b6042ff3f8c6ff591867ae26Greg Clayton            dst_path[dst_len] = '\0';
83a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        }
84a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        else
85b1a9862ba1ceb219b6042ff3f8c6ff591867ae26Greg Clayton            ::bcopy (src_path, dst_path, len + 1);
86b1a9862ba1ceb219b6042ff3f8c6ff591867ae26Greg Clayton
87a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        return len;
88a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    }
89a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham
909c3cfe397d6040a46677e201c2682cc2a5163fe9Eli Friedman    const char *first_slash = ::strchr (src_path, '/');
91a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    char remainder[PATH_MAX];
92a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham
93a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    if (first_slash == NULL)
94a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    {
95a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        // The whole name is the username (minus the ~):
96a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        user_name = src_path + 1;
97a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        remainder[0] = '\0';
98a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    }
99a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    else
100a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    {
101a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        int user_name_len = first_slash - src_path - 1;
102b1a9862ba1ceb219b6042ff3f8c6ff591867ae26Greg Clayton        ::memcpy (user_home, src_path + 1, user_name_len);
103a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        user_home[user_name_len] = '\0';
104a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        user_name = user_home;
105a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham
106b1a9862ba1ceb219b6042ff3f8c6ff591867ae26Greg Clayton        ::strcpy (remainder, first_slash);
107a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    }
108b1a9862ba1ceb219b6042ff3f8c6ff591867ae26Greg Clayton
109a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    if (user_name == NULL)
110a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        return 0;
111a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    // User name of "" means the current user...
112a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham
113a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    struct passwd *user_entry;
11454e7afa84d945f9137f9372ecde432f9e1a702fcGreg Clayton    const char *home_dir = NULL;
115a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham
116a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    if (user_name[0] == '\0')
117a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    {
118a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        home_dir = GetCachedGlobTildeSlash();
119a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    }
120a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    else
121a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    {
122b1a9862ba1ceb219b6042ff3f8c6ff591867ae26Greg Clayton        user_entry = ::getpwnam (user_name);
123a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        if (user_entry != NULL)
124a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham            home_dir = user_entry->pw_dir;
125a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    }
126a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham
127a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    if (home_dir == NULL)
128a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        return 0;
129a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    else
130a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        return ::snprintf (dst_path, dst_len, "%s%s", home_dir, remainder);
131a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham}
132a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham
13354e7afa84d945f9137f9372ecde432f9e1a702fcGreg Claytonsize_t
13424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::Resolve (const char *src_path, char *dst_path, size_t dst_len)
13524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
13624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (src_path == NULL || src_path[0] == '\0')
13724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return 0;
13824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
13924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // Glob if needed for ~/, otherwise copy in case src_path is same as dst_path...
14024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    char unglobbed_path[PATH_MAX];
141a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    if (src_path[0] == '~')
142a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    {
14354e7afa84d945f9137f9372ecde432f9e1a702fcGreg Clayton        size_t return_count = ResolveUsername(src_path, unglobbed_path, sizeof(unglobbed_path));
144a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham
145a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        // If we couldn't find the user referred to, or the resultant path was too long,
146a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        // then just copy over the src_path.
147a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        if (return_count == 0 || return_count >= sizeof(unglobbed_path))
148a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham            ::snprintf (unglobbed_path, sizeof(unglobbed_path), "%s", src_path);
149a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    }
15024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    else
15124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        ::snprintf(unglobbed_path, sizeof(unglobbed_path), "%s", src_path);
15224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
15324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // Now resolve the path if needed
15424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    char resolved_path[PATH_MAX];
15524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (::realpath (unglobbed_path, resolved_path))
15624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
15724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // Success, copy the resolved path
15824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return ::snprintf(dst_path, dst_len, "%s", resolved_path);
15924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
16024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    else
16124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
16224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // Failed, just copy the unglobbed path
16324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return ::snprintf(dst_path, dst_len, "%s", unglobbed_path);
16424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
16524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
16624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
16724943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::FileSpec() :
16824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_directory(),
16924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_filename()
17024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
17124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
17224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
17324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
17424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Default constructor that can take an optional full path to a
17524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// file on disk.
17624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
177c4547c59f2e8390bdbf92484c851be06395b8e77Jim InghamFileSpec::FileSpec(const char *pathname, bool resolve_path) :
178c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    m_directory(),
179c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    m_filename()
180c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham{
181c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    if (pathname && pathname[0])
182c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham        SetFile(pathname, resolve_path);
183c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham}
184c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham
185c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham//------------------------------------------------------------------
18624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Copy constructor
18724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
18824943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::FileSpec(const FileSpec& rhs) :
18924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_directory (rhs.m_directory),
19024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_filename (rhs.m_filename)
19124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
19224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
19324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
19424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
19524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Copy constructor
19624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
19724943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::FileSpec(const FileSpec* rhs) :
19824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_directory(),
19924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_filename()
20024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
20124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (rhs)
20224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        *this = *rhs;
20324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
20424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
20524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
20624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Virtual destrcuctor in case anyone inherits from this class.
20724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
20824943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::~FileSpec()
20924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
21024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
21124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
21224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
21324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Assignment operator.
21424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
21524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerconst FileSpec&
21624943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::operator= (const FileSpec& rhs)
21724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
21824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (this != &rhs)
21924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
22024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        m_directory = rhs.m_directory;
22124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        m_filename = rhs.m_filename;
22224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
22324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return *this;
22424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
22524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
22624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
22724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Update the contents of this object with a new path. The path will
22824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// be split up into a directory and filename and stored as uniqued
22924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// string values for quick comparison and efficient memory usage.
23024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
23124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid
232c4547c59f2e8390bdbf92484c851be06395b8e77Jim InghamFileSpec::SetFile(const char *pathname, bool resolve)
23324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
23424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_filename.Clear();
23524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_directory.Clear();
23624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (pathname == NULL || pathname[0] == '\0')
23724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return;
23824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
23924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    char resolved_path[PATH_MAX];
240c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    bool path_fit = true;
241c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham
242c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    if (resolve)
243c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    {
244c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham        path_fit = (FileSpec::Resolve (pathname, resolved_path, sizeof(resolved_path)) < sizeof(resolved_path) - 1);
245c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    }
246c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    else
247c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    {
248c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham        if (strlen (pathname) > sizeof(resolved_path) - 1)
249c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham            path_fit = false;
250c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham        else
251c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham            strcpy (resolved_path, pathname);
252c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    }
25324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
254c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham
255c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    if (path_fit)
25624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
25724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        char *filename = ::basename (resolved_path);
25824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (filename)
25924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
26024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            m_filename.SetCString (filename);
26124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            // Truncate the basename off the end of the resolved path
26224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
26324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            // Only attempt to get the dirname if it looks like we have a path
26424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (strchr(resolved_path, '/'))
26524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
26624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                char *directory = ::dirname (resolved_path);
26724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
26824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // Make sure we didn't get our directory resolved to "." without having
26924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // specified
27024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (directory)
27124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    m_directory.SetCString(directory);
27224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                else
27324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
27424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    char *last_resolved_path_slash = strrchr(resolved_path, '/');
27524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (last_resolved_path_slash)
27624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
27724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        *last_resolved_path_slash = '\0';
27824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        m_directory.SetCString(resolved_path);
27924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
28024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
28124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
28224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
28324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        else
28424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            m_directory.SetCString(resolved_path);
28524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
28624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
28724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
28824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
28924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Convert to pointer operator. This allows code to check any FileSpec
29024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// objects to see if they contain anything valid using code such as:
29124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
29224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//  if (file_spec)
29324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//  {}
29424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
29524943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::operator
29624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid*() const
29724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
29824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return (m_directory || m_filename) ? const_cast<FileSpec*>(this) : NULL;
29924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
30024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
30124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
30224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Logical NOT operator. This allows code to check any FileSpec
30324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// objects to see if they are invalid using code such as:
30424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
30524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//  if (!file_spec)
30624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//  {}
30724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
30824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool
30924943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::operator!() const
31024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
31124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return !m_directory && !m_filename;
31224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
31324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
31424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
31524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Equal to operator
31624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
31724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool
31824943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::operator== (const FileSpec& rhs) const
31924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
32024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return m_directory == rhs.m_directory && m_filename == rhs.m_filename;
32124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
32224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
32324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
32424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Not equal to operator
32524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
32624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool
32724943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::operator!= (const FileSpec& rhs) const
32824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
32924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return m_filename != rhs.m_filename || m_directory != rhs.m_directory;
33024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
33124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
33224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
33324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Less than operator
33424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
33524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool
33624943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::operator< (const FileSpec& rhs) const
33724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
33824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return FileSpec::Compare(*this, rhs, true) < 0;
33924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
34024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
34124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
34224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Dump a FileSpec object to a stream
34324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
34424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerStream&
34524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerlldb_private::operator << (Stream &s, const FileSpec& f)
34624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
34724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    f.Dump(&s);
34824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return s;
34924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
35024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
35124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
35224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Clear this object by releasing both the directory and filename
35324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// string values and making them both the empty string.
35424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
35524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid
35624943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::Clear()
35724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
35824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_directory.Clear();
35924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_filename.Clear();
36024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
36124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
36224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
36324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Compare two FileSpec objects. If "full" is true, then both
36424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// the directory and the filename must match. If "full" is false,
36524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// then the directory names for "a" and "b" are only compared if
36624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// they are both non-empty. This allows a FileSpec object to only
36724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// contain a filename and it can match FileSpec objects that have
36824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// matching filenames with different paths.
36924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
37024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Return -1 if the "a" is less than "b", 0 if "a" is equal to "b"
37124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// and "1" if "a" is greater than "b".
37224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
37324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerint
37424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::Compare(const FileSpec& a, const FileSpec& b, bool full)
37524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
37624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    int result = 0;
37724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
37824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // If full is true, then we must compare both the directory and filename.
37924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
38024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // If full is false, then if either directory is empty, then we match on
38124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // the basename only, and if both directories have valid values, we still
38224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // do a full compare. This allows for matching when we just have a filename
38324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // in one of the FileSpec objects.
38424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
38524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (full || (a.m_directory && b.m_directory))
38624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
38724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        result = ConstString::Compare(a.m_directory, b.m_directory);
38824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (result)
38924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            return result;
39024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
39124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return ConstString::Compare (a.m_filename, b.m_filename);
39224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
39324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
39424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool
39524943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::Equal (const FileSpec& a, const FileSpec& b, bool full)
39624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
39724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (full)
39824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return a == b;
39924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    else
40024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return a.m_filename == b.m_filename;
40124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
40224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
40324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
40424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
40524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
40624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Dump the object to the supplied stream. If the object contains
40724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// a valid directory name, it will be displayed followed by a
40824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// directory delimiter, and the filename.
40924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
41024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid
41124943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::Dump(Stream *s) const
41224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
41324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (m_filename)
41424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        m_directory.Dump(s, "");    // Provide a default for m_directory when we dump it in case it is invalid
41524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
41624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (m_directory)
41724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
41824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // If dirname was valid, then we need to print a slash between
41924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // the directory and the filename
42024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        s->PutChar('/');
42124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
42224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_filename.Dump(s);
42324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
42424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
42524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
42624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Returns true if the file exists.
42724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
42824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool
42924943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::Exists () const
43024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
43124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    struct stat file_stats;
43224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return GetFileStats (this, &file_stats);
433eddffe93d2c9ebb575e7b03fe1c5e71f9ecaf9f1Caroline Tice}
434eddffe93d2c9ebb575e7b03fe1c5e71f9ecaf9f1Caroline Tice
435eddffe93d2c9ebb575e7b03fe1c5e71f9ecaf9f1Caroline Ticebool
436eddffe93d2c9ebb575e7b03fe1c5e71f9ecaf9f1Caroline TiceFileSpec::ResolveExecutableLocation ()
437eddffe93d2c9ebb575e7b03fe1c5e71f9ecaf9f1Caroline Tice{
438537a7a86687683fd403ce652d178fbc89e06ef9fGreg Clayton    if (!m_directory)
439e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice    {
440e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice        const std::string file_str (m_filename.AsCString());
441e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice        llvm::sys::Path path = llvm::sys::Program::FindProgramByName (file_str);
442e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice        llvm::StringRef dir_ref = path.getDirname();
443e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice        if (! dir_ref.empty())
444e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice        {
445e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice            // FindProgramByName returns "." if it can't find the file.
446e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice            if (strcmp (".", dir_ref.data()) == 0)
447e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice                return false;
448e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice
449e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice            m_directory.SetCString (dir_ref.data());
450e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice            if (Exists())
451e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice                return true;
452e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice            else
453e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice            {
454e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice                // If FindProgramByName found the file, it returns the directory + filename in its return results.
455e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice                // We need to separate them.
456537a7a86687683fd403ce652d178fbc89e06ef9fGreg Clayton                FileSpec tmp_file (dir_ref.data(), false);
457e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice                if (tmp_file.Exists())
458e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice                {
459e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice                    m_directory = tmp_file.m_directory;
460e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice                    return true;
461e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice                }
462e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice            }
463e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice        }
464e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice    }
465e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice
466e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice    return false;
467c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham}
468c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham
469c4547c59f2e8390bdbf92484c851be06395b8e77Jim Inghambool
470c4547c59f2e8390bdbf92484c851be06395b8e77Jim InghamFileSpec::ResolvePath ()
471c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham{
472c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    char path_buf[PATH_MAX];
473c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham
474c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    if (!GetPath (path_buf, PATH_MAX))
475c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham        return false;
476c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    SetFile (path_buf, true);
477c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    return true;
47824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
47924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
48024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattneruint64_t
48124943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::GetByteSize() const
48224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
48324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    struct stat file_stats;
48424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (GetFileStats (this, &file_stats))
48524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return file_stats.st_size;
48624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return 0;
48724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
48824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
48924943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::FileType
49024943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::GetFileType () const
49124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
49224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    struct stat file_stats;
49324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (GetFileStats (this, &file_stats))
49424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
49524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        mode_t file_type = file_stats.st_mode & S_IFMT;
49624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        switch (file_type)
49724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
49824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        case S_IFDIR:   return eFileTypeDirectory;
49924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        case S_IFIFO:   return eFileTypePipe;
50024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        case S_IFREG:   return eFileTypeRegular;
50124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        case S_IFSOCK:  return eFileTypeSocket;
50224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        case S_IFLNK:   return eFileTypeSymbolicLink;
50324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        default:
50424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            break;
50524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
50624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return eFileTypeUknown;
50724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
50824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return eFileTypeInvalid;
50924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
51024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
51124943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerTimeValue
51224943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::GetModificationTime () const
51324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
51424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    TimeValue mod_time;
51524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    struct stat file_stats;
51624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (GetFileStats (this, &file_stats))
517b586901fb633b898e19bdfc8d605b4e89a3ab5b8Eli Friedman        mod_time.OffsetWithSeconds(file_stats.st_mtime);
51824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return mod_time;
51924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
52024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
52124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
52224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Directory string get accessor.
52324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
52424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerConstString &
52524943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::GetDirectory()
52624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
52724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return m_directory;
52824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
52924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
53024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
53124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Directory string const get accessor.
53224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
53324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerconst ConstString &
53424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::GetDirectory() const
53524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
53624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return m_directory;
53724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
53824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
53924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
54024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Filename string get accessor.
54124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
54224943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerConstString &
54324943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::GetFilename()
54424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
54524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return m_filename;
54624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
54724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
54824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
54924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Filename string const get accessor.
55024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
55124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerconst ConstString &
55224943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::GetFilename() const
55324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
55424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return m_filename;
55524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
55624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
55724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
55824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Extract the directory and path into a fixed buffer. This is
55924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// needed as the directory and path are stored in separate string
56024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// values.
56124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
56249ce682dfa7993d31206cea19ce7006cd3f3077eGreg Claytonsize_t
56349ce682dfa7993d31206cea19ce7006cd3f3077eGreg ClaytonFileSpec::GetPath(char *path, size_t path_max_len) const
56424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
56549ce682dfa7993d31206cea19ce7006cd3f3077eGreg Clayton    if (path_max_len)
56624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
56749ce682dfa7993d31206cea19ce7006cd3f3077eGreg Clayton        const char *dirname = m_directory.GetCString();
56849ce682dfa7993d31206cea19ce7006cd3f3077eGreg Clayton        const char *filename = m_filename.GetCString();
56924b48ff28b7c60dd4598212c3e77935a0fc1142dGreg Clayton        if (dirname)
57024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
57124b48ff28b7c60dd4598212c3e77935a0fc1142dGreg Clayton            if (filename)
57249ce682dfa7993d31206cea19ce7006cd3f3077eGreg Clayton                return ::snprintf (path, path_max_len, "%s/%s", dirname, filename);
57324b48ff28b7c60dd4598212c3e77935a0fc1142dGreg Clayton            else
57449ce682dfa7993d31206cea19ce7006cd3f3077eGreg Clayton                return ::snprintf (path, path_max_len, "%s", dirname);
57524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
57624b48ff28b7c60dd4598212c3e77935a0fc1142dGreg Clayton        else if (filename)
57724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
57849ce682dfa7993d31206cea19ce7006cd3f3077eGreg Clayton            return ::snprintf (path, path_max_len, "%s", filename);
57924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
58024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
58124b48ff28b7c60dd4598212c3e77935a0fc1142dGreg Clayton    path[0] = '\0';
58249ce682dfa7993d31206cea19ce7006cd3f3077eGreg Clayton    return 0;
58324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
58424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
58524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
58624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Returns a shared pointer to a data buffer that contains all or
58724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// part of the contents of a file. The data is memory mapped and
58824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// will lazily page in data from the file as memory is accessed.
58924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// The data that is mappped will start "file_offset" bytes into the
59024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// file, and "file_size" bytes will be mapped. If "file_size" is
59124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// greater than the number of bytes available in the file starting
59224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// at "file_offset", the number of bytes will be appropriately
59324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// truncated. The final number of bytes that get mapped can be
59424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// verified using the DataBuffer::GetByteSize() function.
59524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
59624943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerDataBufferSP
59724943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::MemoryMapFileContents(off_t file_offset, size_t file_size) const
59824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
59924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    DataBufferSP data_sp;
60024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    auto_ptr<DataBufferMemoryMap> mmap_data(new DataBufferMemoryMap());
60124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (mmap_data.get())
60224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
60324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (mmap_data->MemoryMapFromFileSpec (this, file_offset, file_size) >= file_size)
60424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            data_sp.reset(mmap_data.release());
60524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
60624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return data_sp;
60724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
60824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
60924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
61024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
61124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Return the size in bytes that this object takes in memory. This
61224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// returns the size in bytes of this object, not any shared string
61324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// values it may refer to.
61424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
61524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnersize_t
61624943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::MemorySize() const
61724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
61824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return m_filename.MemorySize() + m_directory.MemorySize();
61924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
62024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
621704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton
622704363531ee4877ccc6d35d0702876096f54c67bGreg Claytonsize_t
623704363531ee4877ccc6d35d0702876096f54c67bGreg ClaytonFileSpec::ReadFileContents (off_t file_offset, void *dst, size_t dst_len) const
624704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton{
625704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton    size_t bytes_read = 0;
626704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton    char resolved_path[PATH_MAX];
627704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton    if (GetPath(resolved_path, sizeof(resolved_path)))
628704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton    {
629704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton        int fd = ::open (resolved_path, O_RDONLY, 0);
630704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton        if (fd != -1)
631704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton        {
632704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton            struct stat file_stats;
633704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton            if (::fstat (fd, &file_stats) == 0)
634704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton            {
635704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                // Read bytes directly into our basic_string buffer
636704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                if (file_stats.st_size > 0)
637704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                {
638704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                    off_t lseek_result = 0;
639704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                    if (file_offset > 0)
640704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                        lseek_result = ::lseek (fd, file_offset, SEEK_SET);
641704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton
642704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                    if (lseek_result == file_offset)
643704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                    {
644704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                        ssize_t n = ::read (fd, dst, dst_len);
645704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                        if (n >= 0)
646704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                            bytes_read = n;
647704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                    }
648704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                }
649704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton            }
650704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton        }
651704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton        close(fd);
652704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton    }
653704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton    return bytes_read;
654704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton}
655704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton
65624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
65724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Returns a shared pointer to a data buffer that contains all or
65824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// part of the contents of a file. The data copies into a heap based
65924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// buffer that lives in the DataBuffer shared pointer object returned.
66024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// The data that is cached will start "file_offset" bytes into the
66124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// file, and "file_size" bytes will be mapped. If "file_size" is
66224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// greater than the number of bytes available in the file starting
66324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// at "file_offset", the number of bytes will be appropriately
66424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// truncated. The final number of bytes that get mapped can be
66524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// verified using the DataBuffer::GetByteSize() function.
66624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
66724943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerDataBufferSP
668704363531ee4877ccc6d35d0702876096f54c67bGreg ClaytonFileSpec::ReadFileContents (off_t file_offset, size_t file_size) const
66924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
67024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    DataBufferSP data_sp;
67124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    char resolved_path[PATH_MAX];
67224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (GetPath(resolved_path, sizeof(resolved_path)))
67324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
67424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        int fd = ::open (resolved_path, O_RDONLY, 0);
67524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (fd != -1)
67624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
67724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            struct stat file_stats;
67824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (::fstat (fd, &file_stats) == 0)
67924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
68024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (file_stats.st_size > 0)
68124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
68224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    off_t lseek_result = 0;
68324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (file_offset > 0)
68424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        lseek_result = ::lseek (fd, file_offset, SEEK_SET);
68524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
68624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (lseek_result < 0)
68724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
68824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        // Get error from errno
68924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
69024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    else if (lseek_result == file_offset)
69124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
692704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                        const size_t bytes_left = file_stats.st_size - file_offset;
693704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                        size_t num_bytes_to_read = file_size;
694704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                        if (num_bytes_to_read > bytes_left)
695704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                            num_bytes_to_read = bytes_left;
696704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton
69724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        std::auto_ptr<DataBufferHeap> data_heap_ap;
698704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                        data_heap_ap.reset(new DataBufferHeap(num_bytes_to_read, '\0'));
69924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
70024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        if (data_heap_ap.get())
70124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        {
70224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            ssize_t bytesRead = ::read (fd, (void *)data_heap_ap->GetBytes(), data_heap_ap->GetByteSize());
70324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            if (bytesRead >= 0)
70424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            {
70524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                // Make sure we read exactly what we asked for and if we got
70624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                // less, adjust the array
70754e7afa84d945f9137f9372ecde432f9e1a702fcGreg Clayton                                if ((size_t)bytesRead < data_heap_ap->GetByteSize())
70824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                    data_heap_ap->SetByteSize(bytesRead);
70924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                data_sp.reset(data_heap_ap.release());
71024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            }
71124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        }
71224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
71324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
71424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
71524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
71624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        close(fd);
71724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
71824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return data_sp;
71924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
72024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
7213d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Claytonsize_t
72224943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::ReadFileLines (STLStringArray &lines)
72324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
72424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    lines.clear();
7253d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton    char path[PATH_MAX];
7263d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton    if (GetPath(path, sizeof(path)))
72724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
7283d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton        ifstream file_stream (path);
72924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
7303d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton        if (file_stream)
7313d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton        {
7323d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton            std::string line;
7333d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton            while (getline (file_stream, line))
7343d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton                lines.push_back (line);
7353d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton        }
7363d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton    }
7373d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton    return lines.size();
73824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
739