FileSpec.cpp revision d6d806ceff943ca26c008f704013f18920685cfd
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(),
179d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton    m_filename(),
180d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton    m_is_resolved(false)
181c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham{
182c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    if (pathname && pathname[0])
183c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham        SetFile(pathname, resolve_path);
184c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham}
185c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham
186c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham//------------------------------------------------------------------
18724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Copy constructor
18824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
18924943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::FileSpec(const FileSpec& rhs) :
19024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_directory (rhs.m_directory),
191d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton    m_filename (rhs.m_filename),
192d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton    m_is_resolved (rhs.m_is_resolved)
19324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
19424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
19524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
19624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
19724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Copy constructor
19824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
19924943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::FileSpec(const FileSpec* rhs) :
20024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_directory(),
20124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_filename()
20224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
20324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (rhs)
20424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        *this = *rhs;
20524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
20624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
20724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
20824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Virtual destrcuctor in case anyone inherits from this class.
20924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
21024943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::~FileSpec()
21124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
21224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
21324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
21424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
21524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Assignment operator.
21624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
21724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerconst FileSpec&
21824943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::operator= (const FileSpec& rhs)
21924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
22024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (this != &rhs)
22124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
22224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        m_directory = rhs.m_directory;
22324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        m_filename = rhs.m_filename;
224d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        m_is_resolved = rhs.m_is_resolved;
22524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
22624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return *this;
22724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
22824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
22924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
23024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Update the contents of this object with a new path. The path will
23124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// be split up into a directory and filename and stored as uniqued
23224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// string values for quick comparison and efficient memory usage.
23324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
23424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid
235d6d806ceff943ca26c008f704013f18920685cfdGreg ClaytonFileSpec::SetFile (const char *pathname, bool resolve)
23624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
23724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_filename.Clear();
23824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_directory.Clear();
239d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton    m_is_resolved = false;
24024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (pathname == NULL || pathname[0] == '\0')
24124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return;
24224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
24324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    char resolved_path[PATH_MAX];
244c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    bool path_fit = true;
245c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham
246c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    if (resolve)
247c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    {
248c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham        path_fit = (FileSpec::Resolve (pathname, resolved_path, sizeof(resolved_path)) < sizeof(resolved_path) - 1);
249d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        m_is_resolved = path_fit;
250c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    }
251c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    else
252c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    {
253d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        // Copy the path because "basename" and "dirname" want to muck with the
254d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        // path buffer
255d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        if (::strlen (pathname) > sizeof(resolved_path) - 1)
256c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham            path_fit = false;
257c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham        else
258d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton            ::strcpy (resolved_path, pathname);
259c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    }
26024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
261c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham
262c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    if (path_fit)
26324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
26424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        char *filename = ::basename (resolved_path);
26524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (filename)
26624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
26724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            m_filename.SetCString (filename);
26824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            // Truncate the basename off the end of the resolved path
26924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
27024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            // Only attempt to get the dirname if it looks like we have a path
27124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (strchr(resolved_path, '/'))
27224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
27324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                char *directory = ::dirname (resolved_path);
27424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
27524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // Make sure we didn't get our directory resolved to "." without having
27624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // specified
27724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (directory)
27824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    m_directory.SetCString(directory);
27924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                else
28024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
28124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    char *last_resolved_path_slash = strrchr(resolved_path, '/');
28224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (last_resolved_path_slash)
28324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
28424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        *last_resolved_path_slash = '\0';
28524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        m_directory.SetCString(resolved_path);
28624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
28724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
28824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
28924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
29024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        else
29124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            m_directory.SetCString(resolved_path);
29224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
29324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
29424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
29524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
29624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Convert to pointer operator. This allows code to check any FileSpec
29724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// objects to see if they contain anything valid using code such as:
29824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
29924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//  if (file_spec)
30024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//  {}
30124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
30224943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::operator
30324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid*() const
30424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
30524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return (m_directory || m_filename) ? const_cast<FileSpec*>(this) : NULL;
30624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
30724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
30824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
30924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Logical NOT operator. This allows code to check any FileSpec
31024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// objects to see if they are invalid using code such as:
31124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
31224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//  if (!file_spec)
31324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//  {}
31424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
31524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool
31624943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::operator!() const
31724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
31824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return !m_directory && !m_filename;
31924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
32024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
32124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
32224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Equal to operator
32324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
32424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool
32524943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::operator== (const FileSpec& rhs) const
32624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
327d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton    if (m_filename == rhs.m_filename)
328d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton    {
329d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        if (m_directory == rhs.m_directory)
330d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton            return true;
331d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton
332d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        // TODO: determine if we want to keep this code in here.
333d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        // The code below was added to handle a case where we were
334d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        // trying to set a file and line breakpoint and one path
335d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        // was resolved, and the other not and the directory was
336d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        // in a mount point that resolved to a more complete path:
337d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        // "/tmp/a.c" == "/private/tmp/a.c". I might end up pulling
338d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        // this out...
339d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        if (IsResolved() && rhs.IsResolved())
340d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        {
341d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton            // Both paths are resolved, no need to look further...
342d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton            return false;
343d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        }
344d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton
345d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        FileSpec resolved_lhs(*this);
346d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton
347d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        // If "this" isn't resolved, resolve it
348d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        if (!IsResolved())
349d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        {
350d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton            if (resolved_lhs.ResolvePath())
351d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton            {
352d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton                // This path wasn't resolved but now it is. Check if the resolved
353d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton                // directory is the same as our unresolved directory, and if so,
354d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton                // we can mark this object as resolved to avoid more future resolves
355d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton                m_is_resolved = (m_directory == resolved_lhs.m_directory);
356d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton            }
357d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton            else
358d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton                return false;
359d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        }
360d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton
361d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        FileSpec resolved_rhs(rhs);
362d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        if (!rhs.IsResolved())
363d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        {
364d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton            if (resolved_rhs.ResolvePath())
365d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton            {
366d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton                // rhs's path wasn't resolved but now it is. Check if the resolved
367d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton                // directory is the same as rhs's unresolved directory, and if so,
368d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton                // we can mark this object as resolved to avoid more future resolves
369d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton                rhs.m_is_resolved = (m_directory == resolved_rhs.m_directory);
370d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton            }
371d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton            else
372d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton                return false;
373d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        }
374d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton
375d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        // If we reach this point in the code we were able to resolve both paths
376d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        // and since we only resolve the paths if the basenames are equal, then
377d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        // we can just check if both directories are equal...
378d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        return resolved_lhs.GetDirectory() == resolved_rhs.GetDirectory();
379d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton    }
380d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton    return false;
38124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
38224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
38324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
38424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Not equal to operator
38524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
38624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool
38724943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::operator!= (const FileSpec& rhs) const
38824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
389d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton    return !(*this == rhs);
39024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
39124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
39224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
39324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Less than operator
39424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
39524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool
39624943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::operator< (const FileSpec& rhs) const
39724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
39824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return FileSpec::Compare(*this, rhs, true) < 0;
39924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
40024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
40124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
40224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Dump a FileSpec object to a stream
40324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
40424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerStream&
40524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerlldb_private::operator << (Stream &s, const FileSpec& f)
40624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
40724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    f.Dump(&s);
40824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return s;
40924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
41024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
41124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
41224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Clear this object by releasing both the directory and filename
41324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// string values and making them both the empty string.
41424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
41524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid
41624943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::Clear()
41724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
41824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_directory.Clear();
41924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_filename.Clear();
42024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
42124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
42224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
42324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Compare two FileSpec objects. If "full" is true, then both
42424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// the directory and the filename must match. If "full" is false,
42524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// then the directory names for "a" and "b" are only compared if
42624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// they are both non-empty. This allows a FileSpec object to only
42724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// contain a filename and it can match FileSpec objects that have
42824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// matching filenames with different paths.
42924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
43024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Return -1 if the "a" is less than "b", 0 if "a" is equal to "b"
43124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// and "1" if "a" is greater than "b".
43224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
43324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerint
43424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::Compare(const FileSpec& a, const FileSpec& b, bool full)
43524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
43624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    int result = 0;
43724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
43824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // If full is true, then we must compare both the directory and filename.
43924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
44024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // If full is false, then if either directory is empty, then we match on
44124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // the basename only, and if both directories have valid values, we still
44224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // do a full compare. This allows for matching when we just have a filename
44324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // in one of the FileSpec objects.
44424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
44524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (full || (a.m_directory && b.m_directory))
44624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
44724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        result = ConstString::Compare(a.m_directory, b.m_directory);
44824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (result)
44924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            return result;
45024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
45124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return ConstString::Compare (a.m_filename, b.m_filename);
45224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
45324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
45424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool
45524943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::Equal (const FileSpec& a, const FileSpec& b, bool full)
45624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
45724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (full)
45824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return a == b;
45924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    else
46024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return a.m_filename == b.m_filename;
46124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
46224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
46324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
46424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
46524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
46624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Dump the object to the supplied stream. If the object contains
46724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// a valid directory name, it will be displayed followed by a
46824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// directory delimiter, and the filename.
46924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
47024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid
47124943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::Dump(Stream *s) const
47224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
47324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (m_filename)
47424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        m_directory.Dump(s, "");    // Provide a default for m_directory when we dump it in case it is invalid
47524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
47624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (m_directory)
47724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
47824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // If dirname was valid, then we need to print a slash between
47924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // the directory and the filename
48024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        s->PutChar('/');
48124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
48224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_filename.Dump(s);
48324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
48424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
48524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
48624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Returns true if the file exists.
48724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
48824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool
48924943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::Exists () const
49024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
49124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    struct stat file_stats;
49224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return GetFileStats (this, &file_stats);
493eddffe93d2c9ebb575e7b03fe1c5e71f9ecaf9f1Caroline Tice}
494eddffe93d2c9ebb575e7b03fe1c5e71f9ecaf9f1Caroline Tice
495eddffe93d2c9ebb575e7b03fe1c5e71f9ecaf9f1Caroline Ticebool
496eddffe93d2c9ebb575e7b03fe1c5e71f9ecaf9f1Caroline TiceFileSpec::ResolveExecutableLocation ()
497eddffe93d2c9ebb575e7b03fe1c5e71f9ecaf9f1Caroline Tice{
498537a7a86687683fd403ce652d178fbc89e06ef9fGreg Clayton    if (!m_directory)
499e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice    {
500e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice        const std::string file_str (m_filename.AsCString());
501e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice        llvm::sys::Path path = llvm::sys::Program::FindProgramByName (file_str);
502e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice        llvm::StringRef dir_ref = path.getDirname();
503e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice        if (! dir_ref.empty())
504e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice        {
505e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice            // FindProgramByName returns "." if it can't find the file.
506e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice            if (strcmp (".", dir_ref.data()) == 0)
507e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice                return false;
508e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice
509e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice            m_directory.SetCString (dir_ref.data());
510e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice            if (Exists())
511e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice                return true;
512e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice            else
513e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice            {
514e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice                // If FindProgramByName found the file, it returns the directory + filename in its return results.
515e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice                // We need to separate them.
516537a7a86687683fd403ce652d178fbc89e06ef9fGreg Clayton                FileSpec tmp_file (dir_ref.data(), false);
517e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice                if (tmp_file.Exists())
518e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice                {
519e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice                    m_directory = tmp_file.m_directory;
520e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice                    return true;
521e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice                }
522e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice            }
523e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice        }
524e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice    }
525e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice
526e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice    return false;
527c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham}
528c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham
529c4547c59f2e8390bdbf92484c851be06395b8e77Jim Inghambool
530c4547c59f2e8390bdbf92484c851be06395b8e77Jim InghamFileSpec::ResolvePath ()
531c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham{
532d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton    if (m_is_resolved)
533d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        return true;    // We have already resolved this path
534d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton
535d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton    char path_buf[PATH_MAX];
536c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    if (!GetPath (path_buf, PATH_MAX))
537c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham        return false;
538d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton    // SetFile(...) will set m_is_resolved correctly if it can resolve the path
539c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    SetFile (path_buf, true);
540d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton    return m_is_resolved;
54124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
54224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
54324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattneruint64_t
54424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::GetByteSize() const
54524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
54624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    struct stat file_stats;
54724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (GetFileStats (this, &file_stats))
54824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return file_stats.st_size;
54924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return 0;
55024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
55124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
55224943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::FileType
55324943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::GetFileType () const
55424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
55524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    struct stat file_stats;
55624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (GetFileStats (this, &file_stats))
55724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
55824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        mode_t file_type = file_stats.st_mode & S_IFMT;
55924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        switch (file_type)
56024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
56124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        case S_IFDIR:   return eFileTypeDirectory;
56224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        case S_IFIFO:   return eFileTypePipe;
56324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        case S_IFREG:   return eFileTypeRegular;
56424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        case S_IFSOCK:  return eFileTypeSocket;
56524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        case S_IFLNK:   return eFileTypeSymbolicLink;
56624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        default:
56724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            break;
56824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
56924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return eFileTypeUknown;
57024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
57124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return eFileTypeInvalid;
57224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
57324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
57424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerTimeValue
57524943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::GetModificationTime () const
57624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
57724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    TimeValue mod_time;
57824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    struct stat file_stats;
57924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (GetFileStats (this, &file_stats))
580b586901fb633b898e19bdfc8d605b4e89a3ab5b8Eli Friedman        mod_time.OffsetWithSeconds(file_stats.st_mtime);
58124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return mod_time;
58224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
58324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
58424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
58524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Directory string get accessor.
58624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
58724943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerConstString &
58824943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::GetDirectory()
58924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
59024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return m_directory;
59124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
59224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
59324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
59424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Directory string const get accessor.
59524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
59624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerconst ConstString &
59724943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::GetDirectory() const
59824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
59924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return m_directory;
60024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
60124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
60224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
60324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Filename string get accessor.
60424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
60524943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerConstString &
60624943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::GetFilename()
60724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
60824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return m_filename;
60924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
61024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
61124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
61224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Filename string const get accessor.
61324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
61424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerconst ConstString &
61524943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::GetFilename() const
61624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
61724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return m_filename;
61824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
61924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
62024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
62124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Extract the directory and path into a fixed buffer. This is
62224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// needed as the directory and path are stored in separate string
62324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// values.
62424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
62549ce682dfa7993d31206cea19ce7006cd3f3077eGreg Claytonsize_t
62649ce682dfa7993d31206cea19ce7006cd3f3077eGreg ClaytonFileSpec::GetPath(char *path, size_t path_max_len) const
62724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
62849ce682dfa7993d31206cea19ce7006cd3f3077eGreg Clayton    if (path_max_len)
62924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
63049ce682dfa7993d31206cea19ce7006cd3f3077eGreg Clayton        const char *dirname = m_directory.GetCString();
63149ce682dfa7993d31206cea19ce7006cd3f3077eGreg Clayton        const char *filename = m_filename.GetCString();
63224b48ff28b7c60dd4598212c3e77935a0fc1142dGreg Clayton        if (dirname)
63324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
63424b48ff28b7c60dd4598212c3e77935a0fc1142dGreg Clayton            if (filename)
63549ce682dfa7993d31206cea19ce7006cd3f3077eGreg Clayton                return ::snprintf (path, path_max_len, "%s/%s", dirname, filename);
63624b48ff28b7c60dd4598212c3e77935a0fc1142dGreg Clayton            else
63749ce682dfa7993d31206cea19ce7006cd3f3077eGreg Clayton                return ::snprintf (path, path_max_len, "%s", dirname);
63824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
63924b48ff28b7c60dd4598212c3e77935a0fc1142dGreg Clayton        else if (filename)
64024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
64149ce682dfa7993d31206cea19ce7006cd3f3077eGreg Clayton            return ::snprintf (path, path_max_len, "%s", filename);
64224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
64324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
64424b48ff28b7c60dd4598212c3e77935a0fc1142dGreg Clayton    path[0] = '\0';
64549ce682dfa7993d31206cea19ce7006cd3f3077eGreg Clayton    return 0;
64624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
64724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
64824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
64924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Returns a shared pointer to a data buffer that contains all or
65024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// part of the contents of a file. The data is memory mapped and
65124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// will lazily page in data from the file as memory is accessed.
65224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// The data that is mappped will start "file_offset" bytes into the
65324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// file, and "file_size" bytes will be mapped. If "file_size" is
65424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// greater than the number of bytes available in the file starting
65524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// at "file_offset", the number of bytes will be appropriately
65624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// truncated. The final number of bytes that get mapped can be
65724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// verified using the DataBuffer::GetByteSize() function.
65824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
65924943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerDataBufferSP
66024943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::MemoryMapFileContents(off_t file_offset, size_t file_size) const
66124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
66224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    DataBufferSP data_sp;
66324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    auto_ptr<DataBufferMemoryMap> mmap_data(new DataBufferMemoryMap());
66424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (mmap_data.get())
66524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
66624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (mmap_data->MemoryMapFromFileSpec (this, file_offset, file_size) >= file_size)
66724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            data_sp.reset(mmap_data.release());
66824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
66924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return data_sp;
67024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
67124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
67224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
67324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
67424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Return the size in bytes that this object takes in memory. This
67524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// returns the size in bytes of this object, not any shared string
67624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// values it may refer to.
67724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
67824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnersize_t
67924943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::MemorySize() const
68024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
68124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return m_filename.MemorySize() + m_directory.MemorySize();
68224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
68324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
684704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton
685704363531ee4877ccc6d35d0702876096f54c67bGreg Claytonsize_t
686704363531ee4877ccc6d35d0702876096f54c67bGreg ClaytonFileSpec::ReadFileContents (off_t file_offset, void *dst, size_t dst_len) const
687704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton{
688704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton    size_t bytes_read = 0;
689704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton    char resolved_path[PATH_MAX];
690704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton    if (GetPath(resolved_path, sizeof(resolved_path)))
691704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton    {
692704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton        int fd = ::open (resolved_path, O_RDONLY, 0);
693704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton        if (fd != -1)
694704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton        {
695704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton            struct stat file_stats;
696704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton            if (::fstat (fd, &file_stats) == 0)
697704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton            {
698704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                // Read bytes directly into our basic_string buffer
699704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                if (file_stats.st_size > 0)
700704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                {
701704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                    off_t lseek_result = 0;
702704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                    if (file_offset > 0)
703704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                        lseek_result = ::lseek (fd, file_offset, SEEK_SET);
704704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton
705704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                    if (lseek_result == file_offset)
706704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                    {
707704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                        ssize_t n = ::read (fd, dst, dst_len);
708704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                        if (n >= 0)
709704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                            bytes_read = n;
710704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                    }
711704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                }
712704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton            }
713704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton        }
714704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton        close(fd);
715704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton    }
716704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton    return bytes_read;
717704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton}
718704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton
71924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
72024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Returns a shared pointer to a data buffer that contains all or
72124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// part of the contents of a file. The data copies into a heap based
72224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// buffer that lives in the DataBuffer shared pointer object returned.
72324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// The data that is cached will start "file_offset" bytes into the
72424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// file, and "file_size" bytes will be mapped. If "file_size" is
72524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// greater than the number of bytes available in the file starting
72624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// at "file_offset", the number of bytes will be appropriately
72724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// truncated. The final number of bytes that get mapped can be
72824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// verified using the DataBuffer::GetByteSize() function.
72924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
73024943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerDataBufferSP
731704363531ee4877ccc6d35d0702876096f54c67bGreg ClaytonFileSpec::ReadFileContents (off_t file_offset, size_t file_size) const
73224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
73324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    DataBufferSP data_sp;
73424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    char resolved_path[PATH_MAX];
73524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (GetPath(resolved_path, sizeof(resolved_path)))
73624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
73724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        int fd = ::open (resolved_path, O_RDONLY, 0);
73824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (fd != -1)
73924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
74024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            struct stat file_stats;
74124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (::fstat (fd, &file_stats) == 0)
74224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
74324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (file_stats.st_size > 0)
74424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
74524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    off_t lseek_result = 0;
74624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (file_offset > 0)
74724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        lseek_result = ::lseek (fd, file_offset, SEEK_SET);
74824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
74924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (lseek_result < 0)
75024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
75124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        // Get error from errno
75224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
75324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    else if (lseek_result == file_offset)
75424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
755704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                        const size_t bytes_left = file_stats.st_size - file_offset;
756704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                        size_t num_bytes_to_read = file_size;
757704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                        if (num_bytes_to_read > bytes_left)
758704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                            num_bytes_to_read = bytes_left;
759704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton
76024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        std::auto_ptr<DataBufferHeap> data_heap_ap;
761704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton                        data_heap_ap.reset(new DataBufferHeap(num_bytes_to_read, '\0'));
76224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
76324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        if (data_heap_ap.get())
76424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        {
76524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            ssize_t bytesRead = ::read (fd, (void *)data_heap_ap->GetBytes(), data_heap_ap->GetByteSize());
76624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            if (bytesRead >= 0)
76724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            {
76824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                // Make sure we read exactly what we asked for and if we got
76924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                // less, adjust the array
77054e7afa84d945f9137f9372ecde432f9e1a702fcGreg Clayton                                if ((size_t)bytesRead < data_heap_ap->GetByteSize())
77124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                    data_heap_ap->SetByteSize(bytesRead);
77224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                data_sp.reset(data_heap_ap.release());
77324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            }
77424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        }
77524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
77624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
77724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
77824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
77924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        close(fd);
78024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
78124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return data_sp;
78224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
78324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
7843d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Claytonsize_t
78524943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::ReadFileLines (STLStringArray &lines)
78624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
78724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    lines.clear();
7883d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton    char path[PATH_MAX];
7893d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton    if (GetPath(path, sizeof(path)))
79024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
7913d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton        ifstream file_stream (path);
79224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
7933d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton        if (file_stream)
7943d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton        {
7953d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton            std::string line;
7963d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton            while (getline (file_stream, line))
7973d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton                lines.push_back (line);
7983d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton        }
7993d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton    }
8003d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton    return lines.size();
80124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
802