⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcache.c

📁 xorp源码hg
💻 C
📖 第 1 页 / 共 4 页
字号:
    if(check_fn != pc->check_fn || data != pc->data)      pca_remove_marks(pc);/* * Record the new callback locally. */    pc->check_fn = check_fn;    pc->data = data;/* * Configure cpl_file_completions() to use the same callback to * select files of interest. */    cfc_set_check_fn(pc->cfc, check_fn, data);  };  return;}/*....................................................................... * Return a description of the last path-caching error that occurred. * * Input: *  pc     PathCache *   The filename cache that suffered the error. * Output: *  return      char *   The description of the last error. */const char *pca_last_error(PathCache *pc){  return pc ? pc->errmsg : "NULL PathCache argument";}/*....................................................................... * Discard all cached filenames. * * Input: *  pc   PathCache *  The cache to be cleared. */static void pca_clear_cache(PathCache *pc){  if(pc) {/* * Return all path-nodes to the freelist. */    _rst_FreeList(pc->node_mem);    pc->head = pc->tail = NULL;/* * Delete all filename strings. */    rst_CacheMem(pc->abs_mem);    rst_CacheMem(pc->rel_mem);  };  return;}/*....................................................................... * Build the list of files of interest contained in a given * colon-separated list of directories. * * Input: *  pc         PathCache *  The cache in which to store the names of *                          the files that are found in the list of *                          directories. *  path      const char *  A colon-separated list of directory *                          paths. Under UNIX, when searching for *                          executables, this should be the return *                          value of getenv("PATH"). * Output: *  return           int    0 - OK. *                          1 - An error occurred. A description of *                              the error can be acquired by calling *                              pca_last_error(pc). */int pca_scan_path(PathCache *pc, const char *path){  const char *pptr; /* A pointer to the next unprocessed character in path[] */  PathNode *node;   /* A node in the list of directory paths */  char **fptr;      /* A pointer into pc->abs_mem->files[] *//* * Check the arguments. */  if(!pc)    return 1;/* * Clear the outdated contents of the cache. */  pca_clear_cache(pc);/* * If no path list was provided, there is nothing to be added to the * cache. */  if(!path)    return 0;/* * Extract directories from the path list, expanding tilde expressions * on the fly into pc->pathname, then add them to the list of path * nodes, along with a sorted list of the filenames of interest that * the directories hold. */  pptr = path;  while(*pptr) {/* * Extract the next pathname component into pc->path->name. */    if(pca_extract_dir(pc, pptr, &pptr))      return 1;/* * Add a new node to the list of paths, containing both the * directory name and, if not a relative pathname, the list of * files of interest in the directory. */    if(add_PathNode(pc, pc->path->name))      return 1;  };/* * The file arrays in each absolute directory node are sections of * pc->abs_mem->files[]. Record pointers to the starts of each * of these sections in each directory node. Note that this couldn't * be done in add_PathNode(), because pc->abs_mem->files[] may * get reallocated in subsequent calls to add_PathNode(), thus * invalidating any pointers to it. */  fptr = pc->abs_mem->files;  for(node=pc->head; node; node=node->next) {    node->files = fptr;    fptr += node->nfile;  };  return 0;}/*....................................................................... * Extract the next directory path from a colon-separated list of * directories, expanding tilde home-directory expressions where needed. * * Input: *  pc      PathCache *   The cache of filenames. *  path   const char *   A pointer to the start of the next component *                        in the path list. * Input/Output: *  nextp  const char **  A pointer to the next unprocessed character *                        in path[] will be assigned to *nextp. * Output: *  return        int     0 - OK. The extracted path is in pc->path->name. *                        1 - Error. A description of the error will *                            have been left in pc->errmsg. */static int pca_extract_dir(PathCache *pc, const char *path, const char **nextp){  const char *pptr;         /* A pointer into path[] */  const char *sptr;         /* The path following tilde expansion */  int escaped = 0;          /* True if the last character was a backslash *//* * If there is a tilde expression at the beginning of the specified path, * place the corresponding home directory into pc->path. Otherwise * just clear pc->path. */  if(pca_expand_tilde(pc, path, strlen(path), 0, &pptr))    return 1;/* * Keep a record of the current location in the path. */  sptr = pptr;/* * Locate the end of the directory name in the pathname string, stopping * when either the end of the string is reached, or an un-escaped colon * separator is seen. */  while(*pptr && (escaped || *pptr != ':'))    escaped = !escaped && *pptr++ == '\\';/* * Append the rest of the directory path to the pathname buffer. */  if(_pn_append_to_path(pc->path, sptr, pptr - sptr, 1) == NULL) {    strcpy(pc->errmsg, "Insufficient memory to record directory name");    return 1;  };/* * To facilitate subsequently appending filenames to the directory * path name, make sure that the recorded directory name ends in a * directory separator. */  {    int dirlen = strlen(pc->path->name);    if(dirlen < FS_DIR_SEP_LEN ||       strncmp(pc->path->name + dirlen - FS_DIR_SEP_LEN, FS_DIR_SEP,	       FS_DIR_SEP_LEN) != 0) {      if(_pn_append_to_path(pc->path, FS_DIR_SEP, FS_DIR_SEP_LEN, 0) == NULL) {	strcpy(pc->errmsg, "Insufficient memory to record directory name");	return 1;      };    };  };/* * Skip the separator unless we have reached the end of the path. */  if(*pptr==':')    pptr++;/* * Return the unprocessed tail of the path-list string. */  *nextp = pptr;  return 0;}/*....................................................................... * Read a username, stopping when a directory separator is seen, a colon * separator is seen, the end of the string is reached, or the username * buffer overflows. * * Input: *  pc   PathCache *   The cache of filenames. *  string    char *   The string who's prefix contains the name. *  slen       int     The max number of characters to read from string[]. *  literal    int     If true, treat backslashes as literal characters *                     instead of escapes. * Input/Output: *  nextp     char **  A pointer to the next unprocessed character *                     in string[] will be assigned to *nextp. * Output: *  return     int     0 - OK. The username can be found in pc->usrnam. *                     1 - Error. A description of the error message *                         can be found in pc->errmsg. */static int pca_read_username(PathCache *pc, const char *string, int slen,			     int literal, const char **nextp){  int usrlen;         /* The number of characters in pc->usrnam[] */  const char *sptr;   /* A pointer into string[] */  int escaped = 0;    /* True if the last character was a backslash *//* * Extract the username. */  for(sptr=string,usrlen=0; usrlen < USR_LEN && (sptr-string) < slen; sptr++) {/* * Stop if the end of the string is reached, or a directory separator * or un-escaped colon separator is seen. */    if(!*sptr || strncmp(sptr, FS_DIR_SEP, FS_DIR_SEP_LEN)==0 ||       (!escaped && *sptr == ':'))      break;/* * Escape the next character? */    if(!literal && !escaped && *sptr == '\\') {      escaped = 1;    } else {      escaped = 0;      pc->usrnam[usrlen++] = *sptr;    };  };/* * Did the username overflow the buffer? */  if(usrlen >= USR_LEN) {    strcpy(pc->errmsg, "Username too long");    return 1;  };/* * Terminate the string. */  pc->usrnam[usrlen] = '\0';/* * Indicate where processing of the input string should continue. */  *nextp = sptr;  return 0;}/*....................................................................... * Create a new CacheMem object. * * Output: *  return  CacheMem *  The new object, or NULL on error. */static CacheMem *new_CacheMem(void){  CacheMem *cm;  /* The object to be returned *//* * Allocate the container. */  cm = (CacheMem *)malloc(sizeof(CacheMem));  if(!cm) {    fprintf(stderr, "new_CacheMem: Insufficient memory.\n");    return NULL;  };/* * Before attempting any operation that might fail, initialize the * container at least up to the point at which it can safely be passed * to del_CacheMem(). */  cm->sg = NULL;  cm->files_dim = 0;  cm->files = NULL;  cm->nfiles = 0;/* * Allocate a list of string segments for storing filenames. */  cm->sg = _new_StringGroup(_pu_pathname_dim());  if(!cm->sg)    return del_CacheMem(cm);/* * Allocate an array of pointers to filenames. * This will be extended later if needed. */  cm->files_dim = FILES_BLK_FACT;  cm->files = (char **) malloc(sizeof(*cm->files) * cm->files_dim);  if(!cm->files) {    fprintf(stderr,        "new_CacheMem: Insufficient memory to allocate array of files.\n");    return del_CacheMem(cm);  };  return cm;}/*....................................................................... * Delete a CacheMem object. * * Input: *  cm   CacheMem *  The object to be deleted. * Output: *  return CacheMem *  The deleted object (always NULL). */static CacheMem *del_CacheMem(CacheMem *cm){  if(cm) {/* * Delete the memory that was used to record filename strings. */    cm->sg = _del_StringGroup(cm->sg);/* * Delete the array of pointers to filenames. */    cm->files_dim = 0;    if(cm->files) {      free(cm->files);      cm->files = NULL;    };/* * Delete the container. */    free(cm);  };  return NULL;}/*....................................................................... * Re-initialize the memory used to allocate filename strings. * * Input: *  cm     CacheMem *  The memory cache to be cleared. */static void rst_CacheMem(CacheMem *cm){  _clr_StringGroup(cm->sg);  cm->nfiles = 0;  return;}/*....................................................................... * Append a new directory node to the list of directories read from the * path. * * Input: *  pc        PathCache *  The filename cache. *  dirname  const char *  The name of the new directory. * Output: *  return          int    0 - OK. *                         1 - Error. */static int add_PathNode(PathCache *pc, const char *dirname){  PathNode *node;  /* The new directory list node */  int relative;    /* True if dirname[] is a relative pathname *//* * Have we been passed a relative pathname or an absolute pathname? */  relative = strncmp(dirname, FS_ROOT_DIR, FS_ROOT_DIR_LEN) != 0;/* * If it's an absolute pathname, ignore it if the corresponding * directory doesn't exist. */  if(!relative && !_pu_path_is_dir(dirname))    return 0;/* * Allocate a new list node to record the specifics of the new directory. */  node = (PathNode *) _new_FreeListNode(pc->node_mem);  if(!node) {    sprintf(pc->errmsg, "Insufficient memory to cache new directory.");    return 1;  };/* * Initialize the node. */  node->next = NULL;  node->relative = relative;  node->mem = relative ? pc->rel_mem : pc->abs_mem;  node->dir = NULL;  node->nfile = 0;  node->files = NULL;/* * Make a copy of the directory pathname. */  node->dir = _sg_store_string(pc->abs_mem->sg, dirname, 0);  if(!node->dir) {    strcpy(pc->errmsg, "Insufficient memory to store directory name.");    return 1;  };/* * Scan absolute directories for files of interest, recording their names * in node->mem->sg and appending pointers to these names to the * node->mem->files[] array. */  if(!node->relative) {    int nfile = node->nfile = pca_scan_dir(pc, node->dir, node->mem);    if(nfile < 1) {  /* No files matched or an error occurred */      node = (PathNode *) _del_FreeListNode(pc->node_mem, node);      return nfile < 0;    };  };/* * Append the new node to the list. */  if(pc->head) {    pc->tail->next = node;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -