00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "libts.h"
00025
00026 #if HAVE_SYS_STAT_H
00027 #include <sys/stat.h>
00028 #endif
00029
00030 int
00031 ink_fputln(FILE * stream, const char *s)
00032 {
00033 if (stream && s) {
00034 int rc = fputs(s, stream);
00035 if (rc > 0)
00036 rc += fputc('\n', stream);
00037 return rc;
00038 }
00039 else
00040 return -EINVAL;
00041 }
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 int
00063 ink_file_fd_readline(int fd, int bufsz, char *buf)
00064 {
00065 char c;
00066 int i = 0;
00067
00068 if (bufsz < 2)
00069 return (-EINVAL);
00070
00071 while (i < bufsz - 1) {
00072 int n = read(fd, &c, 1);
00073 if (n == 0)
00074 break;
00075 if (n < 0)
00076 return (n);
00077 buf[i++] = c;
00078 if (c == '\n')
00079 break;
00080 }
00081
00082 buf[i] = '\0';
00083 return (i);
00084 }
00085
00086
00087 int
00088 ink_file_fd_writestring(int fd, const char *buf)
00089 {
00090 int len, i = 0;
00091
00092 if (buf && (len = strlen(buf)) > 0 && (i = (int) write(fd, buf, (size_t) len) != len))
00093 i = -1;
00094
00095 return i;
00096 }
00097
00098 int
00099 ink_filepath_merge(char *path, int pathsz, const char *rootpath, const char *addpath, int flags)
00100 {
00101 size_t rootlen;
00102 size_t maxlen;
00103 size_t keptlen;
00104 size_t pathlen;
00105 size_t seglen;
00106 char curdir[PATH_NAME_MAX];
00107
00108
00109
00110 if (!addpath)
00111 addpath = "";
00112
00113 if (addpath[0] == '/') {
00114
00115
00116
00117
00118 if (flags & INK_FILEPATH_SECUREROOTTEST)
00119 return EACCES;
00120 if (flags & INK_FILEPATH_NOTABSOLUTE)
00121 return EISDIR;
00122
00123
00124
00125
00126
00127 if (!rootpath && !(flags & INK_FILEPATH_NOTABOVEROOT))
00128 rootpath = "";
00129 }
00130 else {
00131
00132
00133
00134
00135
00136 if (flags & INK_FILEPATH_NOTABSOLUTE) {
00137 if (!rootpath)
00138 rootpath = "";
00139 else if (rootpath[0] == '/')
00140 return EISDIR;
00141 }
00142 }
00143 if (!rootpath) {
00144
00145
00146
00147
00148 if (!getcwd(curdir, sizeof(curdir))) {
00149 return errno;
00150 }
00151 rootpath = curdir;
00152 }
00153 rootlen = strlen(rootpath);
00154 maxlen = rootlen + strlen(addpath) + 4;
00155
00156
00157 if (maxlen > (size_t)pathsz) {
00158 return E2BIG;
00159 }
00160 if (addpath[0] == '/') {
00161
00162
00163
00164
00165 keptlen = 0;
00166 while (addpath[0] == '/')
00167 ++addpath;
00168 path[0] = '/';
00169 pathlen = 1;
00170 }
00171 else {
00172
00173
00174 if (rootpath[0] != '/' && (flags & INK_FILEPATH_NOTRELATIVE))
00175 return EBADF;
00176
00177
00178
00179 keptlen = rootlen;
00180 memcpy(path, rootpath, rootlen);
00181
00182
00183
00184 if (keptlen && path[keptlen - 1] != '/') {
00185 path[keptlen++] = '/';
00186 }
00187 pathlen = keptlen;
00188 }
00189
00190 while (*addpath) {
00191
00192
00193 const char *next = addpath;
00194 while (*next && (*next != '/')) {
00195 ++next;
00196 }
00197 seglen = next - addpath;
00198
00199 if (seglen == 0 || (seglen == 1 && addpath[0] == '.')) {
00200
00201
00202 }
00203 else if (seglen == 2 && addpath[0] == '.' && addpath[1] == '.') {
00204
00205 if (pathlen == 1 && path[0] == '/') {
00206
00207
00208
00209 if (flags & INK_FILEPATH_SECUREROOTTEST) {
00210 return EACCES;
00211 }
00212
00213
00214
00215
00216 keptlen = 0;
00217 }
00218 else if (pathlen == 0
00219 || (pathlen == 3
00220 && !memcmp(path + pathlen - 3, "../", 3))
00221 || (pathlen > 3
00222 && !memcmp(path + pathlen - 4, "/../", 4))) {
00223
00224
00225
00226 if (flags & INK_FILEPATH_SECUREROOTTEST) {
00227 return EACCES;
00228 }
00229
00230
00231
00232
00233 memcpy(path + pathlen, "../", *next ? 3 : 2);
00234 pathlen += *next ? 3 : 2;
00235 }
00236 else {
00237
00238
00239 do {
00240 --pathlen;
00241 } while (pathlen && path[pathlen - 1] != '/');
00242 }
00243
00244
00245
00246
00247 if (pathlen < keptlen) {
00248 if (flags & INK_FILEPATH_SECUREROOTTEST) {
00249 return EACCES;
00250 }
00251 keptlen = pathlen;
00252 }
00253 }
00254 else {
00255
00256
00257 if (*next) {
00258 seglen++;
00259 }
00260 memcpy(path + pathlen, addpath, seglen);
00261 pathlen += seglen;
00262 }
00263
00264
00265
00266 if (*next) {
00267 ++next;
00268 }
00269
00270 addpath = next;
00271 }
00272 path[pathlen] = '\0';
00273 if (pathlen > 1 && path[pathlen - 1] == '/') {
00274
00275 size_t es = strlen(addpath);
00276 if (es == 0 || addpath[es - 1] != '/') {
00277 --pathlen;
00278 path[pathlen] = '\0';
00279 }
00280 }
00281
00282
00283
00284
00285
00286
00287
00288 if ((flags & INK_FILEPATH_NOTABOVEROOT) && keptlen < rootlen) {
00289 if (strncmp(rootpath, path, rootlen)) {
00290 return EACCES;
00291 }
00292 if (rootpath[rootlen - 1] != '/'
00293 && path[rootlen] && path[rootlen] != '/') {
00294 return EACCES;
00295 }
00296 }
00297
00298 return 0;
00299 }
00300
00301 int
00302 ink_filepath_make(char *path, int pathsz, const char *rootpath, const char *addpath)
00303 {
00304 size_t rootlen;
00305 size_t maxlen;
00306
00307
00308
00309 if (!addpath)
00310 addpath = "";
00311
00312 if (addpath[0] == '/') {
00313
00314 ink_strlcpy(path, addpath, pathsz);
00315 return 0;
00316 }
00317 if (!rootpath || !*rootpath) {
00318
00319 ink_strlcpy(path, addpath, pathsz);
00320 return 0;
00321 }
00322 rootlen = strlen(rootpath);
00323 maxlen = strlen(addpath) + 2;
00324 if (maxlen > (size_t)pathsz) {
00325 *path = '\0';
00326 return (int)maxlen;
00327 }
00328 ink_strlcpy(path, rootpath, pathsz);
00329 path += rootlen;
00330 pathsz -= rootlen;
00331 if (*(path - 1) != '/') {
00332 *(path++) = '/';
00333 --pathsz;
00334 }
00335 ink_strlcpy(path, addpath, pathsz);
00336 return 0;
00337 }
00338
00339 int
00340 ink_file_fd_zerofill(int fd, off_t size)
00341 {
00342
00343 if (ftruncate(fd, 0) < 0) {
00344 return errno;
00345 }
00346
00347
00348
00349 #if HAVE_POSIX_FALLOCATE
00350 if (posix_fallocate(fd, 0, size) == 0) {
00351 return 0;
00352 }
00353 #endif
00354
00355 if (ftruncate(fd, size) < 0) {
00356 return errno;
00357 }
00358
00359 return 0;
00360 }
00361
00362 bool
00363 ink_file_is_directory(const char * path)
00364 {
00365 struct stat sbuf;
00366
00367 if (stat(path, &sbuf) == -1) {
00368 return false;
00369 }
00370
00371 return S_ISDIR(sbuf.st_mode);
00372 }