├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── demokey.jks ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── hzy │ │ └── magic │ │ └── app │ │ ├── MainApplication.java │ │ ├── activity │ │ ├── MainActivity.java │ │ └── SplashActivity.java │ │ ├── adapter │ │ ├── FileItemAdapter.java │ │ └── PathItemAdapter.java │ │ ├── bean │ │ └── FileInfo.java │ │ └── utils │ │ └── FileUtils.java │ └── res │ ├── drawable │ ├── ic_file_unknown.xml │ ├── ic_floder_empty.xml │ ├── ic_folder_full.xml │ └── path_tag_back.xml │ ├── layout │ ├── activity_main.xml │ ├── activity_splash.xml │ ├── path_list_item.xml │ └── storage_list_item.xml │ ├── menu │ └── main_menu.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── libmagic ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ └── magic.mgc.gz │ ├── cpp │ ├── Android.mk │ ├── CMakeLists.txt │ ├── file │ │ ├── apprentice.c │ │ ├── apptype.c │ │ ├── ascmagic.c │ │ ├── asctime_r.c │ │ ├── asprintf.c │ │ ├── buffer.c │ │ ├── cdf.c │ │ ├── cdf.h │ │ ├── cdf_time.c │ │ ├── compress.c │ │ ├── config.h │ │ ├── ctime_r.c │ │ ├── der.c │ │ ├── der.h │ │ ├── dprintf.c │ │ ├── elfclass.h │ │ ├── encoding.c │ │ ├── file.c │ │ ├── file.h │ │ ├── file_opts.h │ │ ├── fmtcheck.c │ │ ├── fsmagic.c │ │ ├── funcs.c │ │ ├── getline.c │ │ ├── getopt_long.c │ │ ├── gmtime_r.c │ │ ├── is_csv.c │ │ ├── is_json.c │ │ ├── is_tar.c │ │ ├── localtime_r.c │ │ ├── magic.c │ │ ├── magic.h │ │ ├── mygetopt.h │ │ ├── pread.c │ │ ├── print.c │ │ ├── readcdf.c │ │ ├── readelf.c │ │ ├── readelf.h │ │ ├── seccomp.c │ │ ├── softmagic.c │ │ ├── strcasestr.c │ │ ├── strlcat.c │ │ ├── strlcpy.c │ │ ├── tar.h │ │ ├── teststrchr.c │ │ └── vasprintf.c │ ├── magicapi.c │ └── ndkhelper.h │ ├── java │ └── com │ │ └── hzy │ │ └── libmagic │ │ └── MagicApi.java │ └── res │ └── values │ └── strings.xml ├── misc └── screen.gif └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/ 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | .cxx/ 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | AndroidMagic(使用LibMagic识别文件类型) 2 | ================== 3 | An android project to query file info with LibMagic 4 | 5 | [![Travis](https://img.shields.io/appveyor/ci/gruntjs/grunt.svg)](https://github.com/huzongyao/AndroidMagic/releases) 6 | [![Travis](https://img.shields.io/badge/file-v5.40-brightgreen.svg)](https://github.com/file/file) 7 | 8 | ### Introduction 9 | The file command is "a file type guesser", that is, a command-line tool that tells you in words 10 | what kind of data a file contains. Unlike most GUI systems, command-line UNIX systems - with this 11 | program leading the charge - don't rely on filename extentions to tell you the type of a file, 12 | but look at the file's actual contents. This is, of course, more reliable, but requires a bit of I/O. 13 | 14 | ### Screenshot 15 | ![screenshot](https://github.com/huzongyao/AndroidMagic/blob/master/misc/screen.gif?raw=true) 16 | 17 | ### Details 18 | This project is for me to learn Java, NDK, and for fun. 19 | * learn how to build ndk and sign apk with android gradle-experimental 20 | * source code is from open source implementation of the file command 21 | * libmagic is "a file type guesser", that tells you in words what kind of data a file contains 22 | 23 | ### 学习记录 24 | * 使用libmagic,我们不用看文件的后缀,就可以识别出常用文件类型 25 | * 移植LibMagic到安卓平台上, 使文件类型的识别不仅通过扩展名 26 | * 使用cmake编译NDK 27 | * Java与本地代码之间内存拷贝GetByteArrayRegion 28 | * butterknife 以及 rxjava的使用 29 | 30 | ### Useful Links 31 | * Official Site: http://www.darwinsys.com/file/ 32 | * GitHub:https://github.com/file/file 33 | 34 | ### About Me 35 | * GitHub: [https://huzongyao.github.io/](https://huzongyao.github.io/) 36 | * ITEye博客:[https://hzy3774.iteye.com/](https://hzy3774.iteye.com/) 37 | * 新浪微博: [https://weibo.com/hzy3774](https://weibo.com/hzy3774) 38 | 39 | ### Contact To Me 40 | * QQ: [377406997](https://wpa.qq.com/msgrd?v=3&uin=377406997&site=qq&menu=yes) 41 | * Gmail: [hzy3774@gmail.com](mailto:hzy3774@gmail.com) 42 | * Foxmail: [hzy3774@qq.com](mailto:hzy3774@qq.com) 43 | * WeChat: hzy3774 44 | 45 | ![image](https://raw.githubusercontent.com/hzy3774/AndroidP7zip/master/misc/wechat.png) 46 | 47 | ### Others 48 | * 想捐助我喝杯热水(¥0.01起捐)
49 | ![donate](https://github.com/huzongyao/JChineseChess/blob/master/misc/donate.png?raw=true) -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | *.iml 3 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 30 5 | 6 | signingConfigs { 7 | demokey { 8 | storeFile file('demokey.jks') 9 | storePassword "demokey" 10 | keyAlias 'demokey' 11 | keyPassword 'demokey' 12 | } 13 | } 14 | defaultConfig { 15 | applicationId "com.hzy.magic.app" 16 | minSdkVersion 15 17 | targetSdkVersion 30 18 | versionCode 3 19 | versionName "1.1.2" 20 | } 21 | compileOptions { 22 | targetCompatibility JavaVersion.VERSION_1_8 23 | sourceCompatibility JavaVersion.VERSION_1_8 24 | } 25 | buildTypes { 26 | debug { 27 | minifyEnabled false 28 | signingConfig signingConfigs.demokey 29 | } 30 | release { 31 | minifyEnabled true 32 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 33 | signingConfig signingConfigs.demokey 34 | } 35 | } 36 | applicationVariants.all { variant -> 37 | variant.outputs.all { 38 | def fileName = project.name + '-' + variant.name + '-V' + 39 | defaultConfig.versionName + ".apk" 40 | outputFileName = fileName 41 | } 42 | } 43 | lintOptions { 44 | abortOnError false 45 | } 46 | dependenciesInfo { 47 | includeInApk false 48 | includeInBundle false 49 | } 50 | } 51 | 52 | dependencies { 53 | implementation fileTree(include: ['*.jar'], dir: 'libs') 54 | implementation 'androidx.appcompat:appcompat:1.2.0' 55 | implementation 'com.google.android.material:material:1.2.1' 56 | implementation 'com.blankj:utilcode:1.26.0' 57 | api 'com.jakewharton:butterknife:10.2.3' 58 | implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' 59 | annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.3' 60 | implementation project(':libmagic') 61 | } 62 | -------------------------------------------------------------------------------- /app/demokey.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huzongyao/AndroidMagic/2a25054a07db0ddffe4e80e6e7847d5c054ea6ed/app/demokey.jks -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in E:\android-sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | -keep class com.hzy.libmagic.** { *; } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/hzy/magic/app/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.hzy.magic.app; 2 | 3 | import android.app.Application; 4 | 5 | import com.blankj.utilcode.util.Utils; 6 | 7 | /** 8 | * Created by huzongyao on 2018/5/28. 9 | */ 10 | 11 | public class MainApplication extends Application { 12 | 13 | @Override 14 | public void onCreate() { 15 | super.onCreate(); 16 | Utils.init(this); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/hzy/magic/app/activity/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.hzy.magic.app.activity; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.annotation.TargetApi; 5 | import android.app.ProgressDialog; 6 | import android.os.Build; 7 | import android.os.Bundle; 8 | import android.os.Environment; 9 | import android.view.Menu; 10 | import android.view.MenuItem; 11 | import android.view.View; 12 | 13 | import androidx.appcompat.app.AlertDialog; 14 | import androidx.appcompat.app.AppCompatActivity; 15 | import androidx.recyclerview.widget.LinearLayoutManager; 16 | import androidx.recyclerview.widget.RecyclerView; 17 | import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; 18 | 19 | import com.blankj.utilcode.constant.PermissionConstants; 20 | import com.blankj.utilcode.util.PermissionUtils; 21 | import com.hzy.libmagic.MagicApi; 22 | import com.hzy.magic.app.R; 23 | import com.hzy.magic.app.adapter.FileItemAdapter; 24 | import com.hzy.magic.app.adapter.PathItemAdapter; 25 | import com.hzy.magic.app.bean.FileInfo; 26 | import com.hzy.magic.app.utils.FileUtils; 27 | 28 | import java.util.List; 29 | import java.util.Stack; 30 | import java.util.concurrent.ExecutorService; 31 | import java.util.concurrent.Executors; 32 | 33 | import butterknife.BindView; 34 | import butterknife.ButterKnife; 35 | 36 | public class MainActivity extends AppCompatActivity 37 | implements View.OnClickListener, SwipeRefreshLayout.OnRefreshListener { 38 | 39 | @BindView(R.id.main_storage_path) 40 | RecyclerView mPathList; 41 | 42 | @BindView(R.id.main_storage_list) 43 | RecyclerView mFileList; 44 | 45 | @BindView(R.id.main_storage_refresh) 46 | SwipeRefreshLayout mSwipeRefresh; 47 | 48 | private PathItemAdapter mPathAdapter; 49 | private FileItemAdapter mFileAdapter; 50 | private String mCurrentPath; 51 | private ProgressDialog mProgressDialog; 52 | private AlertDialog mAboutDialog; 53 | private ExecutorService mThreadPool; 54 | private Stack mHistoryStack; 55 | 56 | @TargetApi(Build.VERSION_CODES.M) 57 | @Override 58 | protected void onCreate(Bundle savedInstanceState) { 59 | super.onCreate(savedInstanceState); 60 | setContentView(R.layout.activity_main); 61 | ButterKnife.bind(this); 62 | mThreadPool = Executors.newFixedThreadPool(8); 63 | mHistoryStack = new Stack<>(); 64 | initUI(); 65 | PermissionUtils.permission(PermissionConstants.STORAGE) 66 | .callback(new PermissionUtils.SimpleCallback() { 67 | @Override 68 | public void onGranted() { 69 | loadInitPath(); 70 | } 71 | 72 | @Override 73 | public void onDenied() { 74 | } 75 | }).request(); 76 | } 77 | 78 | 79 | private void initUI() { 80 | mProgressDialog = new ProgressDialog(this); 81 | mProgressDialog.setCancelable(false); 82 | mProgressDialog.setTitle("Please Wait..."); 83 | mPathList.setAdapter(mPathAdapter = new PathItemAdapter(this, this)); 84 | mPathList.setLayoutManager(new LinearLayoutManager(this, 85 | LinearLayoutManager.HORIZONTAL, false)); 86 | mFileList.setAdapter(mFileAdapter = new FileItemAdapter(this, this)); 87 | mFileList.setLayoutManager(new LinearLayoutManager(this)); 88 | mSwipeRefresh.setOnRefreshListener(this); 89 | } 90 | 91 | @SuppressLint("CheckResult") 92 | private void loadInitPath() { 93 | mCurrentPath = Environment.getExternalStorageDirectory().getPath(); 94 | mHistoryStack.push(mCurrentPath); 95 | loadPathInfo(mCurrentPath); 96 | } 97 | 98 | private void loadPathInfo(String path) { 99 | mThreadPool.submit(() -> { 100 | List infoList = FileUtils.getInfoListFromPath(path); 101 | runOnUiThread(() -> { 102 | mCurrentPath = path; 103 | mFileAdapter.setDataList(infoList); 104 | mPathAdapter.setPathView(mCurrentPath); 105 | mPathList.scrollToPosition(mPathAdapter.getItemCount() - 1); 106 | mFileList.smoothScrollToPosition(0); 107 | mSwipeRefresh.setRefreshing(false); 108 | mProgressDialog.dismiss(); 109 | }); 110 | }); 111 | } 112 | 113 | @Override 114 | protected void onDestroy() { 115 | mThreadPool.shutdownNow(); 116 | MagicApi.close(); 117 | super.onDestroy(); 118 | } 119 | 120 | @Override 121 | public boolean onCreateOptionsMenu(Menu menu) { 122 | getMenuInflater().inflate(R.menu.main_menu, menu); 123 | return super.onCreateOptionsMenu(menu); 124 | } 125 | 126 | @Override 127 | public boolean onOptionsItemSelected(MenuItem item) { 128 | switch (item.getItemId()) { 129 | case R.id.menu_about: 130 | showAboutDialog(); 131 | return true; 132 | case R.id.menu_home: 133 | loadInitPath(); 134 | return true; 135 | } 136 | return super.onOptionsItemSelected(item); 137 | } 138 | 139 | @Override 140 | public void onBackPressed() { 141 | if (mHistoryStack.size() > 1) { 142 | mHistoryStack.pop(); 143 | String backPath = mHistoryStack.peek(); 144 | if (backPath != null) { 145 | loadPathInfo(backPath); 146 | } 147 | } else { 148 | super.onBackPressed(); 149 | } 150 | } 151 | 152 | @Override 153 | public void onClick(View v) { 154 | if (v.getTag() instanceof String) { 155 | mProgressDialog.show(); 156 | String path = (String) v.getTag(); 157 | if (path != null) { 158 | if (mHistoryStack.empty() || !mHistoryStack.peek().equals(path)) { 159 | mHistoryStack.push(path); 160 | } 161 | loadPathInfo(path); 162 | } 163 | } else { 164 | FileInfo info = (FileInfo) v.getTag(); 165 | FileInfo.FileType type = info.getFileType(); 166 | if (type == FileInfo.FileType.folderEmpty 167 | || type == FileInfo.FileType.folderFull) { 168 | mProgressDialog.show(); 169 | String path = info.getFilePath(); 170 | mHistoryStack.push(path); 171 | loadPathInfo(path); 172 | } 173 | } 174 | } 175 | 176 | @Override 177 | public void onRefresh() { 178 | loadPathInfo(mCurrentPath); 179 | } 180 | 181 | private void showAboutDialog() { 182 | if (mAboutDialog == null) { 183 | String packageString = MagicApi.getPackageString(); 184 | mAboutDialog = new AlertDialog.Builder(this) 185 | .setTitle(R.string.app_name) 186 | .setMessage(packageString) 187 | .create(); 188 | } 189 | mAboutDialog.show(); 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /app/src/main/java/com/hzy/magic/app/activity/SplashActivity.java: -------------------------------------------------------------------------------- 1 | package com.hzy.magic.app.activity; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | 7 | import com.hzy.libmagic.MagicApi; 8 | import com.hzy.magic.app.R; 9 | 10 | import java.io.InputStream; 11 | 12 | public class SplashActivity extends Activity { 13 | 14 | @Override 15 | protected void onCreate(Bundle savedInstanceState) { 16 | super.onCreate(savedInstanceState); 17 | setContentView(R.layout.activity_splash); 18 | ensureMagicAndStart(); 19 | } 20 | 21 | private void ensureMagicAndStart() { 22 | new Thread() { 23 | @Override 24 | public void run() { 25 | try { 26 | InputStream inputStream = getAssets().open("magic.mgc"); 27 | int length = inputStream.available(); 28 | byte[] buffer = new byte[length]; 29 | if (inputStream.read(buffer) > 0) { 30 | if (MagicApi.loadFromBytes(buffer) == 0) { 31 | startMainApp(); 32 | return; 33 | } 34 | } 35 | } catch (Exception e) { 36 | e.printStackTrace(); 37 | } 38 | finish(); 39 | } 40 | }.start(); 41 | } 42 | 43 | private void startMainApp() { 44 | startActivity(new Intent(this, MainActivity.class)); 45 | finish(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/hzy/magic/app/adapter/FileItemAdapter.java: -------------------------------------------------------------------------------- 1 | package com.hzy.magic.app.adapter; 2 | 3 | import android.app.Activity; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.ImageView; 8 | import android.widget.TextView; 9 | 10 | import androidx.recyclerview.widget.RecyclerView; 11 | 12 | import com.hzy.magic.app.R; 13 | import com.hzy.magic.app.bean.FileInfo; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | 18 | import butterknife.BindView; 19 | import butterknife.ButterKnife; 20 | 21 | /** 22 | * Created by huzongyao on 17-7-13. 23 | */ 24 | 25 | public class FileItemAdapter extends RecyclerView.Adapter { 26 | 27 | private View.OnClickListener mItemClickListener; 28 | private Activity mActivity; 29 | private List mFileInfoList; 30 | 31 | public FileItemAdapter(Activity activity, View.OnClickListener listener) { 32 | mActivity = activity; 33 | mItemClickListener = listener; 34 | mFileInfoList = new ArrayList<>(); 35 | } 36 | 37 | @Override 38 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 39 | View rootView = LayoutInflater.from(mActivity) 40 | .inflate(R.layout.storage_list_item, parent, false); 41 | rootView.setOnClickListener(mItemClickListener); 42 | return new ViewHolder(rootView); 43 | } 44 | 45 | @Override 46 | public void onBindViewHolder(ViewHolder holder, int position) { 47 | FileInfo item = mFileInfoList.get(position); 48 | int iconId = R.drawable.ic_file_unknown; 49 | switch (item.getFileType()) { 50 | case folderEmpty: 51 | iconId = R.drawable.ic_floder_empty; 52 | break; 53 | case folderFull: 54 | iconId = R.drawable.ic_folder_full; 55 | break; 56 | } 57 | holder.itemView.setTag(item); 58 | holder.fileName.setText(item.getFileName()); 59 | holder.magicInfo.setText(item.getMagicInfo()); 60 | holder.icon.setImageResource(iconId); 61 | } 62 | 63 | @Override 64 | public int getItemCount() { 65 | return mFileInfoList.size(); 66 | } 67 | 68 | public void setDataList(List dataList) { 69 | this.mFileInfoList = dataList; 70 | notifyDataSetChanged(); 71 | } 72 | 73 | public class ViewHolder extends RecyclerView.ViewHolder { 74 | 75 | @BindView(R.id.file_item_icon) 76 | ImageView icon; 77 | 78 | @BindView(R.id.file_item_name) 79 | TextView fileName; 80 | 81 | @BindView(R.id.file_item_magic) 82 | TextView magicInfo; 83 | 84 | public ViewHolder(View itemView) { 85 | super(itemView); 86 | ButterKnife.bind(this, itemView); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /app/src/main/java/com/hzy/magic/app/adapter/PathItemAdapter.java: -------------------------------------------------------------------------------- 1 | package com.hzy.magic.app.adapter; 2 | 3 | import android.app.Activity; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.TextView; 8 | 9 | import androidx.annotation.NonNull; 10 | import androidx.recyclerview.widget.RecyclerView; 11 | 12 | import com.hzy.magic.app.R; 13 | 14 | import java.io.File; 15 | 16 | import butterknife.BindView; 17 | import butterknife.ButterKnife; 18 | 19 | /** 20 | * Created by huzongyao on 17-7-15. 21 | */ 22 | 23 | public class PathItemAdapter extends RecyclerView.Adapter { 24 | 25 | private String[] mPathStringList; 26 | private View.OnClickListener mItemClickListener; 27 | private Activity mActivity; 28 | private String mCurPath; 29 | 30 | public PathItemAdapter(Activity activity, View.OnClickListener listener) { 31 | mActivity = activity; 32 | mItemClickListener = listener; 33 | mPathStringList = new String[0]; 34 | } 35 | 36 | public void setPathView(String path) { 37 | mCurPath = path; 38 | mPathStringList = mCurPath.split(File.separator); 39 | notifyDataSetChanged(); 40 | } 41 | 42 | @Override 43 | public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 44 | View rootView = LayoutInflater.from(mActivity) 45 | .inflate(R.layout.path_list_item, parent, false); 46 | rootView.setOnClickListener(mItemClickListener); 47 | return new ViewHolder(rootView); 48 | } 49 | 50 | @Override 51 | public void onBindViewHolder(@NonNull ViewHolder holder, int position) { 52 | String item = mPathStringList[position]; 53 | StringBuilder curPath = new StringBuilder(); 54 | for (int i = 0; i < position + 1; i++) { 55 | curPath.append(mPathStringList[i]).append(File.separator); 56 | } 57 | holder.itemView.setTag(curPath.toString()); 58 | holder.pathText.setText(item); 59 | } 60 | 61 | @Override 62 | public int getItemCount() { 63 | return mPathStringList.length; 64 | } 65 | 66 | public class ViewHolder extends RecyclerView.ViewHolder { 67 | 68 | @BindView(R.id.path_list_text) 69 | TextView pathText; 70 | 71 | public ViewHolder(View itemView) { 72 | super(itemView); 73 | ButterKnife.bind(this, itemView); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /app/src/main/java/com/hzy/magic/app/bean/FileInfo.java: -------------------------------------------------------------------------------- 1 | package com.hzy.magic.app.bean; 2 | 3 | /** 4 | * Created by huzongyao on 17-7-13. 5 | */ 6 | 7 | public class FileInfo { 8 | private String fileName; 9 | private String filePath; 10 | private String magicInfo; 11 | private FileType fileType; 12 | 13 | public String getFileName() { 14 | return fileName; 15 | } 16 | 17 | public void setFileName(String fileName) { 18 | this.fileName = fileName; 19 | } 20 | 21 | public String getMagicInfo() { 22 | return magicInfo; 23 | } 24 | 25 | public void setMagicInfo(String magicInfo) { 26 | this.magicInfo = magicInfo; 27 | } 28 | 29 | public String getFilePath() { 30 | return filePath; 31 | } 32 | 33 | public void setFilePath(String filePath) { 34 | this.filePath = filePath; 35 | } 36 | 37 | public FileType getFileType() { 38 | return fileType; 39 | } 40 | 41 | public void setFileType(FileType fileType) { 42 | this.fileType = fileType; 43 | } 44 | 45 | public enum FileType { 46 | folderFull, 47 | folderEmpty, 48 | fileKnown 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/hzy/magic/app/utils/FileUtils.java: -------------------------------------------------------------------------------- 1 | package com.hzy.magic.app.utils; 2 | 3 | import com.hzy.libmagic.MagicApi; 4 | import com.hzy.magic.app.bean.FileInfo; 5 | 6 | import java.io.File; 7 | import java.util.ArrayList; 8 | import java.util.Arrays; 9 | import java.util.Comparator; 10 | import java.util.List; 11 | 12 | /** 13 | * Created by huzongyao on 17-7-13. 14 | */ 15 | 16 | public class FileUtils { 17 | 18 | public static FileInfo getFileInfoFromPath(String filePath) { 19 | FileInfo info = new FileInfo(); 20 | info.setFileType(FileInfo.FileType.fileKnown); 21 | File file = new File(filePath); 22 | if (file.isDirectory()) { 23 | File[] subFiles = file.listFiles(); 24 | if (subFiles != null && subFiles.length > 0) { 25 | info.setFileType(FileInfo.FileType.folderFull); 26 | } else { 27 | info.setFileType(FileInfo.FileType.folderEmpty); 28 | } 29 | } 30 | String magicInfo = MagicApi.magicFile(filePath); 31 | info.setMagicInfo(magicInfo); 32 | info.setFileName(file.getName()); 33 | info.setFilePath(file.getAbsolutePath()); 34 | return info; 35 | } 36 | 37 | public static List getInfoListFromPath(String path) { 38 | List fileInfos = new ArrayList<>(); 39 | File folder = new File(path); 40 | if (folder.exists() && folder.isDirectory()) { 41 | File[] fileNames = folder.listFiles(); 42 | if (fileNames != null) { 43 | Arrays.sort(fileNames, new FileComparator()); 44 | for (File file : fileNames) { 45 | fileInfos.add(getFileInfoFromPath(file.getPath())); 46 | } 47 | } 48 | } 49 | return fileInfos; 50 | } 51 | 52 | private static class FileComparator implements Comparator { 53 | @Override 54 | public int compare(File o1, File o2) { 55 | int ret = getFileScore(o2) - getFileScore(o1); 56 | if (ret == 0) { 57 | ret = o1.getName().compareToIgnoreCase(o2.getName()); 58 | } 59 | return ret; 60 | } 61 | } 62 | 63 | private static int getFileScore(File file) { 64 | int score = 0; 65 | score |= file.isDirectory() ? 0x10 : 0; 66 | score |= file.isHidden() ? 0 : 0x01; 67 | return score; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_file_unknown.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_floder_empty.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_folder_full.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/path_tag_back.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 16 | 17 | 21 | 22 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_splash.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 15 | 20 | 21 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/layout/path_list_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 24 | 25 | 31 | -------------------------------------------------------------------------------- /app/src/main/res/layout/storage_list_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 15 | 16 | 22 | 23 | 28 | 29 | 36 | 37 | 45 | 46 | 47 | 48 | 53 | -------------------------------------------------------------------------------- /app/src/main/res/menu/main_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huzongyao/AndroidMagic/2a25054a07db0ddffe4e80e6e7847d5c054ea6ed/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huzongyao/AndroidMagic/2a25054a07db0ddffe4e80e6e7847d5c054ea6ed/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huzongyao/AndroidMagic/2a25054a07db0ddffe4e80e6e7847d5c054ea6ed/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huzongyao/AndroidMagic/2a25054a07db0ddffe4e80e6e7847d5c054ea6ed/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huzongyao/AndroidMagic/2a25054a07db0ddffe4e80e6e7847d5c054ea6ed/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FF5722 4 | #E64A19 5 | #448AFF 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Magic 3 | About 4 | Home 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | google() 7 | } 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:4.1.1' 10 | 11 | // NOTE: Do not place your application dependencies here; they belong 12 | // in the individual module build.gradle files 13 | } 14 | } 15 | 16 | allprojects { 17 | repositories { 18 | jcenter() 19 | google() 20 | } 21 | } 22 | 23 | task clean(type: Delete) { 24 | delete rootProject.buildDir 25 | } 26 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app's APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true 20 | 21 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huzongyao/AndroidMagic/2a25054a07db0ddffe4e80e6e7847d5c054ea6ed/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jan 22 18:20:07 CST 2021 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /libmagic/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | *.iml 3 | .externalNativeBuild 4 | .cxx 5 | -------------------------------------------------------------------------------- /libmagic/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 30 5 | 6 | defaultConfig { 7 | minSdkVersion 15 8 | targetSdkVersion 30 9 | versionCode 2 10 | versionName "1.1.1" 11 | ndk { 12 | abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' 13 | } 14 | externalNativeBuild { 15 | cmake { 16 | arguments '-DANDROID_PLATFORM=android-21' 17 | } 18 | } 19 | } 20 | buildTypes { 21 | debug { 22 | externalNativeBuild { 23 | cmake { 24 | cFlags.add('-DNATIVE_LOG') 25 | } 26 | } 27 | } 28 | } 29 | externalNativeBuild { 30 | cmake { 31 | path 'src/main/cpp/CMakeLists.txt' 32 | } 33 | /*ndkBuild { 34 | path 'src/main/cpp/Android.mk' 35 | }*/ 36 | } 37 | } 38 | 39 | dependencies { 40 | implementation fileTree(dir: 'libs', include: ['*.jar']) 41 | } 42 | -------------------------------------------------------------------------------- /libmagic/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in E:\android-sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /libmagic/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /libmagic/src/main/assets/magic.mgc.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huzongyao/AndroidMagic/2a25054a07db0ddffe4e80e6e7847d5c054ea6ed/libmagic/src/main/assets/magic.mgc.gz -------------------------------------------------------------------------------- /libmagic/src/main/cpp/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | LOCAL_MODULE := magic 5 | 6 | LOCAL_C_INCLUDES := \ 7 | $(LOCAL_PATH) \ 8 | $(LOCAL_PATH)/file 9 | 10 | LOCAL_SRC_FILES := \ 11 | $(wildcard $(LOCAL_PATH)/file/*.c) \ 12 | $(wildcard $(LOCAL_PATH)/*.c) 13 | 14 | 15 | LOCAL_LDLIBS := -llog -lz 16 | include $(BUILD_SHARED_LIBRARY) 17 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Sets the minimum version of CMake required to build the native 2 | # library. You should either keep the default value or only pass a 3 | # value of 3.4.0 or lower. 4 | # by huzongyao 5 | 6 | cmake_minimum_required(VERSION 3.4.1) 7 | 8 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -DHAVE_CONFIG_H") 9 | 10 | # Creates and names a library, sets it as either STATIC 11 | # or SHARED, and provides the relative paths to its source code. 12 | # You can define multiple libraries, and CMake builds it for you. 13 | # Gradle automatically packages shared libraries with your APK. 14 | include_directories(file) 15 | 16 | file(GLOB_RECURSE NATIVE_SRCS "*.c") 17 | 18 | add_library(magic SHARED ${NATIVE_SRCS}) 19 | 20 | # Specifies libraries CMake should link to your target library. You 21 | # can link multiple libraries, such as libraries you define in the 22 | # build script, prebuilt third-party libraries, or system libraries. 23 | target_link_libraries(magic log z) 24 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/apptype.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Adapted from: apptype.c, Written by Eberhard Mattes and put into the 3 | * public domain 4 | * 5 | * Notes: 1. Qualify the filename so that DosQueryAppType does not do extraneous 6 | * searches. 7 | * 8 | * 2. DosQueryAppType will return FAPPTYP_DOS on a file ending with ".com" 9 | * (other than an OS/2 exe or Win exe with this name). Eberhard Mattes 10 | * remarks Tue, 6 Apr 93: Moreover, it reports the type of the (new and very 11 | * bug ridden) Win Emacs as "OS/2 executable". 12 | * 13 | * 3. apptype() uses the filename if given, otherwise a tmp file is created with 14 | * the contents of buf. If buf is not the complete file, apptype can 15 | * incorrectly identify the exe type. The "-z" option of "file" is the reason 16 | * for this ugly code. 17 | */ 18 | 19 | /* 20 | * amai: Darrel Hankerson did the changes described here. 21 | * 22 | * It remains to check the validity of comments (2.) since it's referred to an 23 | * "old" OS/2 version. 24 | * 25 | */ 26 | 27 | #include "file.h" 28 | 29 | #ifndef lint 30 | FILE_RCSID("@(#)$File: apptype.c,v 1.14 2018/09/09 20:33:28 christos Exp $") 31 | #endif /* lint */ 32 | 33 | #include 34 | #include 35 | 36 | #ifdef __EMX__ 37 | #include 38 | #define INCL_DOSSESMGR 39 | #define INCL_DOSERRORS 40 | #define INCL_DOSFILEMGR 41 | #include 42 | typedef ULONG APPTYPE; 43 | 44 | protected int 45 | file_os2_apptype(struct magic_set *ms, const char *fn, const void *buf, 46 | size_t nb) 47 | { 48 | APPTYPE rc, type; 49 | char path[_MAX_PATH], drive[_MAX_DRIVE], dir[_MAX_DIR], 50 | fname[_MAX_FNAME], ext[_MAX_EXT]; 51 | char *filename; 52 | FILE *fp; 53 | 54 | if (fn) 55 | filename = strdup(fn); 56 | else if ((filename = tempnam("./", "tmp")) == NULL) { 57 | file_error(ms, errno, "cannot create tempnam"); 58 | return -1; 59 | } 60 | /* qualify the filename to prevent extraneous searches */ 61 | _splitpath(filename, drive, dir, fname, ext); 62 | (void)sprintf(path, "%s%s%s%s", drive, 63 | (*dir == '\0') ? "./" : dir, 64 | fname, 65 | (*ext == '\0') ? "." : ext); 66 | 67 | if (fn == NULL) { 68 | if ((fp = fopen(path, "wb")) == NULL) { 69 | file_error(ms, errno, "cannot open tmp file `%s'", path); 70 | return -1; 71 | } 72 | if (fwrite(buf, 1, nb, fp) != nb) { 73 | file_error(ms, errno, "cannot write tmp file `%s'", 74 | path); 75 | (void)fclose(fp); 76 | return -1; 77 | } 78 | (void)fclose(fp); 79 | } 80 | rc = DosQueryAppType((unsigned char *)path, &type); 81 | 82 | if (fn == NULL) { 83 | unlink(path); 84 | free(filename); 85 | } 86 | #if 0 87 | if (rc == ERROR_INVALID_EXE_SIGNATURE) 88 | printf("%s: not an executable file\n", fname); 89 | else if (rc == ERROR_FILE_NOT_FOUND) 90 | printf("%s: not found\n", fname); 91 | else if (rc == ERROR_ACCESS_DENIED) 92 | printf("%s: access denied\n", fname); 93 | else if (rc != 0) 94 | printf("%s: error code = %lu\n", fname, rc); 95 | else 96 | #else 97 | 98 | /* 99 | * for our purpose here it's sufficient to just ignore the error and 100 | * return w/o success (=0) 101 | */ 102 | 103 | if (rc) 104 | return (0); 105 | 106 | #endif 107 | 108 | if (type & FAPPTYP_32BIT) 109 | if (file_printf(ms, "32-bit ") == -1) 110 | return -1; 111 | if (type & FAPPTYP_PHYSDRV) { 112 | if (file_printf(ms, "physical device driver") == -1) 113 | return -1; 114 | } else if (type & FAPPTYP_VIRTDRV) { 115 | if (file_printf(ms, "virtual device driver") == -1) 116 | return -1; 117 | } else if (type & FAPPTYP_DLL) { 118 | if (type & FAPPTYP_PROTDLL) 119 | if (file_printf(ms, "protected ") == -1) 120 | return -1; 121 | if (file_printf(ms, "DLL") == -1) 122 | return -1; 123 | } else if (type & (FAPPTYP_WINDOWSREAL | FAPPTYP_WINDOWSPROT)) { 124 | if (file_printf(ms, "Windows executable") == -1) 125 | return -1; 126 | } else if (type & FAPPTYP_DOS) { 127 | /* 128 | * The API routine is partially broken on filenames ending 129 | * ".com". 130 | */ 131 | if (stricmp(ext, ".com") == 0) 132 | if (strncmp((const char *)buf, "MZ", 2)) 133 | return (0); 134 | if (file_printf(ms, "DOS executable") == -1) 135 | return -1; 136 | /* ---------------------------------------- */ 137 | /* Might learn more from the magic(4) entry */ 138 | if (file_printf(ms, ", magic(4)-> ") == -1) 139 | return -1; 140 | return (0); 141 | /* ---------------------------------------- */ 142 | } else if (type & FAPPTYP_BOUND) { 143 | if (file_printf(ms, "bound executable") == -1) 144 | return -1; 145 | } else if ((type & 7) == FAPPTYP_WINDOWAPI) { 146 | if (file_printf(ms, "PM executable") == -1) 147 | return -1; 148 | } else if (file_printf(ms, "OS/2 executable") == -1) 149 | return -1; 150 | 151 | switch (type & (FAPPTYP_NOTWINDOWCOMPAT | 152 | FAPPTYP_WINDOWCOMPAT | 153 | FAPPTYP_WINDOWAPI)) { 154 | case FAPPTYP_NOTWINDOWCOMPAT: 155 | if (file_printf(ms, " [NOTWINDOWCOMPAT]") == -1) 156 | return -1; 157 | break; 158 | case FAPPTYP_WINDOWCOMPAT: 159 | if (file_printf(ms, " [WINDOWCOMPAT]") == -1) 160 | return -1; 161 | break; 162 | case FAPPTYP_WINDOWAPI: 163 | if (file_printf(ms, " [WINDOWAPI]") == -1) 164 | return -1; 165 | break; 166 | } 167 | return 1; 168 | } 169 | #endif 170 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/ascmagic.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Ian F. Darwin 1986-1995. 3 | * Software written by Ian F. Darwin and others; 4 | * maintained 1995-present by Christos Zoulas and others. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice immediately at the beginning of the file, without modification, 11 | * this list of conditions, and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 20 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | /* 29 | * ASCII magic -- try to detect text encoding. 30 | * 31 | * Extensively modified by Eric Fischer in July, 2000, 32 | * to handle character codes other than ASCII on a unified basis. 33 | */ 34 | 35 | #include "file.h" 36 | 37 | #ifndef lint 38 | FILE_RCSID("@(#)$File: ascmagic.c,v 1.109 2021/02/05 23:01:40 christos Exp $") 39 | #endif /* lint */ 40 | 41 | #include "magic.h" 42 | #include 43 | #include 44 | #include 45 | #ifdef HAVE_UNISTD_H 46 | #include 47 | #endif 48 | 49 | #define MAXLINELEN 300 /* longest sane line length */ 50 | #define ISSPC(x) ((x) == ' ' || (x) == '\t' || (x) == '\r' || (x) == '\n' \ 51 | || (x) == 0x85 || (x) == '\f') 52 | 53 | private unsigned char *encode_utf8(unsigned char *, size_t, file_unichar_t *, 54 | size_t); 55 | private size_t trim_nuls(const unsigned char *, size_t); 56 | 57 | /* 58 | * Undo the NUL-termination kindly provided by process() 59 | * but leave at least one byte to look at 60 | */ 61 | private size_t 62 | trim_nuls(const unsigned char *buf, size_t nbytes) 63 | { 64 | while (nbytes > 1 && buf[nbytes - 1] == '\0') 65 | nbytes--; 66 | 67 | return nbytes; 68 | } 69 | 70 | protected int 71 | file_ascmagic(struct magic_set *ms, const struct buffer *b, int text) 72 | { 73 | file_unichar_t *ubuf = NULL; 74 | size_t ulen = 0; 75 | int rv = 1; 76 | struct buffer bb; 77 | 78 | const char *code = NULL; 79 | const char *code_mime = NULL; 80 | const char *type = NULL; 81 | 82 | bb = *b; 83 | bb.flen = trim_nuls(CAST(const unsigned char *, b->fbuf), b->flen); 84 | /* 85 | * Avoid trimming at an odd byte if the original buffer was evenly 86 | * sized; this avoids losing the last character on UTF-16 LE text 87 | */ 88 | if ((bb.flen & 1) && !(b->flen & 1)) 89 | bb.flen++; 90 | 91 | /* If file doesn't look like any sort of text, give up. */ 92 | if (file_encoding(ms, &bb, &ubuf, &ulen, &code, &code_mime, 93 | &type) == 0) 94 | rv = 0; 95 | else 96 | rv = file_ascmagic_with_encoding(ms, &bb, 97 | ubuf, ulen, code, type, text); 98 | 99 | free(ubuf); 100 | 101 | return rv; 102 | } 103 | 104 | protected int 105 | file_ascmagic_with_encoding(struct magic_set *ms, const struct buffer *b, 106 | file_unichar_t *ubuf, size_t ulen, const char *code, const char *type, 107 | int text) 108 | { 109 | struct buffer bb; 110 | const unsigned char *buf = CAST(const unsigned char *, b->fbuf); 111 | size_t nbytes = b->flen; 112 | unsigned char *utf8_buf = NULL, *utf8_end; 113 | size_t mlen, i, len; 114 | int rv = -1; 115 | int mime = ms->flags & MAGIC_MIME; 116 | int need_separator = 0; 117 | 118 | const char *subtype = NULL; 119 | 120 | int has_escapes = 0; 121 | int has_backspace = 0; 122 | int seen_cr = 0; 123 | 124 | int n_crlf = 0; 125 | int n_lf = 0; 126 | int n_cr = 0; 127 | int n_nel = 0; 128 | int executable = 0; 129 | 130 | size_t last_line_end = CAST(size_t, -1); 131 | size_t has_long_lines = 0; 132 | 133 | nbytes = trim_nuls(buf, nbytes); 134 | 135 | /* If we have fewer than 2 bytes, give up. */ 136 | if (nbytes <= 1) { 137 | rv = 0; 138 | goto done; 139 | } 140 | 141 | if (ulen > 0 && (ms->flags & MAGIC_NO_CHECK_SOFT) == 0) { 142 | /* Convert ubuf to UTF-8 and try text soft magic */ 143 | /* malloc size is a conservative overestimate; could be 144 | improved, or at least realloced after conversion. */ 145 | mlen = ulen * 6; 146 | if ((utf8_buf = CAST(unsigned char *, malloc(mlen))) == NULL) { 147 | file_oomem(ms, mlen); 148 | goto done; 149 | } 150 | if ((utf8_end = encode_utf8(utf8_buf, mlen, ubuf, ulen)) 151 | == NULL) 152 | goto done; 153 | buffer_init(&bb, b->fd, &b->st, utf8_buf, 154 | CAST(size_t, utf8_end - utf8_buf)); 155 | 156 | if ((rv = file_softmagic(ms, &bb, NULL, NULL, 157 | TEXTTEST, text)) == 0) 158 | rv = -1; 159 | else 160 | need_separator = 1; 161 | buffer_fini(&bb); 162 | if ((ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION))) { 163 | rv = rv == -1 ? 0 : 1; 164 | goto done; 165 | } 166 | } 167 | 168 | if ((ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION))) { 169 | rv = 0; 170 | goto done; 171 | } 172 | 173 | /* Now try to discover other details about the file. */ 174 | for (i = 0; i < ulen; i++) { 175 | if (ubuf[i] == '\n') { 176 | if (seen_cr) 177 | n_crlf++; 178 | else 179 | n_lf++; 180 | last_line_end = i; 181 | } else if (seen_cr) 182 | n_cr++; 183 | 184 | seen_cr = (ubuf[i] == '\r'); 185 | if (seen_cr) 186 | last_line_end = i; 187 | 188 | if (ubuf[i] == 0x85) { /* X3.64/ECMA-43 "next line" character */ 189 | n_nel++; 190 | last_line_end = i; 191 | } 192 | 193 | /* If this line is _longer_ than MAXLINELEN, remember it. */ 194 | if (i > last_line_end + MAXLINELEN) { 195 | size_t ll = i - last_line_end; 196 | if (ll > has_long_lines) 197 | has_long_lines = ll; 198 | } 199 | 200 | if (ubuf[i] == '\033') 201 | has_escapes = 1; 202 | if (ubuf[i] == '\b') 203 | has_backspace = 1; 204 | } 205 | 206 | /* Beware, if the data has been truncated, the final CR could have 207 | been followed by a LF. If we have ms->bytes_max bytes, it indicates 208 | that the data might have been truncated, probably even before 209 | this function was called. */ 210 | if (seen_cr && nbytes < ms->bytes_max) 211 | n_cr++; 212 | 213 | if (strcmp(type, "binary") == 0) { 214 | rv = 0; 215 | goto done; 216 | } 217 | len = file_printedlen(ms); 218 | if (mime) { 219 | if ((mime & MAGIC_MIME_TYPE) != 0) { 220 | if (len) { 221 | /* 222 | * Softmagic printed something, we 223 | * are either done, or we need a separator 224 | */ 225 | if ((ms->flags & MAGIC_CONTINUE) == 0) { 226 | rv = 1; 227 | goto done; 228 | } 229 | if (need_separator && file_separator(ms) == -1) 230 | goto done; 231 | } else { 232 | if (file_printf(ms, "text/plain") == -1) 233 | goto done; 234 | } 235 | } 236 | } else { 237 | if (len) { 238 | switch (file_replace(ms, " text$", ", ")) { 239 | case 0: 240 | switch (file_replace(ms, " text executable$", 241 | ", ")) { 242 | case 0: 243 | if (file_printf(ms, ", ") == -1) 244 | goto done; 245 | break; 246 | case -1: 247 | goto done; 248 | default: 249 | executable = 1; 250 | break; 251 | } 252 | break; 253 | case -1: 254 | goto done; 255 | default: 256 | break; 257 | } 258 | } 259 | 260 | if (file_printf(ms, "%s", code) == -1) 261 | goto done; 262 | 263 | if (subtype) { 264 | if (file_printf(ms, " %s", subtype) == -1) 265 | goto done; 266 | } 267 | 268 | if (file_printf(ms, " %s", type) == -1) 269 | goto done; 270 | 271 | if (executable) 272 | if (file_printf(ms, " executable") == -1) 273 | goto done; 274 | 275 | if (has_long_lines) 276 | if (file_printf(ms, ", with very long lines (%zu)", 277 | has_long_lines) == -1) 278 | goto done; 279 | 280 | /* 281 | * Only report line terminators if we find one other than LF, 282 | * or if we find none at all. 283 | */ 284 | if ((n_crlf == 0 && n_cr == 0 && n_nel == 0 && n_lf == 0) || 285 | (n_crlf != 0 || n_cr != 0 || n_nel != 0)) { 286 | if (file_printf(ms, ", with") == -1) 287 | goto done; 288 | 289 | if (n_crlf == 0 && n_cr == 0 && 290 | n_nel == 0 && n_lf == 0) { 291 | if (file_printf(ms, " no") == -1) 292 | goto done; 293 | } else { 294 | if (n_crlf) { 295 | if (file_printf(ms, " CRLF") == -1) 296 | goto done; 297 | if (n_cr || n_lf || n_nel) 298 | if (file_printf(ms, ",") == -1) 299 | goto done; 300 | } 301 | if (n_cr) { 302 | if (file_printf(ms, " CR") == -1) 303 | goto done; 304 | if (n_lf || n_nel) 305 | if (file_printf(ms, ",") == -1) 306 | goto done; 307 | } 308 | if (n_lf) { 309 | if (file_printf(ms, " LF") == -1) 310 | goto done; 311 | if (n_nel) 312 | if (file_printf(ms, ",") == -1) 313 | goto done; 314 | } 315 | if (n_nel) 316 | if (file_printf(ms, " NEL") == -1) 317 | goto done; 318 | } 319 | 320 | if (file_printf(ms, " line terminators") == -1) 321 | goto done; 322 | } 323 | 324 | if (has_escapes) 325 | if (file_printf(ms, ", with escape sequences") == -1) 326 | goto done; 327 | if (has_backspace) 328 | if (file_printf(ms, ", with overstriking") == -1) 329 | goto done; 330 | } 331 | rv = 1; 332 | done: 333 | free(utf8_buf); 334 | 335 | return rv; 336 | } 337 | 338 | /* 339 | * Encode Unicode string as UTF-8, returning pointer to character 340 | * after end of string, or NULL if an invalid character is found. 341 | */ 342 | private unsigned char * 343 | encode_utf8(unsigned char *buf, size_t len, file_unichar_t *ubuf, size_t ulen) 344 | { 345 | size_t i; 346 | unsigned char *end = buf + len; 347 | 348 | for (i = 0; i < ulen; i++) { 349 | if (ubuf[i] <= 0x7f) { 350 | if (end - buf < 1) 351 | return NULL; 352 | *buf++ = CAST(unsigned char, ubuf[i]); 353 | continue; 354 | } 355 | if (ubuf[i] <= 0x7ff) { 356 | if (end - buf < 2) 357 | return NULL; 358 | *buf++ = CAST(unsigned char, (ubuf[i] >> 6) + 0xc0); 359 | goto out1; 360 | } 361 | if (ubuf[i] <= 0xffff) { 362 | if (end - buf < 3) 363 | return NULL; 364 | *buf++ = CAST(unsigned char, (ubuf[i] >> 12) + 0xe0); 365 | goto out2; 366 | } 367 | if (ubuf[i] <= 0x1fffff) { 368 | if (end - buf < 4) 369 | return NULL; 370 | *buf++ = CAST(unsigned char, (ubuf[i] >> 18) + 0xf0); 371 | goto out3; 372 | } 373 | if (ubuf[i] <= 0x3ffffff) { 374 | if (end - buf < 5) 375 | return NULL; 376 | *buf++ = CAST(unsigned char, (ubuf[i] >> 24) + 0xf8); 377 | goto out4; 378 | } 379 | if (ubuf[i] <= 0x7fffffff) { 380 | if (end - buf < 6) 381 | return NULL; 382 | *buf++ = CAST(unsigned char, (ubuf[i] >> 30) + 0xfc); 383 | goto out5; 384 | } 385 | /* Invalid character */ 386 | return NULL; 387 | out5: *buf++ = CAST(unsigned char, ((ubuf[i] >> 24) & 0x3f) + 0x80); 388 | out4: *buf++ = CAST(unsigned char, ((ubuf[i] >> 18) & 0x3f) + 0x80); 389 | out3: *buf++ = CAST(unsigned char, ((ubuf[i] >> 12) & 0x3f) + 0x80); 390 | out2: *buf++ = CAST(unsigned char, ((ubuf[i] >> 6) & 0x3f) + 0x80); 391 | out1: *buf++ = CAST(unsigned char, ((ubuf[i] >> 0) & 0x3f) + 0x80); 392 | } 393 | 394 | return buf; 395 | } 396 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/asctime_r.c: -------------------------------------------------------------------------------- 1 | /* $File$ */ 2 | 3 | #include "file.h" 4 | #ifndef lint 5 | FILE_RCSID("@(#)$File: ascmagic.c,v 1.84 2011/12/08 12:38:24 rrt Exp $") 6 | #endif /* lint */ 7 | #include 8 | #include 9 | 10 | /* asctime_r is not thread-safe anyway */ 11 | char * 12 | asctime_r(const struct tm *t, char *dst) 13 | { 14 | char *p = asctime(t); 15 | if (p == NULL) 16 | return NULL; 17 | memcpy(dst, p, 26); 18 | return dst; 19 | } 20 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/asprintf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Ian F. Darwin 1986-1995. 3 | * Software written by Ian F. Darwin and others; 4 | * maintained 1995-present by Christos Zoulas and others. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice immediately at the beginning of the file, without modification, 11 | * this list of conditions, and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 20 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | 29 | #include "file.h" 30 | 31 | #ifndef lint 32 | FILE_RCSID("@(#)$File: asprintf.c,v 1.5 2018/09/09 20:33:28 christos Exp $") 33 | #endif 34 | 35 | int asprintf(char **ptr, const char *fmt, ...) 36 | { 37 | va_list vargs; 38 | int retval; 39 | 40 | va_start(vargs, fmt); 41 | retval = vasprintf(ptr, fmt, vargs); 42 | va_end(vargs); 43 | 44 | return retval; 45 | } 46 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/buffer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Christos Zoulas 2017. 3 | * All Rights Reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice immediately at the beginning of the file, without modification, 10 | * this list of conditions, and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 | * SUCH DAMAGE. 26 | */ 27 | #include "file.h" 28 | 29 | #ifndef lint 30 | FILE_RCSID("@(#)$File: buffer.c,v 1.8 2020/02/16 15:52:49 christos Exp $") 31 | #endif /* lint */ 32 | 33 | #include "magic.h" 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | void 40 | buffer_init(struct buffer *b, int fd, const struct stat *st, const void *data, 41 | size_t len) 42 | { 43 | b->fd = fd; 44 | if (st) 45 | memcpy(&b->st, st, sizeof(b->st)); 46 | else if (b->fd == -1 || fstat(b->fd, &b->st) == -1) 47 | memset(&b->st, 0, sizeof(b->st)); 48 | b->fbuf = data; 49 | b->flen = len; 50 | b->eoff = 0; 51 | b->ebuf = NULL; 52 | b->elen = 0; 53 | } 54 | 55 | void 56 | buffer_fini(struct buffer *b) 57 | { 58 | free(b->ebuf); 59 | } 60 | 61 | int 62 | buffer_fill(const struct buffer *bb) 63 | { 64 | struct buffer *b = CCAST(struct buffer *, bb); 65 | 66 | if (b->elen != 0) 67 | return b->elen == FILE_BADSIZE ? -1 : 0; 68 | 69 | if (!S_ISREG(b->st.st_mode)) 70 | goto out; 71 | 72 | b->elen = CAST(size_t, b->st.st_size) < b->flen ? 73 | CAST(size_t, b->st.st_size) : b->flen; 74 | if ((b->ebuf = malloc(b->elen)) == NULL) 75 | goto out; 76 | 77 | b->eoff = b->st.st_size - b->elen; 78 | if (pread(b->fd, b->ebuf, b->elen, b->eoff) == -1) { 79 | free(b->ebuf); 80 | b->ebuf = NULL; 81 | goto out; 82 | } 83 | 84 | return 0; 85 | out: 86 | b->elen = FILE_BADSIZE; 87 | return -1; 88 | } 89 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/cdf.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2008 Christos Zoulas 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 15 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 16 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 18 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | * POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | /* 27 | * Parse Composite Document Files, the format used in Microsoft Office 28 | * document files before they switched to zipped XML. 29 | * Info from: http://sc.openoffice.org/compdocfileformat.pdf 30 | * 31 | * N.B. This is the "Composite Document File" format, and not the 32 | * "Compound Document Format", nor the "Channel Definition Format". 33 | */ 34 | 35 | #ifndef _H_CDF_ 36 | #define _H_CDF_ 37 | 38 | #ifdef WIN32 39 | #include 40 | #define timespec timeval 41 | #define tv_nsec tv_usec 42 | #endif 43 | #ifdef __DJGPP__ 44 | #define timespec timeval 45 | #define tv_nsec tv_usec 46 | #endif 47 | 48 | typedef int32_t cdf_secid_t; 49 | 50 | #define CDF_LOOP_LIMIT 10000 51 | #define CDF_ELEMENT_LIMIT 100000 52 | 53 | #define CDF_SECID_NULL 0 54 | #define CDF_SECID_FREE -1 55 | #define CDF_SECID_END_OF_CHAIN -2 56 | #define CDF_SECID_SECTOR_ALLOCATION_TABLE -3 57 | #define CDF_SECID_MASTER_SECTOR_ALLOCATION_TABLE -4 58 | 59 | typedef struct { 60 | uint64_t h_magic; 61 | #define CDF_MAGIC 0xE11AB1A1E011CFD0LL 62 | uint64_t h_uuid[2]; 63 | uint16_t h_revision; 64 | uint16_t h_version; 65 | uint16_t h_byte_order; 66 | uint16_t h_sec_size_p2; 67 | uint16_t h_short_sec_size_p2; 68 | uint8_t h_unused0[10]; 69 | uint32_t h_num_sectors_in_sat; 70 | uint32_t h_secid_first_directory; 71 | uint8_t h_unused1[4]; 72 | uint32_t h_min_size_standard_stream; 73 | cdf_secid_t h_secid_first_sector_in_short_sat; 74 | uint32_t h_num_sectors_in_short_sat; 75 | cdf_secid_t h_secid_first_sector_in_master_sat; 76 | uint32_t h_num_sectors_in_master_sat; 77 | cdf_secid_t h_master_sat[436/4]; 78 | } cdf_header_t; 79 | 80 | #define CDF_SEC_SIZE(h) CAST(size_t, 1 << (h)->h_sec_size_p2) 81 | #define CDF_SEC_POS(h, secid) (CDF_SEC_SIZE(h) + (secid) * CDF_SEC_SIZE(h)) 82 | #define CDF_SHORT_SEC_SIZE(h) CAST(size_t, 1 << (h)->h_short_sec_size_p2) 83 | #define CDF_SHORT_SEC_POS(h, secid) ((secid) * CDF_SHORT_SEC_SIZE(h)) 84 | 85 | typedef int32_t cdf_dirid_t; 86 | #define CDF_DIRID_NULL -1 87 | 88 | typedef int64_t cdf_timestamp_t; 89 | #define CDF_BASE_YEAR 1601 90 | #define CDF_TIME_PREC 10000000 91 | 92 | typedef struct { 93 | uint16_t d_name[32]; 94 | uint16_t d_namelen; 95 | uint8_t d_type; 96 | #define CDF_DIR_TYPE_EMPTY 0 97 | #define CDF_DIR_TYPE_USER_STORAGE 1 98 | #define CDF_DIR_TYPE_USER_STREAM 2 99 | #define CDF_DIR_TYPE_LOCKBYTES 3 100 | #define CDF_DIR_TYPE_PROPERTY 4 101 | #define CDF_DIR_TYPE_ROOT_STORAGE 5 102 | uint8_t d_color; 103 | #define CDF_DIR_COLOR_READ 0 104 | #define CDF_DIR_COLOR_BLACK 1 105 | cdf_dirid_t d_left_child; 106 | cdf_dirid_t d_right_child; 107 | cdf_dirid_t d_storage; 108 | uint64_t d_storage_uuid[2]; 109 | uint32_t d_flags; 110 | cdf_timestamp_t d_created; 111 | cdf_timestamp_t d_modified; 112 | cdf_secid_t d_stream_first_sector; 113 | uint32_t d_size; 114 | uint32_t d_unused0; 115 | } cdf_directory_t; 116 | 117 | #define CDF_DIRECTORY_SIZE 128 118 | 119 | typedef struct { 120 | cdf_secid_t *sat_tab; 121 | size_t sat_len; 122 | } cdf_sat_t; 123 | 124 | typedef struct { 125 | cdf_directory_t *dir_tab; 126 | size_t dir_len; 127 | } cdf_dir_t; 128 | 129 | typedef struct { 130 | void *sst_tab; 131 | size_t sst_len; /* Number of sectors */ 132 | size_t sst_dirlen; /* Directory sector size */ 133 | size_t sst_ss; /* Sector size */ 134 | } cdf_stream_t; 135 | 136 | typedef struct { 137 | uint32_t cl_dword; 138 | uint16_t cl_word[2]; 139 | uint8_t cl_two[2]; 140 | uint8_t cl_six[6]; 141 | } cdf_classid_t; 142 | 143 | typedef struct { 144 | uint16_t si_byte_order; 145 | uint16_t si_zero; 146 | uint16_t si_os_version; 147 | uint16_t si_os; 148 | cdf_classid_t si_class; 149 | uint32_t si_count; 150 | } cdf_summary_info_header_t; 151 | 152 | #define CDF_SECTION_DECLARATION_OFFSET 0x1c 153 | 154 | typedef struct { 155 | cdf_classid_t sd_class; 156 | uint32_t sd_offset; 157 | } cdf_section_declaration_t; 158 | 159 | typedef struct { 160 | uint32_t sh_len; 161 | uint32_t sh_properties; 162 | } cdf_section_header_t; 163 | 164 | typedef struct { 165 | uint32_t pi_id; 166 | uint32_t pi_type; 167 | union { 168 | uint16_t _pi_u16; 169 | int16_t _pi_s16; 170 | uint32_t _pi_u32; 171 | int32_t _pi_s32; 172 | uint64_t _pi_u64; 173 | int64_t _pi_s64; 174 | cdf_timestamp_t _pi_tp; 175 | float _pi_f; 176 | double _pi_d; 177 | struct { 178 | uint32_t s_len; 179 | const char *s_buf; 180 | } _pi_str; 181 | } pi_val; 182 | #define pi_u64 pi_val._pi_u64 183 | #define pi_s64 pi_val._pi_s64 184 | #define pi_u32 pi_val._pi_u32 185 | #define pi_s32 pi_val._pi_s32 186 | #define pi_u16 pi_val._pi_u16 187 | #define pi_s16 pi_val._pi_s16 188 | #define pi_f pi_val._pi_f 189 | #define pi_d pi_val._pi_d 190 | #define pi_tp pi_val._pi_tp 191 | #define pi_str pi_val._pi_str 192 | } cdf_property_info_t; 193 | 194 | #define CDF_ROUND(val, by) (((val) + (by) - 1) & ~((by) - 1)) 195 | 196 | /* Variant type definitions */ 197 | #define CDF_EMPTY 0x00000000 198 | #define CDF_NULL 0x00000001 199 | #define CDF_SIGNED16 0x00000002 200 | #define CDF_SIGNED32 0x00000003 201 | #define CDF_FLOAT 0x00000004 202 | #define CDF_DOUBLE 0x00000005 203 | #define CDF_CY 0x00000006 204 | #define CDF_DATE 0x00000007 205 | #define CDF_BSTR 0x00000008 206 | #define CDF_DISPATCH 0x00000009 207 | #define CDF_ERROR 0x0000000a 208 | #define CDF_BOOL 0x0000000b 209 | #define CDF_VARIANT 0x0000000c 210 | #define CDF_UNKNOWN 0x0000000d 211 | #define CDF_DECIMAL 0x0000000e 212 | #define CDF_SIGNED8 0x00000010 213 | #define CDF_UNSIGNED8 0x00000011 214 | #define CDF_UNSIGNED16 0x00000012 215 | #define CDF_UNSIGNED32 0x00000013 216 | #define CDF_SIGNED64 0x00000014 217 | #define CDF_UNSIGNED64 0x00000015 218 | #define CDF_INT 0x00000016 219 | #define CDF_UINT 0x00000017 220 | #define CDF_VOID 0x00000018 221 | #define CDF_HRESULT 0x00000019 222 | #define CDF_PTR 0x0000001a 223 | #define CDF_SAFEARRAY 0x0000001b 224 | #define CDF_CARRAY 0x0000001c 225 | #define CDF_USERDEFINED 0x0000001d 226 | #define CDF_LENGTH32_STRING 0x0000001e 227 | #define CDF_LENGTH32_WSTRING 0x0000001f 228 | #define CDF_FILETIME 0x00000040 229 | #define CDF_BLOB 0x00000041 230 | #define CDF_STREAM 0x00000042 231 | #define CDF_STORAGE 0x00000043 232 | #define CDF_STREAMED_OBJECT 0x00000044 233 | #define CDF_STORED_OBJECT 0x00000045 234 | #define CDF_BLOB_OBJECT 0x00000046 235 | #define CDF_CLIPBOARD 0x00000047 236 | #define CDF_CLSID 0x00000048 237 | #define CDF_VECTOR 0x00001000 238 | #define CDF_ARRAY 0x00002000 239 | #define CDF_BYREF 0x00004000 240 | #define CDF_RESERVED 0x00008000 241 | #define CDF_ILLEGAL 0x0000ffff 242 | #define CDF_ILLEGALMASKED 0x00000fff 243 | #define CDF_TYPEMASK 0x00000fff 244 | 245 | #define CDF_PROPERTY_CODE_PAGE 0x00000001 246 | #define CDF_PROPERTY_TITLE 0x00000002 247 | #define CDF_PROPERTY_SUBJECT 0x00000003 248 | #define CDF_PROPERTY_AUTHOR 0x00000004 249 | #define CDF_PROPERTY_KEYWORDS 0x00000005 250 | #define CDF_PROPERTY_COMMENTS 0x00000006 251 | #define CDF_PROPERTY_TEMPLATE 0x00000007 252 | #define CDF_PROPERTY_LAST_SAVED_BY 0x00000008 253 | #define CDF_PROPERTY_REVISION_NUMBER 0x00000009 254 | #define CDF_PROPERTY_TOTAL_EDITING_TIME 0x0000000a 255 | #define CDF_PROPERTY_LAST_PRINTED 0X0000000b 256 | #define CDF_PROPERTY_CREATE_TIME 0x0000000c 257 | #define CDF_PROPERTY_LAST_SAVED_TIME 0x0000000d 258 | #define CDF_PROPERTY_NUMBER_OF_PAGES 0x0000000e 259 | #define CDF_PROPERTY_NUMBER_OF_WORDS 0x0000000f 260 | #define CDF_PROPERTY_NUMBER_OF_CHARACTERS 0x00000010 261 | #define CDF_PROPERTY_THUMBNAIL 0x00000011 262 | #define CDF_PROPERTY_NAME_OF_APPLICATION 0x00000012 263 | #define CDF_PROPERTY_SECURITY 0x00000013 264 | #define CDF_PROPERTY_LOCALE_ID 0x80000000 265 | 266 | typedef struct { 267 | int i_fd; 268 | const unsigned char *i_buf; 269 | size_t i_len; 270 | } cdf_info_t; 271 | 272 | 273 | typedef struct { 274 | uint16_t ce_namlen; 275 | uint32_t ce_num; 276 | uint64_t ce_timestamp; 277 | uint16_t ce_name[256]; 278 | } cdf_catalog_entry_t; 279 | 280 | typedef struct { 281 | size_t cat_num; 282 | cdf_catalog_entry_t cat_e[1]; 283 | } cdf_catalog_t; 284 | 285 | struct timespec; 286 | int cdf_timestamp_to_timespec(struct timespec *, cdf_timestamp_t); 287 | int cdf_timespec_to_timestamp(cdf_timestamp_t *, const struct timespec *); 288 | int cdf_read_header(const cdf_info_t *, cdf_header_t *); 289 | void cdf_swap_header(cdf_header_t *); 290 | void cdf_unpack_header(cdf_header_t *, char *); 291 | void cdf_swap_dir(cdf_directory_t *); 292 | void cdf_unpack_dir(cdf_directory_t *, char *); 293 | void cdf_swap_class(cdf_classid_t *); 294 | ssize_t cdf_read_sector(const cdf_info_t *, void *, size_t, size_t, 295 | const cdf_header_t *, cdf_secid_t); 296 | ssize_t cdf_read_short_sector(const cdf_stream_t *, void *, size_t, size_t, 297 | const cdf_header_t *, cdf_secid_t); 298 | int cdf_read_sat(const cdf_info_t *, cdf_header_t *, cdf_sat_t *); 299 | size_t cdf_count_chain(const cdf_sat_t *, cdf_secid_t, size_t); 300 | int cdf_read_long_sector_chain(const cdf_info_t *, const cdf_header_t *, 301 | const cdf_sat_t *, cdf_secid_t, size_t, cdf_stream_t *); 302 | int cdf_read_short_sector_chain(const cdf_header_t *, const cdf_sat_t *, 303 | const cdf_stream_t *, cdf_secid_t, size_t, cdf_stream_t *); 304 | int cdf_read_sector_chain(const cdf_info_t *, const cdf_header_t *, 305 | const cdf_sat_t *, const cdf_sat_t *, const cdf_stream_t *, cdf_secid_t, 306 | size_t, cdf_stream_t *); 307 | int cdf_read_dir(const cdf_info_t *, const cdf_header_t *, const cdf_sat_t *, 308 | cdf_dir_t *); 309 | int cdf_read_ssat(const cdf_info_t *, const cdf_header_t *, const cdf_sat_t *, 310 | cdf_sat_t *); 311 | int cdf_read_short_stream(const cdf_info_t *, const cdf_header_t *, 312 | const cdf_sat_t *, const cdf_dir_t *, cdf_stream_t *, 313 | const cdf_directory_t **); 314 | int cdf_read_property_info(const cdf_stream_t *, const cdf_header_t *, uint32_t, 315 | cdf_property_info_t **, size_t *, size_t *); 316 | int cdf_read_user_stream(const cdf_info_t *, const cdf_header_t *, 317 | const cdf_sat_t *, const cdf_sat_t *, const cdf_stream_t *, 318 | const cdf_dir_t *, const char *, cdf_stream_t *); 319 | int cdf_find_stream(const cdf_dir_t *, const char *, int); 320 | int cdf_zero_stream(cdf_stream_t *); 321 | int cdf_read_doc_summary_info(const cdf_info_t *, const cdf_header_t *, 322 | const cdf_sat_t *, const cdf_sat_t *, const cdf_stream_t *, 323 | const cdf_dir_t *, cdf_stream_t *); 324 | int cdf_read_summary_info(const cdf_info_t *, const cdf_header_t *, 325 | const cdf_sat_t *, const cdf_sat_t *, const cdf_stream_t *, 326 | const cdf_dir_t *, cdf_stream_t *); 327 | int cdf_unpack_summary_info(const cdf_stream_t *, const cdf_header_t *, 328 | cdf_summary_info_header_t *, cdf_property_info_t **, size_t *); 329 | int cdf_unpack_catalog(const cdf_header_t *, const cdf_stream_t *, 330 | cdf_catalog_t **); 331 | int cdf_print_classid(char *, size_t, const cdf_classid_t *); 332 | int cdf_print_property_name(char *, size_t, uint32_t); 333 | int cdf_print_elapsed_time(char *, size_t, cdf_timestamp_t); 334 | uint16_t cdf_tole2(uint16_t); 335 | uint32_t cdf_tole4(uint32_t); 336 | uint64_t cdf_tole8(uint64_t); 337 | char *cdf_ctime(const time_t *, char *); 338 | char *cdf_u16tos8(char *, size_t, const uint16_t *); 339 | 340 | #ifdef CDF_DEBUG 341 | void cdf_dump_header(const cdf_header_t *); 342 | void cdf_dump_sat(const char *, const cdf_sat_t *, size_t); 343 | void cdf_dump(const void *, size_t); 344 | void cdf_dump_stream(const cdf_stream_t *); 345 | void cdf_dump_dir(const cdf_info_t *, const cdf_header_t *, const cdf_sat_t *, 346 | const cdf_sat_t *, const cdf_stream_t *, const cdf_dir_t *); 347 | void cdf_dump_property_info(const cdf_property_info_t *, size_t); 348 | void cdf_dump_summary_info(const cdf_header_t *, const cdf_stream_t *); 349 | void cdf_dump_catalog(const cdf_header_t *, const cdf_stream_t *); 350 | #endif 351 | 352 | 353 | #endif /* _H_CDF_ */ 354 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/cdf_time.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2008 Christos Zoulas 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 15 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 16 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 18 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | * POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #include "file.h" 28 | 29 | #ifndef lint 30 | FILE_RCSID("@(#)$File: cdf_time.c,v 1.19 2019/03/12 20:43:05 christos Exp $") 31 | #endif 32 | 33 | #include 34 | #ifdef TEST 35 | #include 36 | #endif 37 | #include 38 | 39 | #include "cdf.h" 40 | 41 | #define isleap(y) ((((y) % 4) == 0) && \ 42 | ((((y) % 100) != 0) || (((y) % 400) == 0))) 43 | 44 | static const int mdays[] = { 45 | 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 46 | }; 47 | 48 | /* 49 | * Return the number of days between jan 01 1601 and jan 01 of year. 50 | */ 51 | static int 52 | cdf_getdays(int year) 53 | { 54 | int days = 0; 55 | int y; 56 | 57 | for (y = CDF_BASE_YEAR; y < year; y++) 58 | days += isleap(y) + 365; 59 | 60 | return days; 61 | } 62 | 63 | /* 64 | * Return the day within the month 65 | */ 66 | static int 67 | cdf_getday(int year, int days) 68 | { 69 | size_t m; 70 | 71 | for (m = 0; m < __arraycount(mdays); m++) { 72 | int sub = mdays[m] + (m == 1 && isleap(year)); 73 | if (days < sub) 74 | return days; 75 | days -= sub; 76 | } 77 | return days; 78 | } 79 | 80 | /* 81 | * Return the 0...11 month number. 82 | */ 83 | static int 84 | cdf_getmonth(int year, int days) 85 | { 86 | size_t m; 87 | 88 | for (m = 0; m < __arraycount(mdays); m++) { 89 | days -= mdays[m]; 90 | if (m == 1 && isleap(year)) 91 | days--; 92 | if (days <= 0) 93 | return CAST(int, m); 94 | } 95 | return CAST(int, m); 96 | } 97 | 98 | int 99 | cdf_timestamp_to_timespec(struct timespec *ts, cdf_timestamp_t t) 100 | { 101 | struct tm tm; 102 | #ifdef HAVE_STRUCT_TM_TM_ZONE 103 | static char UTC[] = "UTC"; 104 | #endif 105 | int rdays; 106 | 107 | /* Unit is 100's of nanoseconds */ 108 | ts->tv_nsec = (t % CDF_TIME_PREC) * 100; 109 | 110 | t /= CDF_TIME_PREC; 111 | tm.tm_sec = CAST(int, t % 60); 112 | t /= 60; 113 | 114 | tm.tm_min = CAST(int, t % 60); 115 | t /= 60; 116 | 117 | tm.tm_hour = CAST(int, t % 24); 118 | t /= 24; 119 | 120 | /* XXX: Approx */ 121 | tm.tm_year = CAST(int, CDF_BASE_YEAR + (t / 365)); 122 | 123 | rdays = cdf_getdays(tm.tm_year); 124 | t -= rdays - 1; 125 | tm.tm_mday = cdf_getday(tm.tm_year, CAST(int, t)); 126 | tm.tm_mon = cdf_getmonth(tm.tm_year, CAST(int, t)); 127 | tm.tm_wday = 0; 128 | tm.tm_yday = 0; 129 | tm.tm_isdst = 0; 130 | #ifdef HAVE_STRUCT_TM_TM_GMTOFF 131 | tm.tm_gmtoff = 0; 132 | #endif 133 | #ifdef HAVE_STRUCT_TM_TM_ZONE 134 | tm.tm_zone = UTC; 135 | #endif 136 | tm.tm_year -= 1900; 137 | ts->tv_sec = mktime(&tm); 138 | if (ts->tv_sec == -1) { 139 | errno = EINVAL; 140 | return -1; 141 | } 142 | return 0; 143 | } 144 | 145 | int 146 | /*ARGSUSED*/ 147 | cdf_timespec_to_timestamp(cdf_timestamp_t *t, const struct timespec *ts) 148 | { 149 | #ifndef __lint__ 150 | (void)&t; 151 | (void)&ts; 152 | #endif 153 | #ifdef notyet 154 | struct tm tm; 155 | if (gmtime_r(&ts->ts_sec, &tm) == NULL) { 156 | errno = EINVAL; 157 | return -1; 158 | } 159 | *t = (ts->ts_nsec / 100) * CDF_TIME_PREC; 160 | *t = tm.tm_sec; 161 | *t += tm.tm_min * 60; 162 | *t += tm.tm_hour * 60 * 60; 163 | *t += tm.tm_mday * 60 * 60 * 24; 164 | #endif 165 | return 0; 166 | } 167 | 168 | char * 169 | cdf_ctime(const time_t *sec, char *buf) 170 | { 171 | char *ptr = ctime_r(sec, buf); 172 | if (ptr != NULL) 173 | return buf; 174 | (void)snprintf(buf, 26, "*Bad* %#16.16" INT64_T_FORMAT "x\n", 175 | CAST(long long, *sec)); 176 | return buf; 177 | } 178 | 179 | 180 | #ifdef TEST_TIME 181 | int 182 | main(int argc, char *argv[]) 183 | { 184 | struct timespec ts; 185 | char buf[25]; 186 | static const cdf_timestamp_t tst = 0x01A5E403C2D59C00ULL; 187 | static const char *ref = "Sat Apr 23 01:30:00 1977"; 188 | char *p, *q; 189 | 190 | cdf_timestamp_to_timespec(&ts, tst); 191 | p = cdf_ctime(&ts.tv_sec, buf); 192 | if ((q = strchr(p, '\n')) != NULL) 193 | *q = '\0'; 194 | if (strcmp(ref, p) != 0) 195 | errx(1, "Error date %s != %s\n", ref, p); 196 | return 0; 197 | } 198 | #endif 199 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/config.h: -------------------------------------------------------------------------------- 1 | /* config.h. Generated from config.h.in by configure. */ 2 | /* config.h.in. Generated from configure.ac by autoheader. */ 3 | 4 | /* Define if building universal (internal helper macro) */ 5 | /* #undef AC_APPLE_UNIVERSAL_BUILD */ 6 | 7 | /* Define in built-in ELF support is used */ 8 | #define BUILTIN_ELF 1 9 | 10 | /* Enable bzlib compression support */ 11 | /* #undef BZLIBSUPPORT */ 12 | 13 | /* Define for ELF core file support */ 14 | #define ELFCORE 1 15 | 16 | /* Define to 1 if you have the `asctime_r' function. */ 17 | #define HAVE_ASCTIME_R 1 18 | 19 | /* Define to 1 if you have the `asprintf' function. */ 20 | #define HAVE_ASPRINTF 1 21 | 22 | /* Define to 1 if you have the header file. */ 23 | /* #undef HAVE_BZLIB_H */ 24 | 25 | /* Define to 1 if you have the `ctime_r' function. */ 26 | #define HAVE_CTIME_R 1 27 | 28 | /* HAVE_DAYLIGHT */ 29 | #define HAVE_DAYLIGHT 1 30 | 31 | /* Define to 1 if you have the declaration of `daylight', and to 0 if you 32 | don't. */ 33 | #define HAVE_DECL_DAYLIGHT 1 34 | 35 | /* Define to 1 if you have the declaration of `tzname', and to 0 if you don't. 36 | */ 37 | #define HAVE_DECL_TZNAME 1 38 | 39 | /* Define to 1 if you have the header file. */ 40 | #define HAVE_DLFCN_H 1 41 | 42 | /* Define to 1 if you have the `dprintf' function. */ 43 | #define HAVE_DPRINTF 1 44 | 45 | /* Define to 1 if you have the header file. */ 46 | #define HAVE_ERR_H 1 47 | 48 | /* Define to 1 if you have the header file. */ 49 | #define HAVE_FCNTL_H 1 50 | 51 | /* Define to 1 if you have the `fmtcheck' function. */ 52 | /* #undef HAVE_FMTCHECK */ 53 | 54 | /* Define to 1 if you have the `fork' function. */ 55 | #define HAVE_FORK 1 56 | 57 | /* Define to 1 if you have the `freelocale' function. */ 58 | #define HAVE_FREELOCALE 1 59 | 60 | /* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ 61 | #define HAVE_FSEEKO 1 62 | 63 | /* Define to 1 if you have the `getline' function. */ 64 | #define HAVE_GETLINE 1 65 | 66 | /* Define to 1 if you have the header file. */ 67 | #define HAVE_GETOPT_H 1 68 | 69 | /* Define to 1 if you have the `getopt_long' function. */ 70 | #define HAVE_GETOPT_LONG 1 71 | 72 | /* Define to 1 if you have the `getpagesize' function. */ 73 | #define HAVE_GETPAGESIZE 1 74 | 75 | /* Define to 1 if you have the `gmtime_r' function. */ 76 | #define HAVE_GMTIME_R 1 77 | 78 | /* Define to 1 if the system has the type `intptr_t'. */ 79 | #define HAVE_INTPTR_T 1 80 | 81 | /* Define to 1 if you have the header file. */ 82 | #define HAVE_INTTYPES_H 1 83 | 84 | /* Define to 1 if you have the `bz2' library (-lbz2). */ 85 | /* #undef HAVE_LIBBZ2 */ 86 | 87 | /* Define to 1 if you have the `gnurx' library (-lgnurx). */ 88 | /* #undef HAVE_LIBGNURX */ 89 | 90 | /* Define to 1 if you have the `lzma' library (-llzma). */ 91 | /* #undef HAVE_LIBLZMA */ 92 | 93 | /* Define to 1 if you have the `seccomp' library (-lseccomp). */ 94 | /* #undef HAVE_LIBSECCOMP */ 95 | 96 | /* Define to 1 if you have the `z' library (-lz). */ 97 | #define HAVE_LIBZ 1 98 | 99 | /* Define to 1 if you have the `localtime_r' function. */ 100 | #define HAVE_LOCALTIME_R 1 101 | 102 | /* Define to 1 if you have the header file. */ 103 | /* #undef HAVE_LZMA_H */ 104 | 105 | /* Define to 1 if mbrtowc and mbstate_t are properly declared. */ 106 | #define HAVE_MBRTOWC 1 107 | 108 | /* Define to 1 if declares mbstate_t. */ 109 | #define HAVE_MBSTATE_T 1 110 | 111 | /* Define to 1 if you have the `memmem' function. */ 112 | #define HAVE_MEMMEM 1 113 | 114 | /* Define to 1 if you have the header file. */ 115 | #define HAVE_MEMORY_H 1 116 | 117 | /* Define to 1 if you have the `mkostemp' function. */ 118 | #define HAVE_MKOSTEMP 1 119 | 120 | /* Define to 1 if you have the `mkstemp' function. */ 121 | #define HAVE_MKSTEMP 1 122 | 123 | /* Define to 1 if you have a working `mmap' system call. */ 124 | #define HAVE_MMAP 1 125 | 126 | /* Define to 1 if you have the `newlocale' function. */ 127 | #define HAVE_NEWLOCALE 1 128 | 129 | /* Define to 1 if you have the `pipe2' function. */ 130 | #define HAVE_PIPE2 1 131 | 132 | /* Define to 1 if you have the `pread' function. */ 133 | #define HAVE_PREAD 1 134 | 135 | /* Have sig_t type */ 136 | #define HAVE_SIG_T 1 137 | 138 | /* Define to 1 if you have the header file. */ 139 | #define HAVE_STDINT_H 1 140 | 141 | /* Define to 1 if you have the header file. */ 142 | #define HAVE_STDLIB_H 1 143 | 144 | /* Define to 1 if you have the `strcasestr' function. */ 145 | #define HAVE_STRCASESTR 1 146 | 147 | /* Define to 1 if you have the header file. */ 148 | #define HAVE_STRINGS_H 1 149 | 150 | /* Define to 1 if you have the header file. */ 151 | #define HAVE_STRING_H 1 152 | 153 | /* Define to 1 if you have the `strlcat' function. */ 154 | /* #undef HAVE_STRLCAT */ 155 | 156 | /* Define to 1 if you have the `strlcpy' function. */ 157 | /* #undef HAVE_STRLCPY */ 158 | 159 | /* Define to 1 if you have the `strndup' function. */ 160 | #define HAVE_STRNDUP 1 161 | 162 | /* Define to 1 if you have the `strtof' function. */ 163 | #define HAVE_STRTOF 1 164 | 165 | /* HAVE_STRUCT_OPTION */ 166 | #define HAVE_STRUCT_OPTION 1 167 | 168 | /* Define to 1 if `st_rdev' is a member of `struct stat'. */ 169 | #define HAVE_STRUCT_STAT_ST_RDEV 1 170 | 171 | /* Define to 1 if `tm_gmtoff' is a member of `struct tm'. */ 172 | #define HAVE_STRUCT_TM_TM_GMTOFF 1 173 | 174 | /* Define to 1 if `tm_zone' is a member of `struct tm'. */ 175 | #define HAVE_STRUCT_TM_TM_ZONE 1 176 | 177 | /* Define to 1 if you have the header file. */ 178 | #define HAVE_SYS_MMAN_H 1 179 | 180 | /* Define to 1 if you have the header file. */ 181 | #define HAVE_SYS_PARAM_H 1 182 | 183 | /* Define to 1 if you have the header file. */ 184 | #define HAVE_SYS_STAT_H 1 185 | 186 | /* Define to 1 if you have the header file. */ 187 | #define HAVE_SYS_SYSMACROS_H 1 188 | 189 | /* Define to 1 if you have the header file. */ 190 | #define HAVE_SYS_TIME_H 1 191 | 192 | /* Define to 1 if you have the header file. */ 193 | #define HAVE_SYS_TYPES_H 1 194 | 195 | /* Define to 1 if you have the header file. */ 196 | /* #undef HAVE_SYS_UTIME_H */ 197 | 198 | /* Define to 1 if you have that is POSIX.1 compatible. */ 199 | #define HAVE_SYS_WAIT_H 1 200 | 201 | /* HAVE_TM_ISDST */ 202 | #define HAVE_TM_ISDST 1 203 | 204 | /* HAVE_TM_ZONE */ 205 | #define HAVE_TM_ZONE 1 206 | 207 | /* HAVE_TZNAME */ 208 | #define HAVE_TZNAME 1 209 | 210 | /* Define to 1 if the system has the type `uintptr_t'. */ 211 | #define HAVE_UINTPTR_T 1 212 | 213 | /* Define to 1 if you have the header file. */ 214 | #define HAVE_UNISTD_H 1 215 | 216 | /* Define to 1 if you have the `uselocale' function. */ 217 | #define HAVE_USELOCALE 1 218 | 219 | /* Define to 1 if you have the `utime' function. */ 220 | #define HAVE_UTIME 1 221 | 222 | /* Define to 1 if you have the `utimes' function. */ 223 | #define HAVE_UTIMES 1 224 | 225 | /* Define to 1 if you have the header file. */ 226 | #define HAVE_UTIME_H 1 227 | 228 | /* Define to 1 if you have the `vasprintf' function. */ 229 | #define HAVE_VASPRINTF 1 230 | 231 | /* Define to 1 if you have the `vfork' function. */ 232 | #define HAVE_VFORK 1 233 | 234 | /* Define to 1 if you have the header file. */ 235 | /* #undef HAVE_VFORK_H */ 236 | 237 | /* Define to 1 or 0, depending whether the compiler supports simple visibility 238 | declarations. */ 239 | #define HAVE_VISIBILITY 1 240 | 241 | /* Define to 1 if you have the header file. */ 242 | #define HAVE_WCHAR_H 1 243 | 244 | /* Define to 1 if you have the header file. */ 245 | #define HAVE_WCTYPE_H 1 246 | 247 | /* Define to 1 if you have the `wcwidth' function. */ 248 | #define HAVE_WCWIDTH 1 249 | 250 | /* Define to 1 if `fork' works. */ 251 | #define HAVE_WORKING_FORK 1 252 | 253 | /* Define to 1 if `vfork' works. */ 254 | #define HAVE_WORKING_VFORK 1 255 | 256 | /* Define to 1 if you have the header file. */ 257 | /* #undef HAVE_XLOCALE_H */ 258 | 259 | /* Define to 1 if you have the header file. */ 260 | /* #undef HAVE_ZLIB_H */ 261 | 262 | /* Define to the sub-directory where libtool stores uninstalled libraries. */ 263 | #define LT_OBJDIR ".libs/" 264 | 265 | /* Define to 1 if `major', `minor', and `makedev' are declared in . 266 | */ 267 | /* #undef MAJOR_IN_MKDEV */ 268 | 269 | /* Define to 1 if `major', `minor', and `makedev' are declared in 270 | . */ 271 | #define MAJOR_IN_SYSMACROS 1 272 | 273 | /* Name of package */ 274 | #define PACKAGE "file" 275 | 276 | /* Define to the address where bug reports for this package should be sent. */ 277 | #define PACKAGE_BUGREPORT "christos@astron.com" 278 | 279 | /* Define to the full name of this package. */ 280 | #define PACKAGE_NAME "file" 281 | 282 | /* Define to the full name and version of this package. */ 283 | #define PACKAGE_STRING "file 5.40" 284 | 285 | /* Define to the one symbol short name of this package. */ 286 | #define PACKAGE_TARNAME "file" 287 | 288 | /* Define to the home page for this package. */ 289 | #define PACKAGE_URL "" 290 | 291 | /* Define to the version of this package. */ 292 | #define PACKAGE_VERSION "5.40" 293 | 294 | /* Define to 1 if you have the ANSI C header files. */ 295 | #define STDC_HEADERS 1 296 | 297 | /* Define to 1 if your declares `struct tm'. */ 298 | /* #undef TM_IN_SYS_TIME */ 299 | 300 | /* Enable extensions on AIX 3, Interix. */ 301 | #ifndef _ALL_SOURCE 302 | # define _ALL_SOURCE 1 303 | #endif 304 | /* Enable GNU extensions on systems that have them. */ 305 | #ifndef _GNU_SOURCE 306 | # define _GNU_SOURCE 1 307 | #endif 308 | /* Enable threading extensions on Solaris. */ 309 | #ifndef _POSIX_PTHREAD_SEMANTICS 310 | # define _POSIX_PTHREAD_SEMANTICS 1 311 | #endif 312 | /* Enable extensions on HP NonStop. */ 313 | #ifndef _TANDEM_SOURCE 314 | # define _TANDEM_SOURCE 1 315 | #endif 316 | /* Enable general extensions on Solaris. */ 317 | #ifndef __EXTENSIONS__ 318 | # define __EXTENSIONS__ 1 319 | #endif 320 | 321 | 322 | /* Version number of package */ 323 | #define VERSION "5.40" 324 | 325 | /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most 326 | significant byte first (like Motorola and SPARC, unlike Intel). */ 327 | #if defined AC_APPLE_UNIVERSAL_BUILD 328 | # if defined __BIG_ENDIAN__ 329 | # define WORDS_BIGENDIAN 1 330 | # endif 331 | #else 332 | # ifndef WORDS_BIGENDIAN 333 | /* # undef WORDS_BIGENDIAN */ 334 | # endif 335 | #endif 336 | 337 | /* Enable xzlib compression support */ 338 | /* #undef XZLIBSUPPORT */ 339 | 340 | /* Enable zlib compression support */ 341 | /* #undef ZLIBSUPPORT */ 342 | 343 | /* Enable large inode numbers on Mac OS X 10.5. */ 344 | #ifndef _DARWIN_USE_64_BIT_INODE 345 | # define _DARWIN_USE_64_BIT_INODE 1 346 | #endif 347 | 348 | /* Number of bits in a file offset, on hosts where this is settable. */ 349 | /* #undef _FILE_OFFSET_BITS */ 350 | 351 | /* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ 352 | /* #undef _LARGEFILE_SOURCE */ 353 | 354 | /* Define for large files, on AIX-style hosts. */ 355 | /* #undef _LARGE_FILES */ 356 | 357 | /* Define to 1 if on MINIX. */ 358 | /* #undef _MINIX */ 359 | 360 | /* Define to 2 if the system does not provide POSIX.1 features except with 361 | this defined. */ 362 | /* #undef _POSIX_1_SOURCE */ 363 | 364 | /* Define to 1 if you need to in order for `stat' and other things to work. */ 365 | /* #undef _POSIX_SOURCE */ 366 | 367 | /* Define for Solaris 2.5.1 so the uint32_t typedef from , 368 | , or is not used. If the typedef were allowed, the 369 | #define below would cause a syntax error. */ 370 | /* #undef _UINT32_T */ 371 | 372 | /* Define for Solaris 2.5.1 so the uint64_t typedef from , 373 | , or is not used. If the typedef were allowed, the 374 | #define below would cause a syntax error. */ 375 | /* #undef _UINT64_T */ 376 | 377 | /* Define for Solaris 2.5.1 so the uint8_t typedef from , 378 | , or is not used. If the typedef were allowed, the 379 | #define below would cause a syntax error. */ 380 | /* #undef _UINT8_T */ 381 | 382 | /* Define to the type of a signed integer type of width exactly 32 bits if 383 | such a type exists and the standard includes do not define it. */ 384 | /* #undef int32_t */ 385 | 386 | /* Define to the type of a signed integer type of width exactly 64 bits if 387 | such a type exists and the standard includes do not define it. */ 388 | /* #undef int64_t */ 389 | 390 | /* Define to the type of a signed integer type wide enough to hold a pointer, 391 | if such a type exists, and if the system does not define it. */ 392 | /* #undef intptr_t */ 393 | 394 | /* Define to a type if does not define. */ 395 | /* #undef mbstate_t */ 396 | 397 | /* Define to `long int' if does not define. */ 398 | /* #undef off_t */ 399 | 400 | /* Define to `int' if does not define. */ 401 | /* #undef pid_t */ 402 | 403 | /* Define to `unsigned int' if does not define. */ 404 | /* #undef size_t */ 405 | 406 | /* Define to the type of an unsigned integer type of width exactly 16 bits if 407 | such a type exists and the standard includes do not define it. */ 408 | /* #undef uint16_t */ 409 | 410 | /* Define to the type of an unsigned integer type of width exactly 32 bits if 411 | such a type exists and the standard includes do not define it. */ 412 | /* #undef uint32_t */ 413 | 414 | /* Define to the type of an unsigned integer type of width exactly 64 bits if 415 | such a type exists and the standard includes do not define it. */ 416 | /* #undef uint64_t */ 417 | 418 | /* Define to the type of an unsigned integer type of width exactly 8 bits if 419 | such a type exists and the standard includes do not define it. */ 420 | /* #undef uint8_t */ 421 | 422 | /* Define to the type of an unsigned integer type wide enough to hold a 423 | pointer, if such a type exists, and if the system does not define it. */ 424 | /* #undef uintptr_t */ 425 | 426 | /* Define as `fork' if `vfork' does not work. */ 427 | /* #undef vfork */ 428 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/ctime_r.c: -------------------------------------------------------------------------------- 1 | /* $File$ */ 2 | 3 | #include "file.h" 4 | #ifndef lint 5 | FILE_RCSID("@(#)$File: ascmagic.c,v 1.84 2011/12/08 12:38:24 rrt Exp $") 6 | #endif /* lint */ 7 | #include 8 | #include 9 | 10 | /* ctime_r is not thread-safe anyway */ 11 | char * 12 | ctime_r(const time_t *t, char *dst) 13 | { 14 | char *p = ctime(t); 15 | if (p == NULL) 16 | return NULL; 17 | memcpy(dst, p, 26); 18 | return dst; 19 | } 20 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/der.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2016 Christos Zoulas 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 15 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 16 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 18 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | * POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | /* 27 | * DER (Distinguished Encoding Rules) Parser 28 | * 29 | * Sources: 30 | * https://en.wikipedia.org/wiki/X.690 31 | * http://fm4dd.com/openssl/certexamples.htm 32 | * http://blog.engelke.com/2014/10/17/parsing-ber-and-der-encoded-asn-1-objects/ 33 | */ 34 | #ifndef TEST_DER 35 | #include "file.h" 36 | 37 | #ifndef lint 38 | FILE_RCSID("@(#)$File: der.c,v 1.21 2020/06/15 00:58:10 christos Exp $") 39 | #endif 40 | #else 41 | #define SIZE_T_FORMAT "z" 42 | #define CAST(a, b) ((a)(b)) 43 | #endif 44 | 45 | #include 46 | 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | 53 | #ifndef TEST_DER 54 | #include "magic.h" 55 | #include "der.h" 56 | #else 57 | #include 58 | #include 59 | #include 60 | #endif 61 | 62 | #define DER_BAD CAST(uint32_t, -1) 63 | 64 | #define DER_CLASS_UNIVERSAL 0 65 | #define DER_CLASS_APPLICATION 1 66 | #define DER_CLASS_CONTEXT 2 67 | #define DER_CLASS_PRIVATE 3 68 | #if defined(DEBUG_DER) || defined(TEST_DER) 69 | static const char der_class[] = "UACP"; 70 | #endif 71 | 72 | #define DER_TYPE_PRIMITIVE 0 73 | #define DER_TYPE_CONSTRUCTED 1 74 | #if defined(DEBUG_DER) || defined(TEST_DER) 75 | static const char der_type[] = "PC"; 76 | #endif 77 | 78 | #define DER_TAG_EOC 0x00 79 | #define DER_TAG_BOOLEAN 0x01 80 | #define DER_TAG_INTEGER 0x02 81 | #define DER_TAG_BIT STRING 0x03 82 | #define DER_TAG_OCTET_STRING 0x04 83 | #define DER_TAG_NULL 0x05 84 | #define DER_TAG_OBJECT_IDENTIFIER 0x06 85 | #define DER_TAG_OBJECT_DESCRIPTOR 0x07 86 | #define DER_TAG_EXTERNAL 0x08 87 | #define DER_TAG_REAL 0x09 88 | #define DER_TAG_ENUMERATED 0x0a 89 | #define DER_TAG_EMBEDDED_PDV 0x0b 90 | #define DER_TAG_UTF8_STRING 0x0c 91 | #define DER_TAG_RELATIVE_OID 0x0d 92 | #define DER_TAG_TIME 0x0e 93 | #define DER_TAG_RESERVED_2 0x0f 94 | #define DER_TAG_SEQUENCE 0x10 95 | #define DER_TAG_SET 0x11 96 | #define DER_TAG_NUMERIC_STRING 0x12 97 | #define DER_TAG_PRINTABLE_STRING 0x13 98 | #define DER_TAG_T61_STRING 0x14 99 | #define DER_TAG_VIDEOTEX_STRING 0x15 100 | #define DER_TAG_IA5_STRING 0x16 101 | #define DER_TAG_UTCTIME 0x17 102 | #define DER_TAG_GENERALIZED_TIME 0x18 103 | #define DER_TAG_GRAPHIC_STRING 0x19 104 | #define DER_TAG_VISIBLE_STRING 0x1a 105 | #define DER_TAG_GENERAL_STRING 0x1b 106 | #define DER_TAG_UNIVERSAL_STRING 0x1c 107 | #define DER_TAG_CHARACTER_STRING 0x1d 108 | #define DER_TAG_BMP_STRING 0x1e 109 | #define DER_TAG_DATE 0x1f 110 | #define DER_TAG_TIME_OF_DAY 0x20 111 | #define DER_TAG_DATE_TIME 0x21 112 | #define DER_TAG_DURATION 0x22 113 | #define DER_TAG_OID_IRI 0x23 114 | #define DER_TAG_RELATIVE_OID_IRI 0x24 115 | #define DER_TAG_LAST 0x25 116 | 117 | static const char *der__tag[] = { 118 | "eoc", "bool", "int", "bit_str", "octet_str", 119 | "null", "obj_id", "obj_desc", "ext", "real", 120 | "enum", "embed", "utf8_str", "rel_oid", "time", 121 | "res2", "seq", "set", "num_str", "prt_str", 122 | "t61_str", "vid_str", "ia5_str", "utc_time", "gen_time", 123 | "gr_str", "vis_str", "gen_str", "univ_str", "char_str", 124 | "bmp_str", "date", "tod", "datetime", "duration", 125 | "oid-iri", "rel-oid-iri", 126 | }; 127 | 128 | #ifdef DEBUG_DER 129 | #define DPRINTF(a) printf a 130 | #else 131 | #define DPRINTF(a) 132 | #endif 133 | 134 | #ifdef TEST_DER 135 | static uint8_t 136 | getclass(uint8_t c) 137 | { 138 | return c >> 6; 139 | } 140 | 141 | static uint8_t 142 | gettype(uint8_t c) 143 | { 144 | return (c >> 5) & 1; 145 | } 146 | #endif 147 | 148 | static uint32_t 149 | gettag(const uint8_t *c, size_t *p, size_t l) 150 | { 151 | uint32_t tag; 152 | 153 | if (*p >= l) 154 | return DER_BAD; 155 | 156 | tag = c[(*p)++] & 0x1f; 157 | 158 | if (tag != 0x1f) 159 | return tag; 160 | 161 | if (*p >= l) 162 | return DER_BAD; 163 | 164 | while (c[*p] >= 0x80) { 165 | tag = tag * 128 + c[(*p)++] - 0x80; 166 | if (*p >= l) 167 | return DER_BAD; 168 | } 169 | return tag; 170 | } 171 | 172 | /* 173 | * Read the length of a DER tag from the input. 174 | * 175 | * `c` is the input, `p` is an output parameter that specifies how much of the 176 | * input we consumed, and `l` is the maximum input length. 177 | * 178 | * Returns the length, or DER_BAD if the end of the input is reached or the 179 | * length exceeds the remaining input. 180 | */ 181 | static uint32_t 182 | getlength(const uint8_t *c, size_t *p, size_t l) 183 | { 184 | uint8_t digits, i; 185 | size_t len; 186 | int is_onebyte_result; 187 | 188 | if (*p >= l) { 189 | DPRINTF(("%s:[1] %zu >= %zu\n", __func__, *p, l)); 190 | return DER_BAD; 191 | } 192 | 193 | /* 194 | * Digits can either be 0b0 followed by the result, or 0b1 195 | * followed by the number of digits of the result. In either case, 196 | * we verify that we can read so many bytes from the input. 197 | */ 198 | is_onebyte_result = (c[*p] & 0x80) == 0; 199 | digits = c[(*p)++] & 0x7f; 200 | if (*p + digits >= l) { 201 | DPRINTF(("%s:[2] %zu + %u >= %zu\n", __func__, *p, digits, l)); 202 | return DER_BAD; 203 | } 204 | 205 | if (is_onebyte_result) 206 | return digits; 207 | 208 | /* 209 | * Decode len. We've already verified that we're allowed to read 210 | * `digits` bytes. 211 | */ 212 | len = 0; 213 | for (i = 0; i < digits; i++) 214 | len = (len << 8) | c[(*p)++]; 215 | 216 | if (len > UINT32_MAX - *p || *p + len > l) { 217 | DPRINTF(("%s:[3] bad len %zu + %zu >= %zu\n", 218 | __func__, *p, len, l)); 219 | return DER_BAD; 220 | } 221 | return CAST(uint32_t, len); 222 | } 223 | 224 | static const char * 225 | der_tag(char *buf, size_t len, uint32_t tag) 226 | { 227 | if (tag < DER_TAG_LAST) 228 | strlcpy(buf, der__tag[tag], len); 229 | else 230 | snprintf(buf, len, "%#x", tag); 231 | return buf; 232 | } 233 | 234 | #ifndef TEST_DER 235 | static int 236 | der_data(char *buf, size_t blen, uint32_t tag, const void *q, uint32_t len) 237 | { 238 | const uint8_t *d = CAST(const uint8_t *, q); 239 | switch (tag) { 240 | case DER_TAG_PRINTABLE_STRING: 241 | case DER_TAG_UTF8_STRING: 242 | case DER_TAG_IA5_STRING: 243 | return snprintf(buf, blen, "%.*s", len, RCAST(const char *, q)); 244 | case DER_TAG_UTCTIME: 245 | if (len < 12) 246 | break; 247 | return snprintf(buf, blen, 248 | "20%c%c-%c%c-%c%c %c%c:%c%c:%c%c GMT", d[0], d[1], d[2], 249 | d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11]); 250 | default: 251 | break; 252 | } 253 | 254 | for (uint32_t i = 0; i < len; i++) { 255 | uint32_t z = i << 1; 256 | if (z < blen - 2) 257 | snprintf(buf + z, blen - z, "%.2x", d[i]); 258 | } 259 | return len * 2; 260 | } 261 | 262 | int32_t 263 | der_offs(struct magic_set *ms, struct magic *m, size_t nbytes) 264 | { 265 | const uint8_t *b = RCAST(const uint8_t *, ms->search.s); 266 | size_t offs = 0, len = ms->search.s_len ? ms->search.s_len : nbytes; 267 | 268 | if (gettag(b, &offs, len) == DER_BAD) { 269 | DPRINTF(("%s: bad tag 1\n", __func__)); 270 | return -1; 271 | } 272 | DPRINTF(("%s1: %d %" SIZE_T_FORMAT "u %u\n", __func__, ms->offset, 273 | offs, m->offset)); 274 | 275 | uint32_t tlen = getlength(b, &offs, len); 276 | if (tlen == DER_BAD) { 277 | DPRINTF(("%s: bad tag 2\n", __func__)); 278 | return -1; 279 | } 280 | DPRINTF(("%s2: %d %" SIZE_T_FORMAT "u %u\n", __func__, ms->offset, 281 | offs, tlen)); 282 | 283 | offs += ms->offset + m->offset; 284 | DPRINTF(("cont_level = %d\n", m->cont_level)); 285 | #ifdef DEBUG_DER 286 | for (size_t i = 0; i < m->cont_level; i++) 287 | printf("cont_level[%" SIZE_T_FORMAT "u] = %u\n", i, 288 | ms->c.li[i].off); 289 | #endif 290 | if (m->cont_level != 0) { 291 | if (offs + tlen > nbytes) 292 | return -1; 293 | ms->c.li[m->cont_level - 1].off = CAST(int, offs + tlen); 294 | DPRINTF(("cont_level[%u] = %u\n", m->cont_level - 1, 295 | ms->c.li[m->cont_level - 1].off)); 296 | } 297 | return CAST(int32_t, offs); 298 | } 299 | 300 | int 301 | der_cmp(struct magic_set *ms, struct magic *m) 302 | { 303 | const uint8_t *b = RCAST(const uint8_t *, ms->search.s); 304 | const char *s = m->value.s; 305 | size_t offs = 0, len = ms->search.s_len; 306 | uint32_t tag, tlen; 307 | char buf[128]; 308 | 309 | DPRINTF(("%s: compare %zu bytes\n", __func__, len)); 310 | 311 | tag = gettag(b, &offs, len); 312 | if (tag == DER_BAD) { 313 | DPRINTF(("%s: bad tag 1\n", __func__)); 314 | return -1; 315 | } 316 | 317 | DPRINTF(("%s1: %d %" SIZE_T_FORMAT "u %u\n", __func__, ms->offset, 318 | offs, m->offset)); 319 | 320 | tlen = getlength(b, &offs, len); 321 | if (tlen == DER_BAD) { 322 | DPRINTF(("%s: bad tag 2\n", __func__)); 323 | return -1; 324 | } 325 | 326 | der_tag(buf, sizeof(buf), tag); 327 | if ((ms->flags & MAGIC_DEBUG) != 0) 328 | fprintf(stderr, "%s: tag %p got=%s exp=%s\n", __func__, b, 329 | buf, s); 330 | size_t slen = strlen(buf); 331 | 332 | if (strncmp(buf, s, slen) != 0) 333 | return 0; 334 | 335 | s += slen; 336 | 337 | again: 338 | switch (*s) { 339 | case '\0': 340 | return 1; 341 | case '=': 342 | s++; 343 | goto val; 344 | default: 345 | if (!isdigit(CAST(unsigned char, *s))) 346 | return 0; 347 | 348 | slen = 0; 349 | do 350 | slen = slen * 10 + *s - '0'; 351 | while (isdigit(CAST(unsigned char, *++s))); 352 | if ((ms->flags & MAGIC_DEBUG) != 0) 353 | fprintf(stderr, "%s: len %" SIZE_T_FORMAT "u %u\n", 354 | __func__, slen, tlen); 355 | if (tlen != slen) 356 | return 0; 357 | goto again; 358 | } 359 | val: 360 | DPRINTF(("%s: before data %" SIZE_T_FORMAT "u %u\n", __func__, offs, 361 | tlen)); 362 | der_data(buf, sizeof(buf), tag, b + offs, tlen); 363 | if ((ms->flags & MAGIC_DEBUG) != 0) 364 | fprintf(stderr, "%s: data %s %s\n", __func__, buf, s); 365 | if (strcmp(buf, s) != 0 && strcmp("x", s) != 0) 366 | return 0; 367 | strlcpy(ms->ms_value.s, buf, sizeof(ms->ms_value.s)); 368 | return 1; 369 | } 370 | #endif 371 | 372 | #ifdef TEST_DER 373 | static void 374 | printtag(uint32_t tag, const void *q, uint32_t len) 375 | { 376 | const uint8_t *d = q; 377 | switch (tag) { 378 | case DER_TAG_PRINTABLE_STRING: 379 | case DER_TAG_UTF8_STRING: 380 | case DER_TAG_IA5_STRING: 381 | case DER_TAG_UTCTIME: 382 | printf("%.*s\n", len, (const char *)q); 383 | return; 384 | default: 385 | break; 386 | } 387 | 388 | for (uint32_t i = 0; i < len; i++) 389 | printf("%.2x", d[i]); 390 | printf("\n"); 391 | } 392 | 393 | static void 394 | printdata(size_t level, const void *v, size_t x, size_t l) 395 | { 396 | const uint8_t *p = v, *ep = p + l; 397 | size_t ox; 398 | char buf[128]; 399 | 400 | while (p + x < ep) { 401 | const uint8_t *q; 402 | uint8_t c = getclass(p[x]); 403 | uint8_t t = gettype(p[x]); 404 | ox = x; 405 | // if (x != 0) 406 | // printf("%.2x %.2x %.2x\n", p[x - 1], p[x], p[x + 1]); 407 | uint32_t tag = gettag(p, &x, ep - p + x); 408 | if (p + x >= ep) 409 | break; 410 | uint32_t len = getlength(p, &x, ep - p + x); 411 | 412 | printf("%" SIZE_T_FORMAT "u %" SIZE_T_FORMAT "u-%" 413 | SIZE_T_FORMAT "u %c,%c,%s,%u:", level, ox, x, 414 | der_class[c], der_type[t], 415 | der_tag(buf, sizeof(buf), tag), len); 416 | q = p + x; 417 | if (p + len > ep) 418 | errx(EXIT_FAILURE, "corrupt der"); 419 | printtag(tag, q, len); 420 | if (t != DER_TYPE_PRIMITIVE) 421 | printdata(level + 1, p, x, len + x); 422 | x += len; 423 | } 424 | } 425 | 426 | int 427 | main(int argc, char *argv[]) 428 | { 429 | int fd; 430 | struct stat st; 431 | size_t l; 432 | void *p; 433 | 434 | if ((fd = open(argv[1], O_RDONLY)) == -1) 435 | err(EXIT_FAILURE, "open `%s'", argv[1]); 436 | if (fstat(fd, &st) == -1) 437 | err(EXIT_FAILURE, "stat `%s'", argv[1]); 438 | l = (size_t)st.st_size; 439 | if ((p = mmap(NULL, l, PROT_READ, MAP_FILE, fd, 0)) == MAP_FAILED) 440 | err(EXIT_FAILURE, "mmap `%s'", argv[1]); 441 | 442 | printdata(0, p, 0, l); 443 | munmap(p, l); 444 | return 0; 445 | } 446 | #endif 447 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/der.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2016 Christos Zoulas 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 15 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 16 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 18 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | * POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | extern int der_offs(struct magic_set *, struct magic *, size_t); 28 | extern int der_cmp(struct magic_set *, struct magic *); 29 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/dprintf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Ian F. Darwin 1986-1995. 3 | * Software written by Ian F. Darwin and others; 4 | * maintained 1995-present by Christos Zoulas and others. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice immediately at the beginning of the file, without modification, 11 | * this list of conditions, and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 20 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | #include "file.h" 29 | 30 | #ifndef lint 31 | FILE_RCSID("@(#)$File: dprintf.c,v 1.2 2018/09/09 20:33:28 christos Exp $") 32 | #endif /* lint */ 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | int 40 | dprintf(int fd, const char *fmt, ...) 41 | { 42 | va_list ap; 43 | /* Simpler than using vasprintf() here, since we never need more */ 44 | char buf[1024]; 45 | int len; 46 | 47 | va_start(ap, fmt); 48 | len = vsnprintf(buf, sizeof(buf), fmt, ap); 49 | va_end(ap); 50 | 51 | if ((size_t)len >= sizeof(buf)) 52 | return -1; 53 | 54 | if (write(fd, buf, (size_t)len) != len) 55 | return -1; 56 | 57 | return len; 58 | } 59 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/elfclass.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Christos Zoulas 2008. 3 | * All Rights Reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice immediately at the beginning of the file, without modification, 10 | * this list of conditions, and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 | * SUCH DAMAGE. 26 | */ 27 | if (nbytes <= sizeof(elfhdr)) 28 | return 0; 29 | 30 | u.l = 1; 31 | (void)memcpy(&elfhdr, buf, sizeof elfhdr); 32 | swap = (u.c[sizeof(int32_t) - 1] + 1) != elfhdr.e_ident[EI_DATA]; 33 | 34 | type = elf_getu16(swap, elfhdr.e_type); 35 | notecount = ms->elf_notes_max; 36 | switch (type) { 37 | #ifdef ELFCORE 38 | case ET_CORE: 39 | phnum = elf_getu16(swap, elfhdr.e_phnum); 40 | if (phnum > ms->elf_phnum_max) 41 | return toomany(ms, "program headers", phnum); 42 | flags |= FLAGS_IS_CORE; 43 | if (dophn_core(ms, clazz, swap, fd, 44 | CAST(off_t, elf_getu(swap, elfhdr.e_phoff)), phnum, 45 | CAST(size_t, elf_getu16(swap, elfhdr.e_phentsize)), 46 | fsize, &flags, ¬ecount) == -1) 47 | return -1; 48 | break; 49 | #endif 50 | case ET_EXEC: 51 | case ET_DYN: 52 | phnum = elf_getu16(swap, elfhdr.e_phnum); 53 | if (phnum > ms->elf_phnum_max) 54 | return toomany(ms, "program", phnum); 55 | shnum = elf_getu16(swap, elfhdr.e_shnum); 56 | if (shnum > ms->elf_shnum_max) 57 | return toomany(ms, "section", shnum); 58 | if (dophn_exec(ms, clazz, swap, fd, 59 | CAST(off_t, elf_getu(swap, elfhdr.e_phoff)), phnum, 60 | CAST(size_t, elf_getu16(swap, elfhdr.e_phentsize)), 61 | fsize, shnum, &flags, ¬ecount) == -1) 62 | return -1; 63 | /*FALLTHROUGH*/ 64 | case ET_REL: 65 | shnum = elf_getu16(swap, elfhdr.e_shnum); 66 | if (shnum > ms->elf_shnum_max) 67 | return toomany(ms, "section headers", shnum); 68 | if (doshn(ms, clazz, swap, fd, 69 | CAST(off_t, elf_getu(swap, elfhdr.e_shoff)), shnum, 70 | CAST(size_t, elf_getu16(swap, elfhdr.e_shentsize)), 71 | fsize, elf_getu16(swap, elfhdr.e_machine), 72 | CAST(int, elf_getu16(swap, elfhdr.e_shstrndx)), 73 | &flags, ¬ecount) == -1) 74 | return -1; 75 | break; 76 | 77 | default: 78 | break; 79 | } 80 | if (notecount == 0) 81 | return toomany(ms, "notes", ms->elf_notes_max); 82 | return 1; 83 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/file_opts.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Table of command-line options 3 | * 4 | * The first column specifies the short name, if any, or 0 if none. 5 | * The second column specifies the long name. 6 | * The third column specifies whether it takes a parameter. 7 | * The fourth columns specifies whether is is marked as "default" 8 | * if POSIXLY_CORRECT is defined: 1, 9 | * if POSIXLY_CORRECT is not defined: 2. 10 | * The fifth column is the documentation. 11 | * 12 | * N.B. The long options' order must correspond to the code in file.c, 13 | * and OPTSTRING must be kept up-to-date with the short options. 14 | * Pay particular attention to the numbers of long-only options in the 15 | * switch statement! 16 | */ 17 | 18 | OPT_LONGONLY("help", 0, 0, 19 | " display this help and exit\n", OPT_HELP) 20 | OPT('v', "version", 0, 0, 21 | " output version information and exit\n") 22 | OPT('m', "magic-file", 1, 0, 23 | " LIST use LIST as a colon-separated list of magic\n" 24 | " number files\n") 25 | OPT('z', "uncompress", 0, 0, 26 | " try to look inside compressed files\n") 27 | OPT('Z', "uncompress-noreport", 0, 0, 28 | " only print the contents of compressed files\n") 29 | OPT('b', "brief", 0, 0, 30 | " do not prepend filenames to output lines\n") 31 | OPT('c', "checking-printout", 0, 0, 32 | " print the parsed form of the magic file, use in\n" 33 | " conjunction with -m to debug a new magic file\n" 34 | " before installing it\n") 35 | OPT('e', "exclude", 1, 0, 36 | " TEST exclude TEST from the list of test to be\n" 37 | " performed for file. Valid tests are:\n" 38 | " %e\n") 39 | OPT_LONGONLY("exclude-quiet", 1, 0, 40 | " TEST like exclude, but ignore unknown tests\n", OPT_EXCLUDE_QUIET) 41 | OPT('f', "files-from", 1, 0, 42 | " FILE read the filenames to be examined from FILE\n") 43 | OPT('F', "separator", 1, 0, 44 | " STRING use string as separator instead of `:'\n") 45 | OPT('i', "mime", 0, 0, 46 | " output MIME type strings (--mime-type and\n" 47 | " --mime-encoding)\n") 48 | OPT_LONGONLY("apple", 0, 0, 49 | " output the Apple CREATOR/TYPE\n", OPT_APPLE) 50 | OPT_LONGONLY("extension", 0, 0, 51 | " output a slash-separated list of extensions\n", OPT_EXTENSIONS) 52 | OPT_LONGONLY("mime-type", 0, 0, 53 | " output the MIME type\n", OPT_MIME_TYPE) 54 | OPT_LONGONLY("mime-encoding", 0, 0, 55 | " output the MIME encoding\n", OPT_MIME_ENCODING) 56 | OPT('k', "keep-going", 0, 0, 57 | " don't stop at the first match\n") 58 | OPT('l', "list", 0, 0, 59 | " list magic strength\n") 60 | #ifdef S_IFLNK 61 | OPT('L', "dereference", 0, 1, 62 | " follow symlinks") 63 | OPT('h', "no-dereference", 0, 2, 64 | " don't follow symlinks") 65 | #endif 66 | OPT('n', "no-buffer", 0, 0, 67 | " do not buffer output\n") 68 | OPT('N', "no-pad", 0, 0, 69 | " do not pad output\n") 70 | OPT('0', "print0", 0, 0, 71 | " terminate filenames with ASCII NUL\n") 72 | #if defined(HAVE_UTIME) || defined(HAVE_UTIMES) 73 | OPT('p', "preserve-date", 0, 0, 74 | " preserve access times on files\n") 75 | #endif 76 | OPT('P', "parameter", 1, 0, 77 | " set file engine parameter limits\n" 78 | " %P\n") 79 | OPT('r', "raw", 0, 0, 80 | " don't translate unprintable chars to \\ooo\n") 81 | OPT('s', "special-files", 0, 0, 82 | " treat special (block/char devices) files as\n" 83 | " ordinary ones\n") 84 | OPT('S', "no-sandbox", 0, 0, 85 | " disable system call sandboxing\n") 86 | OPT('C', "compile", 0, 0, 87 | " compile file specified by -m\n") 88 | OPT('d', "debug", 0, 0, 89 | " print debugging messages\n") 90 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/fmtcheck.c: -------------------------------------------------------------------------------- 1 | /* $NetBSD: fmtcheck.c,v 1.8 2008/04/28 20:22:59 martin Exp $ */ 2 | 3 | /*- 4 | * Copyright (c) 2000 The NetBSD Foundation, Inc. 5 | * All rights reserved. 6 | * 7 | * This code was contributed to The NetBSD Foundation by Allen Briggs. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 1. Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * 2. Redistributions in binary form must reproduce the above copyright 15 | * notice, this list of conditions and the following disclaimer in the 16 | * documentation and/or other materials provided with the distribution. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #include "file.h" 32 | 33 | #include 34 | #include 35 | #include 36 | 37 | enum __e_fmtcheck_types { 38 | FMTCHECK_START, 39 | FMTCHECK_SHORT, 40 | FMTCHECK_INT, 41 | FMTCHECK_LONG, 42 | FMTCHECK_QUAD, 43 | FMTCHECK_SHORTPOINTER, 44 | FMTCHECK_INTPOINTER, 45 | FMTCHECK_LONGPOINTER, 46 | FMTCHECK_QUADPOINTER, 47 | FMTCHECK_DOUBLE, 48 | FMTCHECK_LONGDOUBLE, 49 | FMTCHECK_STRING, 50 | FMTCHECK_WIDTH, 51 | FMTCHECK_PRECISION, 52 | FMTCHECK_DONE, 53 | FMTCHECK_UNKNOWN 54 | }; 55 | typedef enum __e_fmtcheck_types EFT; 56 | 57 | #define RETURN(pf,f,r) do { \ 58 | *(pf) = (f); \ 59 | return r; \ 60 | } /*NOTREACHED*/ /*CONSTCOND*/ while (0) 61 | 62 | static EFT 63 | get_next_format_from_precision(const char **pf) 64 | { 65 | int sh, lg, quad, longdouble; 66 | const char *f; 67 | 68 | sh = lg = quad = longdouble = 0; 69 | 70 | f = *pf; 71 | switch (*f) { 72 | case 'h': 73 | f++; 74 | sh = 1; 75 | break; 76 | case 'l': 77 | f++; 78 | if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN); 79 | if (*f == 'l') { 80 | f++; 81 | quad = 1; 82 | } else { 83 | lg = 1; 84 | } 85 | break; 86 | case 'q': 87 | f++; 88 | quad = 1; 89 | break; 90 | case 'L': 91 | f++; 92 | longdouble = 1; 93 | break; 94 | #ifdef WIN32 95 | case 'I': 96 | f++; 97 | if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN); 98 | if (*f == '3' && f[1] == '2') { 99 | f += 2; 100 | } else if (*f == '6' && f[1] == '4') { 101 | f += 2; 102 | quad = 1; 103 | } 104 | #ifdef _WIN64 105 | else { 106 | quad = 1; 107 | } 108 | #endif 109 | break; 110 | #endif 111 | default: 112 | break; 113 | } 114 | if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN); 115 | if (strchr("diouxX", *f)) { 116 | if (longdouble) 117 | RETURN(pf,f,FMTCHECK_UNKNOWN); 118 | if (lg) 119 | RETURN(pf,f,FMTCHECK_LONG); 120 | if (quad) 121 | RETURN(pf,f,FMTCHECK_QUAD); 122 | RETURN(pf,f,FMTCHECK_INT); 123 | } 124 | if (*f == 'n') { 125 | if (longdouble) 126 | RETURN(pf,f,FMTCHECK_UNKNOWN); 127 | if (sh) 128 | RETURN(pf,f,FMTCHECK_SHORTPOINTER); 129 | if (lg) 130 | RETURN(pf,f,FMTCHECK_LONGPOINTER); 131 | if (quad) 132 | RETURN(pf,f,FMTCHECK_QUADPOINTER); 133 | RETURN(pf,f,FMTCHECK_INTPOINTER); 134 | } 135 | if (strchr("DOU", *f)) { 136 | if (sh + lg + quad + longdouble) 137 | RETURN(pf,f,FMTCHECK_UNKNOWN); 138 | RETURN(pf,f,FMTCHECK_LONG); 139 | } 140 | if (strchr("eEfg", *f)) { 141 | if (longdouble) 142 | RETURN(pf,f,FMTCHECK_LONGDOUBLE); 143 | if (sh + lg + quad) 144 | RETURN(pf,f,FMTCHECK_UNKNOWN); 145 | RETURN(pf,f,FMTCHECK_DOUBLE); 146 | } 147 | if (*f == 'c') { 148 | if (sh + lg + quad + longdouble) 149 | RETURN(pf,f,FMTCHECK_UNKNOWN); 150 | RETURN(pf,f,FMTCHECK_INT); 151 | } 152 | if (*f == 's') { 153 | if (sh + lg + quad + longdouble) 154 | RETURN(pf,f,FMTCHECK_UNKNOWN); 155 | RETURN(pf,f,FMTCHECK_STRING); 156 | } 157 | if (*f == 'p') { 158 | if (sh + lg + quad + longdouble) 159 | RETURN(pf,f,FMTCHECK_UNKNOWN); 160 | RETURN(pf,f,FMTCHECK_LONG); 161 | } 162 | RETURN(pf,f,FMTCHECK_UNKNOWN); 163 | /*NOTREACHED*/ 164 | } 165 | 166 | static EFT 167 | get_next_format_from_width(const char **pf) 168 | { 169 | const char *f; 170 | 171 | f = *pf; 172 | if (*f == '.') { 173 | f++; 174 | if (*f == '*') { 175 | RETURN(pf,f,FMTCHECK_PRECISION); 176 | } 177 | /* eat any precision (empty is allowed) */ 178 | while (isdigit((unsigned char)*f)) f++; 179 | if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN); 180 | } 181 | RETURN(pf,f,get_next_format_from_precision(pf)); 182 | /*NOTREACHED*/ 183 | } 184 | 185 | static EFT 186 | get_next_format(const char **pf, EFT eft) 187 | { 188 | int infmt; 189 | const char *f; 190 | 191 | if (eft == FMTCHECK_WIDTH) { 192 | (*pf)++; 193 | return get_next_format_from_width(pf); 194 | } else if (eft == FMTCHECK_PRECISION) { 195 | (*pf)++; 196 | return get_next_format_from_precision(pf); 197 | } 198 | 199 | f = *pf; 200 | infmt = 0; 201 | while (!infmt) { 202 | f = strchr(f, '%'); 203 | if (f == NULL) 204 | RETURN(pf,f,FMTCHECK_DONE); 205 | f++; 206 | if (!*f) 207 | RETURN(pf,f,FMTCHECK_UNKNOWN); 208 | if (*f != '%') 209 | infmt = 1; 210 | else 211 | f++; 212 | } 213 | 214 | /* Eat any of the flags */ 215 | while (*f && (strchr("#0- +", *f))) 216 | f++; 217 | 218 | if (*f == '*') { 219 | RETURN(pf,f,FMTCHECK_WIDTH); 220 | } 221 | /* eat any width */ 222 | while (isdigit((unsigned char)*f)) f++; 223 | if (!*f) { 224 | RETURN(pf,f,FMTCHECK_UNKNOWN); 225 | } 226 | 227 | RETURN(pf,f,get_next_format_from_width(pf)); 228 | /*NOTREACHED*/ 229 | } 230 | 231 | const char * 232 | fmtcheck(const char *f1, const char *f2) 233 | { 234 | const char *f1p, *f2p; 235 | EFT f1t, f2t; 236 | 237 | if (!f1) return f2; 238 | 239 | f1p = f1; 240 | f1t = FMTCHECK_START; 241 | f2p = f2; 242 | f2t = FMTCHECK_START; 243 | while ((f1t = get_next_format(&f1p, f1t)) != FMTCHECK_DONE) { 244 | if (f1t == FMTCHECK_UNKNOWN) 245 | return f2; 246 | f2t = get_next_format(&f2p, f2t); 247 | if (f1t != f2t) 248 | return f2; 249 | } 250 | return f1; 251 | } 252 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/fsmagic.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Ian F. Darwin 1986-1995. 3 | * Software written by Ian F. Darwin and others; 4 | * maintained 1995-present by Christos Zoulas and others. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice immediately at the beginning of the file, without modification, 11 | * this list of conditions, and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 20 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | /* 29 | * fsmagic - magic based on filesystem info - directory, special files, etc. 30 | */ 31 | 32 | #include "file.h" 33 | 34 | #ifndef lint 35 | FILE_RCSID("@(#)$File: fsmagic.c,v 1.81 2019/07/16 13:30:32 christos Exp $") 36 | #endif /* lint */ 37 | 38 | #include "magic.h" 39 | #include 40 | #ifdef HAVE_UNISTD_H 41 | #include 42 | #endif 43 | #include 44 | /* Since major is a function on SVR4, we cannot use `ifndef major'. */ 45 | #ifdef MAJOR_IN_MKDEV 46 | # include 47 | # define HAVE_MAJOR 48 | #endif 49 | #ifdef HAVE_SYS_SYSMACROS_H 50 | # include 51 | #endif 52 | #ifdef MAJOR_IN_SYSMACROS 53 | # define HAVE_MAJOR 54 | #endif 55 | #if defined(major) && !defined(HAVE_MAJOR) 56 | /* Might be defined in sys/types.h. */ 57 | # define HAVE_MAJOR 58 | #endif 59 | #ifdef WIN32 60 | # define WIN32_LEAN_AND_MEAN 61 | # include 62 | #endif 63 | 64 | #ifndef HAVE_MAJOR 65 | # define major(dev) (((dev) >> 8) & 0xff) 66 | # define minor(dev) ((dev) & 0xff) 67 | #endif 68 | #undef HAVE_MAJOR 69 | #ifdef S_IFLNK 70 | private int 71 | bad_link(struct magic_set *ms, int err, char *buf) 72 | { 73 | int mime = ms->flags & MAGIC_MIME; 74 | if ((mime & MAGIC_MIME_TYPE) && 75 | file_printf(ms, "inode/symlink") 76 | == -1) 77 | return -1; 78 | else if (!mime) { 79 | if (ms->flags & MAGIC_ERROR) { 80 | file_error(ms, err, 81 | "broken symbolic link to %s", buf); 82 | return -1; 83 | } 84 | if (file_printf(ms, "broken symbolic link to %s", buf) == -1) 85 | return -1; 86 | } 87 | return 1; 88 | } 89 | #endif 90 | private int 91 | handle_mime(struct magic_set *ms, int mime, const char *str) 92 | { 93 | if ((mime & MAGIC_MIME_TYPE)) { 94 | if (file_printf(ms, "inode/%s", str) == -1) 95 | return -1; 96 | if ((mime & MAGIC_MIME_ENCODING) && file_printf(ms, 97 | "; charset=") == -1) 98 | return -1; 99 | } 100 | if ((mime & MAGIC_MIME_ENCODING) && file_printf(ms, "binary") == -1) 101 | return -1; 102 | return 0; 103 | } 104 | 105 | protected int 106 | file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb) 107 | { 108 | int ret, did = 0; 109 | int mime = ms->flags & MAGIC_MIME; 110 | int silent = ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION); 111 | #ifdef S_IFLNK 112 | char buf[BUFSIZ+4]; 113 | ssize_t nch; 114 | struct stat tstatbuf; 115 | #endif 116 | 117 | if (fn == NULL) 118 | return 0; 119 | 120 | #define COMMA (did++ ? ", " : "") 121 | /* 122 | * Fstat is cheaper but fails for files you don't have read perms on. 123 | * On 4.2BSD and similar systems, use lstat() to identify symlinks. 124 | */ 125 | #ifdef S_IFLNK 126 | if ((ms->flags & MAGIC_SYMLINK) == 0) 127 | ret = lstat(fn, sb); 128 | else 129 | #endif 130 | ret = stat(fn, sb); /* don't merge into if; see "ret =" above */ 131 | 132 | #ifdef WIN32 133 | { 134 | HANDLE hFile = CreateFile((LPCSTR)fn, 0, FILE_SHARE_DELETE | 135 | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 136 | NULL); 137 | if (hFile != INVALID_HANDLE_VALUE) { 138 | /* 139 | * Stat failed, but we can still open it - assume it's 140 | * a block device, if nothing else. 141 | */ 142 | if (ret) { 143 | sb->st_mode = S_IFBLK; 144 | ret = 0; 145 | } 146 | switch (GetFileType(hFile)) { 147 | case FILE_TYPE_CHAR: 148 | sb->st_mode |= S_IFCHR; 149 | sb->st_mode &= ~S_IFREG; 150 | break; 151 | case FILE_TYPE_PIPE: 152 | sb->st_mode |= S_IFIFO; 153 | sb->st_mode &= ~S_IFREG; 154 | break; 155 | } 156 | CloseHandle(hFile); 157 | } 158 | } 159 | #endif 160 | 161 | if (ret) { 162 | if (ms->flags & MAGIC_ERROR) { 163 | file_error(ms, errno, "cannot stat `%s'", fn); 164 | return -1; 165 | } 166 | if (file_printf(ms, "cannot open `%s' (%s)", 167 | fn, strerror(errno)) == -1) 168 | return -1; 169 | return 0; 170 | } 171 | 172 | ret = 1; 173 | if (!mime && !silent) { 174 | #ifdef S_ISUID 175 | if (sb->st_mode & S_ISUID) 176 | if (file_printf(ms, "%ssetuid", COMMA) == -1) 177 | return -1; 178 | #endif 179 | #ifdef S_ISGID 180 | if (sb->st_mode & S_ISGID) 181 | if (file_printf(ms, "%ssetgid", COMMA) == -1) 182 | return -1; 183 | #endif 184 | #ifdef S_ISVTX 185 | if (sb->st_mode & S_ISVTX) 186 | if (file_printf(ms, "%ssticky", COMMA) == -1) 187 | return -1; 188 | #endif 189 | } 190 | 191 | switch (sb->st_mode & S_IFMT) { 192 | case S_IFDIR: 193 | if (mime) { 194 | if (handle_mime(ms, mime, "directory") == -1) 195 | return -1; 196 | } else if (silent) { 197 | } else if (file_printf(ms, "%sdirectory", COMMA) == -1) 198 | return -1; 199 | break; 200 | #ifdef S_IFCHR 201 | case S_IFCHR: 202 | /* 203 | * If -s has been specified, treat character special files 204 | * like ordinary files. Otherwise, just report that they 205 | * are block special files and go on to the next file. 206 | */ 207 | if ((ms->flags & MAGIC_DEVICES) != 0) { 208 | ret = 0; 209 | break; 210 | } 211 | if (mime) { 212 | if (handle_mime(ms, mime, "chardevice") == -1) 213 | return -1; 214 | } else if (silent) { 215 | } else { 216 | #ifdef HAVE_STRUCT_STAT_ST_RDEV 217 | # ifdef dv_unit 218 | if (file_printf(ms, "%scharacter special (%d/%d/%d)", 219 | COMMA, major(sb->st_rdev), dv_unit(sb->st_rdev), 220 | dv_subunit(sb->st_rdev)) == -1) 221 | return -1; 222 | # else 223 | if (file_printf(ms, "%scharacter special (%ld/%ld)", 224 | COMMA, (long)major(sb->st_rdev), 225 | (long)minor(sb->st_rdev)) == -1) 226 | return -1; 227 | # endif 228 | #else 229 | if (file_printf(ms, "%scharacter special", COMMA) == -1) 230 | return -1; 231 | #endif 232 | } 233 | break; 234 | #endif 235 | #ifdef S_IFBLK 236 | case S_IFBLK: 237 | /* 238 | * If -s has been specified, treat block special files 239 | * like ordinary files. Otherwise, just report that they 240 | * are block special files and go on to the next file. 241 | */ 242 | if ((ms->flags & MAGIC_DEVICES) != 0) { 243 | ret = 0; 244 | break; 245 | } 246 | if (mime) { 247 | if (handle_mime(ms, mime, "blockdevice") == -1) 248 | return -1; 249 | } else if (silent) { 250 | } else { 251 | #ifdef HAVE_STRUCT_STAT_ST_RDEV 252 | # ifdef dv_unit 253 | if (file_printf(ms, "%sblock special (%d/%d/%d)", 254 | COMMA, major(sb->st_rdev), dv_unit(sb->st_rdev), 255 | dv_subunit(sb->st_rdev)) == -1) 256 | return -1; 257 | # else 258 | if (file_printf(ms, "%sblock special (%ld/%ld)", 259 | COMMA, (long)major(sb->st_rdev), 260 | (long)minor(sb->st_rdev)) == -1) 261 | return -1; 262 | # endif 263 | #else 264 | if (file_printf(ms, "%sblock special", COMMA) == -1) 265 | return -1; 266 | #endif 267 | } 268 | break; 269 | #endif 270 | /* TODO add code to handle V7 MUX and Blit MUX files */ 271 | #ifdef S_IFIFO 272 | case S_IFIFO: 273 | if((ms->flags & MAGIC_DEVICES) != 0) 274 | break; 275 | if (mime) { 276 | if (handle_mime(ms, mime, "fifo") == -1) 277 | return -1; 278 | } else if (silent) { 279 | } else if (file_printf(ms, "%sfifo (named pipe)", COMMA) == -1) 280 | return -1; 281 | break; 282 | #endif 283 | #ifdef S_IFDOOR 284 | case S_IFDOOR: 285 | if (mime) { 286 | if (handle_mime(ms, mime, "door") == -1) 287 | return -1; 288 | } else if (silent) { 289 | } else if (file_printf(ms, "%sdoor", COMMA) == -1) 290 | return -1; 291 | break; 292 | #endif 293 | #ifdef S_IFLNK 294 | case S_IFLNK: 295 | if ((nch = readlink(fn, buf, BUFSIZ-1)) <= 0) { 296 | if (ms->flags & MAGIC_ERROR) { 297 | file_error(ms, errno, "unreadable symlink `%s'", 298 | fn); 299 | return -1; 300 | } 301 | if (mime) { 302 | if (handle_mime(ms, mime, "symlink") == -1) 303 | return -1; 304 | } else if (silent) { 305 | } else if (file_printf(ms, 306 | "%sunreadable symlink `%s' (%s)", COMMA, fn, 307 | strerror(errno)) == -1) 308 | return -1; 309 | break; 310 | } 311 | buf[nch] = '\0'; /* readlink(2) does not do this */ 312 | 313 | /* If broken symlink, say so and quit early. */ 314 | #ifdef __linux__ 315 | /* 316 | * linux procfs/devfs makes symlinks like pipe:[3515864880] 317 | * that we can't stat their readlink output, so stat the 318 | * original filename instead. 319 | */ 320 | if (stat(fn, &tstatbuf) < 0) 321 | return bad_link(ms, errno, buf); 322 | #else 323 | if (*buf == '/') { 324 | if (stat(buf, &tstatbuf) < 0) 325 | return bad_link(ms, errno, buf); 326 | } else { 327 | char *tmp; 328 | char buf2[BUFSIZ+BUFSIZ+4]; 329 | 330 | if ((tmp = strrchr(fn, '/')) == NULL) { 331 | tmp = buf; /* in current directory anyway */ 332 | } else { 333 | if (tmp - fn + 1 > BUFSIZ) { 334 | if (ms->flags & MAGIC_ERROR) { 335 | file_error(ms, 0, 336 | "path too long: `%s'", buf); 337 | return -1; 338 | } 339 | if (mime) { 340 | if (handle_mime(ms, mime, 341 | "x-path-too-long") == -1) 342 | return -1; 343 | } else if (silent) { 344 | } else if (file_printf(ms, 345 | "%spath too long: `%s'", COMMA, 346 | fn) == -1) 347 | return -1; 348 | break; 349 | } 350 | /* take dir part */ 351 | (void)strlcpy(buf2, fn, sizeof buf2); 352 | buf2[tmp - fn + 1] = '\0'; 353 | /* plus (rel) link */ 354 | (void)strlcat(buf2, buf, sizeof buf2); 355 | tmp = buf2; 356 | } 357 | if (stat(tmp, &tstatbuf) < 0) 358 | return bad_link(ms, errno, buf); 359 | } 360 | #endif 361 | 362 | /* Otherwise, handle it. */ 363 | if ((ms->flags & MAGIC_SYMLINK) != 0) { 364 | const char *p; 365 | ms->flags &= MAGIC_SYMLINK; 366 | p = magic_file(ms, buf); 367 | ms->flags |= MAGIC_SYMLINK; 368 | if (p == NULL) 369 | return -1; 370 | } else { /* just print what it points to */ 371 | if (mime) { 372 | if (handle_mime(ms, mime, "symlink") == -1) 373 | return -1; 374 | } else if (silent) { 375 | } else if (file_printf(ms, "%ssymbolic link to %s", 376 | COMMA, buf) == -1) 377 | return -1; 378 | } 379 | break; 380 | #endif 381 | #ifdef S_IFSOCK 382 | #ifndef __COHERENT__ 383 | case S_IFSOCK: 384 | if (mime) { 385 | if (handle_mime(ms, mime, "socket") == -1) 386 | return -1; 387 | } else if (silent) { 388 | } else if (file_printf(ms, "%ssocket", COMMA) == -1) 389 | return -1; 390 | break; 391 | #endif 392 | #endif 393 | case S_IFREG: 394 | /* 395 | * regular file, check next possibility 396 | * 397 | * If stat() tells us the file has zero length, report here that 398 | * the file is empty, so we can skip all the work of opening and 399 | * reading the file. 400 | * But if the -s option has been given, we skip this 401 | * optimization, since on some systems, stat() reports zero 402 | * size for raw disk partitions. (If the block special device 403 | * really has zero length, the fact that it is empty will be 404 | * detected and reported correctly when we read the file.) 405 | */ 406 | if ((ms->flags & MAGIC_DEVICES) == 0 && sb->st_size == 0) { 407 | if (mime) { 408 | if (handle_mime(ms, mime, "x-empty") == -1) 409 | return -1; 410 | } else if (silent) { 411 | } else if (file_printf(ms, "%sempty", COMMA) == -1) 412 | return -1; 413 | break; 414 | } 415 | ret = 0; 416 | break; 417 | 418 | default: 419 | file_error(ms, 0, "invalid mode 0%o", sb->st_mode); 420 | return -1; 421 | /*NOTREACHED*/ 422 | } 423 | 424 | if (!silent && !mime && did && ret == 0) { 425 | if (file_printf(ms, " ") == -1) 426 | return -1; 427 | } 428 | /* 429 | * If we were looking for extensions or apple (silent) it is not our 430 | * job to print here, so don't count this as a match. 431 | */ 432 | if (ret == 1 && silent) 433 | return 0; 434 | return ret; 435 | } 436 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/getline.c: -------------------------------------------------------------------------------- 1 | /* $NetBSD: getline.c,v 1.2 2014/09/16 17:23:50 christos Exp $ */ 2 | 3 | /*- 4 | * Copyright (c) 2011 The NetBSD Foundation, Inc. 5 | * All rights reserved. 6 | * 7 | * This code is derived from software contributed to The NetBSD Foundation 8 | * by Christos Zoulas. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #include "file.h" 33 | #if !HAVE_GETLINE 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | public ssize_t 41 | getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp) 42 | { 43 | char *ptr, *eptr; 44 | 45 | 46 | if (*buf == NULL || *bufsiz == 0) { 47 | *bufsiz = BUFSIZ; 48 | if ((*buf = malloc(*bufsiz)) == NULL) 49 | return -1; 50 | } 51 | 52 | for (ptr = *buf, eptr = *buf + *bufsiz;;) { 53 | int c = fgetc(fp); 54 | if (c == -1) { 55 | if (feof(fp)) { 56 | ssize_t diff = (ssize_t)(ptr - *buf); 57 | if (diff != 0) { 58 | *ptr = '\0'; 59 | return diff; 60 | } 61 | } 62 | return -1; 63 | } 64 | *ptr++ = c; 65 | if (c == delimiter) { 66 | *ptr = '\0'; 67 | return ptr - *buf; 68 | } 69 | if (ptr + 2 >= eptr) { 70 | char *nbuf; 71 | size_t nbufsiz = *bufsiz * 2; 72 | ssize_t d = ptr - *buf; 73 | if ((nbuf = realloc(*buf, nbufsiz)) == NULL) 74 | return -1; 75 | *buf = nbuf; 76 | *bufsiz = nbufsiz; 77 | eptr = nbuf + nbufsiz; 78 | ptr = nbuf + d; 79 | } 80 | } 81 | } 82 | 83 | public ssize_t 84 | getline(char **buf, size_t *bufsiz, FILE *fp) 85 | { 86 | return getdelim(buf, bufsiz, '\n', fp); 87 | } 88 | 89 | #endif 90 | 91 | #ifdef TEST 92 | int 93 | main(int argc, char *argv[]) 94 | { 95 | char *p = NULL; 96 | ssize_t len; 97 | size_t n = 0; 98 | 99 | while ((len = getline(&p, &n, stdin)) != -1) 100 | (void)printf("%" SIZE_T_FORMAT "d %s", len, p); 101 | free(p); 102 | return 0; 103 | } 104 | #endif 105 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/gmtime_r.c: -------------------------------------------------------------------------------- 1 | /* $File: gmtime_r.c,v 1.1 2015/01/09 19:28:32 christos Exp $ */ 2 | 3 | #include "file.h" 4 | #ifndef lint 5 | FILE_RCSID("@(#)$File: gmtime_r.c,v 1.1 2015/01/09 19:28:32 christos Exp $") 6 | #endif /* lint */ 7 | #include 8 | #include 9 | 10 | /* asctime_r is not thread-safe anyway */ 11 | struct tm * 12 | gmtime_r(const time_t *t, struct tm *tm) 13 | { 14 | struct tm *tmp = gmtime(t); 15 | if (tmp == NULL) 16 | return NULL; 17 | memcpy(tm, tmp, sizeof(*tm)); 18 | return tmp; 19 | } 20 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/is_csv.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2019 Christos Zoulas 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 15 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 16 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 18 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | * POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | /* 28 | * Parse CSV object serialization format (RFC-4180, RFC-7111) 29 | */ 30 | 31 | #ifndef TEST 32 | #include "file.h" 33 | 34 | #ifndef lint 35 | FILE_RCSID("@(#)$File: is_csv.c,v 1.6 2020/08/09 16:43:36 christos Exp $") 36 | #endif 37 | 38 | #include 39 | #include "magic.h" 40 | #else 41 | #include 42 | #endif 43 | 44 | 45 | #ifdef DEBUG 46 | #include 47 | #define DPRINTF(fmt, ...) printf(fmt, __VA_ARGS__) 48 | #else 49 | #define DPRINTF(fmt, ...) 50 | #endif 51 | 52 | /* 53 | * if CSV_LINES == 0: 54 | * check all the lines in the buffer 55 | * otherwise: 56 | * check only up-to the number of lines specified 57 | * 58 | * the last line count is always ignored if it does not end in CRLF 59 | */ 60 | #ifndef CSV_LINES 61 | #define CSV_LINES 10 62 | #endif 63 | 64 | static int csv_parse(const unsigned char *, const unsigned char *); 65 | 66 | static const unsigned char * 67 | eatquote(const unsigned char *uc, const unsigned char *ue) 68 | { 69 | int quote = 0; 70 | 71 | while (uc < ue) { 72 | unsigned char c = *uc++; 73 | if (c != '"') { 74 | // We already got one, done. 75 | if (quote) { 76 | return --uc; 77 | } 78 | continue; 79 | } 80 | if (quote) { 81 | // quote-quote escapes 82 | quote = 0; 83 | continue; 84 | } 85 | // first quote 86 | quote = 1; 87 | } 88 | return ue; 89 | } 90 | 91 | static int 92 | csv_parse(const unsigned char *uc, const unsigned char *ue) 93 | { 94 | size_t nf = 0, tf = 0, nl = 0; 95 | 96 | while (uc < ue) { 97 | switch (*uc++) { 98 | case '"': 99 | // Eat until the matching quote 100 | uc = eatquote(uc, ue); 101 | break; 102 | case ',': 103 | nf++; 104 | break; 105 | case '\n': 106 | DPRINTF("%zu %zu %zu\n", nl, nf, tf); 107 | nl++; 108 | #if CSV_LINES 109 | if (nl == CSV_LINES) 110 | return tf != 0 && tf == nf; 111 | #endif 112 | if (tf == 0) { 113 | // First time and no fields, give up 114 | if (nf == 0) 115 | return 0; 116 | // First time, set the number of fields 117 | tf = nf; 118 | } else if (tf != nf) { 119 | // Field number mismatch, we are done. 120 | return 0; 121 | } 122 | nf = 0; 123 | break; 124 | default: 125 | break; 126 | } 127 | } 128 | return tf && nl > 2; 129 | } 130 | 131 | #ifndef TEST 132 | int 133 | file_is_csv(struct magic_set *ms, const struct buffer *b, int looks_text) 134 | { 135 | const unsigned char *uc = CAST(const unsigned char *, b->fbuf); 136 | const unsigned char *ue = uc + b->flen; 137 | int mime = ms->flags & MAGIC_MIME; 138 | 139 | if (!looks_text) 140 | return 0; 141 | 142 | if ((ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION)) != 0) 143 | return 0; 144 | 145 | if (!csv_parse(uc, ue)) 146 | return 0; 147 | 148 | if (mime == MAGIC_MIME_ENCODING) 149 | return 1; 150 | 151 | if (mime) { 152 | if (file_printf(ms, "text/csv") == -1) 153 | return -1; 154 | return 1; 155 | } 156 | 157 | if (file_printf(ms, "CSV text") == -1) 158 | return -1; 159 | 160 | return 1; 161 | } 162 | 163 | #else 164 | 165 | #include 166 | #include 167 | #include 168 | #include 169 | #include 170 | #include 171 | #include 172 | #include 173 | 174 | int 175 | main(int argc, char *argv[]) 176 | { 177 | int fd, rv; 178 | struct stat st; 179 | unsigned char *p; 180 | 181 | if ((fd = open(argv[1], O_RDONLY)) == -1) 182 | err(EXIT_FAILURE, "Can't open `%s'", argv[1]); 183 | 184 | if (fstat(fd, &st) == -1) 185 | err(EXIT_FAILURE, "Can't stat `%s'", argv[1]); 186 | 187 | if ((p = malloc(st.st_size)) == NULL) 188 | err(EXIT_FAILURE, "Can't allocate %jd bytes", 189 | (intmax_t)st.st_size); 190 | if (read(fd, p, st.st_size) != st.st_size) 191 | err(EXIT_FAILURE, "Can't read %jd bytes", 192 | (intmax_t)st.st_size); 193 | printf("is csv %d\n", csv_parse(p, p + st.st_size)); 194 | return 0; 195 | } 196 | #endif 197 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/is_json.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018 Christos Zoulas 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 15 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 16 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 18 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | * POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | /* 28 | * Parse JSON object serialization format (RFC-7159) 29 | */ 30 | 31 | #ifndef TEST 32 | #include "file.h" 33 | 34 | #ifndef lint 35 | FILE_RCSID("@(#)$File: is_json.c,v 1.15 2020/06/07 19:05:47 christos Exp $") 36 | #endif 37 | 38 | #include 39 | #include "magic.h" 40 | #endif 41 | 42 | #ifdef DEBUG 43 | #include 44 | #define DPRINTF(a, b, c) \ 45 | printf("%s [%.2x/%c] %.20s\n", (a), *(b), *(b), (const char *)(c)) 46 | #else 47 | #define DPRINTF(a, b, c) do { } while (/*CONSTCOND*/0) 48 | #endif 49 | 50 | #define JSON_ARRAY 0 51 | #define JSON_CONSTANT 1 52 | #define JSON_NUMBER 2 53 | #define JSON_OBJECT 3 54 | #define JSON_STRING 4 55 | #define JSON_ARRAYN 5 56 | #define JSON_MAX 6 57 | 58 | /* 59 | * if JSON_COUNT != 0: 60 | * count all the objects, require that we have the whole data file 61 | * otherwise: 62 | * stop if we find an object or an array 63 | */ 64 | #ifndef JSON_COUNT 65 | #define JSON_COUNT 0 66 | #endif 67 | 68 | static int json_parse(const unsigned char **, const unsigned char *, size_t *, 69 | size_t); 70 | 71 | static int 72 | json_isspace(const unsigned char uc) 73 | { 74 | switch (uc) { 75 | case ' ': 76 | case '\n': 77 | case '\r': 78 | case '\t': 79 | return 1; 80 | default: 81 | return 0; 82 | } 83 | } 84 | 85 | static int 86 | json_isdigit(unsigned char uc) 87 | { 88 | switch (uc) { 89 | case '0': case '1': case '2': case '3': case '4': 90 | case '5': case '6': case '7': case '8': case '9': 91 | return 1; 92 | default: 93 | return 0; 94 | } 95 | } 96 | 97 | static int 98 | json_isxdigit(unsigned char uc) 99 | { 100 | if (json_isdigit(uc)) 101 | return 1; 102 | switch (uc) { 103 | case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': 104 | case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': 105 | return 1; 106 | default: 107 | return 0; 108 | } 109 | } 110 | 111 | static const unsigned char * 112 | json_skip_space(const unsigned char *uc, const unsigned char *ue) 113 | { 114 | while (uc < ue && json_isspace(*uc)) 115 | uc++; 116 | return uc; 117 | } 118 | 119 | static int 120 | json_parse_string(const unsigned char **ucp, const unsigned char *ue) 121 | { 122 | const unsigned char *uc = *ucp; 123 | size_t i; 124 | 125 | DPRINTF("Parse string: ", uc, *ucp); 126 | while (uc < ue) { 127 | switch (*uc++) { 128 | case '\0': 129 | goto out; 130 | case '\\': 131 | if (uc == ue) 132 | goto out; 133 | switch (*uc++) { 134 | case '\0': 135 | goto out; 136 | case '"': 137 | case '\\': 138 | case '/': 139 | case 'b': 140 | case 'f': 141 | case 'n': 142 | case 'r': 143 | case 't': 144 | continue; 145 | case 'u': 146 | if (ue - uc < 4) { 147 | uc = ue; 148 | goto out; 149 | } 150 | for (i = 0; i < 4; i++) 151 | if (!json_isxdigit(*uc++)) 152 | goto out; 153 | continue; 154 | default: 155 | goto out; 156 | } 157 | case '"': 158 | *ucp = uc; 159 | DPRINTF("Good string: ", uc, *ucp); 160 | return 1; 161 | default: 162 | continue; 163 | } 164 | } 165 | out: 166 | DPRINTF("Bad string: ", uc, *ucp); 167 | *ucp = uc; 168 | return 0; 169 | } 170 | 171 | static int 172 | json_parse_array(const unsigned char **ucp, const unsigned char *ue, 173 | size_t *st, size_t lvl) 174 | { 175 | const unsigned char *uc = *ucp; 176 | 177 | DPRINTF("Parse array: ", uc, *ucp); 178 | while (uc < ue) { 179 | if (*uc == ']') 180 | goto done; 181 | if (!json_parse(&uc, ue, st, lvl + 1)) 182 | goto out; 183 | if (uc == ue) 184 | goto out; 185 | switch (*uc) { 186 | case ',': 187 | uc++; 188 | continue; 189 | case ']': 190 | done: 191 | st[JSON_ARRAYN]++; 192 | *ucp = uc + 1; 193 | DPRINTF("Good array: ", uc, *ucp); 194 | return 1; 195 | default: 196 | goto out; 197 | } 198 | } 199 | out: 200 | DPRINTF("Bad array: ", uc, *ucp); 201 | *ucp = uc; 202 | return 0; 203 | } 204 | 205 | static int 206 | json_parse_object(const unsigned char **ucp, const unsigned char *ue, 207 | size_t *st, size_t lvl) 208 | { 209 | const unsigned char *uc = *ucp; 210 | DPRINTF("Parse object: ", uc, *ucp); 211 | while (uc < ue) { 212 | uc = json_skip_space(uc, ue); 213 | if (uc == ue) 214 | goto out; 215 | if (*uc == '}') { 216 | uc++; 217 | goto done; 218 | } 219 | if (*uc++ != '"') { 220 | DPRINTF("not string", uc, *ucp); 221 | goto out; 222 | } 223 | DPRINTF("next field", uc, *ucp); 224 | if (!json_parse_string(&uc, ue)) { 225 | DPRINTF("not string", uc, *ucp); 226 | goto out; 227 | } 228 | uc = json_skip_space(uc, ue); 229 | if (uc == ue) 230 | goto out; 231 | if (*uc++ != ':') { 232 | DPRINTF("not colon", uc, *ucp); 233 | goto out; 234 | } 235 | if (!json_parse(&uc, ue, st, lvl + 1)) { 236 | DPRINTF("not json", uc, *ucp); 237 | goto out; 238 | } 239 | if (uc == ue) 240 | goto out; 241 | switch (*uc++) { 242 | case ',': 243 | continue; 244 | case '}': /* { */ 245 | done: 246 | *ucp = uc; 247 | DPRINTF("Good object: ", uc, *ucp); 248 | return 1; 249 | default: 250 | *ucp = uc - 1; 251 | DPRINTF("not more", uc, *ucp); 252 | goto out; 253 | } 254 | } 255 | out: 256 | DPRINTF("Bad object: ", uc, *ucp); 257 | *ucp = uc; 258 | return 0; 259 | } 260 | 261 | static int 262 | json_parse_number(const unsigned char **ucp, const unsigned char *ue) 263 | { 264 | const unsigned char *uc = *ucp; 265 | int got = 0; 266 | 267 | DPRINTF("Parse number: ", uc, *ucp); 268 | if (uc == ue) 269 | return 0; 270 | if (*uc == '-') 271 | uc++; 272 | 273 | for (; uc < ue; uc++) { 274 | if (!json_isdigit(*uc)) 275 | break; 276 | got = 1; 277 | } 278 | if (uc == ue) 279 | goto out; 280 | if (*uc == '.') 281 | uc++; 282 | for (; uc < ue; uc++) { 283 | if (!json_isdigit(*uc)) 284 | break; 285 | got = 1; 286 | } 287 | if (uc == ue) 288 | goto out; 289 | if (got && (*uc == 'e' || *uc == 'E')) { 290 | uc++; 291 | got = 0; 292 | if (uc == ue) 293 | goto out; 294 | if (*uc == '+' || *uc == '-') 295 | uc++; 296 | for (; uc < ue; uc++) { 297 | if (!json_isdigit(*uc)) 298 | break; 299 | got = 1; 300 | } 301 | } 302 | out: 303 | if (!got) 304 | DPRINTF("Bad number: ", uc, *ucp); 305 | else 306 | DPRINTF("Good number: ", uc, *ucp); 307 | *ucp = uc; 308 | return got; 309 | } 310 | 311 | static int 312 | json_parse_const(const unsigned char **ucp, const unsigned char *ue, 313 | const char *str, size_t len) 314 | { 315 | const unsigned char *uc = *ucp; 316 | 317 | DPRINTF("Parse const: ", uc, *ucp); 318 | for (len--; uc < ue && --len;) { 319 | if (*uc++ == *++str) 320 | continue; 321 | } 322 | if (len) 323 | DPRINTF("Bad const: ", uc, *ucp); 324 | *ucp = uc; 325 | return len == 0; 326 | } 327 | 328 | static int 329 | json_parse(const unsigned char **ucp, const unsigned char *ue, 330 | size_t *st, size_t lvl) 331 | { 332 | const unsigned char *uc; 333 | int rv = 0; 334 | int t; 335 | 336 | uc = json_skip_space(*ucp, ue); 337 | if (uc == ue) 338 | goto out; 339 | 340 | // Avoid recursion 341 | if (lvl > 20) 342 | return 0; 343 | #if JSON_COUNT 344 | /* bail quickly if not counting */ 345 | if (lvl > 1 && (st[JSON_OBJECT] || st[JSON_ARRAYN])) 346 | return 1; 347 | #endif 348 | 349 | DPRINTF("Parse general: ", uc, *ucp); 350 | switch (*uc++) { 351 | case '"': 352 | rv = json_parse_string(&uc, ue); 353 | t = JSON_STRING; 354 | break; 355 | case '[': 356 | rv = json_parse_array(&uc, ue, st, lvl + 1); 357 | t = JSON_ARRAY; 358 | break; 359 | case '{': /* '}' */ 360 | rv = json_parse_object(&uc, ue, st, lvl + 1); 361 | t = JSON_OBJECT; 362 | break; 363 | case 't': 364 | rv = json_parse_const(&uc, ue, "true", sizeof("true")); 365 | t = JSON_CONSTANT; 366 | break; 367 | case 'f': 368 | rv = json_parse_const(&uc, ue, "false", sizeof("false")); 369 | t = JSON_CONSTANT; 370 | break; 371 | case 'n': 372 | rv = json_parse_const(&uc, ue, "null", sizeof("null")); 373 | t = JSON_CONSTANT; 374 | break; 375 | default: 376 | --uc; 377 | rv = json_parse_number(&uc, ue); 378 | t = JSON_NUMBER; 379 | break; 380 | } 381 | if (rv) 382 | st[t]++; 383 | uc = json_skip_space(uc, ue); 384 | out: 385 | *ucp = uc; 386 | DPRINTF("End general: ", uc, *ucp); 387 | if (lvl == 0) 388 | return rv && (st[JSON_ARRAYN] || st[JSON_OBJECT]); 389 | return rv; 390 | } 391 | 392 | #ifndef TEST 393 | int 394 | file_is_json(struct magic_set *ms, const struct buffer *b) 395 | { 396 | const unsigned char *uc = CAST(const unsigned char *, b->fbuf); 397 | const unsigned char *ue = uc + b->flen; 398 | size_t st[JSON_MAX]; 399 | int mime = ms->flags & MAGIC_MIME; 400 | 401 | 402 | if ((ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION)) != 0) 403 | return 0; 404 | 405 | memset(st, 0, sizeof(st)); 406 | 407 | if (!json_parse(&uc, ue, st, 0)) 408 | return 0; 409 | 410 | if (mime == MAGIC_MIME_ENCODING) 411 | return 1; 412 | if (mime) { 413 | if (file_printf(ms, "application/json") == -1) 414 | return -1; 415 | return 1; 416 | } 417 | if (file_printf(ms, "JSON data") == -1) 418 | return -1; 419 | #if JSON_COUNT 420 | #define P(n) st[n], st[n] > 1 ? "s" : "" 421 | if (file_printf(ms, " (%" SIZE_T_FORMAT "u object%s, %" SIZE_T_FORMAT 422 | "u array%s, %" SIZE_T_FORMAT "u string%s, %" SIZE_T_FORMAT 423 | "u constant%s, %" SIZE_T_FORMAT "u number%s, %" SIZE_T_FORMAT 424 | "u >1array%s)", 425 | P(JSON_OBJECT), P(JSON_ARRAY), P(JSON_STRING), P(JSON_CONSTANT), 426 | P(JSON_NUMBER), P(JSON_ARRAYN)) 427 | == -1) 428 | return -1; 429 | #endif 430 | return 1; 431 | } 432 | 433 | #else 434 | 435 | #include 436 | #include 437 | #include 438 | #include 439 | #include 440 | #include 441 | #include 442 | #include 443 | 444 | int 445 | main(int argc, char *argv[]) 446 | { 447 | int fd, rv; 448 | struct stat st; 449 | unsigned char *p; 450 | size_t stats[JSON_MAX]; 451 | 452 | if ((fd = open(argv[1], O_RDONLY)) == -1) 453 | err(EXIT_FAILURE, "Can't open `%s'", argv[1]); 454 | 455 | if (fstat(fd, &st) == -1) 456 | err(EXIT_FAILURE, "Can't stat `%s'", argv[1]); 457 | 458 | if ((p = malloc(st.st_size)) == NULL) 459 | err(EXIT_FAILURE, "Can't allocate %jd bytes", 460 | (intmax_t)st.st_size); 461 | if (read(fd, p, st.st_size) != st.st_size) 462 | err(EXIT_FAILURE, "Can't read %jd bytes", 463 | (intmax_t)st.st_size); 464 | memset(stats, 0, sizeof(stats)); 465 | printf("is json %d\n", json_parse((const unsigned char **)&p, 466 | p + st.st_size, stats, 0)); 467 | return 0; 468 | } 469 | #endif 470 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/is_tar.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Ian F. Darwin 1986-1995. 3 | * Software written by Ian F. Darwin and others; 4 | * maintained 1995-present by Christos Zoulas and others. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice immediately at the beginning of the file, without modification, 11 | * this list of conditions, and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 20 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | /* 29 | * is_tar() -- figure out whether file is a tar archive. 30 | * 31 | * Stolen (by the author!) from the public domain tar program: 32 | * Public Domain version written 26 Aug 1985 John Gilmore (ihnp4!hoptoad!gnu). 33 | * 34 | * @(#)list.c 1.18 9/23/86 Public Domain - gnu 35 | * 36 | * Comments changed and some code/comments reformatted 37 | * for file command by Ian Darwin. 38 | */ 39 | 40 | #include "file.h" 41 | 42 | #ifndef lint 43 | FILE_RCSID("@(#)$File: is_tar.c,v 1.44 2019/02/20 02:35:27 christos Exp $") 44 | #endif 45 | 46 | #include "magic.h" 47 | #include 48 | #include 49 | #include "tar.h" 50 | 51 | #define isodigit(c) ( ((c) >= '0') && ((c) <= '7') ) 52 | 53 | private int is_tar(const unsigned char *, size_t); 54 | private int from_oct(const char *, size_t); /* Decode octal number */ 55 | 56 | static const char tartype[][32] = { /* should be equal to messages */ 57 | "tar archive", /* found in ../magic/Magdir/archive */ 58 | "POSIX tar archive", 59 | "POSIX tar archive (GNU)", /* */ 60 | }; 61 | 62 | protected int 63 | file_is_tar(struct magic_set *ms, const struct buffer *b) 64 | { 65 | const unsigned char *buf = CAST(const unsigned char *, b->fbuf); 66 | size_t nbytes = b->flen; 67 | /* 68 | * Do the tar test first, because if the first file in the tar 69 | * archive starts with a dot, we can confuse it with an nroff file. 70 | */ 71 | int tar; 72 | int mime = ms->flags & MAGIC_MIME; 73 | 74 | if ((ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION)) != 0) 75 | return 0; 76 | 77 | tar = is_tar(buf, nbytes); 78 | if (tar < 1 || tar > 3) 79 | return 0; 80 | 81 | if (mime == MAGIC_MIME_ENCODING) 82 | return 1; 83 | 84 | if (file_printf(ms, "%s", mime ? "application/x-tar" : 85 | tartype[tar - 1]) == -1) 86 | return -1; 87 | 88 | return 1; 89 | } 90 | 91 | /* 92 | * Return 93 | * 0 if the checksum is bad (i.e., probably not a tar archive), 94 | * 1 for old UNIX tar file, 95 | * 2 for Unix Std (POSIX) tar file, 96 | * 3 for GNU tar file. 97 | */ 98 | private int 99 | is_tar(const unsigned char *buf, size_t nbytes) 100 | { 101 | const union record *header = RCAST(const union record *, 102 | RCAST(const void *, buf)); 103 | size_t i; 104 | int sum, recsum; 105 | const unsigned char *p, *ep; 106 | 107 | if (nbytes < sizeof(*header)) 108 | return 0; 109 | 110 | recsum = from_oct(header->header.chksum, sizeof(header->header.chksum)); 111 | 112 | sum = 0; 113 | p = header->charptr; 114 | ep = header->charptr + sizeof(*header); 115 | while (p < ep) 116 | sum += *p++; 117 | 118 | /* Adjust checksum to count the "chksum" field as blanks. */ 119 | for (i = 0; i < sizeof(header->header.chksum); i++) 120 | sum -= header->header.chksum[i]; 121 | sum += ' ' * sizeof(header->header.chksum); 122 | 123 | if (sum != recsum) 124 | return 0; /* Not a tar archive */ 125 | 126 | if (strncmp(header->header.magic, GNUTMAGIC, 127 | sizeof(header->header.magic)) == 0) 128 | return 3; /* GNU Unix Standard tar archive */ 129 | 130 | if (strncmp(header->header.magic, TMAGIC, 131 | sizeof(header->header.magic)) == 0) 132 | return 2; /* Unix Standard tar archive */ 133 | 134 | return 1; /* Old fashioned tar archive */ 135 | } 136 | 137 | 138 | /* 139 | * Quick and dirty octal conversion. 140 | * 141 | * Result is -1 if the field is invalid (all blank, or non-octal). 142 | */ 143 | private int 144 | from_oct(const char *where, size_t digs) 145 | { 146 | int value; 147 | 148 | if (digs == 0) 149 | return -1; 150 | 151 | while (isspace(CAST(unsigned char, *where))) { /* Skip spaces */ 152 | where++; 153 | if (digs-- == 0) 154 | return -1; /* All blank field */ 155 | } 156 | value = 0; 157 | while (digs > 0 && isodigit(*where)) { /* Scan til non-octal */ 158 | value = (value << 3) | (*where++ - '0'); 159 | digs--; 160 | } 161 | 162 | if (digs > 0 && *where && !isspace(CAST(unsigned char, *where))) 163 | return -1; /* Ended on non-(space/NUL) */ 164 | 165 | return value; 166 | } 167 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/localtime_r.c: -------------------------------------------------------------------------------- 1 | /* $File: localtime_r.c,v 1.1 2015/01/09 19:28:32 christos Exp $ */ 2 | 3 | #include "file.h" 4 | #ifndef lint 5 | FILE_RCSID("@(#)$File: localtime_r.c,v 1.1 2015/01/09 19:28:32 christos Exp $") 6 | #endif /* lint */ 7 | #include 8 | #include 9 | 10 | /* asctime_r is not thread-safe anyway */ 11 | struct tm * 12 | localtime_r(const time_t *t, struct tm *tm) 13 | { 14 | struct tm *tmp = localtime(t); 15 | if (tmp == NULL) 16 | return NULL; 17 | memcpy(tm, tmp, sizeof(*tm)); 18 | return tmp; 19 | } 20 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/magic.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Christos Zoulas 2003. 3 | * All Rights Reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice immediately at the beginning of the file, without modification, 10 | * this list of conditions, and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 | * SUCH DAMAGE. 26 | */ 27 | #ifndef _MAGIC_H 28 | #define _MAGIC_H 29 | 30 | #include 31 | 32 | #define MAGIC_NONE 0x0000000 /* No flags */ 33 | #define MAGIC_DEBUG 0x0000001 /* Turn on debugging */ 34 | #define MAGIC_SYMLINK 0x0000002 /* Follow symlinks */ 35 | #define MAGIC_COMPRESS 0x0000004 /* Check inside compressed files */ 36 | #define MAGIC_DEVICES 0x0000008 /* Look at the contents of devices */ 37 | #define MAGIC_MIME_TYPE 0x0000010 /* Return the MIME type */ 38 | #define MAGIC_CONTINUE 0x0000020 /* Return all matches */ 39 | #define MAGIC_CHECK 0x0000040 /* Print warnings to stderr */ 40 | #define MAGIC_PRESERVE_ATIME 0x0000080 /* Restore access time on exit */ 41 | #define MAGIC_RAW 0x0000100 /* Don't convert unprintable chars */ 42 | #define MAGIC_ERROR 0x0000200 /* Handle ENOENT etc as real errors */ 43 | #define MAGIC_MIME_ENCODING 0x0000400 /* Return the MIME encoding */ 44 | #define MAGIC_MIME (MAGIC_MIME_TYPE|MAGIC_MIME_ENCODING) 45 | #define MAGIC_APPLE 0x0000800 /* Return the Apple creator/type */ 46 | #define MAGIC_EXTENSION 0x1000000 /* Return a /-separated list of 47 | * extensions */ 48 | #define MAGIC_COMPRESS_TRANSP 0x2000000 /* Check inside compressed files 49 | * but not report compression */ 50 | #define MAGIC_NODESC (MAGIC_EXTENSION|MAGIC_MIME|MAGIC_APPLE) 51 | 52 | #define MAGIC_NO_CHECK_COMPRESS 0x0001000 /* Don't check for compressed files */ 53 | #define MAGIC_NO_CHECK_TAR 0x0002000 /* Don't check for tar files */ 54 | #define MAGIC_NO_CHECK_SOFT 0x0004000 /* Don't check magic entries */ 55 | #define MAGIC_NO_CHECK_APPTYPE 0x0008000 /* Don't check application type */ 56 | #define MAGIC_NO_CHECK_ELF 0x0010000 /* Don't check for elf details */ 57 | #define MAGIC_NO_CHECK_TEXT 0x0020000 /* Don't check for text files */ 58 | #define MAGIC_NO_CHECK_CDF 0x0040000 /* Don't check for cdf files */ 59 | #define MAGIC_NO_CHECK_CSV 0x0080000 /* Don't check for CSV files */ 60 | #define MAGIC_NO_CHECK_TOKENS 0x0100000 /* Don't check tokens */ 61 | #define MAGIC_NO_CHECK_ENCODING 0x0200000 /* Don't check text encodings */ 62 | #define MAGIC_NO_CHECK_JSON 0x0400000 /* Don't check for JSON files */ 63 | 64 | /* No built-in tests; only consult the magic file */ 65 | #define MAGIC_NO_CHECK_BUILTIN ( \ 66 | MAGIC_NO_CHECK_COMPRESS | \ 67 | MAGIC_NO_CHECK_TAR | \ 68 | /* MAGIC_NO_CHECK_SOFT | */ \ 69 | MAGIC_NO_CHECK_APPTYPE | \ 70 | MAGIC_NO_CHECK_ELF | \ 71 | MAGIC_NO_CHECK_TEXT | \ 72 | MAGIC_NO_CHECK_CSV | \ 73 | MAGIC_NO_CHECK_CDF | \ 74 | MAGIC_NO_CHECK_TOKENS | \ 75 | MAGIC_NO_CHECK_ENCODING | \ 76 | MAGIC_NO_CHECK_JSON | \ 77 | 0 \ 78 | ) 79 | 80 | #define MAGIC_SNPRINTB "\177\020\ 81 | b\0debug\0\ 82 | b\1symlink\0\ 83 | b\2compress\0\ 84 | b\3devices\0\ 85 | b\4mime_type\0\ 86 | b\5continue\0\ 87 | b\6check\0\ 88 | b\7preserve_atime\0\ 89 | b\10raw\0\ 90 | b\11error\0\ 91 | b\12mime_encoding\0\ 92 | b\13apple\0\ 93 | b\14no_check_compress\0\ 94 | b\15no_check_tar\0\ 95 | b\16no_check_soft\0\ 96 | b\17no_check_sapptype\0\ 97 | b\20no_check_elf\0\ 98 | b\21no_check_text\0\ 99 | b\22no_check_cdf\0\ 100 | b\23no_check_reserved0\0\ 101 | b\24no_check_tokens\0\ 102 | b\25no_check_encoding\0\ 103 | b\26no_check_json\0\ 104 | b\27no_check_reserved2\0\ 105 | b\30extension\0\ 106 | b\31transp_compression\0\ 107 | " 108 | 109 | /* Defined for backwards compatibility (renamed) */ 110 | #define MAGIC_NO_CHECK_ASCII MAGIC_NO_CHECK_TEXT 111 | 112 | /* Defined for backwards compatibility; do nothing */ 113 | #define MAGIC_NO_CHECK_FORTRAN 0x000000 /* Don't check ascii/fortran */ 114 | #define MAGIC_NO_CHECK_TROFF 0x000000 /* Don't check ascii/troff */ 115 | 116 | #define MAGIC_VERSION 540 /* This implementation */ 117 | 118 | 119 | #ifdef __cplusplus 120 | extern "C" { 121 | #endif 122 | 123 | typedef struct magic_set *magic_t; 124 | magic_t magic_open(int); 125 | void magic_close(magic_t); 126 | 127 | const char *magic_getpath(const char *, int); 128 | const char *magic_file(magic_t, const char *); 129 | const char *magic_descriptor(magic_t, int); 130 | const char *magic_buffer(magic_t, const void *, size_t); 131 | 132 | const char *magic_error(magic_t); 133 | int magic_getflags(magic_t); 134 | int magic_setflags(magic_t, int); 135 | 136 | int magic_version(void); 137 | int magic_load(magic_t, const char *); 138 | int magic_load_buffers(magic_t, void **, size_t *, size_t); 139 | 140 | int magic_compile(magic_t, const char *); 141 | int magic_check(magic_t, const char *); 142 | int magic_list(magic_t, const char *); 143 | int magic_errno(magic_t); 144 | 145 | #define MAGIC_PARAM_INDIR_MAX 0 146 | #define MAGIC_PARAM_NAME_MAX 1 147 | #define MAGIC_PARAM_ELF_PHNUM_MAX 2 148 | #define MAGIC_PARAM_ELF_SHNUM_MAX 3 149 | #define MAGIC_PARAM_ELF_NOTES_MAX 4 150 | #define MAGIC_PARAM_REGEX_MAX 5 151 | #define MAGIC_PARAM_BYTES_MAX 6 152 | #define MAGIC_PARAM_ENCODING_MAX 7 153 | 154 | int magic_setparam(magic_t, int, const void *); 155 | int magic_getparam(magic_t, int, void *); 156 | 157 | #ifdef __cplusplus 158 | }; 159 | #endif 160 | 161 | #endif /* _MAGIC_H */ 162 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/mygetopt.h: -------------------------------------------------------------------------------- 1 | /* $NetBSD: getopt.h,v 1.8 2007/11/06 19:21:18 christos Exp $ */ 2 | 3 | /*- 4 | * Copyright (c) 2000 The NetBSD Foundation, Inc. 5 | * All rights reserved. 6 | * 7 | * This code is derived from software contributed to The NetBSD Foundation 8 | * by Dieter Baron and Thomas Klausner. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. All advertising materials mentioning features or use of this software 19 | * must display the following acknowledgement: 20 | * This product includes software developed by the NetBSD 21 | * Foundation, Inc. and its contributors. 22 | * 4. Neither the name of The NetBSD Foundation nor the names of its 23 | * contributors may be used to endorse or promote products derived 24 | * from this software without specific prior written permission. 25 | * 26 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 | * POSSIBILITY OF SUCH DAMAGE. 37 | */ 38 | 39 | #ifndef _GETOPT_H_ 40 | #define _GETOPT_H_ 41 | 42 | #include 43 | 44 | /* 45 | * Gnu like getopt_long() and BSD4.4 getsubopt()/optreset extensions 46 | */ 47 | #define no_argument 0 48 | #define required_argument 1 49 | #define optional_argument 2 50 | 51 | struct option { 52 | /* name of long option */ 53 | const char *name; 54 | /* 55 | * one of no_argument, required_argument, and optional_argument: 56 | * whether option takes an argument 57 | */ 58 | int has_arg; 59 | /* if not NULL, set *flag to val when option found */ 60 | int *flag; 61 | /* if flag not NULL, value to set *flag to; else return value */ 62 | int val; 63 | }; 64 | 65 | int getopt_long(int, char * const *, const char *, 66 | const struct option *, int *); 67 | 68 | #endif /* !_GETOPT_H_ */ 69 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/pread.c: -------------------------------------------------------------------------------- 1 | #include "file.h" 2 | #ifndef lint 3 | FILE_RCSID("@(#)$File: pread.c,v 1.2 2013/04/02 16:23:07 christos Exp $") 4 | #endif /* lint */ 5 | #include 6 | #include 7 | 8 | ssize_t 9 | pread(int fd, void *buf, size_t len, off_t off) { 10 | off_t old; 11 | ssize_t rv; 12 | 13 | if ((old = lseek(fd, off, SEEK_SET)) == -1) 14 | return -1; 15 | 16 | if ((rv = read(fd, buf, len)) == -1) 17 | return -1; 18 | 19 | if (lseek(fd, old, SEEK_SET) == -1) 20 | return -1; 21 | 22 | return rv; 23 | } 24 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/print.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Ian F. Darwin 1986-1995. 3 | * Software written by Ian F. Darwin and others; 4 | * maintained 1995-present by Christos Zoulas and others. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice immediately at the beginning of the file, without modification, 11 | * this list of conditions, and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 20 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | /* 29 | * print.c - debugging printout routines 30 | */ 31 | 32 | #include "file.h" 33 | 34 | #ifndef lint 35 | FILE_RCSID("@(#)$File: print.c,v 1.88 2020/05/09 18:57:15 christos Exp $") 36 | #endif /* lint */ 37 | 38 | #include 39 | #include 40 | #include 41 | #ifdef HAVE_UNISTD_H 42 | #include 43 | #endif 44 | #include 45 | 46 | #include "cdf.h" 47 | 48 | #ifndef COMPILE_ONLY 49 | protected void 50 | file_mdump(struct magic *m) 51 | { 52 | static const char optyp[] = { FILE_OPS }; 53 | char tbuf[256]; 54 | 55 | (void) fprintf(stderr, "%u: %.*s %u", m->lineno, 56 | (m->cont_level & 7) + 1, ">>>>>>>>", m->offset); 57 | 58 | if (m->flag & INDIR) { 59 | (void) fprintf(stderr, "(%s,", 60 | /* Note: type is unsigned */ 61 | (m->in_type < file_nnames) ? file_names[m->in_type] : 62 | "*bad in_type*"); 63 | if (m->in_op & FILE_OPINVERSE) 64 | (void) fputc('~', stderr); 65 | (void) fprintf(stderr, "%c%u),", 66 | (CAST(size_t, m->in_op & FILE_OPS_MASK) < 67 | __arraycount(optyp)) ? 68 | optyp[m->in_op & FILE_OPS_MASK] : '?', m->in_offset); 69 | } 70 | (void) fprintf(stderr, " %s%s", (m->flag & UNSIGNED) ? "u" : "", 71 | /* Note: type is unsigned */ 72 | (m->type < file_nnames) ? file_names[m->type] : "*bad type"); 73 | if (m->mask_op & FILE_OPINVERSE) 74 | (void) fputc('~', stderr); 75 | 76 | if (IS_STRING(m->type)) { 77 | if (m->str_flags) { 78 | (void) fputc('/', stderr); 79 | if (m->str_flags & STRING_COMPACT_WHITESPACE) 80 | (void) fputc(CHAR_COMPACT_WHITESPACE, stderr); 81 | if (m->str_flags & STRING_COMPACT_OPTIONAL_WHITESPACE) 82 | (void) fputc(CHAR_COMPACT_OPTIONAL_WHITESPACE, 83 | stderr); 84 | if (m->str_flags & STRING_IGNORE_LOWERCASE) 85 | (void) fputc(CHAR_IGNORE_LOWERCASE, stderr); 86 | if (m->str_flags & STRING_IGNORE_UPPERCASE) 87 | (void) fputc(CHAR_IGNORE_UPPERCASE, stderr); 88 | if (m->str_flags & REGEX_OFFSET_START) 89 | (void) fputc(CHAR_REGEX_OFFSET_START, stderr); 90 | if (m->str_flags & STRING_TEXTTEST) 91 | (void) fputc(CHAR_TEXTTEST, stderr); 92 | if (m->str_flags & STRING_BINTEST) 93 | (void) fputc(CHAR_BINTEST, stderr); 94 | if (m->str_flags & PSTRING_1_BE) 95 | (void) fputc(CHAR_PSTRING_1_BE, stderr); 96 | if (m->str_flags & PSTRING_2_BE) 97 | (void) fputc(CHAR_PSTRING_2_BE, stderr); 98 | if (m->str_flags & PSTRING_2_LE) 99 | (void) fputc(CHAR_PSTRING_2_LE, stderr); 100 | if (m->str_flags & PSTRING_4_BE) 101 | (void) fputc(CHAR_PSTRING_4_BE, stderr); 102 | if (m->str_flags & PSTRING_4_LE) 103 | (void) fputc(CHAR_PSTRING_4_LE, stderr); 104 | if (m->str_flags & PSTRING_LENGTH_INCLUDES_ITSELF) 105 | (void) fputc( 106 | CHAR_PSTRING_LENGTH_INCLUDES_ITSELF, 107 | stderr); 108 | } 109 | if (m->str_range) 110 | (void) fprintf(stderr, "/%u", m->str_range); 111 | } 112 | else { 113 | if (CAST(size_t, m->mask_op & FILE_OPS_MASK) < 114 | __arraycount(optyp)) 115 | (void) fputc(optyp[m->mask_op & FILE_OPS_MASK], stderr); 116 | else 117 | (void) fputc('?', stderr); 118 | 119 | if (m->num_mask) { 120 | (void) fprintf(stderr, "%.8llx", 121 | CAST(unsigned long long, m->num_mask)); 122 | } 123 | } 124 | (void) fprintf(stderr, ",%c", m->reln); 125 | 126 | if (m->reln != 'x') { 127 | switch (m->type) { 128 | case FILE_BYTE: 129 | case FILE_SHORT: 130 | case FILE_LONG: 131 | case FILE_LESHORT: 132 | case FILE_LELONG: 133 | case FILE_MELONG: 134 | case FILE_BESHORT: 135 | case FILE_BELONG: 136 | case FILE_INDIRECT: 137 | (void) fprintf(stderr, "%d", m->value.l); 138 | break; 139 | case FILE_BEQUAD: 140 | case FILE_LEQUAD: 141 | case FILE_QUAD: 142 | case FILE_OFFSET: 143 | (void) fprintf(stderr, "%" INT64_T_FORMAT "d", 144 | CAST(long long, m->value.q)); 145 | break; 146 | case FILE_PSTRING: 147 | case FILE_STRING: 148 | case FILE_REGEX: 149 | case FILE_BESTRING16: 150 | case FILE_LESTRING16: 151 | case FILE_SEARCH: 152 | file_showstr(stderr, m->value.s, 153 | CAST(size_t, m->vallen)); 154 | break; 155 | case FILE_DATE: 156 | case FILE_LEDATE: 157 | case FILE_BEDATE: 158 | case FILE_MEDATE: 159 | (void)fprintf(stderr, "%s,", 160 | file_fmttime(tbuf, sizeof(tbuf), m->value.l, 0)); 161 | break; 162 | case FILE_LDATE: 163 | case FILE_LELDATE: 164 | case FILE_BELDATE: 165 | case FILE_MELDATE: 166 | (void)fprintf(stderr, "%s,", 167 | file_fmttime(tbuf, sizeof(tbuf), m->value.l, 168 | FILE_T_LOCAL)); 169 | break; 170 | case FILE_QDATE: 171 | case FILE_LEQDATE: 172 | case FILE_BEQDATE: 173 | (void)fprintf(stderr, "%s,", 174 | file_fmttime(tbuf, sizeof(tbuf), m->value.q, 0)); 175 | break; 176 | case FILE_QLDATE: 177 | case FILE_LEQLDATE: 178 | case FILE_BEQLDATE: 179 | (void)fprintf(stderr, "%s,", 180 | file_fmttime(tbuf, sizeof(tbuf), m->value.q, 181 | FILE_T_LOCAL)); 182 | break; 183 | case FILE_QWDATE: 184 | case FILE_LEQWDATE: 185 | case FILE_BEQWDATE: 186 | (void)fprintf(stderr, "%s,", 187 | file_fmttime(tbuf, sizeof(tbuf), m->value.q, 188 | FILE_T_WINDOWS)); 189 | break; 190 | case FILE_FLOAT: 191 | case FILE_BEFLOAT: 192 | case FILE_LEFLOAT: 193 | (void) fprintf(stderr, "%G", m->value.f); 194 | break; 195 | case FILE_DOUBLE: 196 | case FILE_BEDOUBLE: 197 | case FILE_LEDOUBLE: 198 | (void) fprintf(stderr, "%G", m->value.d); 199 | break; 200 | case FILE_DEFAULT: 201 | /* XXX - do anything here? */ 202 | break; 203 | case FILE_USE: 204 | case FILE_NAME: 205 | case FILE_DER: 206 | (void) fprintf(stderr, "'%s'", m->value.s); 207 | break; 208 | case FILE_GUID: 209 | (void) file_print_guid(tbuf, sizeof(tbuf), 210 | m->value.guid); 211 | (void) fprintf(stderr, "%s", tbuf); 212 | break; 213 | 214 | default: 215 | (void) fprintf(stderr, "*bad type %d*", m->type); 216 | break; 217 | } 218 | } 219 | (void) fprintf(stderr, ",\"%s\"]\n", m->desc); 220 | } 221 | #endif 222 | 223 | /*VARARGS*/ 224 | protected void 225 | file_magwarn(struct magic_set *ms, const char *f, ...) 226 | { 227 | va_list va; 228 | 229 | /* cuz we use stdout for most, stderr here */ 230 | (void) fflush(stdout); 231 | 232 | if (ms->file) 233 | (void) fprintf(stderr, "%s, %lu: ", ms->file, 234 | CAST(unsigned long, ms->line)); 235 | (void) fprintf(stderr, "Warning: "); 236 | va_start(va, f); 237 | (void) vfprintf(stderr, f, va); 238 | va_end(va); 239 | (void) fputc('\n', stderr); 240 | } 241 | 242 | protected const char * 243 | file_fmttime(char *buf, size_t bsize, uint64_t v, int flags) 244 | { 245 | char *pp; 246 | time_t t; 247 | struct tm *tm, tmz; 248 | 249 | if (flags & FILE_T_WINDOWS) { 250 | struct timespec ts; 251 | cdf_timestamp_to_timespec(&ts, CAST(cdf_timestamp_t, v)); 252 | t = ts.tv_sec; 253 | } else { 254 | // XXX: perhaps detect and print something if overflow 255 | // on 32 bit time_t? 256 | t = CAST(time_t, v); 257 | } 258 | 259 | if (flags & FILE_T_LOCAL) { 260 | tm = localtime_r(&t, &tmz); 261 | } else { 262 | tm = gmtime_r(&t, &tmz); 263 | } 264 | if (tm == NULL) 265 | goto out; 266 | pp = asctime_r(tm, buf); 267 | 268 | if (pp == NULL) 269 | goto out; 270 | pp[strcspn(pp, "\n")] = '\0'; 271 | return pp; 272 | out: 273 | strlcpy(buf, "*Invalid time*", bsize); 274 | return buf; 275 | } 276 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/seccomp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Redistribution and use in source and binary forms, with or without 3 | * modification, are permitted provided that the following conditions 4 | * are met: 5 | * 1. Redistributions of source code must retain the above copyright 6 | * notice immediately at the beginning of the file, without modification, 7 | * this list of conditions, and the following disclaimer. 8 | * 2. Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * 12 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 13 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 15 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 16 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 17 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 18 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 19 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 20 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 21 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 22 | * SUCH DAMAGE. 23 | */ 24 | /* 25 | * libseccomp hooks. 26 | */ 27 | #include "file.h" 28 | 29 | #ifndef lint 30 | FILE_RCSID("@(#)$File: seccomp.c,v 1.18 2021/03/14 17:01:58 christos Exp $") 31 | #endif /* lint */ 32 | 33 | #if HAVE_LIBSECCOMP 34 | #include /* libseccomp */ 35 | #include /* prctl */ 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #define DENY_RULE(call) \ 44 | do \ 45 | if (seccomp_rule_add (ctx, SCMP_ACT_KILL, SCMP_SYS(call), 0) == -1) \ 46 | goto out; \ 47 | while (/*CONSTCOND*/0) 48 | #define ALLOW_RULE(call) \ 49 | do \ 50 | if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(call), 0) == -1) \ 51 | goto out; \ 52 | while (/*CONSTCOND*/0) 53 | 54 | #define ALLOW_IOCTL_RULE(param) \ 55 | do \ 56 | if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, \ 57 | SCMP_CMP(1, SCMP_CMP_EQ, param)) == -1) \ 58 | goto out; \ 59 | while (/*CONSTCOND*/0) 60 | 61 | static scmp_filter_ctx ctx; 62 | 63 | int 64 | enable_sandbox_basic(void) 65 | { 66 | 67 | if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) 68 | return -1; 69 | 70 | if (prctl(PR_SET_DUMPABLE, 0, 0, 0, 0) == -1) 71 | return -1; 72 | 73 | // initialize the filter 74 | ctx = seccomp_init(SCMP_ACT_ALLOW); 75 | if (ctx == NULL) 76 | return 1; 77 | 78 | DENY_RULE(_sysctl); 79 | DENY_RULE(acct); 80 | DENY_RULE(add_key); 81 | DENY_RULE(adjtimex); 82 | DENY_RULE(chroot); 83 | DENY_RULE(clock_adjtime); 84 | DENY_RULE(create_module); 85 | DENY_RULE(delete_module); 86 | DENY_RULE(fanotify_init); 87 | DENY_RULE(finit_module); 88 | DENY_RULE(get_kernel_syms); 89 | DENY_RULE(get_mempolicy); 90 | DENY_RULE(init_module); 91 | DENY_RULE(io_cancel); 92 | DENY_RULE(io_destroy); 93 | DENY_RULE(io_getevents); 94 | DENY_RULE(io_setup); 95 | DENY_RULE(io_submit); 96 | DENY_RULE(ioperm); 97 | DENY_RULE(iopl); 98 | DENY_RULE(ioprio_set); 99 | DENY_RULE(kcmp); 100 | #ifdef __NR_kexec_file_load 101 | DENY_RULE(kexec_file_load); 102 | #endif 103 | DENY_RULE(kexec_load); 104 | DENY_RULE(keyctl); 105 | DENY_RULE(lookup_dcookie); 106 | DENY_RULE(mbind); 107 | DENY_RULE(nfsservctl); 108 | DENY_RULE(migrate_pages); 109 | DENY_RULE(modify_ldt); 110 | DENY_RULE(mount); 111 | DENY_RULE(move_pages); 112 | DENY_RULE(name_to_handle_at); 113 | DENY_RULE(open_by_handle_at); 114 | DENY_RULE(perf_event_open); 115 | DENY_RULE(pivot_root); 116 | DENY_RULE(process_vm_readv); 117 | DENY_RULE(process_vm_writev); 118 | DENY_RULE(ptrace); 119 | DENY_RULE(reboot); 120 | DENY_RULE(remap_file_pages); 121 | DENY_RULE(request_key); 122 | DENY_RULE(set_mempolicy); 123 | DENY_RULE(swapoff); 124 | DENY_RULE(swapon); 125 | DENY_RULE(sysfs); 126 | DENY_RULE(syslog); 127 | DENY_RULE(tuxcall); 128 | DENY_RULE(umount2); 129 | DENY_RULE(uselib); 130 | DENY_RULE(vmsplice); 131 | 132 | // blocking dangerous syscalls that file should not need 133 | DENY_RULE (execve); 134 | DENY_RULE (socket); 135 | // ... 136 | 137 | 138 | // applying filter... 139 | if (seccomp_load (ctx) == -1) 140 | goto out; 141 | // free ctx after the filter has been loaded into the kernel 142 | seccomp_release(ctx); 143 | return 0; 144 | 145 | out: 146 | seccomp_release(ctx); 147 | return -1; 148 | } 149 | 150 | 151 | int 152 | enable_sandbox_full(void) 153 | { 154 | 155 | // prevent child processes from getting more priv e.g. via setuid, 156 | // capabilities, ... 157 | if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) 158 | return -1; 159 | 160 | if (prctl(PR_SET_DUMPABLE, 0, 0, 0, 0) == -1) 161 | return -1; 162 | 163 | // initialize the filter 164 | ctx = seccomp_init(SCMP_ACT_KILL); 165 | if (ctx == NULL) 166 | return -1; 167 | 168 | ALLOW_RULE(access); 169 | ALLOW_RULE(brk); 170 | ALLOW_RULE(close); 171 | ALLOW_RULE(dup2); 172 | ALLOW_RULE(exit); 173 | ALLOW_RULE(exit_group); 174 | ALLOW_RULE(fcntl); 175 | ALLOW_RULE(fcntl64); 176 | ALLOW_RULE(fstat); 177 | ALLOW_RULE(fstat64); 178 | ALLOW_RULE(futex); 179 | ALLOW_RULE(getdents); 180 | #ifdef __NR_getdents64 181 | ALLOW_RULE(getdents64); 182 | #endif 183 | #ifdef FIONREAD 184 | // called in src/compress.c under sread 185 | ALLOW_IOCTL_RULE(FIONREAD); 186 | #endif 187 | #ifdef TIOCGWINSZ 188 | // musl libc may call ioctl TIOCGWINSZ on stdout 189 | ALLOW_IOCTL_RULE(TIOCGWINSZ); 190 | #endif 191 | #ifdef TCGETS 192 | // glibc may call ioctl TCGETS on stdout on physical terminal 193 | ALLOW_IOCTL_RULE(TCGETS); 194 | #endif 195 | ALLOW_RULE(lseek); 196 | ALLOW_RULE(_llseek); 197 | ALLOW_RULE(lstat); 198 | ALLOW_RULE(lstat64); 199 | ALLOW_RULE(madvise); 200 | ALLOW_RULE(mmap); 201 | ALLOW_RULE(mmap2); 202 | ALLOW_RULE(mprotect); 203 | ALLOW_RULE(mremap); 204 | ALLOW_RULE(munmap); 205 | #ifdef __NR_newfstatat 206 | ALLOW_RULE(newfstatat); 207 | #endif 208 | ALLOW_RULE(open); 209 | ALLOW_RULE(openat); 210 | ALLOW_RULE(pread64); 211 | ALLOW_RULE(read); 212 | ALLOW_RULE(readlink); 213 | #ifdef __NR_readlinkat 214 | ALLOW_RULE(readlinkat); 215 | #endif 216 | ALLOW_RULE(rt_sigaction); 217 | ALLOW_RULE(rt_sigprocmask); 218 | ALLOW_RULE(rt_sigreturn); 219 | ALLOW_RULE(select); 220 | ALLOW_RULE(stat); 221 | ALLOW_RULE(statx); 222 | ALLOW_RULE(stat64); 223 | ALLOW_RULE(sysinfo); 224 | ALLOW_RULE(umask); // Used in file_pipe2file() 225 | ALLOW_RULE(getpid); // Used by glibc in file_pipe2file() 226 | ALLOW_RULE(unlink); 227 | ALLOW_RULE(write); 228 | ALLOW_RULE(writev); 229 | 230 | 231 | #if 0 232 | // needed by valgrind 233 | ALLOW_RULE(gettid); 234 | ALLOW_RULE(rt_sigtimedwait); 235 | #endif 236 | 237 | #if 0 238 | /* special restrictions for socket, only allow AF_UNIX/AF_LOCAL */ 239 | if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 1, 240 | SCMP_CMP(0, SCMP_CMP_EQ, AF_UNIX)) == -1) 241 | goto out; 242 | 243 | if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 1, 244 | SCMP_CMP(0, SCMP_CMP_EQ, AF_LOCAL)) == -1) 245 | goto out; 246 | 247 | 248 | /* special restrictions for open, prevent opening files for writing */ 249 | if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 1, 250 | SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_WRONLY | O_RDWR, 0)) == -1) 251 | goto out; 252 | 253 | if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EACCES), SCMP_SYS(open), 1, 254 | SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_WRONLY, O_WRONLY)) == -1) 255 | goto out; 256 | 257 | if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EACCES), SCMP_SYS(open), 1, 258 | SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_RDWR, O_RDWR)) == -1) 259 | goto out; 260 | 261 | 262 | /* allow stderr */ 263 | if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1, 264 | SCMP_CMP(0, SCMP_CMP_EQ, 2)) == -1) 265 | goto out; 266 | #endif 267 | 268 | // applying filter... 269 | if (seccomp_load(ctx) == -1) 270 | goto out; 271 | // free ctx after the filter has been loaded into the kernel 272 | seccomp_release(ctx); 273 | return 0; 274 | 275 | out: 276 | // something went wrong 277 | seccomp_release(ctx); 278 | return -1; 279 | } 280 | #endif 281 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/strcasestr.c: -------------------------------------------------------------------------------- 1 | /* $NetBSD: strcasestr.c,v 1.3 2005/11/29 03:12:00 christos Exp $ */ 2 | 3 | /*- 4 | * Copyright (c) 1990, 1993 5 | * The Regents of the University of California. All rights reserved. 6 | * 7 | * This code is derived from software contributed to Berkeley by 8 | * Chris Torek. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the University nor the names of its contributors 19 | * may be used to endorse or promote products derived from this software 20 | * without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 | * SUCH DAMAGE. 33 | */ 34 | 35 | #if defined(LIBC_SCCS) && !defined(lint) 36 | __RCSID("$NetBSD: strcasestr.c,v 1.3 2005/11/29 03:12:00 christos Exp $"); 37 | __RCSID("$NetBSD: strncasecmp.c,v 1.2 2007/06/04 18:19:27 christos Exp $"); 38 | #endif /* LIBC_SCCS and not lint */ 39 | 40 | #include "file.h" 41 | 42 | #include 43 | #include 44 | #include 45 | 46 | static int 47 | _strncasecmp(const char *s1, const char *s2, size_t n) 48 | { 49 | if (n != 0) { 50 | const unsigned char *us1 = (const unsigned char *)s1, 51 | *us2 = (const unsigned char *)s2; 52 | 53 | do { 54 | if (tolower(*us1) != tolower(*us2++)) 55 | return tolower(*us1) - tolower(*--us2); 56 | if (*us1++ == '\0') 57 | break; 58 | } while (--n != 0); 59 | } 60 | return 0; 61 | } 62 | 63 | /* 64 | * Find the first occurrence of find in s, ignore case. 65 | */ 66 | char * 67 | strcasestr(const char *s, const char *find) 68 | { 69 | char c, sc; 70 | size_t len; 71 | 72 | if ((c = *find++) != 0) { 73 | c = tolower((unsigned char)c); 74 | len = strlen(find); 75 | do { 76 | do { 77 | if ((sc = *s++) == 0) 78 | return (NULL); 79 | } while ((char)tolower((unsigned char)sc) != c); 80 | } while (_strncasecmp(s, find, len) != 0); 81 | s--; 82 | } 83 | return (char *)(intptr_t)(s); 84 | } 85 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/strlcat.c: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */ 2 | 3 | /* 4 | * Copyright (c) 1998 Todd C. Miller 5 | * 6 | * Permission to use, copy, modify, and distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | /* OPENBSD ORIGINAL: lib/libc/string/strlcat.c */ 20 | #include "file.h" 21 | 22 | #include 23 | #include 24 | 25 | /* 26 | * Appends src to string dst of size siz (unlike strncat, siz is the 27 | * full size of dst, not space left). At most siz-1 characters 28 | * will be copied. Always NUL terminates (unless siz <= strlen(dst)). 29 | * Returns strlen(src) + MIN(siz, strlen(initial dst)). 30 | * If retval >= siz, truncation occurred. 31 | */ 32 | size_t 33 | strlcat(char *dst, const char *src, size_t siz) 34 | { 35 | char *d = dst; 36 | const char *s = src; 37 | size_t n = siz; 38 | size_t dlen; 39 | 40 | /* Find the end of dst and adjust bytes left but don't go past end */ 41 | while (n-- != 0 && *d != '\0') 42 | d++; 43 | dlen = d - dst; 44 | n = siz - dlen; 45 | 46 | if (n == 0) 47 | return(dlen + strlen(s)); 48 | while (*s != '\0') { 49 | if (n != 1) { 50 | *d++ = *s; 51 | n--; 52 | } 53 | s++; 54 | } 55 | *d = '\0'; 56 | 57 | return(dlen + (s - src)); /* count does not include NUL */ 58 | } 59 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/strlcpy.c: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: strlcpy.c,v 1.10 2005/08/08 08:05:37 espie Exp $ */ 2 | 3 | /* 4 | * Copyright (c) 1998 Todd C. Miller 5 | * 6 | * Permission to use, copy, modify, and distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | /* OPENBSD ORIGINAL: lib/libc/string/strlcpy.c */ 20 | #include "file.h" 21 | 22 | #include 23 | #include 24 | 25 | /* 26 | * Copy src to string dst of size siz. At most siz-1 characters 27 | * will be copied. Always NUL terminates (unless siz == 0). 28 | * Returns strlen(src); if retval >= siz, truncation occurred. 29 | */ 30 | size_t 31 | strlcpy(char *dst, const char *src, size_t siz) 32 | { 33 | char *d = dst; 34 | const char *s = src; 35 | size_t n = siz; 36 | 37 | /* Copy as many bytes as will fit */ 38 | if (n != 0 && --n != 0) { 39 | do { 40 | if ((*d++ = *s++) == 0) 41 | break; 42 | } while (--n != 0); 43 | } 44 | 45 | /* Not enough room in dst, add NUL and traverse rest of src */ 46 | if (n == 0) { 47 | if (siz != 0) 48 | *d = '\0'; /* NUL-terminate dst */ 49 | while (*s++) 50 | ; 51 | } 52 | 53 | return(s - src - 1); /* count does not include NUL */ 54 | } 55 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/tar.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Ian F. Darwin 1986-1995. 3 | * Software written by Ian F. Darwin and others; 4 | * maintained 1995-present by Christos Zoulas and others. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice immediately at the beginning of the file, without modification, 11 | * this list of conditions, and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 20 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | /* 29 | * Header file for public domain tar (tape archive) program. 30 | * 31 | * @(#)tar.h 1.20 86/10/29 Public Domain. 32 | * 33 | * Created 25 August 1985 by John Gilmore, ihnp4!hoptoad!gnu. 34 | * 35 | * $File: tar.h,v 1.12 2008/02/07 00:58:52 christos Exp $ # checkin only 36 | */ 37 | 38 | /* 39 | * Header block on tape. 40 | * 41 | * I'm going to use traditional DP naming conventions here. 42 | * A "block" is a big chunk of stuff that we do I/O on. 43 | * A "record" is a piece of info that we care about. 44 | * Typically many "record"s fit into a "block". 45 | */ 46 | #define RECORDSIZE 512 47 | #define NAMSIZ 100 48 | #define TUNMLEN 32 49 | #define TGNMLEN 32 50 | 51 | union record { 52 | unsigned char charptr[RECORDSIZE]; 53 | struct header { 54 | char name[NAMSIZ]; 55 | char mode[8]; 56 | char uid[8]; 57 | char gid[8]; 58 | char size[12]; 59 | char mtime[12]; 60 | char chksum[8]; 61 | char linkflag; 62 | char linkname[NAMSIZ]; 63 | char magic[8]; 64 | char uname[TUNMLEN]; 65 | char gname[TGNMLEN]; 66 | char devmajor[8]; 67 | char devminor[8]; 68 | } header; 69 | }; 70 | 71 | /* The magic field is filled with this if uname and gname are valid. */ 72 | #define TMAGIC "ustar" /* 5 chars and a null */ 73 | #define GNUTMAGIC "ustar " /* 7 chars and a null */ 74 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/file/teststrchr.c: -------------------------------------------------------------------------------- 1 | #ifdef TEST 2 | #include 3 | #include 4 | #include 5 | int 6 | main(void) 7 | { 8 | char *strchr(); 9 | 10 | if (strchr(1, "abc", 'c') == NULL) 11 | errx(1, "error 1"); 12 | if (strchr("abc", 'd') != NULL) 13 | errx(1, "error 2"); 14 | if (strchr("abc", 'a') == NULL) 15 | errx(1, "error 3"); 16 | if (strchr("abc", 'c') == NULL) 17 | errx(1, "error 4"); 18 | return 0; 19 | } 20 | #endif 21 | -------------------------------------------------------------------------------- /libmagic/src/main/cpp/magicapi.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "ndkhelper.h" 7 | 8 | struct magic_set *g_magic; 9 | 10 | static void ensure_open(int flag) { 11 | if (g_magic != NULL) { 12 | magic_close(g_magic); 13 | } 14 | g_magic = magic_open(flag); 15 | LOGD("magic open [0x%x]!", (int) g_magic); 16 | } 17 | 18 | static void ensure_close() { 19 | if (g_magic != NULL) { 20 | LOGD("magic open [0x%x]!", (int) g_magic); 21 | magic_close(g_magic); 22 | g_magic = NULL; 23 | } 24 | } 25 | 26 | JNIEXPORT jint JNICALL 27 | Java_com_hzy_libmagic_MagicApi_getMagicVersion(JNIEnv *env, jclass type) { 28 | return magic_version(); 29 | } 30 | 31 | JNIEXPORT jint JNICALL 32 | Java_com_hzy_libmagic_MagicApi_loadFromFile(JNIEnv *env, jclass type, jstring magicPath_, 33 | jint flag) { 34 | const char *magicPath = (*env)->GetStringUTFChars(env, magicPath_, 0); 35 | ensure_open(flag); 36 | int ret = magic_load(g_magic, magicPath); 37 | (*env)->ReleaseStringUTFChars(env, magicPath_, magicPath); 38 | return ret; 39 | } 40 | 41 | JNIEXPORT jint JNICALL 42 | Java_com_hzy_libmagic_MagicApi_loadFromBytes(JNIEnv *env, jclass type, jbyteArray magicBytes_, 43 | jint flag) { 44 | jsize jbufferSize = (*env)->GetArrayLength(env, magicBytes_); 45 | LOGD("malloc buffer size[%d]!", jbufferSize); 46 | jbyte *cBuffer = malloc((size_t) jbufferSize * sizeof(jbyte)); 47 | (*env)->GetByteArrayRegion(env, magicBytes_, 0, jbufferSize, cBuffer); 48 | ensure_open(flag); 49 | size_t size = (size_t) jbufferSize; 50 | int ret = magic_load_buffers(g_magic, (void **) &cBuffer, &size, 1); 51 | return ret; 52 | } 53 | 54 | JNIEXPORT jstring JNICALL 55 | Java_com_hzy_libmagic_MagicApi_magicFile(JNIEnv *env, jclass type, jstring filePath_) { 56 | const char *filePath = (*env)->GetStringUTFChars(env, filePath_, 0); 57 | const char *ret = magic_file(g_magic, filePath); 58 | (*env)->ReleaseStringUTFChars(env, filePath_, filePath); 59 | return (*env)->NewStringUTF(env, ret); 60 | } 61 | 62 | JNIEXPORT jint JNICALL 63 | Java_com_hzy_libmagic_MagicApi_close(JNIEnv *env, jclass type) { 64 | ensure_close(); 65 | return 0; 66 | } 67 | 68 | JNIEXPORT jstring JNICALL 69 | Java_com_hzy_libmagic_MagicApi_getVersionName(JNIEnv *env, jclass type) { 70 | return (*env)->NewStringUTF(env, VERSION); 71 | } 72 | 73 | JNIEXPORT jstring JNICALL 74 | Java_com_hzy_libmagic_MagicApi_getPackageString(JNIEnv *env, jclass type) { 75 | return (*env)->NewStringUTF(env, PACKAGE_STRING); 76 | } -------------------------------------------------------------------------------- /libmagic/src/main/cpp/ndkhelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by hzy on 17-6-13. 3 | // 4 | 5 | #ifndef ANDROIDUN7ZIP_NDKHELPER_H 6 | #define ANDROIDUN7ZIP_NDKHELPER_H 7 | 8 | #include 9 | 10 | #ifdef NATIVE_LOG 11 | #define LOG_TAG "NATIVE.LOG" 12 | #include 13 | 14 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__) 15 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) 16 | #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__) 17 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) 18 | #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG_TAG,__VA_ARGS__) 19 | #else 20 | #define LOGD(...) do{}while(0) 21 | #define LOGI(...) do{}while(0) 22 | #define LOGW(...) do{}while(0) 23 | #define LOGE(...) do{}while(0) 24 | #define LOGF(...) do{}while(0) 25 | #endif 26 | 27 | #endif //ANDROIDUN7ZIP_NDKHELPER_H 28 | -------------------------------------------------------------------------------- /libmagic/src/main/java/com/hzy/libmagic/MagicApi.java: -------------------------------------------------------------------------------- 1 | package com.hzy.libmagic; 2 | 3 | /** 4 | * Created by HZY on 2017/7/8. 5 | */ 6 | 7 | public class MagicApi { 8 | 9 | public static final int MAGIC_NONE = 0x0000000; /* No flags */ 10 | public static final int MAGIC_DEBUG = 0x0000001; /* Turn on debugging */ 11 | public static final int MAGIC_SYMLINK = 0x0000002; /* Follow symlinks */ 12 | public static final int MAGIC_COMPRESS = 0x0000004;/* Check inside compressed files */ 13 | public static final int MAGIC_DEVICES = 0x0000008;/* Look at the contents of devices */ 14 | public static final int MAGIC_MIME_TYPE = 0x0000010;/* Return the MIME type */ 15 | public static final int MAGIC_CONTINUE = 0x0000020;/* Return all matches */ 16 | public static final int MAGIC_CHECK = 0x0000040; /* Print warnings to stderr */ 17 | public static final int MAGIC_PRESERVE_ATIME = 0x0000080;/* Restore access time on exit */ 18 | public static final int MAGIC_RAW = 0x0000100; /* Don't convert unprintable chars */ 19 | public static final int MAGIC_ERROR = 0x0000200;/* Handle ENOENT etc as real errors */ 20 | public static final int MAGIC_MIME_ENCODING = 0x0000400;/* Return the MIME encoding */ 21 | public static final int MAGIC_MIME = (MAGIC_MIME_TYPE | MAGIC_MIME_ENCODING); 22 | public static final int MAGIC_APPLE = 0x0000800; /* Return the Apple creator/type */ 23 | public static final int MAGIC_EXTENSION = 0x1000000; /* Return a /-separated list of extensions */ 24 | public static final int MAGIC_COMPRESS_TRANSP = 0x2000000; /* Check inside compressed files but not report compression */ 25 | public static final int MAGIC_NODESC = (MAGIC_EXTENSION | MAGIC_MIME | MAGIC_APPLE); 26 | 27 | public static int loadFromFile(String magicPath) { 28 | return loadFromFile(magicPath, MAGIC_NONE); 29 | } 30 | 31 | public static int loadFromBytes(byte[] magicBytes) { 32 | return loadFromBytes(magicBytes, MAGIC_NONE); 33 | } 34 | 35 | public static native int getMagicVersion(); 36 | 37 | public static native String getVersionName(); 38 | 39 | public static native String getPackageString(); 40 | 41 | public static native int loadFromFile(String magicPath, int flag); 42 | 43 | public static native int loadFromBytes(byte[] magicBytes, int flag); 44 | 45 | public static native String magicFile(String filePath); 46 | 47 | public static native int close(); 48 | 49 | static { 50 | System.loadLibrary("magic"); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /libmagic/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | libmagic 3 | 4 | -------------------------------------------------------------------------------- /misc/screen.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huzongyao/AndroidMagic/2a25054a07db0ddffe4e80e6e7847d5c054ea6ed/misc/screen.gif -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':libmagic' 2 | --------------------------------------------------------------------------------