/ncftp-3.2.5/libncftp/c_utime.c
C | 196 lines | 150 code | 14 blank | 32 comment | 84 complexity | 6985b27188a6c7a96656863476f88102 MD5 | raw file
Possible License(s): AGPL-3.0
1/* c_utime.c
2 *
3 * Copyright (c) 1996-2005 Mike Gleason, NcFTP Software.
4 * All rights reserved.
5 *
6 */
7
8#include "syshdrs.h"
9#ifdef PRAGMA_HDRSTOP
10# pragma hdrstop
11#endif
12
13#define _CRT_SECURE_NO_WARNINGS 1
14
15static void
16GmTimeStr(char *const dst, const size_t dstsize, time_t t)
17{
18 char buf[64];
19 struct tm gt;
20
21 if (Gmtime(t, >) == NULL) {
22 dst[0] = '\0';
23 } else {
24#ifdef HAVE_SNPRINTF
25 buf[sizeof(buf) - 1] = '\0';
26 (void) snprintf(buf, sizeof(buf) - 1, "%04d%02d%02d%02d%02d%02d",
27#else
28 (void) sprintf(buf, "%04d%02d%02d%02d%02d%02d",
29#endif
30 gt.tm_year + 1900,
31 gt.tm_mon + 1,
32 gt.tm_mday,
33 gt.tm_hour,
34 gt.tm_min,
35 gt.tm_sec
36 );
37 (void) Strncpy(dst, buf, dstsize);
38 }
39} /* GmTimeStr */
40
41
42
43
44int
45FTPUtime(const FTPCIPtr cip, const char *const file, time_t actime, time_t modtime, time_t crtime)
46{
47 char mstr[64], astr[64], cstr[64];
48 time_t now;
49 int result = kNoErr;
50 int wantToSetCrTime = 1;
51 ResponsePtr rp;
52
53 if (cip == NULL)
54 return (kErrBadParameter);
55 if (strcmp(cip->magic, kLibraryMagic))
56 return (kErrBadMagic);
57
58 now = (time_t) 0;
59 if ((modtime == (time_t) 0) || (modtime == (time_t) -1))
60 modtime = time(&now);
61 (void) GmTimeStr(mstr, sizeof(mstr), modtime);
62
63 if ((actime == (time_t) 0) || (actime == (time_t) -1)) {
64 if (now != (time_t) 0) {
65 actime = now;
66 } else {
67 actime = time(&now);
68 }
69 }
70 if ((crtime == (time_t) 0) || (crtime == (time_t) -1)) {
71 wantToSetCrTime = 0;
72 if (now != (time_t) 0) {
73 crtime = now;
74 } else {
75 crtime = time(&now);
76 }
77 }
78 (void) GmTimeStr(astr, sizeof(astr), actime);
79 (void) GmTimeStr(cstr, sizeof(cstr), crtime);
80
81 if ((cip->hasMFF == kCommandAvailable) && (wantToSetCrTime != 0)) {
82 result = FTPCmd(cip, "MFF Modify=%s;Create=%s %s", mstr, cstr, file);
83 if ((result == 2) || (result == 0)) {
84 result = kNoErr;
85 return (result);
86 } else {
87 cip->errNo = kErrUTIMEFailed;
88 result = kErrUTIMEFailed;
89 /* It may not have liked us trying to set the creation time.
90 * Fallthrough and try just setting the modification time.
91 */
92 }
93 }
94
95 if (cip->hasMFMT == kCommandAvailable) {
96 result = FTPCmd(cip, "MFMT %s %s", mstr, file);
97 if ((result == 2) || (result == 0)) {
98 result = kNoErr;
99 } else {
100 cip->errNo = kErrUTIMEFailed;
101 result = kErrUTIMEFailed;
102 }
103 return (result);
104 }
105
106 if (result == kNoErr)
107 result = kErrUTIMENotAvailable;
108 if (cip->hasSITE_UTIME != kCommandNotAvailable) {
109 rp = InitResponse();
110 if (rp == NULL) {
111 result = kErrMallocFailed;
112 cip->errNo = kErrMallocFailed;
113 FTPLogError(cip, kDontPerror, "Malloc failed.\n");
114 } else {
115 result = RCmd(cip, rp, "SITE UTIME %s %s %s %s UTC", file, astr, mstr, cstr);
116 if (result < 0) {
117 DoneWithResponse(cip, rp);
118 return (result);
119 } else if (result == 2) {
120 cip->hasSITE_UTIME = kCommandAvailable;
121 result = kNoErr;
122 DoneWithResponse(cip, rp);
123 } else if ((FTP_UNIMPLEMENTED_CMD(rp->code)) || (FTP_SYNTAX_ERROR_IN_PARAMETERS(rp->code))) {
124 cip->hasSITE_UTIME = kCommandNotAvailable;
125 cip->errNo = kErrUTIMENotAvailable;
126 result = kErrUTIMENotAvailable;
127 DoneWithResponse(cip, rp);
128 } else if ((cip->serverType == kServerTypeNcFTPd) && (strchr(file, ' ') != NULL)) {
129 /* Workaround bug with filenames containing
130 * spaces.
131 */
132 DoneWithResponse(cip, rp);
133 result = FTPCmd(cip, "MDTM %s %s", mstr, file);
134 if ((result == 2) || (result == 0)) {
135 result = kNoErr;
136 } else {
137 cip->errNo = kErrUTIMEFailed;
138 result = kErrUTIMEFailed;
139 }
140 } else {
141 cip->errNo = kErrUTIMEFailed;
142 result = kErrUTIMEFailed;
143 DoneWithResponse(cip, rp);
144 }
145 }
146 }
147 if (result == kErrUTIMENotAvailable) {
148 if ((cip->hasMDTM == kCommandNotAvailable) || (cip->hasMDTM_set == kCommandNotAvailable)) {
149 cip->errNo = kErrUTIMENotAvailable;
150 result = kErrUTIMENotAvailable;
151 } else {
152 rp = InitResponse();
153 if (rp == NULL) {
154 result = kErrMallocFailed;
155 cip->errNo = kErrMallocFailed;
156 FTPLogError(cip, kDontPerror, "Malloc failed.\n");
157 } else {
158 result = RCmd(cip, rp, "MDTM %s %s", mstr, file);
159 if (result < 0) {
160 DoneWithResponse(cip, rp);
161 return (result);
162 } else if (result == 2) {
163 cip->hasMDTM_set = kCommandAvailable;
164 result = kNoErr;
165 } else {
166 /* Ideally, we would only disable
167 * the MDTM_set feature if we
168 * received a code that corresponds
169 * to an unimplemented command.
170 * Unfortunately, since the regular
171 * syntax of MDTM uses a pathname
172 * parameter, we'll often get back
173 * a 550 response when we try to
174 * set the timestamp, because a
175 * server that doesn't support this
176 * feature reads the timestamp
177 * as a pathname which doesn't
178 * exist. As a result, this feature
179 * could get disabled if a server
180 * which does support the feature
181 * returns a 550 when it turns
182 * out that the file exists but
183 * we didn't have permission to
184 * change the timestamp.
185 */
186 if ((FTP_UNIMPLEMENTED_CMD(rp->code)) || (FTP_SYNTAX_ERROR_IN_PARAMETERS(rp->code)) || (rp->code == 550))
187 cip->hasMDTM_set = kCommandNotAvailable;
188 cip->errNo = kErrUTIMENotAvailable;
189 result = kErrUTIMENotAvailable;
190 }
191 DoneWithResponse(cip, rp);
192 }
193 }
194 }
195 return (result);
196} /* FTPUtime */