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 }