更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
date_shellcmd.c
浏览该文件的文档.
1/*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include "shcmd.h"
33#include "shell.h"
34#include "stdlib.h"
35#include "time.h"
36#include "los_typedef.h"
37#include "sys/stat.h"
38#include "securec.h"
39
40#if defined(__LP64__)
41#define timeval64 timeval
42#define settimeofday64 settimeofday
43#define gettimeofday64 gettimeofday
44#endif
45
46#define localtime64 localtime
47#define ctime64 ctime
48#define mktime64 mktime
49
50#define DATE_ERR_INFO 1
51#define DATE_HELP_INFO 0
52#define DATE_ERR (-1)
53#define DATE_OK 0
54#define DATE_BASE_YEAR 1900
55#define LEAPYEAR(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
56
57STATIC const INT32 g_monLengths[2][12] = { /* 2: 2 Column,Contains leap year; 12: 12 months */
58 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
59 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
60};
61
62STATIC VOID OsCopyTm(struct tm *destTm, const struct tm *srcTm)
63{
64 if (srcTm == NULL) {
65 (VOID)memset_s(destTm, sizeof(struct tm), 0, sizeof(struct tm));
66 } else {
67 destTm->tm_sec = srcTm->tm_sec;
68 destTm->tm_min = srcTm->tm_min;
69 destTm->tm_hour = srcTm->tm_hour;
70 destTm->tm_mday = srcTm->tm_mday;
71 destTm->tm_mon = srcTm->tm_mon;
72 destTm->tm_year = srcTm->tm_year;
73 destTm->tm_wday = srcTm->tm_wday;
74 destTm->tm_yday = srcTm->tm_yday;
75 destTm->tm_isdst = srcTm->tm_isdst;
76 destTm->tm_gmtoff = srcTm->tm_gmtoff;
77 destTm->tm_zone = srcTm->tm_zone;
78 }
79}
80
81STATIC VOID OsCmdUsageDate(INT32 order)
82{
83 if (order) {
84 PRINTK("date: invalid option or parameter.\n");
85 PRINTK("Try 'date --help' for more information.\n");
86 return;
87 }
88 PRINTK("\nUsage: date [+FORMAT]\n");
89 PRINTK(" or: date [-s] [YY/MM/DD] [hh:mm:ss]\n");
90 PRINTK("Display the current time in the given FORMAT, or set the system date.\n");
91 PRINTK("FORMAT controls the output. Interpreted sequences are:\n");
92 PRINTK(" %%b The abbreviated month name according to the current locale.\n");
93 PRINTK(" %%B The full month name according to the current locale.\n");
94 PRINTK(" %%C The century number (year/100) as a 2-digit integer. (SU)\n");
95 PRINTK(" %%d The day of the month as a decimal number (range 01 to 31).\n");
96 PRINTK(" %%e Like %%d, the day of the month as a decimal number, \n");
97 PRINTK(" but a leading zero is replaced by a space.\n");
98 PRINTK(" %%h Equivalent to %%b. (SU)\n");
99 PRINTK(" %%H The hour as a decimal number using a 24-hour clock (range 00 to 23).\n");
100 PRINTK(" %%I The hour as a decimal number using a 12-hour clock (range 01 to 12).\n");
101 PRINTK(" %%j The day of the year as a decimal number (range 001 to 366).\n");
102 PRINTK(" %%k The hour (24-hour clock) as a decimal number (range 0 to 23); \n");
103 PRINTK(" single digits are preceded by a blank. (See also %H.) (TZ)\n");
104 PRINTK(" %%l The hour (12-hour clock) as a decimal number (range 1 to 12); \n");
105 PRINTK(" single digits are preceded by a blank. (See also %I.) (TZ)\n");
106 PRINTK(" %%m The month as a decimal number (range 01 to 12).\n");
107 PRINTK(" %%M The minute as a decimal number (range 00 to 59).\n");
108 PRINTK(" %%n A newline character. (SU)\n");
109 PRINTK(" %%p Either \"AM\" or \"PM\" according to the given time value, \n");
110 PRINTK(" or the corresponding strings for the current locale.\n");
111 PRINTK(" Noon is treated as \"PM\" and midnight as \"AM\".\n");
112 PRINTK(" %%P Like %%p but in lowercase: \"am\" or \"pm\" \n");
113 PRINTK(" or a corresponding string for the current locale. (GNU)\n");
114 PRINTK(" %%s The number of seconds since the Epoch, that is,\n");
115 PRINTK(" since 1970-01-01 00:00:00 UTC. (TZ)\n");
116 PRINTK(" %%S The second as a decimal number (range 00 to 60).\n");
117 PRINTK(" (The range is up to 60 to allow for occasional leap seconds.)\n");
118 PRINTK(" %%t A tab character. (SU)\n");
119 PRINTK(" %%y The year as a decimal number without a century (range 00 to 99).\n");
120 PRINTK(" %%Y The year as a decimal number including the century.\n");
121 PRINTK(" %%%% A literal '%%' character.\n");
122 PRINTK("\nExamples:\n");
123 PRINTK("Set system date (2017-01-01)\n");
124 PRINTK("$ date -s 20170101\n");
125 PRINTK("Set system time (12:00:00)\n");
126 PRINTK("$ date -s 12:00:00\n");
127 PRINTK("Show the time with format Year-Month-Day\n");
128 PRINTK("$ date +%%Y-%%m-%%d\n");
129}
130
131STATIC INT32 OsStrToTm(const CHAR *str, struct tm *tm)
132{
133 CHAR *ret = NULL;
134 UINT32 strLen = strlen(str);
135 if (strLen == 8) { /* 8:Time format string length, such as hh:mm:ss or yyyymmdd */
136 if (str[2] == ':') { /* 2:Index of Eigenvalues */
137 ret = strptime(str, "%H:%M:%S", tm);
138 } else {
139 ret = strptime(str, "%Y%m%d", tm);
140 }
141 } else if (strLen == 10) { /* 10:Time format string length,such as yyyy/mm/dd */
142 ret = strptime(str, "%Y/%m/%d", tm);
143 } else if (strLen == 5) { /* 5:Time format string length,such as hh:mm or mm/dd */
144 if (str[2] == ':') { /* 2:Index of Eigenvalues */
145 ret = strptime(str, "%H:%M", tm);
146 } else if (str[2] == '/') { /* 2:Index of Eigenvalues */
147 ret = strptime(str, "%m/%d", tm);
148 }
149 } else if (strLen == 7) { /* 7:Time format string length,such as yyyy/mm */
150 if (str[4] == '/') { /* 4:Index of Eigenvalues */
151 ret = strptime(str, "%Y/%m", tm);
152 }
153 }
154
155 if (tm->tm_year < 70) { /* 70:the year is starting in 1970,tm_year must be greater than 70 */
156 PRINTK("\nUsage: date -s set system time starting from 1970.\n");
157 return DATE_ERR;
158 }
159
160 if (tm->tm_mday > g_monLengths[(INT32)LEAPYEAR(tm->tm_year + DATE_BASE_YEAR)][tm->tm_mon]) {
161 return DATE_ERR;
162 }
163
164 if ((tm->tm_sec < 0) || (tm->tm_sec > 59)) { /* Seconds (0-59), leap seconds shall not be used when set time. */
165 return DATE_ERR;
166 }
167 return (ret == NULL) ? DATE_ERR : DATE_OK;
168}
169
170STATIC INT32 OsFormatPrintTime(const CHAR *formatStr)
171{
172 CHAR timebuf[SHOW_MAX_LEN] = {0};
173 struct tm *tm = NULL;
174 struct timeval64 nowTime = {0};
175
176 if (strlen(formatStr) < 2) { /* 2:check format string length */
177 OsCmdUsageDate(DATE_ERR_INFO);
178 return DATE_ERR;
179 }
180
181 if (gettimeofday64(&nowTime, NULL)) {
182 return DATE_ERR;
183 }
184 tm = localtime64(&nowTime.tv_sec);
185 if (tm == NULL) {
186 return DATE_ERR;
187 }
188
189 if (strftime(timebuf, SHOW_MAX_LEN - 1, formatStr + 1, tm)) {
190 PRINTK("%s\n", timebuf);
191 } else {
192 OsCmdUsageDate(DATE_ERR_INFO);
193 return DATE_ERR;
194 }
195 return DATE_OK;
196}
197
198STATIC INT32 OsDateSetTime(const CHAR *timeStr)
199{
200 struct tm tm = {0};
201 struct timeval64 nowTime = {0};
202 struct timeval64 setTime = {0};
203
204 if (gettimeofday64(&nowTime, NULL)) {
205 PRINTK("Setting time failed...\n");
206 return DATE_ERR;
207 }
208
209 setTime.tv_usec = nowTime.tv_usec;
210 OsCopyTm(&tm, localtime64(&nowTime.tv_sec));
211
212 if (OsStrToTm(timeStr, &tm)) {
213 OsCmdUsageDate(DATE_ERR_INFO);
214 return DATE_ERR;
215 }
216
217 setTime.tv_sec = mktime64(&tm);
218
219 if (settimeofday64(&setTime, NULL)) {
220 PRINTK("setting time failed...\n");
221 return DATE_ERR;
222 }
223
224 return DATE_OK;
225}
226
227#ifdef LOSCFG_FS_VFS
228STATIC INT32 OsViewFileTime(const CHAR *filename)
229{
230#define BUFFER_SIZE 26 /* The buffer size is equal to the size used by the asctime_r interface */
231 struct stat statBuf = {0};
232 CHAR *fullpath = NULL;
233 INT32 ret;
234 CHAR buf[BUFFER_SIZE];
235 CHAR *shellWorkingDirectory = OsShellGetWorkingDirectory();
236
237 ret = vfs_normalize_path(shellWorkingDirectory, filename, &fullpath);
238 if (ret < 0) {
239 set_errno(-ret);
240 perror("date error");
241 return DATE_ERR;
242 }
243
244 if (stat(fullpath, &statBuf) != 0) {
245 OsCmdUsageDate(DATE_ERR_INFO);
246 free(fullpath);
247 return DATE_ERR;
248 }
249 PRINTK("%s\n", ctime_r(&(statBuf.st_mtim.tv_sec), buf));
250 free(fullpath);
251 return DATE_OK;
252}
253#endif
254
255INT32 OsShellCmdDate(INT32 argc, const CHAR **argv)
256{
257 struct timeval64 nowTime = {0};
258
259 if (argc == 1) { /* 1:count of parameters */
260 if (gettimeofday64(&nowTime, NULL)) {
261 return DATE_ERR;
262 }
263 PRINTK("%s\n", ctime64(&nowTime.tv_sec));
264 return DATE_OK;
265 }
266
267 if (argc == 2) { /* 2:count of parameters */
268 if (argv == NULL) {
269 OsCmdUsageDate(DATE_HELP_INFO);
270 return DATE_ERR;
271 }
272
273 if (!(strcmp(argv[1], "--help"))) {
274 OsCmdUsageDate(DATE_HELP_INFO);
275 return DATE_OK;
276 }
277 if (!(strncmp(argv[1], "+", 1))) {
278 return OsFormatPrintTime(argv[1]);
279 }
280 }
281
282 if (argc > 2) { /* 2:count of parameters */
283 if (argv == NULL) {
284 OsCmdUsageDate(DATE_HELP_INFO);
285 return DATE_ERR;
286 }
287
288 if (!(strcmp(argv[1], "-s"))) {
289 return OsDateSetTime(argv[2]); /* 2:index of parameters */
290 } else if (!(strcmp(argv[1], "-r"))) {
291#ifdef LOSCFG_FS_VFS
292 return OsViewFileTime(argv[2]); /* 2:index of parameters */
293#endif
294 }
295 }
296
297 OsCmdUsageDate(DATE_ERR_INFO);
298 return DATE_OK;
299}
300
@ CMD_TYPE_STD
支持的标准命令参数输入,所有输入的字符都会通过命令解析后被传入。
Definition: shell.h:90
char * OsShellGetWorkingDirectory(void)
Definition: shcmd.c:94
INT32 OsShellCmdDate(INT32 argc, const CHAR **argv)
STATIC const INT32 g_monLengths[2][12]
Definition: date_shellcmd.c:57
STATIC VOID OsCopyTm(struct tm *destTm, const struct tm *srcTm)
Definition: date_shellcmd.c:62
STATIC INT32 OsViewFileTime(const CHAR *filename)
STATIC INT32 OsStrToTm(const CHAR *str, struct tm *tm)
SHELLCMD_ENTRY(date_shellcmd, CMD_TYPE_STD, "date", XARGS,(CmdCallBackFunc) OsShellCmdDate)
STATIC INT32 OsDateSetTime(const CHAR *timeStr)
STATIC INT32 OsFormatPrintTime(const CHAR *formatStr)
STATIC VOID OsCmdUsageDate(INT32 order)
Definition: date_shellcmd.c:81
int vfs_normalize_path(const char *directory, const char *filename, char **pathname)
Definition: fullpath.c:245
signed int INT32
Definition: los_typedef.h:60
unsigned int UINT32
Definition: los_typedef.h:57
char CHAR
Definition: los_typedef.h:63
void free(void *ptr)
释放ptr所指向的内存空间
Definition: malloc.c:66
int settimeofday64(const struct timeval64 *tv, const struct timezone *tz)
Definition: time.c:346
int gettimeofday64(struct timeval64 *tv, struct timezone *tz)
Definition: time.c:391
u32_t(* CmdCallBackFunc)(u32_t argc, const char **argv)
Definition: types_adapt.h:86