/************************************************************************ Module: cli **** License **** This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. A copy of the GNU General Public License is available as `/usr/share/common-licenses/GPL' in the Debian GNU/Linux distribution or on the World Wide Web at `http://www.gnu.org/copyleft/gpl.html'. You can also obtain it by writing to the Free Software Foundation, Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. This code was originally developed by Vyatta, Inc. Portions created by Vyatta are Copyright (C) 2007 Vyatta, Inc. All Rights Reserved. Author: Oleg Moskalenko Date: 2007 Description: "new" cli path-handling utilities **** End License **** *************************************************************************/ #if !defined(_GNU_SOURCE) #define _GNU_SOURCE #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "cli_path_utils.h" #include "cli_val.h" /********************* * Data definitions * *********************/ typedef char* clind_dir_name; /** * Definition of the path structure to hold all path-like information: */ struct _clind_path_impl { int absolute; int path_len; char* path_string; clind_dir_name* path; }; /****************************** * Path utils. We use them * to manipulate the path-like * structures. * ******************************/ static void clind_reset_path_string(clind_path_impl* obj) { char* newpath=NULL; if(obj->path_len<1) { newpath=strdup(""); } else { int i=0; if(!obj->absolute || (strlen(obj->path[0])>0 && ((char*)(obj->path[0]))[0]=='/')) { newpath=strdup(obj->path[0]); } else { newpath=(char*)malloc(strlen(obj->path[0])+1+1); newpath[0]='/'; strcpy(newpath+1,(char*)(obj->path[0])); } for(i=1;ipath_len;i++) { newpath=(char*)realloc(newpath,strlen(newpath)+1+strlen(obj->path[i])+1); strcpy(newpath+strlen(newpath),"/"); strcpy(newpath+strlen(newpath),obj->path[i]); } } if(obj->path_string==NULL) { obj->path_string=newpath; } else { obj->path_string=(char*)realloc(obj->path_string,strlen(newpath)+1); strcpy(obj->path_string,newpath); free(newpath); } } clind_path_ref clind_path_construct(const char* path) { if(!path) return NULL; else { const char* delim="/ \t"; clind_path_impl *obj = (clind_path_impl*)malloc(sizeof(clind_path_impl)); char* tokpath=strdup(path); char* token=strtok(tokpath,delim); obj->path_len=0; obj->path_string=strdup(""); obj->path=NULL; while(token) { clind_path_push((clind_path_ref)obj,token); token=strtok(NULL,delim); } free(tokpath); obj->absolute=(*path=='/'); clind_reset_path_string(obj); return (clind_path_ref)obj; } } void clind_path_destruct(clind_path_ref* path) { if(path && *path) { clind_path_impl* obj = (clind_path_impl*)(*path); if(obj->path_string) { free(obj->path_string); obj->path_string=NULL; } if(obj->path) { while(obj->path_len>0) { char* dir_name = (char*)(obj->path[obj->path_len-1]); if(dir_name) { free(dir_name); } obj->path_len--; } free(obj->path); obj->path=0; } *path=0; } } clind_path_ref clind_path_clone(const clind_path_ref path) { clind_path_ref ret=NULL; if(path) { clind_path_impl* obj = (clind_path_impl*)path; ret = clind_path_construct(obj->path_string); if(ret) { ((clind_path_impl*)ret)->absolute=obj->absolute; clind_reset_path_string((clind_path_impl*)ret); } } return ret; } int clind_path_get_size(clind_path_ref path) { if(path) { clind_path_impl* obj = (clind_path_impl*)path; return obj->path_len; } return 0; } const char* clind_path_get_path_string(clind_path_ref path) { if(path) { clind_path_impl* obj = (clind_path_impl*)path; if(obj->path_string) { return obj->path_string; } } return ""; } int clind_path_is_absolute(clind_path_ref path) { if(path) { clind_path_impl* obj = (clind_path_impl*)path; return obj->absolute; } return 0; } void clind_path_push(clind_path_ref path,const char* dir) { if(path && dir && *dir) { clind_path_impl* obj = (clind_path_impl*)path; int absolute=(*dir=='/'); while(*dir && *dir=='/') dir++; if(obj->path_len<=0) { obj->path_len=1; obj->absolute=absolute; if(obj->path) { free(obj->path); } obj->path=(clind_dir_name*)malloc(sizeof(clind_dir_name)); obj->path[0]=(clind_dir_name)strdup(dir); } else { obj->path_len++; obj->path=(clind_dir_name*)realloc(obj->path, sizeof(clind_dir_name)*(obj->path_len)); obj->path[obj->path_len-1]=strdup(dir); } clind_reset_path_string(obj); } } char* clind_path_pop_string(clind_path_ref path) { char* ret=NULL; if(path) { clind_path_impl* obj = (clind_path_impl*)path; if(obj->path_len<=0) { return ret; } obj->path_len--; if(obj->path) { if(obj->path[obj->path_len]) { ret = obj->path[obj->path_len]; obj->path[obj->path_len]=NULL; } } if(obj->path_len<1) { obj->absolute=0; } clind_reset_path_string(obj); } return ret; } int clind_path_pop(clind_path_ref path) { int ret=-1; char* ps = clind_path_pop_string(path); if(ps) { free(ps); ret=0; } return ret; } const char* clind_path_last_string(clind_path_ref path) { char* ret=NULL; if(path) { clind_path_impl* obj = (clind_path_impl*)path; if(obj->path && obj->path_len>0) { ret=obj->path[obj->path_len-1]; } } return ret; } void clind_path_unshift(clind_path_ref path,const char* dir) { if(path && dir && *dir) { clind_path_impl* obj = (clind_path_impl*)path; int absolute=(*dir=='/'); while(*dir && *dir=='/') dir++; if(obj->path_len<=0) { clind_path_push(path,dir); } else { obj->path_len++; obj->path=(clind_dir_name*)realloc(obj->path, sizeof(clind_dir_name)*(obj->path_len)); memmove((char*)(obj->path)+sizeof(clind_dir_name),(char*)(obj->path), sizeof(clind_dir_name)*(obj->path_len-1)); obj->path[0]=strdup(dir); } obj->absolute=absolute; clind_reset_path_string(obj); } } const char* clind_path_get_string(clind_path_ref path,int index) { const char* ret=NULL; if(path) { clind_path_impl* obj = (clind_path_impl*)path; if(obj->path && obj->path_len>index) { ret=obj->path[index]; } } return ret; } const char* clind_path_first_string(clind_path_ref path) { return clind_path_get_string(path,0); } char* clind_path_shift_string(clind_path_ref path) { char* ret=NULL; if(path) { clind_path_impl* obj = (clind_path_impl*)path; if(obj->path_len<=0) { return ret; } obj->path_len--; if(obj->path) { if(obj->path[0]) { ret = obj->path[0]; obj->path[0]=NULL; } memmove((char*)(obj->path),(char*)(obj->path)+sizeof(clind_dir_name), sizeof(clind_dir_name)*obj->path_len); } obj->absolute=0; clind_reset_path_string(obj); } return ret; } int clind_path_shift(clind_path_ref path) { int ret=-1; char* ps = clind_path_shift_string(path); if(ps) { free(ps); ret=0; } return ret; } void clind_path_debug_print(clind_path_ref path) { if(path) { int i=0; clind_path_impl* obj = (clind_path_impl*)path; if(obj->path_string) { printf("obj->path_string=%s, obj->path_len=%d,obj->absolute=%d\n", obj->path_string,obj->path_len,obj->absolute); } else { printf("obj->path_string=NULL, obj->path_len=%d,obj->absolute=%d\n", obj->path_len,obj->absolute); } if(obj->path) { for(i=0;ipath_len;i++) { if(obj->path[i]) { printf(" obj->path[%d]=%s\n",i,obj->path[i]); } else { printf(" obj->path[%d]=NULL\n",i); } } } else { printf(" obj->path=NULL\n"); } } } int clind_file_exists(const char* dir,const char* file) { int ret=0; if(file) { char* fname=strdup(file); struct stat statbuf; if(dir) { free(fname); fname=(char*)malloc(strlen(dir)+1+strlen(file)+1); strcpy(fname,dir); strcpy(fname+strlen(fname),"/"); strcpy(fname+strlen(fname),file); } if (lstat(fname, &statbuf) == 0) { ret=1; } free(fname); } return ret; } char *clind_unescape(const char *name) { const char *cp; char *rcp, *ret; unsigned long len; for(cp=name, len=0;*cp;++cp, ++len) if(*cp=='%') cp +=2; rcp = ret = malloc(len+1); for(cp=name, len=0;*cp;++cp, ++rcp) if(*cp=='%') { ++cp; if (*cp >='a' && *cp<='f') *rcp = (*cp-'a'+10)*16; else if (*cp >='A' && *cp<='F') *rcp = (*cp-'A'+10)*16; else if (*cp >='0' && *cp<='9') *rcp = (*cp-'0')*16; else { bye("Bad escape in |%s|\n", name); } ++cp; if (*cp >='a' && *cp<='f') *rcp += (*cp-'a'+10); else if (*cp >='A' && *cp<='F') *rcp += (*cp-'A'+10); else if (*cp >='0' && *cp<='9') *rcp += (*cp-'0'); else { bye("Bad escape in |%s|\n", name); } }else *rcp = *cp; *rcp = 0; return ret; } char* clind_quote(const char* s) { char* ret=NULL; if(s) { int i=0; int len=strlen(s); int sz=0; char SQ='\''; ret=(char*)malloc(1+5*len+1+1+10); ret[sz++]=SQ; for(i=0;i