Lua File System on Mac OSX

I’ve been using Lua File System on Mac OSX (Yosemite) and have found some interesting results.

I am attempting to traverse a series of directories, discover their file types and permissions, and store them in a series of arrays - Which are then serialised into two JSON files.

However, when I attempt to access some files/folders, which have valid permission bits set (rwxr-xr-x), I get a permission error. Further, directories created in Finder display only ‘nil’ type and ‘nil’ permission bits. Anybody have any idea why/a work around?

If you post (or PM) a sample project that demonstrates the issue, I’ll take a look.

We use LFS in our build process (and have done so for years) and I’ve never seen issues like that.

I’ve (sort of) gotten around it with PCall() to trap the error and ignore it.

I’ll post my code below:

local path = system.pathForFile("", system.DocumentsDirectory); lfs.chdir(path) local isSuccess = lfs.chdir("/") local currentDir = lfs.currentdir(); local backupFiles = {} local directories ={} local function splitBits(protection) local table = {} local i = 1; while i \<= 9 do table[i]= protection:sub(i, i) i = i + 1 end return table end local function traverseDir(currentDir, backupFiles, directories) directories["Files"] = {} local i = 1; for file in lfs.dir( currentDir ) do -- "file" is the current file or directory name if (tostring(file) ~= "." and tostring(file) ~= "..") then print(currentDir) local mode = lfs.attributes(file, "mode") local prot = lfs.attributes(file, "permissions") print(file, mode, prot) --print(file.." "..mode.." "..prot) if (mode == "directory" or mode == nil) then directories[file] = {} directories[file]["root"] = {} directories[file]["root"]["Address"] = currentDir..file if (prot ~= nil) then directories[file]["root"]["Protection"] = splitBits(prot) directories[file]["root"]["Protection"]["Base"] = prot end err, message, directories[file]["root"]["Tree"] = pcall(function() traverseDir(currentDir.."/"..file, backupFiles, directories[file]) end) else if (file == "Backup.zip") then backupFiles[#backupFiles] = {} backupFiles[#backupFiles - 1]["Address"] = currentDir..file break; end --directories["Files"][i] = {} --directories["Files"][i]["File"] = file; --directories["Files"][i]["Protection"] = splitBits(prot) --directories["Files"][i]["Mode"] = mode; --i = i + 1 end end end return directories, backupFiles end for file in lfs.dir( "/Users/matthewharrop/" ) do if (tostring(file) ~= "." and tostring(file) ~= "..") then local dir = "" dir = "/Users/matthewharrop/"..file local err, message, directories, backupFiles = pcall(function() traverseDir(dir, backupFiles, directories) end) --print(err, message, directories, backupFiles) if (err) then print("work"); else print("fail") --break; end end end --local directories, backupFiles = traverseDir("/Users/matthewharrop/", backupFiles, directories) local jsonPath = system.pathForFile("map.json", system.DocumentsDirectory) local openJSON = io.open(jsonPath, "w") local c = json.encode(directories) openJSON:write(c) openJSON:close() jsonPath = system.pathForFile("backfiles.json", system.DocumentsDirectory) openJSON = io.open(jsonPath, "w") c = json.encode(backupFiles) openJSON:write(c) openJSON:close()

Ignore the commented out calls, I’m prototyping something and those calls will be included in the full program, for now they’re just place holders of sorts.

What “print(file, mode, prot)” returns is:

/Users/matthewharrop/Documents/Tarzender Publishing nil nil

However with base directories (located in /) it returns:

/dev directory rwxr-xr-x

I think you’re missing the current directory when making your lfs calls:

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; local mode = lfs.attributes(currentDir.."/"..file, "mode") &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; local prot = lfs.attributes(currentDir.."/"..file, "permissions")

If you post (or PM) a sample project that demonstrates the issue, I’ll take a look.

We use LFS in our build process (and have done so for years) and I’ve never seen issues like that.

I’ve (sort of) gotten around it with PCall() to trap the error and ignore it.

I’ll post my code below:

local path = system.pathForFile("", system.DocumentsDirectory); lfs.chdir(path) local isSuccess = lfs.chdir("/") local currentDir = lfs.currentdir(); local backupFiles = {} local directories ={} local function splitBits(protection) local table = {} local i = 1; while i \<= 9 do table[i]= protection:sub(i, i) i = i + 1 end return table end local function traverseDir(currentDir, backupFiles, directories) directories["Files"] = {} local i = 1; for file in lfs.dir( currentDir ) do -- "file" is the current file or directory name if (tostring(file) ~= "." and tostring(file) ~= "..") then print(currentDir) local mode = lfs.attributes(file, "mode") local prot = lfs.attributes(file, "permissions") print(file, mode, prot) --print(file.." "..mode.." "..prot) if (mode == "directory" or mode == nil) then directories[file] = {} directories[file]["root"] = {} directories[file]["root"]["Address"] = currentDir..file if (prot ~= nil) then directories[file]["root"]["Protection"] = splitBits(prot) directories[file]["root"]["Protection"]["Base"] = prot end err, message, directories[file]["root"]["Tree"] = pcall(function() traverseDir(currentDir.."/"..file, backupFiles, directories[file]) end) else if (file == "Backup.zip") then backupFiles[#backupFiles] = {} backupFiles[#backupFiles - 1]["Address"] = currentDir..file break; end --directories["Files"][i] = {} --directories["Files"][i]["File"] = file; --directories["Files"][i]["Protection"] = splitBits(prot) --directories["Files"][i]["Mode"] = mode; --i = i + 1 end end end return directories, backupFiles end for file in lfs.dir( "/Users/matthewharrop/" ) do if (tostring(file) ~= "." and tostring(file) ~= "..") then local dir = "" dir = "/Users/matthewharrop/"..file local err, message, directories, backupFiles = pcall(function() traverseDir(dir, backupFiles, directories) end) --print(err, message, directories, backupFiles) if (err) then print("work"); else print("fail") --break; end end end --local directories, backupFiles = traverseDir("/Users/matthewharrop/", backupFiles, directories) local jsonPath = system.pathForFile("map.json", system.DocumentsDirectory) local openJSON = io.open(jsonPath, "w") local c = json.encode(directories) openJSON:write(c) openJSON:close() jsonPath = system.pathForFile("backfiles.json", system.DocumentsDirectory) openJSON = io.open(jsonPath, "w") c = json.encode(backupFiles) openJSON:write(c) openJSON:close()

Ignore the commented out calls, I’m prototyping something and those calls will be included in the full program, for now they’re just place holders of sorts.

What “print(file, mode, prot)” returns is:

/Users/matthewharrop/Documents/Tarzender Publishing nil nil

However with base directories (located in /) it returns:

/dev directory rwxr-xr-x

I think you’re missing the current directory when making your lfs calls:

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; local mode = lfs.attributes(currentDir.."/"..file, "mode") &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; local prot = lfs.attributes(currentDir.."/"..file, "permissions")