Skip to content

Instantly share code, notes, and snippets.

@nnposter
Created August 10, 2020 02:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nnposter/9d45542b811d620dc615d5fca796cee2 to your computer and use it in GitHub Desktop.
Save nnposter/9d45542b811d620dc615d5fca796cee2 to your computer and use it in GitHub Desktop.
Speed improvement for script afp-ls
* Significantly improves performance of AFP directory listings
--- a/nselib/afp.lua
+++ b/nselib/afp.lua
@@ -1567,15 +1567,22 @@
-- @param depth number containing the current depth (used when called recursively)
-- @param parent table containing information about the parent object (used when called recursively)
-- @return status boolean true on success, false on failure
- -- @return dir table containing a table for each directory item with the following <code>type</code>,
- -- <code>name</code> and <code>id</code>
+ -- @return dir table containing a table for each directory item with the following:
+ -- <code>type</code>, <code>name</code>, <code>id</code>,
+ -- <code>fsize</code>, <code>uid</code>, <code>gid</code>,
+ -- <code>privs</code>, <code>create</code>, <code>modify</code>
Dir = function( self, str_path, options, depth, parent )
local status, result
local depth = depth or 1
local options = options or { max_depth = 1 }
local response, records
- local f_bm = FILE_BITMAP.NodeId + FILE_BITMAP.ParentDirId + FILE_BITMAP.LongName
- local d_bm = DIR_BITMAP.NodeId + DIR_BITMAP.ParentDirId + DIR_BITMAP.LongName
+ local f_bm = FILE_BITMAP.NodeId | FILE_BITMAP.ParentDirId
+ | FILE_BITMAP.LongName | FILE_BITMAP.UnixPrivileges
+ | FILE_BITMAP.CreationDate | FILE_BITMAP.ModificationDate
+ | FILE_BITMAP.ExtendedDataForkSize
+ local d_bm = DIR_BITMAP.NodeId | DIR_BITMAP.ParentDirId
+ | DIR_BITMAP.LongName | DIR_BITMAP.UnixPrivileges
+ | DIR_BITMAP.CreationDate | DIR_BITMAP.ModificationDate
local TYPE_DIR = 0x80
@@ -1597,29 +1604,39 @@
end
local path = { type=PATH_TYPE.LongName, name="" }
- response = self.proto:fp_enumerate_ext2( parent.vol_id, parent.did, f_bm, d_bm, 1000, 1, 52800, path)
+ response = self.proto:fp_enumerate_ext2( parent.vol_id, parent.did, f_bm, d_bm, 1000, 1, 1000 * 300, path)
if response:getErrorCode() ~= ERROR.FPNoErr then
return false, response:getErrorMessage()
end
records = response.result or {}
- local dir_item = {}
+ local dir_items = {}
for _, record in ipairs( records ) do
- if ( options and options.dironly ) then
- if ( record.type == TYPE_DIR ) then
- table.insert( dir_item, { ['type'] = record.type, ['name'] = record.LongName, ['id'] = record.NodeId } )
+ local isdir = record.type == TYPE_DIR
+ -- Skip non-directories if option "dironly" is set
+ if isdir or not options.dironly then
+ local item = {type = record.type,
+ name = record.LongName,
+ id = record.NodeId,
+ fsize = record.ExtendedDataForkSize or 0}
+ local privs = (record.UnixPrivileges or {}).ua_permissions
+ if privs then
+ item.uid = record.UnixPrivileges.uid
+ item.gid = record.UnixPrivileges.gid
+ item.privs = (isdir and "d" or "-") .. Util.decode_unix_privs(privs)
end
- else
- table.insert( dir_item, { ['type'] = record.type, ['name'] = record.LongName, ['id'] = record.NodeId } )
+ item.create = Util.time_to_string(record.CreationDate)
+ item.modify = Util.time_to_string(record.ModificationDate)
+ table.insert( dir_items, item )
end
- if ( record.type == TYPE_DIR ) then
- self:Dir("", options, depth + 1, { vol_id = parent.vol_id, did=record.NodeId, dir_name=record.LongName, out_tbl=dir_item} )
+ if isdir then
+ self:Dir("", options, depth + 1, { vol_id = parent.vol_id, did=record.NodeId, dir_name=record.LongName, out_tbl=dir_items} )
end
end
- table.insert( parent.out_tbl, dir_item )
+ table.insert( parent.out_tbl, dir_items )
return true, parent.out_tbl
end,
--- a/scripts/afp-ls.nse
+++ b/scripts/afp-ls.nse
@@ -94,8 +94,11 @@
-- <elem key="bytes">0</elem>
-- </table>
--- Version 0.1
+-- Version 0.2
-- Created 04/03/2011 - v0.1 - created by Patrik Karlsson
+-- Modified 08/02/2020 - v0.2 - replaced individual date/size/ownership calls
+-- with direct sourcing from the output of
+-- afp.Helper.Dir
author = "Patrik Karlsson"
@@ -147,41 +150,24 @@
for _, vol in ipairs( vols ) do
local status, tbl = afpHelper:Dir( vol )
if ( not(status) ) then
- ls.report_error(
- output,
- ("ERROR: Failed to list the contents of %s"):format(vol))
+ ls.report_error(output, ("ERROR: Failed to list the contents of %s"):format(vol))
else
ls.new_vol(output, vol, true)
- local continue = true
for _, item in ipairs(tbl[1]) do
- if ( item and item.name ) then
- local status, result = afpHelper:GetFileUnixPermissions(
- vol, item.name)
- if ( status ) then
- local status, fsize = afpHelper:GetFileSize( vol, item.name)
- if ( not(status) ) then
- ls.report_error(
- output,
- ("ERROR: Failed to retrieve file size for %/%s"):format(vol, item.name))
- else
- local status, date = afpHelper:GetFileDates( vol, item.name)
- if ( not(status) ) then
- ls.report_error(
- output,
- ("\n\nERROR: Failed to retrieve file dates for %/%s"):format(vol, item.name))
- else
- continue = ls.add_file(output, {
- result.privs, result.uid, result.gid,
- fsize, date.create, item.name
- })
- end
+ if item and item.name then
+ if not (item.privs and item.create) then
+ ls.report_error(output, ("ERROR: Failed to retrieve file details for %/%s"):format(vol, item.name))
+ else
+ local continue = ls.add_file(output, {
+ item.privs, item.uid, item.gid,
+ item.fsize, item.create, item.name
+ })
+ if not continue then
+ ls.report_info(output, ("maxfiles limit reached (%d)"):format(maxfiles))
+ break
end
end
end
- if not continue then
- ls.report_info(output, ("maxfiles limit reached (%d)"):format(maxfiles))
- break
- end
end
ls.end_vol(output)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment