📄 fileutil.c
字号:
{ UChar *line = NULL; UChar *next_line = NULL; UChar *cptr; Int32 len, oldlen; line = fget_alloc_str(fp); if(!line) return(NULL); oldlen = strlen(line) + 1; cptr = first_nospace(line); if(*cptr == '#') *cptr = '\0'; len = strlen(line); if(line[len - 1] == '\n'){ len--; line[len] = '\0'; } while(line[len - 1] == '\\'){ line[len - 1] = '\0'; next_line = fget_alloc_str(fp); /* returns seg_alloc aligned ptr */ if(!next_line) return(line); line = seg_realloc(line, sizeof(UChar) * (len + 1 + strlen(next_line)), oldlen); oldlen = sizeof(UChar) * (len + 1 + strlen(next_line)); if(!line) GETOUT; strcpy(line + len - 1, next_line); free(next_line); cptr = strchr(line, '#'); if(cptr) *cptr = '\0'; len = strlen(line); if(line[len - 1] == '\n'){ len--; line[len] = '\0'; } } return(line); getout: if(line) free(line); if(next_line) free(next_line); return(NULL);}static Int32allocate_re_buffers(Int32 new_num_buffers){ if(new_num_buffers <= num_re_buffers) return(0); re_buffers = ZRENEWP(re_buffers, RE_cmp_buffer, new_num_buffers); if(!re_buffers){ num_re_buffers = 0; return(errno); } memset(re_buffers + num_re_buffers, 0, sizeof(RE_cmp_buffer) * (new_num_buffers - num_re_buffers)); num_re_buffers = new_num_buffers; return(NO_ERROR);}/* * find_program * * Given a program name, returns the pathname to that program. * * If argv0 contains a directory separator character ('/', in UNIX parlance), * returns a malloc'd copy of argv0. In this case, no check for existence * is done. * * If argv0 does not contain a directory separator character, then the * directories specified by the "PATH" environment variable are searched. * If argv0 is found there and is executable, then the malloc'd pathname * is returned. * * Returns NULL if the program is not found or if an error occurs (such as * a malloc error). * * Note that in the pathological case of passing in the empty string, a * string containing the root directory will be returned. */UChar *find_program(UChar * argv0){ UChar *largv0 = NULL, *lpath = NULL, *ret = NULL, *cptr, *next; if(FN_ISPATH(argv0)) return((UChar *) strdup(argv0)); largv0 = (UChar *) strdup(argv0); if(!largv0) CLEANUP; lpath = getenv("PATH"); if(!lpath) CLEANUP; lpath = (UChar *) strdup(lpath); if(!lpath) CLEANUP; ret = NEWP(UChar, strlen(argv0) + strlen(lpath) + 2); if(!ret) CLEANUP; cptr = lpath; forever{ next = (UChar *) strchr(cptr, ENV_PATHSEPCHR); if(next) *next = '\0'; strcpy(ret, cptr); strcat(ret, FN_DIRSEPSTR); strcat(ret, argv0); if(!access(ret, X_OK)) CLEANUP; if(!next) break; cptr = next + 1; } free(ret); ret = NULL; cleanup: if(largv0) free(largv0); if(lpath) free(lpath); return(ret);}/* * Checks the list {cmd1, ...} to ensure that all arguments are executable * commands. The command could be either a fully qualified pathname, or * just a basename if the command exists in the PATH environment variable. * * If all commands are executable and are regular files (no symlinks!), * then this function returns NULL. If any of the commands are not * executable (or not regular files), then a pointer to a malloc'd copy * of the offending command is returned. * * Note that under some rare circumstances, the returned string may be from * the data segment rather than from the heap, so it's best not to free it. * This can be determined from the first character. If this is '<', then * malloc did not succeed and the string must not be freed */UChar *check_commands_executable(Flag empty_is_ok, UChar * cmd1, ...){ UChar *cmd, *argv0, *prog = NULL, *r = NULL; struct stat statb; va_list args; va_start(args, cmd1); for(cmd = cmd1; cmd; cmd = va_arg(args, UChar *)){ if(empty_is_ok && word_count(cmd) < 1) continue; argv0 = strwordq(cmd, 0); if(!argv0){ r = strdup(cmd); if(!r) r = "<Error: Cannot allocate memory for filename>"; else if(r[0] == '<') r[0] = '['; CLEANUP; } prog = find_program(argv0); if(!prog) CLEANUPR(argv0); if(access(prog, X_OK)) CLEANUPR(argv0); if(stat(prog, &statb) < 0) CLEANUPR(argv0); if(!S_ISREG(statb.st_mode)) CLEANUPR(argv0); free(argv0); ZFREE(prog); } cleanup: va_end(args); ZFREE(prog); return(r);}/* * eliminate superfluous character sequences from the given * path, e.g. a trailing /. , a leading ./ , /./ or other stuff * * the result might be called somewhat 'normalized' or 'unified' */Int32cleanpath(UChar * path){ UChar *cptr1, *cptr2, modified; if(!path){ errno = EINVAL; return(errno); } if(!(*path)) return(0); do{ modified = 0; if(FN_TRAILINGDUMMY(path)){ *(FN_LASTDIRDELIM(path) + 1) = '\0'; modified = 1; } cptr1 = path + strlen(path) - 1; while(FN_ISDIRSEP(*cptr1) && ! FN_ISROOTDIR(path)){ *(cptr1--) = '\0'; modified = 1; } } while(modified); while( (cptr1 = FN_STRDBLDIRSEP(path)) ){ cptr1++; cptr2 = cptr1 + 1; while(FN_ISDIRSEP(*cptr2)) cptr2++; while(*cptr2) *(cptr1++) = *(cptr2++); *cptr1 = '\0'; } while( (cptr1 = FN_STREMPTYDIRSEP(path)) ){ cptr1++; cptr2 = cptr1 + 2; while(*cptr2) *(cptr1++) = *(cptr2++); *cptr1 = '\0'; } if(FN_LEADINGDUMMY(path)){ cptr1 = path; cptr2 = path + 2; while(*cptr2) *(cptr1++) = *(cptr2++); *cptr1 = '\0'; } return(0);}/* * like cleanpath, but also eliminates sequences like * /subdir/../ */Int32cleanpath__(UChar * path){ UChar *cptr1, *cptr2, *cptr3, *orgpath; UChar updir[10], dirup[10], rootdummy[10]; Int32 updirlen, diruplen, rootdummylen; cleanpath(path); strcpy(updir, FN_PARENTDIR FN_DIRSEPSTR); updirlen = strlen(updir); strcpy(dirup, FN_DIRSEPSTR FN_PARENTDIR); diruplen = strlen(dirup); strcpy(rootdummy, FN_DIRSEPSTR FN_PARENTDIR); rootdummylen = strlen(rootdummy); orgpath = path; forever{ while(!strncmp(path, updir, updirlen)) path += updirlen; while(!strncmp(path, rootdummy, rootdummylen) && (!path[rootdummylen] || FN_ISDIRSEP(path[rootdummylen]))){ cptr1 = path; cptr2 = cptr1 + rootdummylen; if(FN_ISDIRSEP(*cptr2)){ cptr1++; cptr2++; } while(*cptr2) *(cptr1++) = *(cptr2++); *cptr1 = '\0'; if(!*path){ path[0] = FN_DIRSEPCHR; path[1] = '\0'; GETOUT; } } if(FN_ISDIRSEP(*path)) path++; cptr1 = FN_FIRSTDIRSEP(path); if(!cptr1) GETOUT; cptr2 = cptr1 + 1 - updirlen; cptr3 = cptr1 + diruplen; if(!strncmp(cptr1, dirup, diruplen) && (!(*cptr3) || FN_ISDIRSEP(*cptr3)) && strncmp(cptr2, updir, updirlen)){ cptr2 = cptr1 + diruplen; if(FN_ISDIRSEP(*cptr2)) cptr2++; cptr1 = path; while(*cptr2) *(cptr1++) = *(cptr2++); *cptr1 = '\0'; path = orgpath; } else{ path = cptr1 + 1; } } getout: cleanpath(orgpath); return(0);}/* * makes a complete absolute path from the given path (if relative), * and the current working directory. If the given path is already * an absolute one, it is left unchanged. * * If retpath is non-NULL, the result is put there, otherwise memory * is malloc'ed for the result and the pointer returned. * * On error, NULL is returned */UChar *mkabspath(UChar * path, UChar * retpath){ UChar *curpath; if(FN_ISABSPATH(path)){ if(retpath){ strcpy(retpath, path); return(retpath); } else{ return(strdup(path)); } } if(FN_LEADINGDUMMY(path)) path += 2; curpath = getcwd(NULL, MAXPATHLEN); if(!curpath) return(NULL); if(retpath){ sprintf(retpath, "%s" FN_DIRSEPSTR "%s", curpath, path); } else{ retpath = strchain(curpath, FN_DIRSEPSTR, path, NULL); } free(curpath); return(retpath);}Int32mkrelpath(UChar * path){ UChar *cptr; if(!path) return(0); cleanpath(path); if(FN_ISABSPATH(path)){ for(cptr = FN_FIRSTDIRSEP(path); FN_ISDIRSEP(*cptr); cptr++); memmove(path, cptr, (strlen(cptr) + 1) * sizeof(UChar)); } return(0);}/* Function to resolve symbolic links from path, producing a new path * not containing any symbolic link any more. New path is stored in * retpath, if not NULL, otherwise malloced. Pointer to it returned. */UChar *resolve_path(UChar * path, UChar * retpath){ UChar *newpath, *cptr, *oldpath, *dirdelim; UChar linkpath[MAXPATHLEN + 1]; UChar c; /* uninitialized OK */ Int32 i; struct stat statb; path = strdup(path); if(!path) return(NULL); restart: cleanpath(path); oldpath = path; if(FN_ISABSPATH(oldpath)) oldpath = FN_FIRSTDIRSEP(oldpath) + 1; forever{ while(FN_ISDIRSEP(*oldpath)) oldpath++; if(!oldpath[0]) break; dirdelim = FN_FIRSTDIRSEP(oldpath); if(dirdelim){ c = *dirdelim; *dirdelim = '\0'; } if(lstat(path, &statb)) CLEANUP; if(S_ISLNK(statb.st_mode)){ i = readlink(path, linkpath, MAXPATHLEN); if(i < 0) CLEANUP; linkpath[i] = '\0'; cptr = dirdelim ? dirdelim + 1 : (UChar *) ""; if(FN_ISABSPATH(linkpath)){ newpath = strchain(linkpath, FN_DIRSEPSTR, cptr, NULL); } else{ *oldpath = '\0'; newpath = strchain(path, path[0] ? FN_DIRSEPSTR : "", linkpath, FN_DIRSEPSTR, cptr, NULL); } if(!newpath) CLEANUP; free(path); path = newpath; newpath = NULL; goto restart; } if(!dirdelim) break; *dirdelim = c; oldpath = dirdelim + 1; } if(retpath){ strcpy(retpath, path); return(retpath); } else return(path); cleanup: ZFREE(path); return(NULL);}/* Same as resolve_path, but furthermore removing ../ parts from * path, thus giving the true position of the given file in the * filesystem */UChar *resolve_path__(UChar * path, UChar * retpath){ UChar *newpath; newpath = resolve_path(path, retpath); if(!newpath) return(NULL); cleanpath__(newpath); return(newpath);}typedef struct __find_file_node__ { dev_t dev; ino_t ino;} FindFileNode;static Int32real_find1( UChar *filename, FindParams *params, Int32 (*func)(UChar *, void *, struct stat *), void *funcarg, dev_t device, Flag have_device, UChar **excl_dirs_names, FindFileNode *excl_dirs_nodes, UChar **excl_files_names, FindFileNode *excl_files_nodes){ FindParams lparams; DIR *dir = NULL; Int32 ret, i; UChar **files, **excl_files, **excl_dirs; UChar **local_excl_files = NULL; Uns32 num_local_excl_files = 0; UChar *excl_filename; Uns32 options; UChar *cptr, **names; UChar *buf = NULL; struct stat statb; struct dirent *entry; Flag processit; UChar *bname; UChar *fstype; if(!filename || !func) return(EINVAL); ret = 0; filename = strdup(filename); if(!filename) return(errno); cleanpath(filename); if(!params){ memset(&lparams, 0, sizeof(lparams)); params = &lparams; } excl_dirs = excl_dirs_names; excl_files = excl_files_names; files = params->names; options = params->options; if(options & FIND_FOLLOW_SLINKS){ if(stat(filename, &statb)){ if(params->errfunc){ ret = (*params->errfunc)(filename, params->errfunc_param); } CLEANUP; } } else{ if(lstat(filename, &statb)){ if(params->errfunc){ ret = (*params->errfunc)(filename, params->errfunc_param); } CLEANUP; } } if(!have_device && (options & FIND_LOCAL_DEV)){ have_device = YES; device = statb.st_dev; } if(S_ISLNK(statb.st_mode) && (options & FIND_NO_SLINKS)){ ret = 0; CLEANUP; } if(S_ISFIFO(statb.st_mode) && (options & FIND_NO_FIFOS)){ ret = 0; CLEANUP; } if(S_ISREG(statb.st_mode) && (options & FIND_NO_FILES)){ ret = 0; CLEANUP; } if(S_ISBLK(statb.st_mode) && (options & FIND_NO_BDEVS)){ ret = 0; CLEANUP; } if(S_ISCHR(statb.st_mode) && (options & FIND_NO_CDEVS)){ ret = 0; CLEANUP; } if(S_ISSOCK(statb.st_mode) && (options & FIND_NO_SOCKS)){ ret = 0; CLEANUP; } if((options & FIND_LOCAL_DEV) && have_device && device != statb.st_dev){ ret = 0; CLEANUP; } processit = YES; if(params->newer_than){ processit = NO; if(statb.st_mtime >= params->newer_than) processit = YES; if((options & FIND_CMP_CTIME) && statb.st_ctime >= params->newer_than) processit = YES; } if(params->older_than){ processit = NO; if(statb.st_mtime < params->older_than) processit = YES; if((options & FIND_CMP_CTIME) && statb.st_ctime < params->older_than) processit = YES; } bname = FN_BASENAME(filename); if(files && processit){ processit = NO; for(names = files; *names; names++){ if(FN_ISPATH(*names)){ if(!fn_match(*names, filename, 0)) break; } else{ if(!fn_match(*names, bname, GFNM_PATHNAME)) break; } } if(*names) processit = YES; } if(excl_files && processit){ for(i = 0, names = excl_files; *names; i++, names++){ if((*names)[0]){ /* use filename to match */ if(FN_ISPATH(*names)){ if(!fn_match(*names, filename, 0)) break; } else{ if(!fn_match(*names, bname, GFNM_PATHNAME)) break; } } else{ /* use inode and device info */ if(excl_files_nodes[i].dev == statb.st_dev && excl_files_nodes[i].ino == statb.st_ino) break; } } if(*names) processit = NO; } if(params->fstypes_to_search || params->fstypes_to_skip || params->fstypes_to_prune) fstype = get_fstype_by_devno_dir(statb.st_dev, filename); else fstype = NULL; if(fstype && params->fstypes_to_search && processit){ processit = NO; for(names = params->fstypes_to_search; *names; names++){ if(!strcmp(*names, fstype)){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -