atlas-engineer / nfiles

User configuration and data file management
BSD 3-Clause "New" or "Revised" License
17 stars 5 forks source link

`sb-posix:getpwnam` is not defined for Android #10

Closed aadcg closed 1 year ago

aadcg commented 1 year ago

nfiles relies on sb-posix:getpwnam which is not defined for Android.

Any ideas on how to be able to run this library on Android?

#-(or win32 android)
(macrolet ((define-obj-call (name arg type conv)
  ;; FIXME: this isn't the documented way of doing this, surely?
  (let ((lisp-name (intern (string-upcase name) :sb-posix)))
    `(progn
      (export ',lisp-name :sb-posix)
      (declaim (inline ,lisp-name))
      (defun ,lisp-name (,arg)
        (let ((r (alien-funcall (extern-alien ,name ,type) ,arg)))
          (if (null-alien r)
              nil
              (,conv r))))))))

(define-obj-call "getpwnam" login-name (function (* alien-passwd) (c-string :not-null t))
                 alien-to-passwd)
(define-obj-call "getpwuid" uid (function (* alien-passwd) uid-t)
                 alien-to-passwd)
(define-obj-call "getgrnam" login-name (function (* alien-group) (c-string :not-null t))
                 alien-to-group)
(define-obj-call "getgrgid" gid (function (* alien-group) gid-t)
                 alien-to-group)
) ; end MACROLET
Ambrevar commented 1 year ago

Does (iolib/syscalls:getpwnam new-user) work on Android?

Alternatively we chould use the id -u USERNAME shell command. It adds overhead though.

Ambrevar commented 1 year ago

It seems that on Android users are represented very differently. In any case, Nfiles needs to know some user identifier to return the owner name or set the new owner.

aadcg commented 1 year ago

iolib depends on libfixposix. I need to check whether I'm able to install libfixposix on Android with this fix.

aadcg commented 1 year ago

Alternatively we chould use the id -u USERNAME shell command.

This would be a reasonable hot fix for the moment. Thanks.

Ambrevar commented 1 year ago

Wanna send a pull request?

aadcg commented 1 year ago

I need to test it first.

aadcg commented 1 year ago

A kind gentleman helped me to package libfixposix for Termux!

So I can now test @Ambrevar's suggestion:

Does (iolib/syscalls:getpwnam new-user) work on Android?

Ambrevar commented 1 year ago

Hooray!

aadcg commented 1 year ago

It turns out that running iolib on Termux isn't as easy as I supposed. Maybe someone will help me figure it out.

aadcg commented 1 year ago

Alternatively we chould use the id -u USERNAME shell command. It adds overhead though.

This is not pretty indeed, but it would work indeed!

CL-USER> (uiop:run-program "id -u u0_a256" :output t)
10256
NIL
NIL
0 (0 bits, #x0, #o0, #b0)

Note: Don't get scared by the odd username u0_a256.

Termux is single-user

Android applications are sandboxed and have their own Linux user id and SELinux label. Termux is no exception and everything within Termux is executed with the same user id as the Termux application itself. The username may look like u0_a231 and cannot be changed as it is derived from the user id by Bionic libc.

All our packages (except root-only ones) are patched to drop any multiuser, setuid/setgid and other similar functionality. We also changed default ports for server packages: ftpd, httpd and sshd have their default ports set to 8021, 8080 and 8022 respectively.

You have free read-write access to all application components including $PREFIX. Be careful since it is very easy to break things by accidentally deleting or overwriting files in $PREFIX.

aadcg commented 1 year ago

Another amazing update. iolib runs on Termux!!!

aadcg commented 1 year ago

That means that I can go back to @Ambrevar's idea and report that it indeed works!

Does (iolib/syscalls:getpwnam new-user) work on Android?

CL-USER> (iolib/syscalls:getpwnam "u0_a256")
"u0_a256"
NIL
10256 (14 bits, #x2810)
10256 (14 bits, #x2810)
NIL
"/data"
"/bin/sh"
aadcg commented 1 year ago

Conclusion: there is at least one case when SBCL is available but sb-posix:getpwnam, sb-posix:start-gid or sb-posix:lstat aren't defined.

My suggestion is that we should depend on iolib even when SBCL is available.

Another way to do it would be to complicate the directives passed to #- and #+ but I think it's much complexity for too little gain. Plus, I don't know how to define a predicate that would say "this is an Android device" (SBCL does it somehow).

Does that make sense? @Ambrevar @aartaka

aartaka commented 1 year ago

Conclusion: there is at least one case when SBCL is available but sb-posix:getpwnam, sb-posix:start-gid or sb-posix:lstat aren't defined.

My suggestion is that we should depend on iolib even when SBCL is available.

iolib is quite huge, not sure it's good to always depend on it. The perfect solution to me seems to be: contribute SBCL-specifics to iolib as a separate back-end. This way we can unconditionally include iolib everywhere, while having nice and abstraction-less operations on SBCL.

But that should be a lot of work, I guess.

Another way to do it would be to complicate the directives passed to #- and #+ but I think it's much complexity for too little gain. Plus, I don't know how to define a predicate that would say "this is an Android device" (SBCL does it somehow).

Should be possible via *features*. ECL on android has :unix, :android, :mobile, :arm64, and :aarch64 on my device. SBCL on Termux should have something like that too.

aadcg commented 1 year ago

All good observations. See #12.

aadcg commented 1 year ago

Plus, I don't know how to define a predicate that would say "this is an Android device" (SBCL does it somehow).

To be clear: I didn't know that the variable *features* handles that.

aartaka commented 1 year ago

No day without learning about new and exciting features (pun intended) of CL :D

aadcg commented 1 year ago

See d146e4a.