diff options
| author | Philipp Gesang <phg@phi-gamma.net> | 2016-06-08 08:23:38 +0200 | 
|---|---|---|
| committer | Philipp Gesang <phg@phi-gamma.net> | 2016-06-08 08:23:43 +0200 | 
| commit | 37f8c42a1b560df3f1bc1444405c772f00340f88 (patch) | |
| tree | b04a709daa2929a82eb9497149610321f14dba43 /src | |
| parent | 68f523b6660baaabd4fee994d5be79a3a9afda37 (diff) | |
| download | luaotfload-37f8c42a1b560df3f1bc1444405c772f00340f88.tar.gz | |
[db] resolve symlinks when traversing the file system
Addresses #359 and #325
To avoid duplicate entries, paths have to be resolved before collecting
them. This necessitates loop detection of some sort, currently
implemented naively as a flat table containing the directories already
traversed.
Diffstat (limited to 'src')
| -rw-r--r-- | src/luaotfload-database.lua | 72 | 
1 files changed, 41 insertions, 31 deletions
diff --git a/src/luaotfload-database.lua b/src/luaotfload-database.lua index da2d5d0..5645b63 100644 --- a/src/luaotfload-database.lua +++ b/src/luaotfload-database.lua @@ -2033,7 +2033,7 @@ local locate_matching_pfb = function (afmfile, dir)  end  local process_dir_tree -process_dir_tree = function (acc, dirs) +process_dir_tree = function (acc, dirs, done)      if not next (dirs) then --- done          return acc      end @@ -2042,46 +2042,56 @@ process_dir_tree = function (acc, dirs)      local dir   = dirs[#dirs]      dirs[#dirs] = nil -    if lfschdir (dir) then -        lfschdir (pwd) - -        local newfiles = { } -        local blacklist = names.blacklist -        for ent in lfsdir (dir) do -            --- filter right away -            if ent ~= "." and ent ~= ".." and not blacklist[ent] then -                local fullpath = dir .. "/" .. ent -                if lfsisdir (fullpath) -                and not lpegmatch (p_blacklist, fullpath) -                then -                    dirs[#dirs+1] = fullpath -                elseif lfsisfile (fullpath) then -                    ent = stringlower (ent) - -                    if lpegmatch (p_font_filter, ent) then -                        newfiles[#newfiles+1] = fullpath -                        if filesuffix (ent) == "afm" then -                            local pfbpath = locate_matching_pfb (ent, dir) -                            if pfbpath then -                                newfiles[#newfiles+1] = pfbpath -                            end -                        else -                            newfiles[#newfiles+1] = fullpath +    if not lfschdir (dir) then +        --- Cannot cd; skip. +        return process_dir_tree (acc, dirs, done) +    end + +    dir = lfscurrentdir () --- resolve symlinks +    lfschdir (pwd) +    if tablecontains (done, dir) then +        --- Already traversed. Note that it’d be unsafe to rely on the +        --- hash part above due to Lua only processing up to 32 bytes +        --- of string data. The lookup shouldn’t impact performance too +        --- much but we could check the performance of alternative data +        --- structures at some point. +        return process_dir_tree (acc, dirs, done) +    end + +    local newfiles = { } +    local blacklist = names.blacklist +    for ent in lfsdir (dir) do +        --- filter right away +        if ent ~= "." and ent ~= ".." and not blacklist[ent] then +            local fullpath = dir .. "/" .. ent +            if lfsisdir (fullpath) +            and not lpegmatch (p_blacklist, fullpath) +            then +                dirs[#dirs+1] = fullpath +            elseif lfsisfile (fullpath) then +                ent = stringlower (ent) +                if lpegmatch (p_font_filter, ent) then +                    newfiles[#newfiles+1] = fullpath +                    if filesuffix (ent) == "afm" then +                        local pfbpath = locate_matching_pfb (ent, dir) +                        if pfbpath then +                            newfiles[#newfiles+1] = pfbpath                          end +                    else +                        newfiles[#newfiles+1] = fullpath                      end -                  end              end          end -        return process_dir_tree (tableappend (acc, newfiles), dirs)      end -    --- cannot cd; skip -    return process_dir_tree (acc, dirs) +    done [#done + 1] = dir +    return process_dir_tree (tableappend (acc, newfiles), dirs, done)  end  local process_dir = function (dir)      local pwd = lfscurrentdir ()      if lfschdir (dir) then +        dir = lfscurrentdir () --- resolve symlinks          lfschdir (pwd)          local files = { } @@ -2114,7 +2124,7 @@ end  local find_font_files = function (root, recurse)      if lfsisdir (root) then          if recurse == true then -            return process_dir_tree ({}, { root }) +            return process_dir_tree ({}, { root }, {})          else --- kpathsea already delivered the necessary subdirs              return process_dir (root)          end  | 
