Browse Source

works on Windows

tags/v0.3.0
Bob Rudis 8 years ago
parent
commit
134bdb04f3
  1. 19
      DESCRIPTION
  2. 5
      NAMESPACE
  3. 5
      NEWS.md
  4. 27
      R/RcppExports.R
  5. 4
      R/wand-package.R
  6. 76
      R/wand.r
  7. 15
      R/zzz.r
  8. 4
      README.Rmd
  9. 8
      README.md
  10. 0
      configure.win
  11. BIN
      inst/db/win/magic.mgc.zip
  12. BIN
      inst/exec/file.exe
  13. 2
      man/incant.Rd
  14. 4
      man/magic_wand_file.Rd
  15. 9
      src/Makevars
  16. 9
      src/Makevars.win
  17. 8
      src/RcppExports.cpp
  18. 42
      src/wand.cpp
  19. 5
      tools/getfile.R

19
DESCRIPTION

@ -1,28 +1,29 @@
Package: wand Package: wand
Type: Package Type: Package
Title: Retrieve 'Magic' Attributes from Files and Directories Title: Retrieve 'Magic' Attributes from Files and Directories
Version: 0.1.0 Version: 0.2.0
Date: 2016-08-12 Date: 2016-08-13
Author: Bob Rudis (@hrbrmstr), Christos Zoulas [libmagic] Author: Bob Rudis (@hrbrmstr), Christos Zoulas [libmagic]
Maintainer: Bob Rudis <bob@rudis.net> Maintainer: Bob Rudis <bob@rud.is>
Description: The 'libmagic' library provides functions to determine Description: The 'libmagic' library provides functions to determine
mime type and other metadata from files through their "magic" mime type and other metadata from files through their "magic"
attributes. attributes.
URL: http://github.com/hrbrmstr/wand URL: http://github.com/hrbrmstr/wand
BugReports: https://github.com/hrbrmstr/wand/issues BugReports: https://github.com/hrbrmstr/wand/issues
SystemRequirements: libmagic SystemRequirements: libmagic (>= 5.14)
License: AGPL License: AGPL
Suggests: Suggests:
testthat, testthat
tibble,
magrittr,
dplyr
Depends: Depends:
R (>= 3.0.0) R (>= 3.0.0)
Imports: Imports:
purrr, purrr,
Rcpp, Rcpp,
rappdirs, rappdirs,
utils tibble,
utils,
tidyr,
stringi,
dplyr
LinkingTo: Rcpp LinkingTo: Rcpp
RoxygenNote: 5.0.1 RoxygenNote: 5.0.1

5
NAMESPACE

@ -3,7 +3,12 @@
export(incant) export(incant)
export(magic_wand_file) export(magic_wand_file)
import(purrr) import(purrr)
import(stringi)
import(tibble)
import(tidyr)
importFrom(Rcpp,sourceCpp) importFrom(Rcpp,sourceCpp)
importFrom(dplyr,left_join)
importFrom(dplyr,mutate)
importFrom(rappdirs,user_cache_dir) importFrom(rappdirs,user_cache_dir)
importFrom(utils,unzip) importFrom(utils,unzip)
useDynLib(wand) useDynLib(wand)

5
NEWS.md

@ -1,2 +1,5 @@
0.1.0 # 0.2.0
* Works on Windows
# 0.1.0
* Initial release * Initial release

27
R/RcppExports.R

@ -1,31 +1,8 @@
# This file was generated by Rcpp::compileAttributes # This file was generated by Rcpp::compileAttributes
# Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 # Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393
#' Retrieve 'magic' attributes from files and directories incant_ <- function(path, magic_db = "system") {
#' .Call('wand_incant_', PACKAGE = 'wand', path, magic_db)
#' @param path character vector of files to use magic on
#' @param magic_db either "\code{system}" (the default) to use the system
#' \code{magic} database or an atomic character vector with a
#' colon-separated list of full paths to custom \code{magic} database(s).
#' @return a \code{tibble} / \code{data.frame} of file magic attributes.
#' Specifically, mime type, encoding, possible file extensions and
#' type description are returned as colums in the data frame along
#' with \code{path}.
#' @note Various fields might not be available depending on the version
#' of \code{libmagic} you have installed.
#' @references See \url{http://openpreservation.org/blog/2012/08/09/magic-editing-and-creation-primer/}
#' for information on how to create your own \code{magic} database
#' @export
#' @examples
#' library(magrittr)
#' library(dplyr)
#'
#' system.file("img", package="filemagic") %>%
#' list.files(full.names=TRUE) %>%
#' incant() %>%
#' glimpse()
incant <- function(path, magic_db = "system") {
.Call('wand_incant', PACKAGE = 'wand', path, magic_db)
} }
lib_version <- function() { lib_version <- function() {

4
R/wand-package.R

@ -4,8 +4,12 @@
#' @docType package #' @docType package
#' @author Bob Rudis (@@hrbrmstr) #' @author Bob Rudis (@@hrbrmstr)
#' @import purrr #' @import purrr
#' @import tibble
#' @import tidyr
#' @import stringi
#' @importFrom rappdirs user_cache_dir #' @importFrom rappdirs user_cache_dir
#' @useDynLib wand #' @useDynLib wand
#' @importFrom Rcpp sourceCpp #' @importFrom Rcpp sourceCpp
#' @importFrom utils unzip #' @importFrom utils unzip
#' @importFrom dplyr mutate left_join
NULL NULL

76
R/wand.r

@ -0,0 +1,76 @@
#' Retrieve 'magic' attributes from files and directories
#'
#' @param path character vector of files to use magic on
#' @param magic_db either "\code{system}" (the default) to use the system
#' \code{magic} database or an atomic character vector with a
#' colon-separated list of full paths to custom \code{magic} database(s).
#' @return a \code{tibble} / \code{data.frame} of file magic attributes.
#' Specifically, mime type, encoding, possible file extensions and
#' type description are returned as colums in the data frame along
#' with \code{path}.
#' @note Various fields might not be available depending on the version
#' of \code{libmagic} you have installed.
#' @references See \url{http://openpreservation.org/blog/2012/08/09/magic-editing-and-creation-primer/}
#' for information on how to create your own \code{magic} database
#' @export
#' @examples
#' library(magrittr)
#' library(dplyr)
#'
#' system.file("img", package="filemagic") %>%
#' list.files(full.names=TRUE) %>%
#' incant() %>%
#' glimpse()
incant <- function(path, magic_db="system") {
if (get_os() == "win") {
file_exe <- system.file("exec/file.exe", package="wand")
magic_db <- normalizePath(magic_wand_file())
tf <- tempfile()
writeLines(path, tf)
system2(file_exe,
c("--mime-type", "--mime-encoding", "--no-buffer", "--preserve-date",
'--separator "||"', sprintf('--magic-file "%s"', magic_db),
sprintf('--files-from "%s"', tf)),
stdout=TRUE) -> output_1
system2(file_exe,
c("--no-buffer", "--preserve-date", '--separator "||"',
sprintf('--magic-file "%s"', magic_db),
sprintf('--files-from "%s"', tf)),
stdout=TRUE) -> output_2
unlink(tf)
stri_split_fixed(output_1, "||", n=2, simplify=TRUE) %>%
as_data_frame() %>%
setNames(c("file", "response")) %>%
separate(response, c("mime_type", "encoding"), sep=";", extra="drop", fill="right") %>%
mutate(encoding=stri_replace_first_regex(encoding, "charset=", "")) -> df1
stri_split_fixed(output_2, "||", n=2, simplify=TRUE) %>%
as_data_frame() %>%
setNames(c("file", "description")) -> df2
left_join(df1, df2, by="file")
} else {
incant_(path, magic_db)
}
}
get_os <- function () {
if (.Platform$OS.type == "windows") {
"win"
} else if (Sys.info()["sysname"] == "Darwin") {
"mac"
} else if (.Platform$OS.type == "unix") {
"unix"
} else {
stop("Unknown OS")
}
}

15
R/zzz.r

@ -8,7 +8,7 @@
#' perform the decompression unless \code{force} is \code{TRUE} or the #' perform the decompression unless \code{force} is \code{TRUE} or the
#' cache directory has been cleared. #' cache directory has been cleared.
#' #'
#' @param force ensure the lastest copy of the pacakge "magic" #' @param refresh ensure the lastest copy of the pacakge "magic"
#' database is used. #' database is used.
#' @export #' @export
#' @examples #' @examples
@ -19,18 +19,19 @@
#' list.files(full.names=TRUE) %>% #' list.files(full.names=TRUE) %>%
#' incant(magic_wand_file()) %>% #' incant(magic_wand_file()) %>%
#' glimpse() #' glimpse()
magic_wand_file <- function(force=FALSE) { magic_wand_file <- function(refresh=FALSE) {
cache <- rappdirs::user_cache_dir("wandr") cache <- rappdirs::user_cache_dir("wandr")
if (!dir.exists(cache)) dir.create(cache, showWarnings=FALSE) if (!dir.exists(cache)) dir.create(cache, recursive=TRUE, showWarnings=FALSE)
if (!dir.exists(cache)) return("system") if (!dir.exists(cache)) return(NULL)
if (lib_version() >= 528) vers <- "new" else vers <- "old" if (lib_version() >= 528) vers <- "new" else vers <- "old"
if (get_os() == "win") vers <- "win"
if (!file.exists(file.path(rappdirs::user_cache_dir("wandr"), "magic.mgc"))) { if (refresh | (!file.exists(file.path(rappdirs::user_cache_dir("wandr"), "magic.mgc")))) {
suppressWarnings(unzip(system.file("db", vers, "magic.mgc.zip", package="wand"), unzip(system.file("db", vers, "magic.mgc.zip", package="wand"),
exdir=cache, overwrite=force)) exdir=cache, overwrite=TRUE)
} }
file.path(rappdirs::user_cache_dir("wandr"), "magic.mgc") file.path(rappdirs::user_cache_dir("wandr"), "magic.mgc")

4
README.Rmd

@ -6,14 +6,14 @@ output: rmarkdown::github_document
`wand` : Retrieve 'Magic' Attributes from Files and Directories `wand` : Retrieve 'Magic' Attributes from Files and Directories
The `libmagic` library must be installed and available to use this. The `libmagic` library must be installed on *nix/macOS and available to use this.
- `apt-get install libmagic-dev` on Debian-ish systems - `apt-get install libmagic-dev` on Debian-ish systems
- `brew install libmagic` on macOS - `brew install libmagic` on macOS
While the package was developed using the 5.28 version of `libmagic` it has been configured to work with older versions. Note that some fields in the resultant data frame might not be available with older library versions. When using the function `magic_wand_file()` it checks for which version of `libmagic` is installed on your system and provides a suitable `magic.mgc` file for it. While the package was developed using the 5.28 version of `libmagic` it has been configured to work with older versions. Note that some fields in the resultant data frame might not be available with older library versions. When using the function `magic_wand_file()` it checks for which version of `libmagic` is installed on your system and provides a suitable `magic.mgc` file for it.
The package should also be pretty straightforward to get working on Windows. Assistance to do that is welcome. Think of all the fame and glory you'll receive! The package also works on Windows but it's a bit of a hack because, well, _Windows_. Seriously, folks, use a real operating system. The Windows version makes two `system2()` calls, so it's sub-optimal at best. Help to get it working in C would be greatly appreciated.
The following functions are implemented: The following functions are implemented:

8
README.md

@ -3,14 +3,14 @@
`wand` : Retrieve 'Magic' Attributes from Files and Directories `wand` : Retrieve 'Magic' Attributes from Files and Directories
The `libmagic` library must be installed and available to use this. The `libmagic` library must be installed on \*nix/macOS and available to use this.
- `apt-get install libmagic-dev` on Debian-ish systems - `apt-get install libmagic-dev` on Debian-ish systems
- `brew install libmagic` on macOS - `brew install libmagic` on macOS
While the package was developed using the 5.28 version of `libmagic` it has been configured to work with older versions. Note that some fields in the resultant data frame might not be available with older library versions. When using the function `magic_wand_file()` it checks for which version of `libmagic` is installed on your system and provides a suitable `magic.mgc` file for it. While the package was developed using the 5.28 version of `libmagic` it has been configured to work with older versions. Note that some fields in the resultant data frame might not be available with older library versions. When using the function `magic_wand_file()` it checks for which version of `libmagic` is installed on your system and provides a suitable `magic.mgc` file for it.
The package should also be pretty straightforward to get working on Windows. Assistance to do that is welcome. Think of all the fame and glory you'll receive! The package also works on Windows but it's a bit of a hack because, well, *Windows*. Seriously, folks, use a real operating system. The Windows version makes two `system2()` calls, so it's sub-optimal at best. Help to get it working in C would be greatly appreciated.
The following functions are implemented: The following functions are implemented:
@ -68,7 +68,7 @@ system.file("img", package="wand") %>%
packageVersion("wand") packageVersion("wand")
``` ```
## [1] '0.1.0' ## [1] '0.2.0'
### Test Results ### Test Results
@ -79,7 +79,7 @@ library(testthat)
date() date()
``` ```
## [1] "Sat Aug 13 12:12:14 2016" ## [1] "Sun Aug 14 18:36:44 2016"
``` r ``` r
test_dir("tests/") test_dir("tests/")

0
configure.win

BIN
inst/db/win/magic.mgc.zip

Binary file not shown.

BIN
inst/exec/file.exe

Binary file not shown.

2
man/incant.Rd

@ -1,5 +1,5 @@
% Generated by roxygen2: do not edit by hand % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/RcppExports.R % Please edit documentation in R/wand.r
\name{incant} \name{incant}
\alias{incant} \alias{incant}
\title{Retrieve 'magic' attributes from files and directories} \title{Retrieve 'magic' attributes from files and directories}

4
man/magic_wand_file.Rd

@ -4,10 +4,10 @@
\alias{magic_wand_file} \alias{magic_wand_file}
\title{Use the "magic" file that comes with the package} \title{Use the "magic" file that comes with the package}
\usage{ \usage{
magic_wand_file(force = FALSE) magic_wand_file(refresh = FALSE)
} }
\arguments{ \arguments{
\item{force}{ensure the lastest copy of the pacakge "magic" \item{refresh}{ensure the lastest copy of the pacakge "magic"
database is used.} database is used.}
} }
\description{ \description{

9
src/Makevars

@ -1 +1,8 @@
PKG_LIBS = -lmagic PKG_LIBS = -lmagic
all: clean
clean:
rm -f $(OBJECTS) wand.dll
.PHONY: all clean

9
src/Makevars.win

@ -0,0 +1,9 @@
all: winlibs
clean:
rm -f $(OBJECTS) wand.dll
winlibs:
"${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" "../tools/getfile.R"
.PHONY: all winlibs clean

8
src/RcppExports.cpp

@ -5,15 +5,15 @@
using namespace Rcpp; using namespace Rcpp;
// incant // incant_
DataFrame incant(CharacterVector path, std::string magic_db); DataFrame incant_(CharacterVector path, std::string magic_db);
RcppExport SEXP wand_incant(SEXP pathSEXP, SEXP magic_dbSEXP) { RcppExport SEXP wand_incant_(SEXP pathSEXP, SEXP magic_dbSEXP) {
BEGIN_RCPP BEGIN_RCPP
Rcpp::RObject __result; Rcpp::RObject __result;
Rcpp::RNGScope __rngScope; Rcpp::RNGScope __rngScope;
Rcpp::traits::input_parameter< CharacterVector >::type path(pathSEXP); Rcpp::traits::input_parameter< CharacterVector >::type path(pathSEXP);
Rcpp::traits::input_parameter< std::string >::type magic_db(magic_dbSEXP); Rcpp::traits::input_parameter< std::string >::type magic_db(magic_dbSEXP);
__result = Rcpp::wrap(incant(path, magic_db)); __result = Rcpp::wrap(incant_(path, magic_db));
return __result; return __result;
END_RCPP END_RCPP
} }

42
src/wand.cpp

@ -1,34 +1,23 @@
#include <Rcpp.h> #include <Rcpp.h>
using namespace Rcpp; using namespace Rcpp;
#ifdef _WIN32
#define WINDOWS
#endif
#ifdef _WIN64
#define WINDOWS
#endif
#ifndef WINDOWS
#include "magic.h" #include "magic.h"
#include "limits.h" #include "limits.h"
#endif
//' Retrieve 'magic' attributes from files and directories #ifndef WINDOWS
//'
//' @param path character vector of files to use magic on
//' @param magic_db either "\code{system}" (the default) to use the system
//' \code{magic} database or an atomic character vector with a
//' colon-separated list of full paths to custom \code{magic} database(s).
//' @return a \code{tibble} / \code{data.frame} of file magic attributes.
//' Specifically, mime type, encoding, possible file extensions and
//' type description are returned as colums in the data frame along
//' with \code{path}.
//' @note Various fields might not be available depending on the version
//' of \code{libmagic} you have installed.
//' @references See \url{http://openpreservation.org/blog/2012/08/09/magic-editing-and-creation-primer/}
//' for information on how to create your own \code{magic} database
//' @export
//' @examples
//' library(magrittr)
//' library(dplyr)
//'
//' system.file("img", package="filemagic") %>%
//' list.files(full.names=TRUE) %>%
//' incant() %>%
//' glimpse()
// [[Rcpp::export]] // [[Rcpp::export]]
DataFrame incant(CharacterVector path, std::string magic_db="system") { DataFrame incant_(CharacterVector path, std::string magic_db="system") {
unsigned int input_size = path.size(); unsigned int input_size = path.size();
@ -149,6 +138,11 @@ DataFrame incant(CharacterVector path, std::string magic_db="system") {
return(df); return(df);
} }
#else
DataFrame incant_(CharacterVector path, std::string magic_db="system") {
return(DataFrame::create());
}
#endif
// [[Rcpp::export]] // [[Rcpp::export]]
int lib_version() { int lib_version() {

5
tools/getfile.R

@ -0,0 +1,5 @@
if(getRversion() < "3.3.0") setInternet2()
download.file("https://www.stats.ox.ac.uk/pub/Rtools/goodies/file-5.03.zip", "file.zip", quiet = TRUE)
dir.create("../inst/exec", showWarnings = FALSE)
unzip("file.zip", "file.exe", exdir = "../inst/exec")
unlink("file.zip")
Loading…
Cancel
Save