blob: d12cd1647ede708ad787a8917c76e8f9f3efd3f1 [file] [log] [blame]
Michael J. Spencerdffde992010-11-29 22:28:51 +00001//===- llvm/Support/Unix/PathV2.cpp - Unix Path Implementation --*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the Unix specific implementation of the PathV2 API.
11//
12//===----------------------------------------------------------------------===//
13
14//===----------------------------------------------------------------------===//
15//=== WARNING: Implementation here must contain only generic UNIX code that
16//=== is guaranteed to work on *all* UNIX variants.
17//===----------------------------------------------------------------------===//
18
19#include "Unix.h"
Michael J. Spencerbee0c382010-12-01 19:32:01 +000020#if HAVE_SYS_STAT_H
21#include <sys/stat.h>
22#endif
23#if HAVE_FCNTL_H
24#include <fcntl.h>
25#endif
26#if HAVE_SYS_TYPES_H
27#include <sys/types.h>
28#endif
29
30namespace {
31 struct AutoFD {
32 int FileDescriptor;
33
34 AutoFD(int fd) : FileDescriptor(fd) {}
35 ~AutoFD() {
36 if (FileDescriptor >= 0)
37 ::close(FileDescriptor);
38 }
39
40 int take() {
41 int ret = FileDescriptor;
42 FileDescriptor = -1;
43 return ret;
44 }
45
46 operator int() const {return FileDescriptor;}
47 };
48}
Michael J. Spencerdffde992010-11-29 22:28:51 +000049
50namespace llvm {
51namespace sys {
52namespace path {
53
54error_code current_path(SmallVectorImpl<char> &result) {
55 long size = ::pathconf(".", _PC_PATH_MAX);
56 result.reserve(size + 1);
57 result.set_size(size + 1);
58
59 if (::getcwd(result.data(), result.size()) == 0)
60 return error_code(errno, system_category());
61
62 result.set_size(strlen(result.data()));
63 return make_error_code(errc::success);
64}
65
66} // end namespace path
Michael J. Spencerbee0c382010-12-01 19:32:01 +000067
68namespace fs{
69
70error_code copy_file(const Twine &from, const Twine &to, copy_option copt) {
71 // Get arguments.
72 SmallString<128> from_storage;
73 SmallString<128> to_storage;
74 StringRef f = from.toStringRef(from_storage);
75 StringRef t = to.toStringRef(to_storage);
76
77 const size_t buf_sz = 32768;
78 char buffer[buf_sz];
79 int from_file = -1, to_file = -1;
80
81 // Open from.
82 if ((from_file = ::open(f.begin(), O_RDONLY)) < 0)
83 return error_code(errno, system_category());
84 AutoFD from_fd(from_file);
85
86 // Stat from.
87 struct stat from_stat;
88 if (::stat(f.begin(), &from_stat) != 0)
89 return error_code(errno, system_category());
90
91 // Setup to flags.
92 int to_flags = O_CREAT | O_WRONLY;
93 if (copt == copy_option::fail_if_exists)
94 to_flags |= O_EXCL;
95
96 // Open to.
97 if ((to_file = ::open(t.begin(), to_flags, from_stat.st_mode)) < 0)
98 return error_code(errno, system_category());
99 AutoFD to_fd(to_file);
100
101 // Copy!
102 ssize_t sz, sz_read = 1, sz_write;
103 while (sz_read > 0 &&
104 (sz_read = ::read(from_fd, buffer, buf_sz)) > 0) {
105 // Allow for partial writes - see Advanced Unix Programming (2nd Ed.),
106 // Marc Rochkind, Addison-Wesley, 2004, page 94
107 sz_write = 0;
108 do {
109 if ((sz = ::write(to_fd, buffer + sz_write, sz_read - sz_write)) < 0) {
110 sz_read = sz; // cause read loop termination.
111 break; // error.
112 }
113 sz_write += sz;
114 } while (sz_write < sz_read);
115 }
116
117 // After all the file operations above the return value of close actually
118 // matters.
119 if (::close(from_fd.take()) < 0) sz_read = -1;
120 if (::close(to_fd.take()) < 0) sz_read = -1;
121
122 // Check for errors.
123 if (sz_read < 0)
124 return error_code(errno, system_category());
125
126 return make_error_code(errc::success);
127}
128
129} // end namespace fs
Michael J. Spencerdffde992010-11-29 22:28:51 +0000130} // end namespace sys
131} // end namespace llvm