📄 filetype.c
字号:
/* * filetype.c * * Copyright (C) 1993 Alain Knaff */#define _LARGEFILE64_SOURCE#define _GNU_SOURCE#include "sysincludes.h"static int is_initialised=0;static FilenameActions *filenameActions;static char *default_uncompressor[]= { UNCOMPR, 0 };#ifndef SECURITYstatic char *custom_uncompressor[]= { 0, 0 };#endifchar *zlib_ext;int zlib_extlen;int zlib_mode;char *zlib_tmp;char **zlib_uncompressor;#define ENV_PREFIX "LD_ZLIB_"/** * Remove LD_PRELOAD=uncompress.o from environment in case CM_DISAB_CHILDREN * is set * We cannot use putenv or setenv here, because they work on a copy of the * environment, which will be overwritten between the time this _init is * called, and main is called */static void remove_ld_preload() { if(zlib_mode & CM_DISAB_CHILD) { char preload_name[]="LD_PRELOAD="; char *uncompr = "/uncompress.o"; int i; for(i=0; environ[i]; i++) { if(!strncmp(environ[i], preload_name, sizeof(preload_name)-1)) { /* strip out all items contains "uncompress.o" from LD_PRELOAD var */ char *rptr = environ[i] + sizeof(preload_name) - 1; char *lastbegin=rptr; char *wptr = rptr; int comp=1; int atbegin=1; lastbegin = wptr; while(1) { if(*rptr == ':') { if(uncompr[comp] == '\0') { wptr = lastbegin; if(atbegin) { rptr++; comp=1; continue; } } comp = 1; lastbegin = wptr; atbegin=0; } else if(*rptr == '\0') { if(uncompr[comp] == '\0') { wptr = lastbegin; } *wptr='\0'; break; } else if(*rptr == uncompr[comp]) { comp++; } else { comp=0; } *wptr++=*rptr++; } } } }}static char *mode_table[] = { "DISABLE", "READDIR_COMPR", "VERBOSE", "UNLINK", "NOCONF"};void zlib_initialise(void){ int modemask; int olderrno;#ifndef SECURITY int i; char env_buffer[1024]; char *value;#endif olderrno = errno; if ( !is_initialised ){ CommandActions *cma;#ifdef HAVE_PROC char cmdline[1025]; int fd,n;#else char *cmdline;#endif char *progname=0; zlib_mode = modemask = 0; zlib_ext = EXT; zlib_extlen = strlen(zlib_ext); zlib_uncompressor = default_uncompressor; zlib_tmp = TMP;#ifndef SECURITY if (getuid() == geteuid() || getgid() == getegid()){ zlib_tmp = getenv("LD_ZLIB_TMP"); if ( zlib_tmp == 0 ) zlib_tmp = TMP; zlib_ext= getenv("LD_ZLIB_EXT"); if ( zlib_ext == 0 ) zlib_ext = EXT; zlib_extlen = strlen(zlib_ext); if ( zlib_extlen > MAXEXTLEN ){ fprintf(stderr,"extension too long, taking default\n"); zlib_ext = EXT; } custom_uncompressor[0] = getenv("LD_ZLIB_UNCOMPRESSOR"); if ( custom_uncompressor[0] ){ zlib_uncompressor = custom_uncompressor; } else zlib_uncompressor = default_uncompressor; strcpy(env_buffer, ENV_PREFIX); for ( i=0; i< ( sizeof(mode_table) / sizeof(char *) ); i++){ strcpy( env_buffer+(sizeof( ENV_PREFIX ) - 1 ), mode_table[i] ); if ( (value=getenv ( env_buffer )) ){ if ( ( strcmp( value, "on" ) == 0 ) || ( strcmp( value, "1" ) == 0 )){ zlib_mode |= ( 1 << ( i + 1 )); }else if ( ( strcmp( value, "off" ) ) && ( strcmp( value, "0" ) )) continue; modemask |= ( 1 << ( i + 1 )); } } if ( zlib_mode & CM_DISAB){ is_initialised = 2; errno = olderrno; return; } }#endif#ifdef HAVE_PROC /* get command line */ strcpy(cmdline, "unknown"); fd=syscall(SYS_open,"/proc/self/cmdline", O_RDONLY); if ( fd > 0 ){ cmdline[1024]='\0'; n = read( fd, cmdline,1024 ); if ( n < 1 ) cmdline[0] = '\0'; else cmdline[n] = '\0'; close(fd); }#else /* where does the command line live on a sun ? */ /* horrible undocumented kludge... This might even work on a proc-less * linux*/ do { extern char **environ; int zerosfound; if ( environ == 0 ){ cmdline=""; break; } cmdline = *environ; if ( cmdline == 0 ){ cmdline=""; break; } zerosfound = 0; while(zerosfound < 2 ){ cmdline--; if ( *cmdline == 0 ) zerosfound++; else zerosfound = 0; } cmdline +=2; } while(0);#endif progname = strrchr(cmdline, '/' ); if ( !progname ) progname = cmdline; else progname++; if ( zlib_mode & CM_VERBOSE) fprintf(stderr,"progname = %s\n",progname); is_initialised = 1; /* get user configuration */#ifndef NO_RT_CONF if ( ! ( zlib_mode & CM_NORTCONF ) ) zlib_getuserconf(progname, &filenameActions, &zlib_mode, &modemask);#endif if ( modemask != CM_ALL_MODES ){ /* if we couldn't get the user configuration, use compiled in defaults */ cma = zlib_commandActions; while ( cma->name && strcmp(cma->name, progname ) ) cma++; if ( ( modemask & CM_HAVE_FA ) == 0 ) filenameActions = cma->actions; zlib_mode |= ( cma->cm_type & ~modemask); } remove_ld_preload(); is_initialised = 2; /* initialisation completely done */ } errno = olderrno;}#ifdef __ELF__#ifdef RTLD_NEXTint (*zlib_real_access)(const char *, int);int (*zlib_real_chmod) (const char *, mode_t);int (*zlib_real_chown) (const char *, uid_t, gid_t);int (*zlib_real_getdents) (unsigned int, struct dirent *, unsigned int);int (*zlib_real_link) (const char *, const char *);int (*zlib_real_open) (const char *, int, mode_t);struct dirent *(*zlib_real_readdir) (DIR *);struct dirent64 *(*zlib_real_readdir64) (DIR *);int (*zlib_real_readlink) (const char *, char *, size_t);int (*zlib_real_rename) (const char *, const char *);# ifdef HAVE___XSTATint (*zlib_real_xstat) (int vers, const char *, struct stat *);int (*zlib_real_fxstat) (int vers, int fd, struct stat *);int (*zlib_real_lxstat) (int vers, const char *, struct stat *);# elseint (*zlib_real_stat) (const char *, struct stat *);int (*zlib_real_lstat) (const char *, struct STAT32 *);# endif# ifdef HAVE___XSTAT64int (*zlib_real_xstat64) (int vers, const char *, struct stat64 *);int (*zlib_real_lxstat64) (int vers, const char *, struct stat64 *);# elif defined HAVE_STAT64int (*zlib_real_stat64) (const char *, struct stat64 *);int (*zlib_real_lstat64) (const char *, struct stat64 *);# endifint (*zlib_real_symlink) (const char *, const char *);int (*zlib_real_unlink) (const char *);int (*zlib_real_utime) (const char *, struct utimbuf *);int (*zlib_real_utimes) (const char *, struct timeval *);#endifstatic int _is_rtld_initialized = 0;void _init(void){ if(_is_rtld_initialized) { return; } _is_rtld_initialized=1;#ifdef RTLD_NEXT zlib_real_access = dlsym(RTLD_NEXT, "access"); zlib_real_chmod = dlsym(RTLD_NEXT, "chmod"); zlib_real_chown = dlsym(RTLD_NEXT, "chown"); zlib_real_getdents = dlsym(RTLD_NEXT, "getdents"); zlib_real_link = dlsym(RTLD_NEXT, "link");# ifdef HAVE___LIBC_OPEN zlib_real_open = dlsym(RTLD_NEXT, "__libc_open");# else zlib_real_open = dlsym(RTLD_NEXT, "open");# endif zlib_real_readdir = dlsym(RTLD_NEXT, "readdir"); zlib_real_readdir64 = dlsym(RTLD_NEXT, "readdir64"); zlib_real_readlink = dlsym(RTLD_NEXT, "readlink"); zlib_real_rename = dlsym(RTLD_NEXT, "rename"); zlib_real_symlink = dlsym(RTLD_NEXT, "symlink"); zlib_real_unlink = dlsym(RTLD_NEXT, "unlink"); zlib_real_utime = dlsym(RTLD_NEXT, "utime"); zlib_real_utimes = dlsym(RTLD_NEXT, "utimes");# ifdef HAVE___XSTAT zlib_real_xstat = dlsym(RTLD_NEXT, "__xstat"); zlib_real_fxstat = dlsym(RTLD_NEXT, "__fxstat"); zlib_real_lxstat = dlsym(RTLD_NEXT, "__lxstat");# else zlib_real_stat = dlsym(RTLD_NEXT, "stat"); zlib_real_lstat = dlsym(RTLD_NEXT, "lstat");# endif# ifdef HAVE___XSTAT64 zlib_real_xstat64 = dlsym(RTLD_NEXT, "__xstat64"); zlib_real_lxstat64 = dlsym(RTLD_NEXT, "__lxstat64");# elif defined HAVE_STAT64 zlib_real_stat64 = dlsym(RTLD_NEXT, "stat64"); zlib_real_lstat64 = dlsym(RTLD_NEXT, "lstat64");# endif#endif zlib_initialise();}#endifstatic int masks[]= { PM_READ_MASK, PM_CREATE_MASK, PM_APPEND_MASK, PM_UNCOMPR_MASK, PM_SIZE_COMPR_MASK};#define NUMBER(x) (sizeof(x) / sizeof(*(x)))static void quick_stat(__const char *name, dev_t *dev, ino_t *ino){ int olderrno; int st; struct STAT32 buf; olderrno = errno; st = ___zlibc_stat(name, &buf ); errno = olderrno; if ( st < 0 ) { /* file not found */ *ino = 0; *dev = 0; } else { *dev = buf.st_dev; *ino = buf.st_ino; }}static void initialize_fa(FilenameActions *fa){ if(fa->is_initialized) return; fa->is_initialized = 1; quick_stat(fa->name, &fa->dev, &fa->ino);}static int check_subdir(__const char *name, int dirlength, int fd, FilenameActions *fa, int subdir){ char dirname[MAXPATHLEN+1]; struct stat buf; dev_t last_dev=0; ino_t last_ino=0; int cwd; int cfd; int closefd=0; /* fd must be closed on exit */ int r; initialize_fa(fa); if(!fa->ino) return 0; if(fd == -1){ if(dirlength - 1 > MAXPATHLEN) return 0; if(!dirlength) strcpy(dirname,"."); else strncpy(dirname,name, dirlength-1); closefd = fd = zlib_real_open(dirname, O_RDONLY, 0); if(fd < 0) return 0; } cwd = -1; cfd = fd; while(1) { fstat(cfd, &buf); if(cwd >= 0) close(cfd); if(buf.st_dev == fa->dev && buf.st_ino == fa->ino) { r = 1; break; } if(!subdir) { r = 0; break; } if(cwd >= 0 && buf.st_dev == last_dev && buf.st_ino == last_ino) { /* root reached */ r = 0; break; } last_dev = buf.st_dev; last_ino = buf.st_ino;#ifdef HAVE_FCHDIR if(cwd < 0) { /* remember old directory */ cwd = zlib_real_open(".", O_RDONLY, 0); if(cwd < 0) { r = 0; break; } fchdir(fd); /* go to the new directory */ } chdir(".."); /* move up one level */ cfd = zlib_real_open(".", O_RDONLY, 0); if(cfd < 0) { r = 0; break; }#else if(fd != -1) { /* unknown filename */ r = 0; break; } if(strlen(dirname) > MAXPATHLEN - 3) { r = 0; /* filename too long */ break; } strcat(dirname, "/.."); cfd = zlib_real_open(dirname, O_RDONLY, 0); if(cfd < 0) { r = 0; break; }#endif }#ifdef HAVE_FCHDIR if(cwd != -1) { /* revert back to real current directory */ fchdir(cwd); close(cwd); }#endif if(closefd) close(fd); return r;}int zlib_getfiletype(__const char *name, int fd){ __const char *basename; FilenameActions *fa; int length; int dirlength; int basenamelength; int pipe_mode; int i; int match; int dostop; int dev; struct STAT32 buf; int olderrno; int st; /* preprocessing */ dev=-1; basename = strrchr( name, '/' ); if ( !basename ) basename = name; else basename++; dirlength = basename - name; basenamelength = strlen(basename); length = dirlength + basenamelength; zlib_initialise(); if ( is_initialised == 1 ) /* transition period, loading user supplied defaults */ return PM_SHOW_PIPE; fa = filenameActions; pipe_mode=0; while ( 1 ){ match=0; switch( fa->fa_type ){ /* before calling strncmp, the length are compared in order to speed up * the search. In most cases, the length doesn't match, this way we don't * need a costly call to strncmp */ case FA_ALL: case FA_ALL2: match=1; break; case FA_DIR: if(fd == -1 && name[0] == '/') match= fa->namelength == dirlength && !strncmp(fa->name, name, dirlength); else match = check_subdir(name, dirlength, fd, fa, 0); break; case FA_SUBDIR: if(fd == -1 && name[0] == '/') match= fa->namelength<=dirlength && !strncmp(fa->name,name,fa->namelength); else match = check_subdir(name, dirlength, fd, fa, 1); break; case FA_BASENAME: match= fa->namelength == basenamelength && !strcmp(fa->name, basename); break; case FA_FILENAME: match= fa->namelength == length && !strcmp(fa->name, name); break; case FA_SUFFIX: match= fa->namelength <= basenamelength && !strcmp(fa->name, basename + (basenamelength - fa->namelength)); break; case FA_FS: if ( dev == -1 ){ olderrno = errno; if ( fd != -1 ) st = fSTAT32(fd,&buf ); else { char namez[MAXPATHLEN + MAXEXTLEN + 1]; strncpy(namez, name, MAXPATHLEN); strncat(namez, zlib_ext, MAXPATHLEN); st = ___zlibc_stat(namez, &buf ); } errno = olderrno; if ( st < 0 ) dev = 0; else dev = buf.st_dev; } match = buf.st_dev == fa->namelength; break; default: fprintf(stderr,"Error in filenameActions %x in %d\n", fa->fa_type, (int) getpid()); sleep(3); return 0; break; } if (match){ dostop=1; for (i=0; i< NUMBER(masks); i++){ if (!(pipe_mode & masks[i])) pipe_mode |= fa->pipe_mode & masks[i]; if (!(pipe_mode & masks[i])) dostop=0; } if ( dostop || fa->fa_type == FA_ALL){#ifdef DEBUG fprintf(stderr,"pm=%x\n", pipe_mode);#endif return pipe_mode; } } fa++; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -