source: MondoRescue/branches/3.3/mindi-busybox/coreutils/touch.c@ 3865

Last change on this file since 3865 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

File size: 5.6 KB
RevLine 
[821]1/* vi: set sw=4 ts=4: */
2/*
3 * Mini touch implementation for busybox
4 *
5 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
6 *
[2725]7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
[821]8 */
9
[3232]10/* BB_AUDIT SUSv3 _NOT_ compliant -- options -a, -m not supported. */
[821]11/* http://www.opengroup.org/onlinepubs/007904975/utilities/touch.html */
12
13/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
14 *
15 * Previous version called open() and then utime(). While this will be
16 * be necessary to implement -r and -t, it currently only makes things bigger.
17 * Also, exiting on a failure was a bug. All args should be processed.
18 */
19
[1765]20#include "libbb.h"
[821]21
[3232]22//config:config TOUCH
23//config: bool "touch"
24//config: default y
25//config: help
26//config: touch is used to create or change the access and/or
27//config: modification timestamp of specified files.
28//config:
[3621]29//config:config FEATURE_TOUCH_NODEREF
30//config: bool "Add support for -h"
31//config: default y
32//config: depends on TOUCH
33//config: help
34//config: Enable touch to have the -h option.
35//config: This requires libc support for lutimes() function.
36//config:
[3232]37//config:config FEATURE_TOUCH_SUSV3
38//config: bool "Add support for SUSV3 features (-d -t -r)"
39//config: default y
40//config: depends on TOUCH
41//config: help
42//config: Enable touch to use a reference file or a given date/time argument.
43
44//applet:IF_TOUCH(APPLET_NOFORK(touch, touch, BB_DIR_BIN, BB_SUID_DROP, touch))
45
46//kbuild:lib-$(CONFIG_TOUCH) += touch.o
47
48//usage:#define touch_trivial_usage
49//usage: "[-c]" IF_FEATURE_TOUCH_SUSV3(" [-d DATE] [-t DATE] [-r FILE]") " FILE..."
50//usage:#define touch_full_usage "\n\n"
51//usage: "Update the last-modified date on the given FILE[s]\n"
52//usage: "\n -c Don't create files"
[3621]53//usage: IF_FEATURE_TOUCH_NODEREF(
54//usage: "\n -h Don't follow links"
55//usage: )
[3232]56//usage: IF_FEATURE_TOUCH_SUSV3(
57//usage: "\n -d DT Date/time to use"
58//usage: "\n -t DT Date/time to use"
59//usage: "\n -r FILE Use FILE's date/time"
60//usage: )
61//usage:
62//usage:#define touch_example_usage
63//usage: "$ ls -l /tmp/foo\n"
64//usage: "/bin/ls: /tmp/foo: No such file or directory\n"
65//usage: "$ touch /tmp/foo\n"
66//usage: "$ ls -l /tmp/foo\n"
67//usage: "-rw-rw-r-- 1 andersen andersen 0 Apr 15 01:11 /tmp/foo\n"
68
[1765]69/* This is a NOFORK applet. Be very careful! */
70
[2725]71/* coreutils implements:
72 * -a change only the access time
73 * -c, --no-create
74 * do not create any files
75 * -d, --date=STRING
76 * parse STRING and use it instead of current time
77 * -f (ignored, BSD compat)
78 * -m change only the modification time
[3621]79 * -h, --no-dereference
[2725]80 * -r, --reference=FILE
81 * use this file's times instead of current time
82 * -t STAMP
83 * use [[CC]YY]MMDDhhmm[.ss] instead of current time
84 * --time=WORD
85 * change the specified time: WORD is access, atime, or use
86 */
87
88int touch_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
89int touch_main(int argc UNUSED_PARAM, char **argv)
[821]90{
91 int fd;
92 int status = EXIT_SUCCESS;
[2725]93 int opts;
[3621]94 enum {
95 OPT_c = (1 << 0),
96 OPT_r = (1 << 1) * ENABLE_FEATURE_TOUCH_SUSV3,
97 OPT_d = (1 << 2) * ENABLE_FEATURE_TOUCH_SUSV3,
98 OPT_t = (1 << 3) * ENABLE_FEATURE_TOUCH_SUSV3,
99 OPT_h = (1 << 4) * ENABLE_FEATURE_TOUCH_NODEREF,
100 };
[3232]101#if ENABLE_FEATURE_TOUCH_SUSV3
[2725]102# if ENABLE_LONG_OPTS
103 static const char touch_longopts[] ALIGN1 =
104 /* name, has_arg, val */
105 "no-create\0" No_argument "c"
106 "reference\0" Required_argument "r"
107 "date\0" Required_argument "d"
[3621]108 IF_FEATURE_TOUCH_NODEREF("no-dereference\0" No_argument "h")
[2725]109 ;
110# endif
111 char *reference_file = NULL;
112 char *date_str = NULL;
113 struct timeval timebuf[2];
114 timebuf[1].tv_usec = timebuf[0].tv_usec = 0;
115#else
116# define reference_file NULL
117# define date_str NULL
118# define timebuf ((struct timeval*)NULL)
119#endif
[821]120
[3232]121#if ENABLE_FEATURE_TOUCH_SUSV3 && ENABLE_LONG_OPTS
[2725]122 applet_long_options = touch_longopts;
123#endif
124 /* -d and -t both set time. In coreutils,
125 * accepted data format differs a bit between -d and -t.
126 * We accept the same formats for both */
[3232]127 opts = getopt32(argv, "c" IF_FEATURE_TOUCH_SUSV3("r:d:t:")
[3621]128 IF_FEATURE_TOUCH_NODEREF("h")
[2725]129 /*ignored:*/ "fma"
[3232]130 IF_FEATURE_TOUCH_SUSV3(, &reference_file)
131 IF_FEATURE_TOUCH_SUSV3(, &date_str)
132 IF_FEATURE_TOUCH_SUSV3(, &date_str)
[2725]133 );
134
[821]135 argv += optind;
136 if (!*argv) {
137 bb_show_usage();
138 }
139
[2725]140 if (reference_file) {
141 struct stat stbuf;
142 xstat(reference_file, &stbuf);
143 timebuf[1].tv_sec = timebuf[0].tv_sec = stbuf.st_mtime;
[3621]144 /* Can use .st_mtim.tv_nsec
145 * (or is it .st_mtimensec?? see date.c)
146 * to set microseconds too.
147 */
[2725]148 }
149
150 if (date_str) {
151 struct tm tm_time;
152 time_t t;
153
[3232]154 //memset(&tm_time, 0, sizeof(tm_time));
155 /* Better than memset: makes "HH:MM" dates meaningful */
156 time(&t);
157 localtime_r(&t, &tm_time);
[2725]158 parse_datestr(date_str, &tm_time);
159
160 /* Correct any day of week and day of year etc. fields */
161 tm_time.tm_isdst = -1; /* Be sure to recheck dst */
162 t = validate_tm_time(date_str, &tm_time);
163
164 timebuf[1].tv_sec = timebuf[0].tv_sec = t;
165 }
166
[821]167 do {
[3621]168 int result;
169 result = (
170#if ENABLE_FEATURE_TOUCH_NODEREF
171 (opts & OPT_h) ? lutimes :
172#endif
173 utimes)(*argv, (reference_file || date_str) ? timebuf : NULL);
174 if (result != 0) {
175 if (errno == ENOENT) { /* no such file? */
176 if (opts & OPT_c) {
177 /* Creation is disabled, so ignore */
[821]178 continue;
179 }
[2725]180 /* Try to create the file */
181 fd = open(*argv, O_RDWR | O_CREAT, 0666);
182 if (fd >= 0) {
183 xclose(fd);
184 if (reference_file || date_str)
185 utimes(*argv, timebuf);
[821]186 continue;
187 }
188 }
189 status = EXIT_FAILURE;
[2725]190 bb_simple_perror_msg(*argv);
[821]191 }
192 } while (*++argv);
193
194 return status;
195}
Note: See TracBrowser for help on using the repository browser.