FreeNOS
forkexec.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 Niek Linnenbank
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <FreeNOS/User.h>
19 #include <Lz4Decompressor.h>
20 #include <Types.h>
21 #include <string.h>
22 #include <sys/stat.h>
23 #include <errno.h>
24 #include <fcntl.h>
25 #include "unistd.h"
26 
27 int forkexec(const char *path, const char *argv[])
28 {
29  int fd, ret = 0;
30  struct stat st;
31 
32  // Find program image
33  if (stat(path, &st) != 0)
34  return -1;
35 
36  // Open program image
37  if ((fd = open(path, O_RDONLY)) < 0)
38  return -1;
39 
40  // Map memory buffer for the compressed program image
41  Memory::Range compressed;
42  compressed.virt = ZERO;
43  compressed.phys = ZERO;
44  compressed.size = st.st_size;
46 
47  // Create mapping
48  if (VMCtl(SELF, MapContiguous, &compressed) != API::Success)
49  {
50  errno = EFAULT;
51  return -1;
52  }
53 
54  // Read the program image
55  ret = read(fd, (void *) compressed.virt, st.st_size);
56 
57  // Close file handle
58  close(fd);
59 
60  if (ret != st.st_size)
61  {
62  VMCtl(SELF, Release, &compressed);
63  errno = EIO;
64  return -1;
65  }
66 
67  // Initialize decompressor
68  Lz4Decompressor lz4((const void *)compressed.virt, st.st_size);
69  const Lz4Decompressor::Result result = lz4.initialize();
70  if (result != Lz4Decompressor::Success)
71  {
72  VMCtl(SELF, Release, &compressed);
73  errno = EFAULT;
74  return -1;
75  }
76 
77  // Map memory buffer for the uncompressed program image
78  Memory::Range uncompressed;
79  uncompressed.virt = ZERO;
80  uncompressed.phys = ZERO;
81  uncompressed.size = lz4.getUncompressedSize();
83 
84  // Create mapping
85  if (VMCtl(SELF, MapContiguous, &uncompressed) != API::Success)
86  {
87  VMCtl(SELF, Release, &compressed);
88  errno = EFAULT;
89  return -1;
90  }
91 
92  // Decompress entire file
93  const Lz4Decompressor::Result readResult = lz4.read((void *)uncompressed.virt, lz4.getUncompressedSize());
94  if (readResult != Lz4Decompressor::Success)
95  {
96  VMCtl(SELF, Release, &compressed);
97  VMCtl(SELF, Release, &uncompressed);
98  errno = EFAULT;
99  return -1;
100  }
101 
102  // Cleanup compressed program buffer
103  if (VMCtl(SELF, Release, &compressed) != API::Success)
104  {
105  VMCtl(SELF, Release, &uncompressed);
106  errno = EFAULT;
107  return -1;
108  }
109 
110  // Spawn the new program
111  ret = spawn(uncompressed.virt, lz4.getUncompressedSize(), argv);
112 
113  // Cleanup uncompressed program buffer
114  if (VMCtl(SELF, Release, &uncompressed) != API::Success)
115  {
116  errno = EFAULT;
117  return -1;
118  }
119 
120  return ret;
121 }
stat::st_size
off_t st_size
For regular files, the file size in bytes.
Definition: stat.h:226
stat
The <sys/stat.h> header shall define the stat structure.
Definition: stat.h:176
Memory::Range
Memory range.
Definition: Memory.h:55
fcntl.h
Types.h
errno
C int errno
The lvalue errno is used by many functions to return error values.
string.h
Memory::Writable
@ Writable
Definition: Memory.h:42
Memory::User
@ User
Definition: Memory.h:44
Lz4Decompressor::getUncompressedSize
u64 getUncompressedSize() const
Get size of the uncompressed data.
Definition: Lz4Decompressor.cpp:125
Lz4Decompressor::initialize
Result initialize()
Initialize the decompressor.
Definition: Lz4Decompressor.cpp:35
VMCtl
API::Result VMCtl(const ProcessID procID, const MemoryOperation op, Memory::Range *range=ZERO)
Prototype for user applications.
Definition: VMCtl.h:61
open
int open(const char *path, int oflag,...)
Open file relative to directory file descriptor.
Definition: open.cpp:26
Memory::Readable
@ Readable
Definition: Memory.h:41
read
ssize_t read(int fildes, void *buf, size_t nbyte)
Read from a file.
Definition: read.cpp:22
Lz4Decompressor::Success
@ Success
Definition: Lz4Decompressor.h:72
SELF
#define SELF
Definition: ProcessID.h:35
Lz4Decompressor.h
Release
@ Release
Definition: VMCtl.h:40
Memory::Range::phys
Address phys
Physical address.
Definition: Memory.h:58
close
int close(int fildes)
Close a file descriptor.
Definition: close.cpp:22
forkexec
int forkexec(const char *path, const char *argv[])
Create a new process and execute program.
Definition: forkexec.cpp:27
EIO
#define EIO
I/O error.
Definition: errno.h:130
EFAULT
#define EFAULT
Bad address.
Definition: errno.h:106
stat
int stat(const char *path, struct stat *buf)
Get file status.
Definition: stat.cpp:25
Lz4Decompressor::Result
Result
Result codes.
Definition: Lz4Decompressor.h:70
stat.h
unistd.h
Lz4Decompressor::read
Result read(void *buffer, const Size size) const
Reads compressed data.
Definition: Lz4Decompressor.cpp:130
Lz4Decompressor
Decompress data using the LZ4 algorithm created by Yann Collet.
Definition: Lz4Decompressor.h:39
spawn
int spawn(Address program, Size programSize, const char *argv[])
Create a new process using in-memory image.
Definition: spawn.cpp:29
API::Success
@ Success
Definition: API.h:70
Memory::Range::virt
Address virt
Virtual address.
Definition: Memory.h:57
Memory::Range::size
Size size
Size in number of bytes.
Definition: Memory.h:59
Memory::Range::access
Access access
Page access flags.
Definition: Memory.h:60
ZERO
#define ZERO
Zero value.
Definition: Macros.h:43
MapContiguous
@ MapContiguous
Definition: VMCtl.h:37
O_RDONLY
#define O_RDONLY
Open for reading only.
Definition: fcntl.h:81
errno.h