]> git.tdb.fi Git - builder.git/blob - source/copy.cpp
Make symlink a feature of the Install target rather than a target on its own
[builder.git] / source / copy.cpp
1 #include <errno.h>
2 #include <sys/stat.h>
3 #include <msp/fs/dir.h>
4 #include <msp/fs/stat.h>
5 #include <msp/fs/utils.h>
6 #include <msp/io/file.h>
7 #include <msp/io/print.h>
8 #include "builder.h"
9 #include "copy.h"
10 #include "package.h"
11
12 using namespace std;
13 using namespace Msp;
14
15 Copy::Copy(Builder &b, const Package &pkg, const FS::Path &s, const FS::Path &d, const FS::Path &l):
16         InternalAction(b),
17         src(s),
18         dest(d),
19         link(l)
20 {
21         announce(pkg.get_name(), "COPY", dest.str());
22         if(builder.get_verbose()>=2)
23                 IO::print("%s -> %s\n", s, d);
24
25         if(!builder.get_dry_run())
26                 worker = new Worker(*this);
27 }
28
29
30 Copy::Worker::Worker(Copy &c):
31         copy(c)
32 {
33         launch();
34 }
35
36 void Copy::Worker::main()
37 {
38         FS::mkpath(FS::dirname(copy.dest), 0755);
39
40         // Remove old file.  Not doing this would cause Bad Stuff when installing libraries.
41         if(FS::exists(copy.dest))
42         {
43                 try
44                 {
45                         unlink(copy.dest);
46                 }
47                 catch(const exception &e)
48                 {
49                         IO::print(IO::cerr, "%s\n", e.what());
50                         done = error = true;
51                         return;
52                 }
53         }
54
55         try
56         {
57                 IO::File in(copy.src.str());
58                 IO::File out(copy.dest.str(), IO::M_WRITE);
59
60                 // Actual transfer loop
61                 char buf[16384];
62                 while(!in.eof())
63                 {
64                         unsigned len = in.read(buf, sizeof(buf));
65                         out.write(buf, len);
66                 }
67         }
68         catch(const exception &e)
69         {
70                 IO::print(IO::cerr, "%s\n", e.what());
71                 done = error = true;
72                 return;
73         }
74
75         // Preserve file permissions
76         struct stat st;
77         if(stat(copy.src.str().c_str(), &st)==0)
78                 chmod(copy.dest.str().c_str(), st.st_mode&0777);
79
80         if(!copy.link.empty())
81         {
82                 FS::Path relpath = FS::relative(copy.dest, FS::dirname(copy.link));
83                 symlink(relpath.str().c_str(), copy.link.str().c_str());
84         }
85
86         done = true;
87 }