1 // SPDX-License-Identifier: GPL-2.0+ OR Apache-2.0
2 /*
3 * Copyright (C) 2018-2019 HUAWEI, Inc.
4 * http://www.huawei.com/
5 * Created by Li Guifu <[email protected]>
6 */
7 #include <string.h>
8 #include <stdlib.h>
9 #include <stdarg.h>
10 #include <unistd.h>
11 #include "erofs/print.h"
12 #include "erofs/internal.h"
13 #include "liberofs_private.h"
14 #ifdef HAVE_SYS_IOCTL_H
15 #include <sys/ioctl.h>
16 #endif
17 #ifdef HAVE_UNISTD_H
18 #include <unistd.h>
19 #endif
20
21 struct erofs_configure cfg;
22 struct erofs_sb_info g_sbi;
23 bool erofs_stdout_tty;
24
erofs_init_configure(void)25 void erofs_init_configure(void)
26 {
27 memset(&cfg, 0, sizeof(cfg));
28
29 cfg.c_dbg_lvl = EROFS_WARN;
30 cfg.c_version = PACKAGE_VERSION;
31 cfg.c_dry_run = false;
32 cfg.c_ignore_mtime = false;
33 cfg.c_force_inodeversion = 0;
34 cfg.c_inline_xattr_tolerance = 2;
35 cfg.c_unix_timestamp = -1;
36 cfg.c_uid = -1;
37 cfg.c_gid = -1;
38 cfg.c_max_decompressed_extent_bytes = -1;
39 erofs_stdout_tty = isatty(STDOUT_FILENO);
40 }
41
erofs_show_config(void)42 void erofs_show_config(void)
43 {
44 const struct erofs_configure *c = &cfg;
45
46 if (c->c_dbg_lvl < EROFS_INFO)
47 return;
48 erofs_dump("\tc_version: [%8s]\n", c->c_version);
49 erofs_dump("\tc_dbg_lvl: [%8d]\n", c->c_dbg_lvl);
50 erofs_dump("\tc_dry_run: [%8d]\n", c->c_dry_run);
51 }
52
erofs_exit_configure(void)53 void erofs_exit_configure(void)
54 {
55 int i;
56
57 #ifdef HAVE_LIBSELINUX
58 if (cfg.sehnd)
59 selabel_close(cfg.sehnd);
60 #endif
61 if (cfg.c_img_path)
62 free(cfg.c_img_path);
63 if (cfg.c_src_path)
64 free(cfg.c_src_path);
65 for (i = 0; i < EROFS_MAX_COMPR_CFGS && cfg.c_compr_opts[i].alg; i++)
66 free(cfg.c_compr_opts[i].alg);
67 }
68
erofs_get_configure()69 struct erofs_configure *erofs_get_configure()
70 {
71 return &cfg;
72 }
73
74 static unsigned int fullpath_prefix; /* root directory prefix length */
75
erofs_set_fs_root(const char * rootdir)76 void erofs_set_fs_root(const char *rootdir)
77 {
78 fullpath_prefix = strlen(rootdir);
79 }
80
erofs_fspath(const char * fullpath)81 const char *erofs_fspath(const char *fullpath)
82 {
83 const char *s = fullpath + fullpath_prefix;
84
85 while (*s == '/')
86 s++;
87 return s;
88 }
89
90 #ifdef HAVE_LIBSELINUX
erofs_selabel_open(const char * file_contexts)91 int erofs_selabel_open(const char *file_contexts)
92 {
93 struct selinux_opt seopts[] = {
94 { .type = SELABEL_OPT_PATH, .value = file_contexts }
95 };
96
97 if (cfg.sehnd) {
98 erofs_info("ignore duplicated file contexts \"%s\"",
99 file_contexts);
100 return -EBUSY;
101 }
102
103 cfg.sehnd = selabel_open(SELABEL_CTX_FILE, seopts, 1);
104 if (!cfg.sehnd) {
105 erofs_err("failed to open file contexts \"%s\"",
106 file_contexts);
107 return -EINVAL;
108 }
109 return 0;
110 }
111 #endif
112
113 static bool __erofs_is_progressmsg;
114
erofs_trim_for_progressinfo(const char * str,int placeholder)115 char *erofs_trim_for_progressinfo(const char *str, int placeholder)
116 {
117 int col, len;
118
119 if (!erofs_stdout_tty) {
120 return strdup(str);
121 } else {
122 #ifdef GWINSZ_IN_SYS_IOCTL
123 struct winsize winsize;
124 if(ioctl(1, TIOCGWINSZ, &winsize) >= 0 &&
125 winsize.ws_col > 0)
126 col = winsize.ws_col;
127 else
128 #endif
129 col = 80;
130 }
131
132 if (col <= placeholder)
133 return strdup("");
134
135 len = strlen(str);
136 /* omit over long prefixes */
137 if (len > col - placeholder) {
138 char *s = strdup(str + len - (col - placeholder));
139
140 if (col > placeholder + 2) {
141 s[0] = '[';
142 s[1] = ']';
143 }
144 return s;
145 }
146 return strdup(str);
147 }
148
erofs_msg(int dbglv,const char * fmt,...)149 void erofs_msg(int dbglv, const char *fmt, ...)
150 {
151 va_list ap;
152 FILE *f = dbglv >= EROFS_ERR ? stderr : stdout;
153
154 if (__erofs_is_progressmsg) {
155 fputc('\n', stdout);
156 __erofs_is_progressmsg = false;
157 }
158 va_start(ap, fmt);
159 vfprintf(f, fmt, ap);
160 va_end(ap);
161 }
162
erofs_update_progressinfo(const char * fmt,...)163 void erofs_update_progressinfo(const char *fmt, ...)
164 {
165 char msg[8192];
166 va_list ap;
167
168 if (cfg.c_dbg_lvl >= EROFS_INFO || !cfg.c_showprogress)
169 return;
170
171 va_start(ap, fmt);
172 vsprintf(msg, fmt, ap);
173 va_end(ap);
174
175 if (erofs_stdout_tty) {
176 printf("\r\033[K%s", msg);
177 __erofs_is_progressmsg = true;
178 fflush(stdout);
179 return;
180 }
181 fputs(msg, stdout);
182 fputc('\n', stdout);
183 }
184
erofs_get_available_processors(void)185 unsigned int erofs_get_available_processors(void)
186 {
187 #if defined(HAVE_UNISTD_H) && defined(HAVE_SYSCONF)
188 return sysconf(_SC_NPROCESSORS_ONLN);
189 #else
190 return 0;
191 #endif
192 }
193