blob: 02bc9a9044f323cc283e8da66bdde9e8c7de6fc0 [file] [log] [blame]
Gunnar Millse91d3212017-04-19 15:42:47 -05001#include <string>
Gunnar Mills19e4ce52017-04-27 11:24:19 -05002#include <experimental/filesystem>
3#include <stdlib.h>
4#include <cstring>
5#include <stdio.h>
6#include <unistd.h>
7#include <sys/wait.h>
8#include <sys/stat.h>
9#include <phosphor-logging/log.hpp>
10#include "config.h"
11#include "version.hpp"
Gunnar Millse91d3212017-04-19 15:42:47 -050012#include "image_manager.hpp"
13
14namespace phosphor
15{
16namespace software
17{
18namespace manager
19{
20
Gunnar Mills19e4ce52017-04-27 11:24:19 -050021using namespace phosphor::logging;
22namespace fs = std::experimental::filesystem;
23
24struct RemovablePath
25{
26 fs::path path;
27
28 RemovablePath(const fs::path& path) : path(path) {}
29 ~RemovablePath()
30 {
31 fs::remove_all(path);
32 }
33};
34
Gunnar Millse91d3212017-04-19 15:42:47 -050035int processImage(const std::string& tarFilePath)
36{
Gunnar Mills19e4ce52017-04-27 11:24:19 -050037 if (!fs::is_regular_file(tarFilePath))
38 {
39 log<level::ERR>("Error tarball does not exist",
40 entry("FILENAME=%s", tarFilePath));
41 return -1;
42
43 }
44 RemovablePath tarPathRemove(tarFilePath);
45 fs::path tmpDirPath(std::string{IMG_UPLOAD_DIR});
46 tmpDirPath /= "imageXXXXXX";
47
48 // Need tmp dir to write MANIFEST file to.
49 if (!mkdtemp(const_cast<char*>(tmpDirPath.c_str())))
50 {
51 log<level::ERR>("Error occured during mkdtemp",
52 entry("ERRNO=%d", errno));
53 return -1;
54 }
55
56 RemovablePath tmpDirRemove(tmpDirPath);
57 fs::path manifestPath = tmpDirPath;
58 manifestPath /= MANIFEST_FILE_NAME;
59 int status = 0;
60 pid_t pid = fork();
61
62 // Get the MANIFEST FILE
63 if (pid == 0)
64 {
65 // child process
66 execl("/bin/tar", "tar", "-xf", tarFilePath.c_str(), MANIFEST_FILE_NAME,
67 "-C", tmpDirPath.c_str(), (char*)0);
68 // execl only returns on fail
69 log<level::ERR>("Failed to untar file",
70 entry("FILENAME=%s", tarFilePath));
71 return -1;
72 }
73 else if (pid > 0)
74 {
75 waitpid(pid, &status, 0);
76 }
77 else
78 {
79 log<level::ERR>("fork() failed.");
80 return -1;
81 }
82
83 // Verify the manifest file
84 if (!fs::is_regular_file(manifestPath))
85 {
86 log<level::ERR>("Error No manifest file");
87 return -1;
88 }
89
90 // Get version
91 auto version = Version::getValue(manifestPath.string(), "version");
92 if (version.empty())
93 {
94 log<level::ERR>("Error unable to read version from manifest file");
95 return -1;
96 }
97
98 // Compute id
99 auto id = Version::getId(version);
100
101 fs::path imageDirPath = std::string{IMG_UPLOAD_DIR};
102 imageDirPath /= id;
103
104 if (mkdir(imageDirPath.c_str(), S_IRWXU) != 0)
105 {
106 log<level::ERR>("Error occured during mkdir",
107 entry("ERRNO=%d", errno));
108 return -1;
109 }
110
111 // Untar tarball
112 auto rc = unTar(tarFilePath, imageDirPath.string());
113 if (rc < 0)
114 {
115 log<level::ERR>("Error occured during untar");
116 return -1;
117 }
118
Gunnar Millse91d3212017-04-19 15:42:47 -0500119 return 0;
120}
121
Gunnar Mills19e4ce52017-04-27 11:24:19 -0500122int unTar(const std::string& tarFilePath, const std::string& extractDirPath)
123{
124 if (tarFilePath.empty())
125 {
126 log<level::ERR>("Error TarFilePath is empty");
127 return -1;
128 }
129 if (extractDirPath.empty())
130 {
131 log<level::ERR>("Error ExtractDirPath is empty");
132 return -1;
133 }
134
135 log<level::INFO>("Untaring",
136 entry("FILENAME=%s", tarFilePath),
137 entry("EXTRACTIONDIR=%s", extractDirPath));
138 int status = 0;
139 pid_t pid = fork();
140
141 if (pid == 0)
142 {
143 // child process
144 execl("/bin/tar", "tar", "-xf", tarFilePath.c_str(),
145 "-C", extractDirPath.c_str(), (char*)0);
146 // execl only returns on fail
147 log<level::ERR>("Failed to untar file",
148 entry("FILENAME=%s", tarFilePath));
149 return -1;
150 }
151 else if (pid > 0)
152 {
153 waitpid(pid, &status, 0);
154 }
155 else
156 {
157 log<level::ERR>("fork() failed.");
158 return -1;
159 }
160
161 return 0;
162}
Gunnar Millse91d3212017-04-19 15:42:47 -0500163} // namespace manager
164} // namespace software
165} // namepsace phosphor