2012-12-24 15:36:14 +04:00
|
|
|
#ifndef __CR_UTIL_H__
|
|
|
|
#define __CR_UTIL_H__
|
2011-09-23 12:00:45 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Some bits are stolen from perf and kvm tools
|
|
|
|
*/
|
|
|
|
#include <signal.h>
|
2011-10-24 13:43:21 +04:00
|
|
|
#include <stdio.h>
|
2012-01-22 20:20:40 +04:00
|
|
|
#include <errno.h>
|
2012-11-29 21:12:51 +03:00
|
|
|
#include <string.h>
|
2011-09-23 12:00:45 +04:00
|
|
|
#include <sys/types.h>
|
2012-05-04 13:38:00 +04:00
|
|
|
#include <sys/statfs.h>
|
2011-10-24 13:43:21 +04:00
|
|
|
#include <dirent.h>
|
2011-09-23 12:00:45 +04:00
|
|
|
|
|
|
|
#include "compiler.h"
|
2013-01-09 17:02:47 +04:00
|
|
|
#include "asm/types.h"
|
2013-04-02 21:15:27 +04:00
|
|
|
#include "xmalloc.h"
|
2013-02-26 17:08:43 +04:00
|
|
|
#include "bug.h"
|
2012-02-17 12:17:00 +04:00
|
|
|
#include "log.h"
|
2013-04-01 19:27:33 +04:00
|
|
|
#include "err.h"
|
2011-09-23 12:00:45 +04:00
|
|
|
|
2013-02-15 17:33:06 +04:00
|
|
|
#include "protobuf/vma.pb-c.h"
|
2012-07-19 12:43:36 +04:00
|
|
|
|
2011-11-24 15:07:03 +04:00
|
|
|
#define PREF_SHIFT_OP(pref, op, size) ((size) op (pref ##BYTES_SHIFT))
|
|
|
|
#define KBYTES_SHIFT 10
|
|
|
|
#define MBYTES_SHIFT 20
|
|
|
|
#define GBYTES_SHIFT 30
|
|
|
|
|
|
|
|
#define KBYTES(size) PREF_SHIFT_OP(K, >>, size)
|
|
|
|
#define MBYTES(size) PREF_SHIFT_OP(M, >>, size)
|
|
|
|
#define GBYTES(size) PREF_SHIFT_OP(G, >>, size)
|
|
|
|
|
|
|
|
#define KILO(size) PREF_SHIFT_OP(K, <<, size)
|
|
|
|
#define MEGA(size) PREF_SHIFT_OP(K, <<, size)
|
|
|
|
#define GIGA(size) PREF_SHIFT_OP(K, <<, size)
|
|
|
|
|
2012-01-22 20:20:40 +04:00
|
|
|
/*
|
|
|
|
* Write buffer @ptr of @size bytes into @fd file
|
|
|
|
* Returns
|
|
|
|
* 0 on success
|
|
|
|
* -1 on error (error message is printed)
|
|
|
|
*/
|
2012-03-06 14:20:00 +04:00
|
|
|
static inline int write_img_buf(int fd, const void *ptr, int size)
|
2012-01-22 20:20:40 +04:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
ret = write(fd, ptr, size);
|
|
|
|
if (ret == size)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (ret < 0)
|
2012-01-31 15:13:05 +04:00
|
|
|
pr_perror("Can't write img file");
|
2012-01-22 20:20:40 +04:00
|
|
|
else
|
|
|
|
pr_err("Img trimmed %d/%d\n", ret, size);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define write_img(fd, ptr) write_img_buf((fd), (ptr), sizeof(*(ptr)))
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read buffer @ptr of @size bytes from @fd file
|
|
|
|
* Returns
|
|
|
|
* 1 on success
|
|
|
|
* 0 on EOF (silently)
|
|
|
|
* -1 on error (error message is printed)
|
|
|
|
*/
|
|
|
|
static inline int read_img_buf_eof(int fd, void *ptr, int size)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
ret = read(fd, ptr, size);
|
|
|
|
if (ret == size)
|
|
|
|
return 1;
|
|
|
|
if (ret == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (ret < 0)
|
2012-01-31 15:13:05 +04:00
|
|
|
pr_perror("Can't read img file");
|
2012-01-22 20:20:40 +04:00
|
|
|
else
|
|
|
|
pr_err("Img trimmed %d/%d\n", ret, size);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define read_img_eof(fd, ptr) read_img_buf_eof((fd), (ptr), sizeof(*(ptr)))
|
2011-09-23 12:00:45 +04:00
|
|
|
|
2012-01-22 20:20:40 +04:00
|
|
|
/*
|
|
|
|
* Read buffer @ptr of @size bytes from @fd file
|
|
|
|
* Returns
|
|
|
|
* 1 on success
|
|
|
|
* -1 on error or EOF (error message is printed)
|
|
|
|
*/
|
|
|
|
static inline int read_img_buf(int fd, void *ptr, int size)
|
|
|
|
{
|
|
|
|
int ret;
|
2011-09-23 12:00:45 +04:00
|
|
|
|
2012-01-22 20:20:40 +04:00
|
|
|
ret = read_img_buf_eof(fd, ptr, size);
|
|
|
|
if (ret == 0) {
|
|
|
|
pr_err("Unexpected EOF\n");
|
|
|
|
ret = -1;
|
|
|
|
}
|
2011-09-23 12:00:45 +04:00
|
|
|
|
2012-01-22 20:20:40 +04:00
|
|
|
return ret;
|
|
|
|
}
|
2011-09-23 12:00:45 +04:00
|
|
|
|
2012-01-22 20:20:40 +04:00
|
|
|
#define read_img(fd, ptr) read_img_buf((fd), (ptr), sizeof(*(ptr)))
|
2011-09-23 12:00:45 +04:00
|
|
|
|
|
|
|
struct vma_area;
|
|
|
|
struct list_head;
|
|
|
|
|
2012-03-06 14:20:00 +04:00
|
|
|
extern void pr_vma(unsigned int loglevel, const struct vma_area *vma_area);
|
2011-09-23 12:00:45 +04:00
|
|
|
|
2012-03-02 00:59:59 +04:00
|
|
|
#define pr_info_vma(vma_area) pr_vma(LOG_INFO, vma_area)
|
|
|
|
#define pr_msg_vma(vma_area) pr_vma(LOG_MSG, vma_area)
|
|
|
|
|
|
|
|
#define pr_vma_list(level, head) \
|
2012-01-18 18:38:47 +04:00
|
|
|
do { \
|
|
|
|
struct vma_area *vma; \
|
|
|
|
list_for_each_entry(vma, head, list) \
|
2012-03-02 00:59:59 +04:00
|
|
|
pr_vma(level, vma); \
|
2011-09-23 12:00:45 +04:00
|
|
|
} while (0)
|
2012-03-02 00:59:59 +04:00
|
|
|
#define pr_info_vma_list(head) pr_vma_list(LOG_INFO, head)
|
2011-09-23 12:00:45 +04:00
|
|
|
|
2011-12-26 21:48:00 +04:00
|
|
|
extern int move_img_fd(int *img_fd, int want_fd);
|
2011-12-19 21:46:03 +04:00
|
|
|
extern int close_safe(int *fd);
|
2011-09-23 12:00:45 +04:00
|
|
|
|
2012-04-12 19:50:00 +04:00
|
|
|
extern int reopen_fd_as_safe(char *file, int line, int new_fd, int old_fd, bool allow_reuse_fd);
|
|
|
|
#define reopen_fd_as(new_fd, old_fd) reopen_fd_as_safe(__FILE__, __LINE__, new_fd, old_fd, false)
|
|
|
|
#define reopen_fd_as_nocheck(new_fd, old_fd) reopen_fd_as_safe(__FILE__, __LINE__, new_fd, old_fd, true)
|
2012-01-13 13:15:57 +04:00
|
|
|
|
2013-11-15 14:04:48 +04:00
|
|
|
extern void close_proc(void);
|
|
|
|
extern int open_pid_proc(pid_t pid);
|
|
|
|
extern int close_pid_proc(void);
|
|
|
|
extern int set_proc_fd(int fd);
|
2012-02-17 01:39:35 +04:00
|
|
|
|
2013-11-15 14:04:48 +04:00
|
|
|
extern int do_open_proc(pid_t pid, int flags, const char *fmt, ...);
|
2012-02-17 01:39:36 +04:00
|
|
|
|
2014-04-25 00:54:00 +04:00
|
|
|
#define __open_proc(pid, flags, fmt, ...) \
|
|
|
|
({ \
|
|
|
|
int __fd = do_open_proc(pid, flags, \
|
|
|
|
fmt, ##__VA_ARGS__); \
|
|
|
|
if (__fd < 0) \
|
|
|
|
pr_perror("Can't open %d/" fmt " on procfs", \
|
|
|
|
pid, ##__VA_ARGS__); \
|
|
|
|
\
|
|
|
|
__fd; \
|
2012-02-17 01:39:35 +04:00
|
|
|
})
|
|
|
|
|
2012-02-17 01:39:36 +04:00
|
|
|
/* int open_proc(pid_t pid, const char *fmt, ...); */
|
|
|
|
#define open_proc(pid, fmt, ...) \
|
|
|
|
__open_proc(pid, O_RDONLY, fmt, ##__VA_ARGS__)
|
2012-02-17 01:39:35 +04:00
|
|
|
|
2012-02-17 01:39:36 +04:00
|
|
|
/* int open_proc_rw(pid_t pid, const char *fmt, ...); */
|
|
|
|
#define open_proc_rw(pid, fmt, ...) \
|
|
|
|
__open_proc(pid, O_RDWR, fmt, ##__VA_ARGS__)
|
2012-02-17 01:39:35 +04:00
|
|
|
|
2012-02-17 01:39:36 +04:00
|
|
|
/* DIR *opendir_proc(pid_t pid, const char *fmt, ...); */
|
|
|
|
#define opendir_proc(pid, fmt, ...) \
|
2012-02-17 01:39:35 +04:00
|
|
|
({ \
|
2012-02-17 01:39:36 +04:00
|
|
|
int __fd = open_proc(pid, fmt, ##__VA_ARGS__); \
|
2012-02-17 01:39:35 +04:00
|
|
|
DIR *__d = NULL; \
|
|
|
|
\
|
2013-11-21 13:40:35 +04:00
|
|
|
if (__fd >= 0) { \
|
2012-02-17 01:39:35 +04:00
|
|
|
__d = fdopendir(__fd); \
|
|
|
|
if (__d == NULL) \
|
|
|
|
pr_perror("Can't fdopendir %d " \
|
2014-04-25 00:54:00 +04:00
|
|
|
"(%d/" fmt " on procfs)", \
|
2012-02-17 01:39:35 +04:00
|
|
|
__fd, pid, ##__VA_ARGS__); \
|
2013-11-21 13:40:35 +04:00
|
|
|
} \
|
2012-02-17 01:39:35 +04:00
|
|
|
__d; \
|
|
|
|
})
|
|
|
|
|
2012-02-17 01:39:36 +04:00
|
|
|
/* FILE *fopen_proc(pid_t pid, const char *fmt, ...); */
|
|
|
|
#define fopen_proc(pid, fmt, ...) \
|
2012-02-17 01:39:35 +04:00
|
|
|
({ \
|
2012-02-17 01:39:36 +04:00
|
|
|
int __fd = open_proc(pid, fmt, ##__VA_ARGS__); \
|
2012-02-17 01:39:35 +04:00
|
|
|
FILE *__f = NULL; \
|
|
|
|
\
|
2013-11-21 13:40:35 +04:00
|
|
|
if (__fd >= 0) { \
|
2012-02-17 01:39:35 +04:00
|
|
|
__f = fdopen(__fd, "r"); \
|
|
|
|
if (__f == NULL) \
|
|
|
|
pr_perror("Can't fdopen %d " \
|
2014-04-25 00:54:00 +04:00
|
|
|
"(%d/" fmt " on procfs)", \
|
2012-02-17 01:39:35 +04:00
|
|
|
__fd, pid, ##__VA_ARGS__); \
|
2013-11-21 13:40:35 +04:00
|
|
|
} \
|
2012-02-17 01:39:35 +04:00
|
|
|
__f; \
|
|
|
|
})
|
2011-10-24 13:43:21 +04:00
|
|
|
|
2012-03-02 00:59:59 +04:00
|
|
|
#define pr_img_head(type, ...) pr_msg("\n"#type __VA_ARGS__ "\n----------------\n")
|
|
|
|
#define pr_img_tail(type) pr_msg("----------------\n")
|
2012-01-12 15:16:33 +04:00
|
|
|
|
2013-01-17 14:46:33 +04:00
|
|
|
#define DEVZERO (makedev(1, 5))
|
|
|
|
|
2012-02-08 16:09:04 +04:00
|
|
|
#define KDEV_MINORBITS 20
|
|
|
|
#define KDEV_MINORMASK ((1UL << KDEV_MINORBITS) - 1)
|
2012-08-11 22:19:34 +04:00
|
|
|
#define MKKDEV(ma, mi) (((ma) << KDEV_MINORBITS) | (mi))
|
2012-02-08 16:09:04 +04:00
|
|
|
|
|
|
|
static inline u32 kdev_major(u32 kdev)
|
|
|
|
{
|
|
|
|
return kdev >> KDEV_MINORBITS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline u32 kdev_minor(u32 kdev)
|
|
|
|
{
|
|
|
|
return kdev & KDEV_MINORMASK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline dev_t kdev_to_odev(u32 kdev)
|
|
|
|
{
|
|
|
|
/*
|
2013-11-01 17:40:54 +04:00
|
|
|
* New kernels encode devices in a new form.
|
|
|
|
* See kernel's fs/stat.c for details, there
|
|
|
|
* choose_32_64 helpers which are the key.
|
2012-02-08 16:09:04 +04:00
|
|
|
*/
|
2013-11-01 17:40:54 +04:00
|
|
|
unsigned major = kdev_major(kdev);
|
|
|
|
unsigned minor = kdev_minor(kdev);
|
2014-05-05 14:26:00 +04:00
|
|
|
|
|
|
|
return makedev(major, minor);
|
2012-02-08 16:09:04 +04:00
|
|
|
}
|
|
|
|
|
2013-11-15 14:04:48 +04:00
|
|
|
extern int copy_file(int fd_in, int fd_out, size_t bytes);
|
2014-02-02 22:14:29 +04:00
|
|
|
extern int is_anon_link_type(char *link, char *type);
|
2012-04-13 17:52:35 +04:00
|
|
|
|
2012-05-10 21:07:00 +04:00
|
|
|
#define is_hex_digit(c) \
|
|
|
|
(((c) >= '0' && (c) <= '9') || \
|
|
|
|
((c) >= 'a' && (c) <= 'f') || \
|
|
|
|
((c) >= 'A' && (c) <= 'F'))
|
|
|
|
|
2012-06-27 20:57:35 +04:00
|
|
|
/*
|
|
|
|
* read_img_str -- same as read_img_buf, but allocates memory for
|
|
|
|
* the buffer and puts the '\0' at the end
|
|
|
|
*/
|
|
|
|
|
|
|
|
static inline int read_img_str(int fd, char **pstr, int size)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
char *str;
|
|
|
|
|
|
|
|
str = xmalloc(size + 1);
|
|
|
|
if (!str)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
ret = read_img_buf(fd, str, size);
|
|
|
|
if (ret < 0) {
|
|
|
|
xfree(str);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
str[size] = '\0';
|
|
|
|
*pstr = str;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-08-16 20:41:34 +04:00
|
|
|
extern void *shmalloc(size_t bytes);
|
2012-09-02 17:23:27 +04:00
|
|
|
extern void shfree_last(void *ptr);
|
2012-09-17 20:05:39 +04:00
|
|
|
extern int run_scripts(char *action);
|
2012-08-16 20:41:34 +04:00
|
|
|
|
2012-09-28 14:09:57 +04:00
|
|
|
extern int cr_system(int in, int out, int err, char *cmd, char *const argv[]);
|
2014-01-28 22:35:59 +04:00
|
|
|
extern int cr_daemon(int nochdir, int noclose);
|
2013-12-13 00:02:00 +04:00
|
|
|
extern int is_root_user(void);
|
2012-09-28 14:09:57 +04:00
|
|
|
|
2012-11-29 21:12:51 +03:00
|
|
|
static inline bool dir_dots(struct dirent *de)
|
|
|
|
{
|
|
|
|
return !strcmp(de->d_name, ".") || !strcmp(de->d_name, "..");
|
|
|
|
}
|
|
|
|
|
2013-10-15 13:59:59 +04:00
|
|
|
/*
|
|
|
|
* Size of buffer to carry the worst case or /proc/self/fd/N
|
|
|
|
* path. Since fd is an integer, we can easily estimate one :)
|
|
|
|
*/
|
|
|
|
#define PSFDS (sizeof("/proc/self/fd/2147483647"))
|
|
|
|
|
2013-03-15 15:03:16 +04:00
|
|
|
extern int read_fd_link(int lfd, char *buf, size_t size);
|
|
|
|
|
2013-05-09 22:11:38 +04:00
|
|
|
#define USEC_PER_SEC 1000000L
|
2013-06-27 23:32:23 +04:00
|
|
|
#define NSEC_PER_SEC 1000000000L
|
2013-05-09 22:11:38 +04:00
|
|
|
|
2014-01-30 23:34:53 +04:00
|
|
|
int vaddr_to_pfn(unsigned long vaddr, u64 *pfn);
|
|
|
|
|
2012-12-25 22:40:24 +04:00
|
|
|
#endif /* __CR_UTIL_H__ */
|