Giter Site home page Giter Site logo

Comments (10)

ararslan avatar ararslan commented on June 3, 2024 1

Unfortunately, this has not been easy so far, given limitations about what symbols I have access to (using your nm --dynamic trick); hint: not all of the functions in ZFS's source I have access to...

Some things to note regarding nm:

  • --defined-only may be additionally useful for identifying what's directly available vs. linked from elsewhere (ldd will tell you what it's linking to)
  • nm doesn't have struct names
  • nm doesn't have anything defined as a preprocessor macro (e.g. f in #define f(x) ...)

Also, if you're doing this on FreeBSD, I recommend looking at the OpenZFS included in FreeBSD's monolithic source tree in case there are any differences compared to upstream.

from hiddenfiles.jl.

ararslan avatar ararslan commented on June 3, 2024 1

Do you know how exactly to call structs

What do you mean by "call" in this case? If you define a Julia type with a layout compatible with the C struct, you can return objects with that type from ccall. Say for example you have

typedef struct _t {
    int a;
    int b;
} t;

void populate_t(t* thing) { ... }

then you can do

struct T
    a::Cint
    b::Cint
end

t = Ref{T}()
ccall((:populate_t, libwhatever), Cvoid, (Ref{T},), t)

(completely untested example but that's the gist). How exactly you go about it depends on the functions available from the library you're calling into.

definitions as a preprocessor macros

You'd have to reference whatever the macro expands to in your call on the Julia side since C macros exist only during the preprocessor phase; a compiled library has no knowledge of whether some part of its code was generated by a macro.

Or even how to call anything of the "D" type that nm displays

You need cglobal:

julia> cglobal((:zfs_attr_table, "/lib/libzpool.so.2"))
Ptr{Nothing} @0x0000000895cdaf20

do you know anything about how I might programmatically check if a file is stored on a ZFS partition?

Unfortunately I don't, sorry πŸ˜•

from hiddenfiles.jl.

ararslan avatar ararslan commented on June 3, 2024 1

The problem with znode_t is that I can't find it in any of the object files, so I guess I will have to figure out another way to get the znode struct.

You wouldn't find znode_t itself in an object file but you may find a function that returns a znode_t (or, more likely, a pointer to one).

Potentially stupid question, but how do you actually use the result? It's a pointer to some object in memory, but I'm not sure how exactly to make that into an array or whatever it should be.

That's not a stupid question at all. The crucial piece here is "whatever it should be," as what it should be will determine how you go about retrieving that. cglobal has another positional argument that tells it the type of data being referenced, and what you get back is a pointer with that type. If you want to turn it into a Julia array, you can use unsafe_wrap, or you can unsafe_load individual indices.

from hiddenfiles.jl.

jakewilliami avatar jakewilliami commented on June 3, 2024

It appears that BSD also has the UF_HIDDEN flag in chflags, so they have this in common. Furthermore, as FreeBSD uses ZFS, there is another type of hidden file: snapshots of ZFS mounts are hidden, even from ls -a. Currently working on figuring out from source how to pull this information myself. To do this I will also need to implement an iszfs check, which may, in and of itself, be no mean task.

from hiddenfiles.jl.

jakewilliami avatar jakewilliami commented on June 3, 2024

I spent a long time looking through the source of OpenZFS (see above). After many possible avenues, I wanted to actually some real code, however suddenly I couldn't even do it in C; use of undeclared identifier 'znode_t'. I asked resident FreeBSD Γ— Julia enthusiast @ararslan, who told me that many FreeBSD functions are obtained from object files, most of which tucked away in the /lib directory. Helpfully, Alex told me, you can get exposed functions by the command nm --dynamic <object file> (the second time both in this project and in my life that I've used the nm command!). I wanted to search all throughout this /lib directory so I wrote:

function main(strs::String...)
    io = IOBuffer()
    for f in readdir("/lib", join = true)
        isfile(f) || continue
        try
            run(pipeline(`nm --dynamic $f`, stdout = io, stderr = devnull))
            cmd_out = lowercase(String(take!(io)))
            any(occursin(s, cmd_out) for s in strs) && println(f)
        finally
            continue
        end
    end
end

I figured out that there are also many object files in the /usr/lib directory.

Making good progress now that we

  1. have a background understanding of what to look for once we get some ZFS structures created (from all the code scouring);
  2. have a way to search available functions (thanks Alex); and
  3. know where the libraries are stored for running this in Julia!

from hiddenfiles.jl.

jakewilliami avatar jakewilliami commented on June 3, 2024

I should also note that this depends on ZFS, rather than FreeBSD

from hiddenfiles.jl.

ararslan avatar ararslan commented on June 3, 2024

At least as I understand it, hidden files on BSDs are the same as on Linux (and likely macOS). While FreeBSD can use ZFS, it doesn't have to; installers let you pick between UFS and ZFS with the former actually being the default for prebuilt VM images.

Are you looking to implement ishidden on systems using ZFS such that a path pointing to some object within a ZFS control directory (.zfs at the ZFS VFS mountpoint) is considered hidden? If so, you may be able to locate the mount points of all snapshots and check that the path falls within one of those. Also, this may provide some useful information for you: https://github.com/freebsd/freebsd-src/blob/271171e0d97b88ba2a7c3bf750c9672b484c1c13/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_ctldir.c#L27-L66

from hiddenfiles.jl.

jakewilliami avatar jakewilliami commented on June 3, 2024

@ararslan yeah, I realised that when I started looking into this, that the .zfs files are specific to ZSF rather than BSD. I will need to work on a function to check if the file system of the file and see whether it's ZFS. Let me know if you have any thoughts on this.

Luckily I don't have to locate any of the .zfs filesβ€”but yes, I'm hoping to allow users using ZFS to provide a .zfs file and for the function to be able to determine whether it is hidden. I have a lot to implement, but my current idea is to (using ccall) construct an inode so that I can convert it to a znode (I don't know how else to create a znode struct), from which I can get the attribute z_pflags and it's simple enough from there. Unfortunately, this has not been easy so far, given limitations about what symbols I have access to (using your nm --dynamic trick); hint: not all of the functions in ZFS's source I have access to...

Your idea of finding all the mount points might be good though. Do you think that would be easier than what I explained above? The other thing I have to consider is: are all subfiles/directories of this .zfs directory also hidden? My intuition says yes (similar to how I have implemented packages/bundles in macOS).

Thank you for the useful information, that helps me to understand :)

from hiddenfiles.jl.

jakewilliami avatar jakewilliami commented on June 3, 2024

Thanks Alex, good to know about nm.

  • nm doesn't have struct names
  • nm doesn't have anything defined as a preprocessor macro (e.g. f in #define f(x) ...)

Do you know how exactly to call structs (such as znode) or definitions as a preprocessor macros in Julia (such as ITOZ)? Or even how to call anything of the "D" type that nm displays (i.e., D - A global symbol naming initialized data). In particular, I am wondering if this one will help me:

00000000003b8010 D zfs_attr_table

Because I'm clearly doing it wrong!

julia> ccall((:zfs_attr_table, "libzpool"), Cvoid, ())

signal (11): Segmentation fault
in expression starting at REPL[1]:1
zfs_attr_table at /usr/lib/libzpool.so (unknown line)
# ...

Ultimately I need to find a way to create a znode type in Julia, but I can't even get that working in C...

if you're doing this on FreeBSD, I recommend looking at the OpenZFS included in FreeBSD's monolithic source tree in case there are any differences compared to upstream.

Indeed, I'm developing on FreeBSD currently. I've been looking lots at the OpenZFS source on GitHub, but I haven't looked at in within the machine itself. I'll see if I can find it.

Also, do you know anything about how I might programmatically check if a file is stored on a ZFS partition? As this is no longer going to be a job for if Sys.isbsd(), I'll need to find a way to check for existence of ZFS.

from hiddenfiles.jl.

jakewilliami avatar jakewilliami commented on June 3, 2024

If you define a Julia type with a layout compatible with the C struct, you can return objects with that type from ccall.

Thanks for your help with making structs from Julia. I hadn't figured that out yet, so I was just using Vectors, and indexing directly (instead of named fields). The problem with znode_t is that I can't find it in any of the object files, so I guess I will have to figure out another way to get the znode struct.

You'd have to reference whatever the macro expands to in your call on the Julia side

Ah, that makes sense, I figured that would be the case.

You need cglobal:

Oh neat, I didn't know about this function! Potentially stupid question, but how do you actually use the result? It's a pointer to some object in memory, but I'm not sure how exactly to make that into an array or whatever it should be.

do you know anything about how I might programmatically check if a file is stored on a ZFS partition?

Unfortunately I don't, sorry πŸ˜•

No worries, I'll figure something out. You've been ever so helpful, thank you Alex πŸ™‚

from hiddenfiles.jl.

Related Issues (17)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.