#include #include #include #include #include #include #include #include "runtime.h" #include "misc.h" char *tidy_path(char *path) { char last_char=0,next_char=0; char *last_slash,*last_dir; char *src,*dst; last_dir=last_slash=src=dst=path; while(*src) { next_char = *(src + 1); /* Skip multiple slashes */ if (*src == '/' && last_char == '/') { src++; continue; } if (*src == '.' && last_char == '/' && next_char == '.' && *(src+2) == '/') { /* A /../ */ last_slash=dst=last_dir; *(dst+1) = 0; dst++; src+=2; continue; } if (*src == '.' && last_char == '/' && next_char == '/') { /* A /./ */ src++; continue; } last_char = *src; *dst = *src; if (*dst == '/') { last_dir = last_slash; last_slash = dst; } dst++; src++; } *dst = 0; return path; } /* The safe character, what to replace bad chars with */ #define SFC '.' #define DEFAULT_CLEAN_ARRAY medium_safe_char_array /* Strips \\'s /'s and upper and lower chars */ char medium_safe_char_array[256] = { SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //0-9 SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //10 SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //20 SFC,SFC,' ','!','"','#','$','%','&',SFC, //30 '(',')','*','+',',','-',SFC,SFC,'0','1', //40 '2','3','4','5','6','7','8','9',':',';', //50 '<','=','>','?','@','A','B','C','D','E', //60 'F','G','H','I','J','K','L','M','N','O', //70 'P','Q','R','S','T','U','V','W','X','Y', //80 'Z','[',SFC,']','^','_','`','a','b','c', //90 'd','e','f','g','h','i','j','k','l','m', //100 'n','o','p','q','r','s','t','u','v','w', //110 'x','y','z','{','|','}','~',SFC,SFC,SFC, //120 SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //130 SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //140 SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //150 SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //160 SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //170 SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //180 SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //190 SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //200 SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //210 SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //220 SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //230 SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //240 SFC,SFC,SFC,SFC,SFC,SFC }; /* Strips everything that isn't usually used. * Leaves a-z, A-Z, 0-9, -, ., (, ), !,+, and space * @, [,],^,_,~ */ char very_safe_char_array[256] = { SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //0-9 SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //10 SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //20 SFC,SFC,' ','!',SFC,SFC,SFC,SFC,SFC,SFC, //30 '(',')',SFC,'+',',','-',SFC,SFC,'0','1', //40 '2','3','4','5','6','7','8','9',SFC,SFC, //50 SFC,SFC,SFC,SFC,'@','A','B','C','D','E', //60 'F','G','H','I','J','K','L','M','N','O', //70 'P','Q','R','S','T','U','V','W','X','Y', //80 'Z','[',SFC,']','^','_',SFC,'a','b','c', //90 'd','e','f','g','h','i','j','k','l','m', //100 'n','o','p','q','r','s','t','u','v','w', //110 'x','y','z',SFC,SFC,SFC,'~',SFC,SFC,SFC, //120 SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //130 SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //140 SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //150 SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //160 SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //170 SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //180 SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //190 SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //200 SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //210 SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //220 SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //230 SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC,SFC, //240 SFC,SFC,SFC,SFC,SFC,SFC }; char *clean_filename(char *filename) { char *sp, *dp; unsigned char c; dp = sp = filename; while(*sp) { c = (unsigned char) *sp; *dp = DEFAULT_CLEAN_ARRAY[c]; sp++; dp++; } *dp = 0; return filename; } char *clean_path(char *path) { char *sp,*dp,last_char=0,next_char=0; sp = dp = path; while(*sp) { next_char = *(sp+1); if (*sp == '/' && last_char=='/') { sp++; continue; } if (*sp == '.' && last_char == '/' && next_char == '.' && *(sp+2) == '/') { /* A /../ */ sp+=2; continue; } if (*sp == '.' && last_char == '/' && next_char == '/') { /* A /./ */ sp++; continue; } last_char = *sp; *dp = *sp; dp++; sp++; } *dp = 0; return path; } char *remove_path(char *path) { char *cp; cp = strrchr(path,'/'); if (cp == NULL) return path; if (*(cp+1) == 0) { /* Was /blah/ */ *cp = 0; cp = strrchr(path,'/'); if (cp == NULL) return path; } cp++; memmove(path,cp,strlen(cp)+1); return path; } const char *const_skip_to_whitespace(const char *cp) { while(*cp && !isspace(*cp)) cp++; return cp; } const char *const_skip_whitespace(const char *cp) { while(isspace(*cp)) cp++; return cp; } char *skip_to_whitespace(char *cp) { while(*cp && !isspace(*cp)) cp++; return cp; } char *skip_whitespace(char *cp) { while(isspace(*cp)) cp++; return cp; } char *trim(char *str) { char *sp; int len; sp = str; while(isspace(*sp)) sp++; //At first non whitespace if (sp != str) { len = strlen(sp)+1; memmove(str,sp,len); sp = str; } //str shifted whitespace out while(*sp) sp++; //at null sp--; //at Last char while(sp >= str && isspace(*sp)) sp--; //at str-1 or last nonspace sp++; //at str or last space or null *sp = 0; return str; } char *trim_comments(char *str) { char *sp,inquote=0; for(sp=str;*sp;sp++) { if (*sp == '\\' && *(sp+1) != 0) { sp++; continue; } if (*sp == inquote) { inquote = 0; continue; } if (*sp == '"' || *sp == '\'') { inquote = *sp; continue; } if (!inquote && *sp == '#') break; } *sp = 0; return trim(str); } #define ONE_KIB (1024L) #define TEN_KIB (10240L) #define ONE_MIB (1048576L) #define TEN_MIB (10485760L) #define ONE_GIB (1073741824L) #define TEN_GIB (10737418240L) const char *nice_size(size_t size) { static char nice_buffer[15]; double ns; int prec=2; const char *append; if (size < 1024) { ns = size; append = "B"; prec = 0; } else if (size < TEN_KIB) { ns = ((double)size) / ((double)ONE_KIB); append = "KiB"; } else if (size < ONE_MIB) { ns = size / ONE_KIB; append = "KiB"; prec=0; } else if (size < TEN_MIB) { ns = ((double)size) / ((double)ONE_MIB); append = "MiB"; } else if (size < ONE_GIB) { ns = size / ONE_MIB; prec = 0; append = "MiB"; } else { ns = ((double)size) / ((double)ONE_GIB); append = "GiB"; } snprintf(nice_buffer,14,"%.*f%s",prec,ns,append); nice_buffer[14] = 0; return nice_buffer; } int my_write_delay(int fd, const void *buffer, size_t size); int my_write(int fd, const void *buffer, size_t size) { int r; r = write(fd,buffer,size); if (r == -1 && errno == EAGAIN) { return my_write_delay(fd,buffer,size); } else if (r == -1) { return -1; } else if (r == 0) { return 0; } else if (r != size) { return r+my_write_delay(fd,buffer+r,size-r); } return r; } int write_delay_ohno=0; int my_write_delay(int fd, const void *buffer, size_t size) { int r; size_t orig_size = size; fd_set fdw; do { write_delay_ohno++; r = write(fd,buffer,size); if (r == -1 && errno == EAGAIN) { FD_ZERO(&fdw); FD_SET(fd,&fdw); r = select(fd+1,NULL,&fdw,NULL,NULL); if (r == -1 && errno == EINTR) continue; if (r == -1) return -1; continue; } if (r == 0) return 0; buffer+=r; size-=r; } while(size > 0); return orig_size; } char **strarray_create(POOL p, const char *str, char ch) { int count,i=0,len; const char *cp,*start,*lastnws,*end; char **a; count = 1; for(cp = str; *cp != 0; cp++) { if (*cp == ch) count++; } a = palloc(p, sizeof(char *) * (count+1)); if (a == NULL) return NULL; cp = str; while(*cp) { ASSERT(i < count); while(isspace(*cp)) cp++; lastnws = start = cp; while(*cp && *cp != ch) { if (!isspace(*cp)) lastnws=cp; cp++; } if (*lastnws != ch) end = lastnws+1; else end = cp; if (*cp) cp++; len = (end - start); a[i] = (char *)palloc(p,sizeof(char) * (len+1)); memcpy(a[i],start,len); a[i][len] = 0; i++; } a[i] = NULL; return a; } int strarray_join(char *buffer,size_t size, char **a, char ch) { int i,len,r=0; char *cp=buffer; size--; /* Make room for NULL */ for(i = 0; a[i] != NULL; i++) { len = strlen(a[i]); if (len > size) { len = size; r = -1; } memcpy(cp,a[i],len); cp+=len; size-=len; if (a[i+1] != NULL) { /* Add ch */ if (size > 0) { *cp = ch; cp++; } else { r = -1; } } *cp = 0; } return r; } char *strarray_random(char **a) { int c,i; ASSERT(a); for(c=0;a[c] != NULL; c++) {} /* From rand(3) man page */ /* Doesn't work! i=(int) (c*rand()/(RAND_MAX+1.0)); */ i = rand() % c; return a[i]; } char *pstrdup_portion(POOL p, const char *str, int stop_ch, char **stop_pos) { const char *cp; char *ret; size_t len=0; cp = str; while(*cp != stop_ch && *cp != 0) { len++; cp++; } /* There is no easy way in C to have a pointer to a const char pointer * Unless you do: * struct p2ccp { * const char *ccp; * }; * struct p2ccp test; * Which is a little crazy */ *stop_pos = (char *)cp; ret = palloc(p, sizeof(char) * (len + 1)); memcpy(ret, str, len); ret[len] = 0; return ret; } int strcasecmp_portion(const char *str_a, const char *str_b, int b_stop_ch, char **b_stop_pos) { const char *a, *b; a = str_a; b = str_b; while(*b != b_stop_ch && *b != 0 && *a == *b) { a++; b++; } *b_stop_pos = (char *)b; if (*b == b_stop_ch && *a == 0) return 0; if (*b == *a) { /* Both 0 */ return 0; } return -1; }