📄 fileutil.c
字号:
return(-1); file_existed = YES; } lockfd = -1; if(flags & KFILE_LOCKED){ lockfd = set_wlock_forced(filen); if(lockfd < 0) cleanup_ret(-7); } if(!i){ rfp = fopen(filen, "r"); if(!rfp) return(-2); } nfilen = strapp(filen, ".tmp"); if(!nfilen) cleanup_ret(-3); unlink(nfilen); if(!access(nfilen, F_OK)) cleanup_ret(-4); wfp = fopen(nfilen, "w"); if(!wfp) cleanup_ret(-5); if(rfp){ if(flags & KFILE_SORTN) if(sscanf(key, "%d", &i1) < 1) i1 = MAXINT; while(!feof(rfp)){ ZFREE(line); line = fget_alloc_str(rfp); if(!line) continue; chop(line); tkey = ZRENEWP(tkey, UChar, strlen(line) + 1); if(!tkey) getout_ret(-8); sscanwordq(line, tkey); if(!strcmp(key, tkey)){ ZFREE(line); break; } sorted_by_n = NO; if(flags & KFILE_SORTN){ if(sscanf(line, "%d", &i2) < 1) i2 = -2; else sorted_by_n = YES; if(i2 >= i1) break; } if((flags & KFILE_SORT) && !sorted_by_n){ i = strcmp(tkey, key); if(i >= 0) break; } fprintf(wfp, "%s\n", line); } } if(insert){ fprintwordq(wfp, key); fprintf(wfp, " %s\n", value); } if(rfp){ if(line) fprintf(wfp, "%s\n", line); while(!feof(rfp)){ ZFREE(line); line = fget_alloc_str(rfp); if(!line) continue; chop(line); tkey = ZRENEWP(tkey, UChar, strlen(line) + 1); if(!tkey) getout_ret(-9); sscanwordq(line, tkey); if(strcmp(tkey, key)) fprintf(wfp, "%s\n", line); } } fclose(wfp); wfp = NULL; if(file_existed){ chown(nfilen, statb.st_uid, statb.st_gid); chmod(nfilen, statb.st_mode); } if(rename(nfilen, filen)) getout_ret(-6); if(lockfd >= 0) close(lockfd); cleanup: ZFREE(tkey); ZFREE(nfilen); ZFREE(line); if(rfp) fclose(rfp); if(wfp) fclose(wfp); return(res); getout: if(nfilen) unlink(nfilen); CLEANUP;}/* * Opens the file <filen>, searches for a key <key> as the word or (if * containing whitespace) string in double quotes in the first column of * a line, and replaces the key's value (i.e. the rest of the line) with * the string passed in value. If the <key> has not been found, a new * line is created for the new <key> <value> pair. If KFILE_SORT is set * in <flags>, the lines in the file are sorted in ASCII order of the * <key> fields. If KFILE_SORTN is set, it is attempted to interpret the * <key> fields as numerical values and to sort the lines accordingly. * If both are set, sorting by numerical value has higher priority than * sorting by ASCII. If KFILE_LOCKED is set in <flags>, then the file is * locked before modifying it. * If <filen> does not exist, it is created. * * Returns NULL on error. */Int32kfile_insert(UChar * filen, UChar * key, UChar * value, Uns32 flags){ return(kfile_proc(filen, key, value, flags, YES));}/* * Opens the file <filen>, searches for a key <key> as the word or (if * containing whitespace) string in double quotes in the first column of * a line, and removes this line from the file. If KFILE_LOCKED is set in * <flags>, then the file is locked before modifying it. */Int32kfile_delete(UChar * filen, UChar * key, Uns32 flags){ return(kfile_proc(filen, key, "", flags, NO));}/* * Opens the file <filen>, searches for a key <key> as the word or (if * containing whitespace) string in double quotes in the first column of * a line, and returns a malloc'd string containing the key's value (i.e. * the rest of the line). If KFILE_LOCKED is set in <flags>, then the file * is locked before reading it. * * Returns NULL on error or if no line starting with <key> is found. * * kfile_get does not make assumptions on the file being sorted */UChar *kfile_get(UChar * filen, UChar * key, Uns32 flags){ UChar *fval = NULL, *line = NULL, *tkey = NULL, *cptr; FILE *fp; int lockfd; /* make sure the file exists and we can read it */ if(access(filen, F_OK)) return(NULL); /* we cannot do the access(..., F_OK | R_OK) as documented, but must * do it in two steps, because F_OK is usually defined as 0, so in * fact this form would be the same like access(..., R_OK) :-( */ if(access(filen, R_OK)){ return(NULL); } lockfd = -1; if(flags & KFILE_LOCKED){ lockfd = set_wlock_forced(filen); if(lockfd < 0) return(NULL); } fp = fopen(filen, "r"); if(!fp) return(NULL); while(!feof(fp)){ ZFREE(line); line = fget_alloc_str(fp); if(!line) continue; chop(line); tkey = ZRENEWP(tkey, UChar, strlen(line) + 1); if(!tkey) GETOUT; cptr = sscanwordq(line, tkey); if(cptr){ if(!strcmp(key, tkey)){ if(*(cptr - 1) == ' '){ strcpy(tkey, cptr); tkey = RENEWP(tkey, UChar, strlen(tkey) + 1); fval = tkey; tkey = NULL; CLEANUP; } } } } cleanup: if(fp) fclose(fp); if(lockfd >= 0) close(lockfd); ZFREE(tkey); ZFREE(line); return(fval); getout: ZFREE(fval); CLEANUP;}KeyValuePair *kfile_getall(UChar * filename, Int32 * num, Uns32 flags){ KeyValuePair *all_pairs = NULL; UChar **lines, **cpptr, *line, *cptr; Int32 i, n, num_lines; int lockfd; /* uninitialized ok */ if(flags & KFILE_LOCKED){ lockfd = set_wlock_forced(filename); if(lockfd < 0) return(NULL); } lines = read_asc_file(filename, &num_lines); if(flags & KFILE_LOCKED) close(lockfd); if(!lines){ if(num) *num = 0; return(NULL); } n = 0; for(cpptr = lines; *cpptr; cpptr++){ line = *cpptr; if(word_count(line) > 0){ all_pairs = ZRENEWP(all_pairs, KeyValuePair, n + 2); if(!all_pairs) GETOUT; memset(all_pairs + n, 0, 2 * sizeof(KeyValuePair)); if(!(cptr = all_pairs[n].key = strwordq(line, 0))) GETOUT; cptr = sscanwordq(line, NULL); if(*cptr && isspace(*cptr)) cptr++; if(!(all_pairs[n].value = strdup(cptr))) GETOUT; n++; } } if(num) *num = n; cleanup: free_asc_file(lines, 0); return(all_pairs); getout: for(i = 0; i < n; i++){ ZFREE(all_pairs[i].key); ZFREE(all_pairs[i].value); } ZFREE(all_pairs); CLEANUP;}voidkfile_freeall(KeyValuePair * kvs, Int32 num){ Int32 i; if(!kvs) return; for(i = 0; num < 1 || i < num; i++){ if(num < 1 && !kvs[i].key && !kvs[i].value) break; ZFREE(kvs[i].key); ZFREE(kvs[i].value); } free(kvs);}Int32add_to_int_list_file(UChar * filename, Int32 val){ UChar nbuf[32]; sprintf(nbuf, "%d", (int) val); return(kfile_insert(filename, nbuf, "", KFILE_SORTN | KFILE_LOCKED));}Int32 *get_list_from_int_list_file(UChar * filename, Int32 * rnum){ KeyValuePair *values; Int32 i, num_vals, *intvals; int i1; values = kfile_getall(filename, &num_vals, 0); if(!values) return(NULL); intvals = NEWP(Int32, num_vals); if(!intvals) CLEANUP; for(i = 0; i < num_vals; i++){ intvals[i] = 0; if(sscanf(values[i].key, "%d", &i1) > 0) intvals[i] = i1; } if(rnum) *rnum = num_vals; cleanup: kfile_freeall(values, num_vals); return(intvals);}UChar *tmp_name(UChar * base){ static Int32 count = 0; UChar *tmpdir = NULL, *cptr; Int32 pid, i, n, tc; time_t t1, t2, t3; struct timeval tv1, tv2, *tv; if(!base) base = FN_TMPDIR FN_DIRSEPSTR; tmpdir = NEWP(UChar, strlen(base) + 100); if(!tmpdir) CLEANUP; do{ tc = count; /* to be multithreading-safe */ count++; }while(count != tc + 1); do{ strcpy(tmpdir, base); n = strlen(tmpdir); if(n > 0){ if(!strchr("_.-", tmpdir[n - 1])) strcat(tmpdir, "_"); } cptr = tmpdir + strlen(tmpdir); do{ t1 = time(NULL); gettimeofday(&tv1, NULL); t2 = time(NULL); gettimeofday(&tv2, NULL); t3 = time(NULL); }while(t1 != t2 && t2 != t3); tv = &tv1; if(t2 == t3){ t1 = t2; tv = &tv2; } pid = getpid(); /* to be unique in this millisecond */ while(pid > 0){ *(cptr++) = char64((Int32) (pid & 63)); pid >>= 6; } *(cptr++) = '_'; /* to be more unique and in this process */ i = (Int32) (drandom() * 65536) | (tc << 16); while(i > 0){ *(cptr++) = char64((Int32) (i & 63)); i >>= 6; } *(cptr++) = '_'; /* to be unique in seconds */ while(t1 > 0){ *(cptr++) = char64((Int32) (t1 & 63)); t1 >>= 6; } *(cptr++) = '_'; while(tv->tv_usec > 0){ /* to be unique within this second */ *(cptr++) = char64((Int32) (tv->tv_usec & 63)); tv->tv_usec >>= 6; } *cptr = '\0'; }while(!access(tmpdir, F_OK)); tmpdir = RENEWP(tmpdir, UChar, strlen(tmpdir) + 1); cleanup: return(tmpdir);}inttmp_file(UChar * base){ UChar *tmpn; int fd = -1; do{ tmpn = tmp_name(base); if(!tmpn) return(-1); fd = open(tmpn, O_RDWR | O_CREAT | O_EXCL, 0600); unlink(tmpn); free(tmpn); }while(fd < 0); return(fd);}FILE *tmp_fp(UChar * base){ int fd; fd = tmp_file(base); if(fd < 0) return(NULL); return(fdopen(fd, "r+"));}/* returns 0 on success; 1, if chuid/chgid failed; < 0, if mkdir failed */Int32mkbasedir(UChar * name, mode_t mode, uid_t uid, gid_t gid){ UChar *cptr; struct stat statb; Int32 r, i; name = strdup(name); if(!name) return(-1); cleanpath(name); r = 0; cptr = FN_LASTDIRDELIM(name); if(cptr){ if(cptr == name) CLEANUPR(0); *cptr = '\0'; i = stat(name, &statb); if(!i){ if(!S_ISDIR(statb.st_mode)){ errno = EEXIST; CLEANUPR(-1); } } if(i < 0){ if( (r = mkbasedir(name, mode, uid, gid)) < 0){ *cptr = FN_DIRSEPCHR; CLEANUPR(r); } r = mkdir(name, mode); if(r){ *cptr = FN_DIRSEPCHR; CLEANUPR(-errno); } if(uid != (uid_t) -1 || gid != (gid_t) -1){ if(chown(name, uid, gid)){ *cptr = FN_DIRSEPCHR; r = 1; } } } *cptr = FN_DIRSEPCHR; } cleanup: free(name); return(r);}Int32mkdirpath(UChar * name, mode_t mode, uid_t uid, gid_t gid){ Int32 i; name = strapp(name, FN_DIRSEPSTR "a"); if(!name) return(-1); i = mkbasedir(name, mode, uid, gid); free(name); return(i);}Int32perms_from_string(UChar * string, mode_t * rperms){ UChar *locstr = NULL, *cptr; Int32 r = 0; mode_t perms = 0; int i1, n1, whomap; if(!(locstr = strdup(string))) CLEANUP; for(cptr = locstr; *cptr; cptr++){ if(isspace(*cptr)){ memmove(cptr, cptr + 1, strlen(cptr)); cptr--; } } i1 = n1 = -1; sscanf(locstr, "%o%n", &i1, &n1); if(n1 == strlen(locstr)){ perms = i1; } else{ perms = 0; for(cptr = locstr; *cptr; cptr++){ if(*cptr == ',') continue; whomap = 0; if(!strchr("ugoa-=", *cptr)) CLEANUPR(-1); while(*cptr && strchr("ugoa-", *cptr)){ switch(*cptr){ case 'u': whomap |= 04700; break; case 'g': whomap |= 02070; break; case 'o': whomap |= 01007; break; case 'a': whomap |= 07777; break; } cptr++; } if(*cptr == ',') continue; if(*cptr != '=') CLEANUPR(-2); cptr++; if(*cptr == ',') continue; if(!strchr("rwxst-", *cptr)) CLEANUPR(-3); while(*cptr && strchr("rwxst-", *cptr)){ switch(*cptr){ case 'r': perms |= (whomap & 0444); break; case 'w': perms |= (whomap & 0222); break; case 'x': perms |= (whomap & 0111); break; case 't': perms |= 01000; break; case 's': perms |= (whomap & 06000); break; } cptr++; } if(*cptr && *cptr != ',') CLEANUPR(-1); } } if(rperms) *rperms = perms; cleanup: ZFREE(locstr); return(r);}static Int32close_fd(Int32 fd, void * data){ close((int) fd); return(0);}voidclose_fd_ranges(Uns32Range * fds){ foreach_Uns32Ranges(fds, close_fd, NULL);}Int32pipethrough(int infd, int outfd){ int ifd, ofd, pid, n; UChar buf[8192]; ifd = ABS(infd); ofd = ABS(outfd); pid = fork_forced(); if(pid < 0) return(-1); if(pid == 0){ chdir("/"); setsid(); detach_from_tty(); do{ n = read(ifd, buf, 8192); if(n > 0 && infd != outfd) write(ofd, buf, n); }while(n > 0); exit(0); } if(infd < 0) close(ifd); if(outfd < 0) close(ofd); return(0); }/************ end of $RCSfile: fileutil.c,v $ ******************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -