Spreadsheet-Edit
view release on metacpan or search on metacpan
lib/Spreadsheet/Edit/IO.pm view on Meta::CPAN
use Exporter 'import';
our @EXPORT = qw/convert_spreadsheet OpenAsCsv cx2let let2cx cxrx2sheetaddr
sheetname_from_spec filepath_from_spec
form_spec_with_sheetname/;
our @EXPORT_OK = qw/can_cvt_spreadsheets can_extract_allsheets can_extract_named_sheet
openlibreoffice_path
@sane_CSV_read_options @sane_CSV_write_options/;
# TODO: Provide "known_attributes" function ala Text::CSV::known_attributes()
use version ();
use Carp;
use File::Copy ();
use File::Copy::Recursive ();
use File::Glob qw/bsd_glob/;
use Path::Tiny 0.146 qw/path/;
# Path::Tiny OBVIATES NEED for many but we still need this
use File::Spec ();
use File::Spec::Functions qw/devnull tmpdir rootdir catdir catfile/;
# Still sometimes convenient...
use File::Basename qw(basename);
use File::BOM ();
use File::Which qw/which/;
use URI::file ();
use Guard qw(guard scope_guard);
use Fcntl qw(:flock :seek);
use Symbol qw/qualify_to_ref/;
use Scalar::Util qw/blessed openhandle/;
use List::Util qw/none all notall first min max/;
use Encode qw(encode decode);
use File::Glob qw/bsd_glob GLOB_NOCASE/;
use Digest::MD5 qw/md5_base64/;
use Data::Hexify qw/Hexify/;
use Text::CSV ();
# DDI 5.025 is needed for Windows-aware qsh()
use Data::Dumper::Interp 5.025 qw/vis visq visO dvis dvisq dvisO ivis ivisq avis hvis qsh qshlist u visnew/;
use Spreadsheet::Edit::Log qw/log_call fmt_call log_methcall fmt_methcall oops :btw/;
our %SpreadsheetEdit_Log_Options = (
is_public_api => sub{
$_[1][3] =~ /(?: ::|^ )(?: [a-z][^:]* | OpenAsCsv | ConvertSpreadsheet )$/x
},
subst_pkg => "IO",
);
my $progname = path($0)->basename;
sub _get_username(;$) {
my ($uid) = @_;
$uid //= eval{ $> } // -1; # default to EUID
state $answer = {};
return $answer->{$uid} //= do {
# https://stackoverflow.com/questions/12081246/how-to-get-system-user-full-name-on-windows-in-perl
eval { getpwuid($uid) // $uid }
||
($^O =~ /MSWin/ && $uid == (eval{$>}//-1) && eval{ # untested...
require Win32API::Net;
Win32API::Net::UserGetInfo($ENV{LOGONSERVER}||'',Win32::LoginName(),10,my $info={});
$info->{fullName}
})
||
"UID$uid"
};
}
# A private Libre/Open Office profile dir is needed to avoid conflicts
# with interactive sessions, see
# https://ask.libreoffice.org/en/question/290306/how-to-start-independent-lo-instance-process
#
# We use a persistent profile dir shared among processes for a given user
# (actually one for each unique external tool which needs one).
# Sharing is okay because we get an exclusive lock before actually using it.
state $profile_parent_dir = do{ # also used for lockfile
my $user = _get_username();
my $dname = __PACKAGE__."_${user}_profileparent";
$dname =~ s/::/-/g;
$dname =~ s/[^-\w.:]/_/g;
(my $path = path(File::Spec->tmpdir)->child($dname))->mkpath;
$path # Path::Tiny
};
sub _get_tool_profdir($) {
my ($tool_path) = @_;
my $fingerprint = _file_fingerprint($tool_path);
(my $toolname = path($tool_path)->basename(qw/\.\w+$/)) =~ s/[^-\w.:]/_/g;
my $path = $profile_parent_dir->child("${toolname}_$fingerprint");
$path->mkpath;
$path
}
# Prevent concurrent document conversions.
# LO & OO can't handle concurrent access to the same profile.
my $locked_fh;
sub _get_exclusive_lock($) { # returns lock object
my $opts = shift;
my $lockfile_path = $profile_parent_dir->child("LOCKFILE")->canonpath;
my $sleeptime = 1;
my $lock_fh;
while (! defined $lock_fh) {
#warn "$$ : ### AA1 open $lockfile_path ...\n";
open $lock_fh, "+>>", $lockfile_path or die $!;
#warn "$$ : ### AA2 open succeeded.\n";
eval { chmod 0666, $lock_fh; }; # sometimes not implemented
#warn "$$ : ### AA3 flock ...\n";
if (! flock($lock_fh, LOCK_EX|LOCK_NB)) {
#warn "$$ : ### AA4 flock FAILED\n";
seek($lock_fh, 0, SEEK_SET) or die;
my @lines = <$lock_fh>;
close($lock_fh) or die "close:$!"; $lock_fh = undef;
#warn "$$ : ### AA6 fh closed...\n";
my $owner = $lines[-1] // ""; # pid NNN (progname)
{ my ($pid) = ($owner =~ /pid (\d+)/) or last;
my @s = stat("/proc/$pid") or last;
$owner = _get_username($s[4])." ".$owner;
( run in 2.779 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )