1 /*
2 * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 /*
8 * @file utils.c
9 * @brief Linux libmetal utility functions.
10 */
11
12 #include <metal/utilities.h>
13 #include <metal/sys.h>
14
15 /**
16 * @brief Open (or create) a file.
17 *
18 * This function opens or creates a file with read/write permissions and the
19 * O_CLOEXEC flag set.
20 *
21 * @param[in] path File path to open.
22 * @param[in] shm Open shared memory (via shm_open) if non-zero.
23 * @return File descriptor.
24 */
metal_open(const char * path,int shm)25 int metal_open(const char *path, int shm)
26 {
27 const int flags = O_RDWR | O_CREAT | O_CLOEXEC;
28 const int mode = S_IRUSR | S_IWUSR;
29 int fd;
30
31 if (!path || !strlen(path))
32 return -EINVAL;
33
34 fd = shm ? shm_open(path, flags, mode) : open(path, flags, mode);
35 return fd < 0 ? -errno : fd;
36 }
37
38 /**
39 * @brief Map a segment of a file/device.
40 *
41 * This function maps a segment of a file or device into the process address
42 * space, after optionally expanding the file if necessary. If required, the
43 * file is expanded to hold the requested map area. This is done under and
44 * advisory lock, and therefore the called must not have an advisory lock on
45 * the file being mmapped.
46 *
47 * @param[in] fd File descriptor to map.
48 * @param[in] offset Offset in file to map.
49 * @param[in] size Size of region to map.
50 * @param[in] expand Allow file expansion via ftruncate if non-zero.
51 * @param[in] flags Flags for mmap(), MAP_SHARED included implicitly.
52 * @param[out] result Returned pointer to new memory map.
53 * @return 0 on success, or -errno on error.
54 */
metal_map(int fd,off_t offset,size_t size,int expand,int flags,void ** result)55 int metal_map(int fd, off_t offset, size_t size, int expand, int flags,
56 void **result)
57 {
58 int prot = PROT_READ | PROT_WRITE, error;
59 void *mem;
60
61 flags |= MAP_SHARED;
62
63 if (fd < 0) {
64 fd = -1;
65 flags = MAP_PRIVATE | MAP_ANONYMOUS;
66 } else if (expand) {
67 off_t reqsize = offset + size;
68 struct stat stat;
69
70 error = flock(fd, LOCK_EX) < 0 ? -errno : 0;
71 if (!error)
72 error = fstat(fd, &stat);
73 if (!error && stat.st_size < reqsize)
74 error = ftruncate(fd, reqsize);
75 if (!error)
76 flock(fd, LOCK_UN);
77 if (error)
78 return -errno;
79 }
80
81 mem = mmap(NULL, size, prot, flags, fd, offset);
82 if (mem == MAP_FAILED)
83 return -errno;
84 *result = mem;
85 return 0;
86 }
87
88 /**
89 * @brief Unmap a segment of the process address space.
90 *
91 * This function unmaps a segment of the process address space.
92 *
93 * @param[in] mem Segment to unmap.
94 * @param[in] size Size of region to unmap.
95 * @return 0 on success, or -errno on error.
96 */
metal_unmap(void * mem,size_t size)97 int metal_unmap(void *mem, size_t size)
98 {
99 return munmap(mem, size) < 0 ? -errno : 0;
100 }
101