├── .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 | [](https://github.com/huzongyao/AndroidMagic/releases)
6 | [](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 | 
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 | 
46 |
47 | ### Others
48 | * 想捐助我喝杯热水(¥0.01起捐)
49 | 
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------