📄 fileutil.c
字号:
processit = YES; break; } } } if(fstype && params->fstypes_to_skip && processit){ for(names = params->fstypes_to_skip; *names; names++){ if(!strcmp(*names, fstype)){ processit = NO; break; } } } if(processit && !(S_ISDIR(statb.st_mode) && (params->options & FIND_DEPTH))){ if( (ret = (*func)(filename, funcarg, &statb)) ) CLEANUP; } if(! S_ISDIR(statb.st_mode)){ ret = 0; CLEANUP; } if(excl_dirs){ for(i = 0, names = excl_dirs; *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_dirs_nodes[i].dev == statb.st_dev && excl_dirs_nodes[i].ino == statb.st_ino) break; } } if(*names){ ret = 0; CLEANUP; } } if(fstype && params->fstypes_to_prune){ for(names = params->fstypes_to_prune; *names; names++){ if(!strcmp(*names, fstype)){ ret = 0; CLEANUP; } } } dir = opendir(filename); if(!dir){ if(params->errfunc){ ret = (*params->errfunc)(filename, params->errfunc_param); } CLEANUP; } buf = NEWP(UChar, 1); if(!buf){ ret = ENOMEM; CLEANUP; } if(params->excl_filename){ excl_filename = strchain(filename, FN_DIRSEPSTR, params->excl_filename, NULL); if(!excl_filename){ ret = ENOMEM; CLEANUP; } if(!access(excl_filename, R_OK)){ FILE *fp; fp = fopen(excl_filename, "r"); while(!feof(fp)){ cptr = fget_alloc_str(fp); if(!cptr) break; massage_string(cptr); if(num_local_excl_files) local_excl_files = RENEWP(local_excl_files, UChar *, num_local_excl_files + 1); else local_excl_files = NEWP(UChar *, 1); local_excl_files[num_local_excl_files++] = cptr; } fclose(fp); } free(excl_filename); } forever{ entry = readdir(dir); if(! entry) break; cptr = (UChar *) &(entry->d_name[0]); if(!strcmp(cptr, FN_CURDIR) || !strcmp(cptr, FN_PARENTDIR)) continue; if(local_excl_files){ for(i = 0; i < num_local_excl_files; i++){ if(!fn_match(local_excl_files[i], cptr, 0)) break; } if(i < num_local_excl_files) continue; } buf = RENEWP(buf, UChar, strlen(filename) + strlen(cptr) + 2); if(!buf){ ret = ENOMEM; CLEANUP; } sprintf(buf, "%s%c%s", filename, FN_DIRSEPCHR, cptr); if( (ret = real_find1(buf, params, func, funcarg, device, have_device, excl_dirs_names, excl_dirs_nodes, excl_files_names, excl_files_nodes)) ){ CLEANUP; } } if(processit && S_ISDIR(statb.st_mode) && (params->options & FIND_DEPTH)){ if( (ret = (*func)(filename, funcarg, &statb)) ) CLEANUP; } cleanup: if(params->interrupted) if(*params->interrupted) ret = 128; if(buf) free(buf); if(dir) closedir(dir); if(filename) free(filename); if(local_excl_files){ for(i = 0; i < num_local_excl_files; i++) ZFREE(local_excl_files[i]); free(local_excl_files); } return(ret);}Int32find1( UChar *filename, FindParams *params, Int32 (*func)(UChar *, void *, struct stat *), void *funcarg){ UChar **excl_dirs_names = NULL; FindFileNode *excl_dirs_nodes = NULL; UChar **excl_files_names = NULL; FindFileNode *excl_files_nodes = NULL; UChar **cpptr; Int32 i, n, r; Flag use_ino_inf; struct stat statb; if(params->excl_dirs){ /* for the dirs to excl containing slashes ... */ for(n = 0, cpptr = params->excl_dirs; *cpptr; cpptr++, n++); if(n > 0){ excl_dirs_names = NEWP(UChar *, n + 1); if(!excl_dirs_names) CLEANUPR(-2); memset(excl_dirs_names, 0, (n + 1) * sizeof(UChar *)); excl_dirs_nodes = NEWP(FindFileNode, n); if(!excl_dirs_nodes) CLEANUPR(-3); memset(excl_dirs_nodes, 0, n * sizeof(FindFileNode)); for(i = 0; i < n; i++){ /* ... use inode and device info for exclusion */ use_ino_inf = NO; if(FN_ISPATH(params->excl_dirs[i])){ if(!stat(params->excl_dirs[i], &statb)){ /* if we cannot stat, there */ excl_dirs_nodes[i].dev = statb.st_dev; /* is no need to really */ excl_dirs_nodes[i].ino = statb.st_ino; /* exclude -> leave as is */ use_ino_inf = YES; } } if(use_ino_inf) excl_dirs_names[i] = ""; /* empty string as marker */ else excl_dirs_names[i] = params->excl_dirs[i]; } } } if(params->excl_names){ /* for the files to excl containing slashes ... */ for(n = 0, cpptr = params->excl_names; *cpptr; cpptr++, n++); if(n > 0){ excl_files_names = NEWP(UChar *, n + 1); if(!excl_files_names) CLEANUPR(-2); memset(excl_files_names, 0, (n + 1) * sizeof(UChar *)); excl_files_nodes = NEWP(FindFileNode, n); if(!excl_files_nodes) CLEANUPR(-3); memset(excl_files_nodes, 0, n * sizeof(FindFileNode)); for(i = 0; i < n; i++){ /* ... use inode and device info for exclusion */ use_ino_inf = NO; if(FN_ISPATH(params->excl_names[i])){ if(!stat(params->excl_names[i], &statb)){ /* if we cannot stat, there */ excl_files_nodes[i].dev = statb.st_dev; /* is no need to really */ excl_files_nodes[i].ino = statb.st_ino; /* exclude -> leave as is */ use_ino_inf = YES; } } if(use_ino_inf) excl_files_names[i] = ""; /* empty string as marker */ else excl_files_names[i] = params->excl_names[i]; } } } r = real_find1(filename, params, func, funcarg, (dev_t) 0, NO, excl_dirs_names, excl_dirs_nodes, excl_files_names, excl_files_nodes); cleanup: ZFREE(excl_dirs_names); ZFREE(excl_dirs_nodes); ZFREE(excl_files_names); ZFREE(excl_files_nodes); return(r);}UChar **fnglob1(UChar * namepat){ UChar **matches = NULL, **m, *cptr; UChar *buf = NULL; DIR *dir = NULL; UChar *dirname = NULL; struct dirent *entry; Int32 num_matches; if(!namepat){ errno = EINVAL; return(NULL); } namepat = strdup(namepat); if(!namepat) return(NULL); cleanpath(namepat); if(FN_ISROOTDIR(namepat)){ matches = NEWP(UChar *, 2); if(!matches) return(NULL); matches[0] = strdup(namepat); if(!matches[0]) GETOUT; matches[1] = NULL; return(matches); } if(FN_ISPATH(namepat)){ dirname = strdup(namepat); if(!dirname) return(NULL); cptr = FN_LASTDIRDELIM(dirname); if(cptr){ if(cptr > dirname) *cptr = '\0'; else dirname[1] = '\0'; } dir = opendir(dirname); } else{ dir = opendir(FN_CURDIR); } if( (matches = NEWP(UChar *, 1)) ) *matches = NULL; if(!dir) CLEANUP; buf = strdup(""); if(!buf || !matches) GETOUT; num_matches = 0; forever{ entry = readdir(dir); if(! entry) break; cptr = (UChar *) &(entry->d_name[0]); if((!strcmp(cptr, FN_CURDIR) || !strcmp(cptr, FN_PARENTDIR)) && strcmp(cptr, FN_BASENAME(namepat))) continue; buf = RENEWP(buf, UChar, (dirname ? strlen(dirname) : 0) + strlen(cptr) + 2); if(!buf) GETOUT; if(dirname){ sprintf(buf, "%s%c%s", dirname, FN_DIRSEPCHR, cptr); } else{ strcpy(buf, cptr); } cleanpath(buf); if(!fn_match(namepat, buf, GFNM_PATHNAME)){ matches = RENEWP(matches, UChar *, num_matches + 2); if(!matches) GETOUT; matches[num_matches] = strdup(buf); if(!matches[num_matches]) GETOUT; num_matches++; matches[num_matches] = NULL; } } cleanup: if(buf) free(buf); if(dirname) free(dirname); if(namepat) free(namepat); if(dir) closedir(dir); return(matches); getout: if(matches){ for(m = matches; *m; m++) free(*m); free(matches); } matches = NULL; CLEANUP;}UChar **fnglob(UChar * namepat){ UChar **uppermatches = NULL, **matches = NULL, **m; UChar **newmatches = NULL, **mi; UChar *buf = NULL, *bname = NULL, *cptr; Int32 i, j; if(FN_ISROOTDIR(namepat) || ! FN_ISPATH(namepat)) return(fnglob1(namepat)); buf = strdup(""); namepat = strdup(namepat); if(!namepat || !buf) GETOUT; cleanpath(namepat); bname = strdup(FN_BASENAME(namepat)); if(!bname) GETOUT; cptr = FN_LASTDIRDELIM(namepat); if(cptr){ if(cptr > namepat) *cptr = '\0'; else namepat[1] = '\0'; } uppermatches = fnglob(namepat); if(!uppermatches) GETOUT; matches = NEWP(UChar *, 1); if(!matches) GETOUT; *matches = NULL; for(m = uppermatches; *m; m++){ buf = RENEWP(buf, UChar, strlen(*m) + strlen(bname) + 2); if(!buf) GETOUT; sprintf(buf, "%s%c%s", *m, FN_DIRSEPCHR, bname); newmatches = fnglob1(buf); if(!newmatches) GETOUT; for(mi = matches, i = 0; *mi; mi++, i++); for(mi = newmatches, j = 0; *mi; mi++, j++); matches = RENEWP(matches, UChar *, i + j + 1); if(!matches) GETOUT; memcpy(matches + i, newmatches, j * sizeof(UChar *)); matches[i + j] = NULL; free(newmatches); newmatches = NULL; } cleanup: if(uppermatches){ for(m = uppermatches; *m; m++) free(*m); free(uppermatches); } if(buf) free(buf); if(bname) free(bname); if(namepat) free(namepat); return(matches); getout: if(matches){ for(m = matches; *m; m++) free(*m); free(matches); } if(newmatches){ for(m = newmatches; *m; m++) free(*m); free(newmatches); } matches = NULL; CLEANUP;}Int32find( UChar **filenames, FindParams *params, Int32 (*func)(UChar *, void *, struct stat *), void *funcarg){ UChar **matches = NULL, **m, **fn; Int32 ret = 0; if(!filenames){ return(errno = EINVAL); } for(fn = filenames; *fn; fn++){ matches = fnglob(*fn); if(!matches){ ret = errno; CLEANUP; } for(m = matches; *m; m++){ if( (ret = find1(*m, params, func, funcarg)) ) CLEANUP; } for(m = matches; *m; m++) free(*m); free(matches); matches = NULL; } cleanup: if(matches){ for(m = matches; *m; m++) free(*m); free(matches); } return(ret);}/* copies srcfile to destfile. Permissions are preserved. * * returns 0 on success, otherwise errno i.e. a value != 0 */Int32copy_file(UChar * srcfile, UChar * destfile){ int infd, outfd, i; UChar buf[BUFSIZ]; struct stat statb; Int32 ret = 0; if(stat(srcfile, &statb)) return(errno); infd = open(srcfile, O_RDONLY); if(infd < 0) return(errno); unlink(destfile); outfd = open(destfile, O_WRONLY | O_BINARY | O_CREAT | O_EXCL | O_TRUNC, 0600); if(outfd < 0){ close(infd); return(errno); } while((i = read(infd, buf, BUFSIZ)) > 0){ if(write_forced(outfd, buf, i) < i){ ret = errno; break; } } close(outfd); close(infd); if(chmod(destfile, statb.st_mode)){ if(!ret) ret = errno; } if(ret) unlink(destfile); return(ret);}/* sets a write lock on the (entire) file with the given name * and returns the filedescriptor to the open file. On failure * a value < 0 is returned */static intset_lock(UChar * name, int filemode, int lockmode){ int fd, i; struct flock lockb; fd = open(name, filemode, 0600); if(fd < 0) return(fd); SETZERO(lockb); lockb.l_type = lockmode; i = fcntl(fd, F_SETLK, &lockb); if(i < 0) close(fd); return(i < 0 ? i : fd);}intset_wlock(UChar * name){ return(set_lock(name, O_WRONLY | O_CREAT, F_WRLCK));}intset_rlock(UChar * name){ return(set_lock(name, O_RDONLY, F_RDLCK));}/* given the name of a file, probably a complete path to a file * (i.e. not only the 'basename'), a filename with a leading dot * . is produced, memory malloc'ed for it and the pointer to it * returned. On failure NULL is returned * * example: /path/to/file results in /path/to/.file */UChar *hidden_filename(UChar * filename){ UChar *new_name, *cptr; new_name = NEWP(UChar, strlen(filename) + 2); if(!new_name) return(NULL); strcpy(new_name, filename); cptr = FN_LASTDIRDELIM(new_name); if(cptr) cptr++; else cptr = new_name; memmove(cptr + 1, cptr, (strlen(cptr) + 1) * sizeof(UChar)); *cptr = '.'; return(new_name);}#define cleanup_ret(n) { res = n; CLEANUP; }#define getout_ret(n) { res = n; GETOUT; }/* like mkdir -p <name> i.e. a complete directory path is created, * if not existing. If uid and/or gid is -1, owner/group remains * unchanged. mode is applied for permissions */Int32make_dirpath(UChar * name, Uns32 mode, uid_t uid, gid_t gid){ UChar *cptr, c; struct stat statb; Int32 res, i; res = 0; name = strdup(name); if(!name) return(-1); cleanpath(name); i = lstat(name, &statb); if(!i){ if(!S_ISDIR(statb.st_mode)){ errno = EEXIST; cleanup_ret(-1); } cleanup_ret(0); } if(i < 0){ cptr = FN_LASTDIRDELIM(name); if(cptr){ if(cptr > name){ c = *cptr; *cptr = '\0'; i = make_dirpath(name, mode, uid, gid); if(i < 0) /* if only chown failed, continue making path */ cleanup_ret(-errno); *cptr = c; } } i = mkdir(name, mode); if(i && errno != EEXIST) cleanup_ret(-errno); if(!i && (uid != (uid_t) -1 || gid != (gid_t) -1)) if(chown(name, uid, gid)) cleanup_ret(1); /* return positive on non-fatal chown */ } cleanup: free(name); return(res);}static Int32kfile_proc(UChar * filen, UChar * key, UChar * value, Uns32 flags, Flag insert){ FILE *rfp = NULL, *wfp = NULL; UChar *line = NULL, *tkey = NULL, *nfilen = NULL; Int32 i, res = 0; int i1, i2, lockfd; Flag file_existed = NO, sorted_by_n; struct stat statb; i = access(filen, F_OK); if(!i){ if(access(filen, R_OK)) return(-1); if(stat(filen, &statb) < 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -