lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Hi!

Am 15.08.2013 15:57 schröbte Lorenzo Donati:

[...]

BTW. If Lua team doesn't deem it useful enough to enhance popen in this
sense, IMO this should be added at least to lfs

On a related note, although a robust workhorse, I find lfs a bit
lacking. I'd really like it to be a little more feature complete.

Maybe you are looking at the wrong library. What about lua-apr[1][2] (also available as a rock[3])?

  [1]:  https://github.com/xolox/lua-apr/
  [2]:  http://peterodding.com/code/lua/apr/
  [3]:  http://luarocks.org/repositories/rocks/#lua-apr

lua-apr is still for Lua 5.1 only, but I have a quick-and-dirty patch for Lua 5.2 support, if you are interested ...


Features I miss from lfs (which should be easy to bind to already
existing APIs in the host OS):

* mkdir cannot create directories recursively ( mkdir "a/b/c" gives an
error if "a" doesn't exist, whereas I'd like to have a flag to tell it
"do make all the intermediate dirs")

    apr.dir_make_recursive(path [, permissions]) → status


* File copy operations.

    apr.file_copy(source, target [, permissions]) → status
    apr.file_append(source, target [, permissions]) → status
    apr.file_link(source, target) → status


* Pathname existance checking and
canonalization/normalization/resolution (e.g. lfs.exists
"/foo/bar/a/b/../../c" would return "/foo/bar/c" if this file exists, or
nil otherwise)

    apr.filepath_root(path [, option, ...]) → root, path
    apr.filepath_parent(path [, option, ...]) → parent, filename
    apr.filepath_name(path [, split]) → filename [, extension]
    apr.filepath_merge(root, path [, option, ...]) → merged

etc...


* lfs.dir iterator should not return ".." and "." as directories.
Especially ".." is dangerous when building recursive functions on top of
lfs.dir: you could by mistake recurse upwards (I'm always wrapping
lfs.dir to remove ".." and ".", but this inconvenient and error prone -
I don't know you, but I never used lfs.dir output directly). At least
this behaviour should be documented.

Other operations that are not strictly file-system operations, but IMO
too much connected to them:

* lfs.setenv (to pair os.getenv)

    apr.env_set(name, value) → status
    apr.env_delete(name) → status


* lfs.popen (as said above)

* lfs.execute  having a richer API than os.execute (e.g. see wxWidgets
wxExecute) and allowing sync/async execution

    apr.proc_create(program) → process
    apr.proc_detach(daemonize) → status
    process:user_set(username [, password]) → status
    process:cmdtype_set(type) → status
    process:dir_set(path) → status
    process:io_set(stdin, stdout, stderr) → status
    process:exec([args]) → status
    process:wait(how) → done [, why, code]
    process:kill(how) → status

etc....

Regarding your enhanced popen, this is as far as I got:

    local apr = require( "apr" )
    local proc = assert( apr.proc_create( "./xxx.sh" ) )
    assert( proc:cmdtype_set( "program" ) )
    assert( proc:io_set( 'none', 'parent-block', 'parent-block' ) )
    assert( proc:exec{} )
    local out = proc:out_get()
    local err = proc:err_get()
    print( out:read() )
    print( err:read() )
    local done, why, code = assert( proc:wait( true ) )
    if why == "exit" then
      print( "exit status:", code )
    else
      print( "killed by signal:", code )
    end

The problem (which lfs would face as well) is multiplexing the io of stdout and stderr so that no process is blocked and no output lost ...


I acknowledge that many of the above can be built on top of lfs, but
sometimes it is tricky and anyway not as efficient as wrapping existing
OS APIs.

Cheers.

-- Lorenzo


Philipp