# FFI: 'file' size of a non-file file descriptor

**URL:** <https://racket.discourse.group/t/ffi-file-size-of-a-non-file-file-descriptor/3341>\
**Category:** Questions & Answers\
**Tags:** question, ffi\
**Created:** [November 20, 2024, 3:47pm UTC](https://racket.discourse.group/t/ffi-file-size-of-a-non-file-file-descriptor/3341 "2024-11-20T15:47:16Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Laurent.O](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/laurent.o/32/18_2.png) [@Laurent.O](https://racket.discourse.group/u/Laurent.O)\
**Post date:** [November 20, 2024, 3:47pm UTC](https://racket.discourse.group/t/ffi-file-size-of-a-non-file-file-descriptor/3341/1 "2024-11-20T15:47:16Z")

</div>

I'm currently playing with shared memory spaces via the FFI, looking into `shm_open` and `mmap`.  
After obtaining a file descriptor `fd` corresponding to an existing such space, I want to find out the underlying 'file' size. However, it's not an actual file in the file system so there is no associated file-system path — as far as I understand.

If possible, I would really prefer to avoid writing a binding to `fstat` and its struct, in particular because it must have been done already for Racket/ChezScheme.

Unfortunately, Racket's `file-size` is only for paths on the system, not file descriptors nor file-stream-port (otherwise `file-descriptor->unsafe-port` would have worked).

Any idea?

---

<div class="post-metadata">

**Author:** ![Laurent.O](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/laurent.o/32/18_2.png) [@Laurent.O](https://racket.discourse.group/u/Laurent.O)\
**Post date:** [November 20, 2024, 4:15pm UTC](https://racket.discourse.group/t/ffi-file-size-of-a-non-file-file-descriptor/3341/2 "2024-11-20T16:15:47Z")

</div>

Hm, I think I might be able to use [lseek](https://man7.org/linux/man-pages/man2/lseek.2.html) instead (save position with SEEK\_CUR, get position of the end with SEEK\_END, restore position with SEEK\_SET). Hopefully this is not too slow compared to `fstat`.

Please let me know if that's a bad idea 😬

---

<div class="post-metadata">

**Author:** ![gneuner](https://avatars.discourse-cdn.com/v4/letter/g/b9e5f3/32.png) [@gneuner](https://racket.discourse.group/u/gneuner)\
**Post date:** [November 20, 2024, 8:37pm UTC](https://racket.discourse.group/t/ffi-file-size-of-a-non-file-file-descriptor/3341/3 "2024-11-20T20:37:38Z")

</div>

Technically, shared memory objects ARE in the file system - under /dev/shm ... but typically you are not able to access them AS files.

I would be worried a little about trusting lseek - it may work currently, but even if it does, there is no guarantee that it will continue to work in the future. Unfortunately the only /documented/ method to find the size of a memory object is fstat.

Since, as you noted, there must already be a binding to fstat, I would try to find it and see if I could use it directly. Obviously YMMV.

---

<div class="post-metadata">

**Author:** ![Laurent.O](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/laurent.o/32/18_2.png) [@Laurent.O](https://racket.discourse.group/u/Laurent.O)\
**Post date:** [November 20, 2024, 9:00pm UTC](https://racket.discourse.group/t/ffi-file-size-of-a-non-file-file-descriptor/3341/4 "2024-11-20T21:00:24Z")

</div>

> [@gneuner](#):
>
> I would be worried a little about trusting lseek - it may work currently, but even if it does, there is no guarantee that it will continue to work in the future.

Can you expand on why there is no guarantee?  
`man lseek` says:

> [@](#):
>
> SEEK\_END  
> The file offset is set to the size of the file plus offset bytes.

Isn't that a documented version of "file size in bytes"?

---

<div class="post-metadata">

**Author:** ![mflatt](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/mflatt/32/6_2.png) [@mflatt](https://racket.discourse.group/u/mflatt)\
**Post date:** [November 20, 2024, 9:05pm UTC](https://racket.discourse.group/t/ffi-file-size-of-a-non-file-file-descriptor/3341/5 "2024-11-20T21:05:43Z")

</div>

I don't think there's a way to get at the existing `fstat` call, but I'll add `port-file-stat` to v8.16.0.6.

---

<div class="post-metadata">

**Author:** ![gneuner](https://avatars.discourse-cdn.com/v4/letter/g/b9e5f3/32.png) [@gneuner](https://racket.discourse.group/u/gneuner)\
**Post date:** [November 20, 2024, 9:08pm UTC](https://racket.discourse.group/t/ffi-file-size-of-a-non-file-file-descriptor/3341/6 "2024-11-20T21:08:50Z")

</div>

Shared memory objects are a kind of "special" file. You can open and close and stat special files, but nothing else is guaranteed to work.

---

<div class="post-metadata">

**Author:** ![Laurent.O](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/laurent.o/32/18_2.png) [@Laurent.O](https://racket.discourse.group/u/Laurent.O)\
**Post date:** [November 20, 2024, 9:16pm UTC](https://racket.discourse.group/t/ffi-file-size-of-a-non-file-file-descriptor/3341/7 "2024-11-20T21:16:21Z")

</div>

Awesome, thank you Matthew!

---

<div class="post-metadata">

**Author:** ![Laurent.O](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/laurent.o/32/18_2.png) [@Laurent.O](https://racket.discourse.group/u/Laurent.O)\
**Post date:** [November 20, 2024, 9:26pm UTC](https://racket.discourse.group/t/ffi-file-size-of-a-non-file-file-descriptor/3341/8 "2024-11-20T21:26:42Z")

</div>

Oh right, I just saw [this](https://pubs.opengroup.org/onlinepubs/9699919799/functions/lseek.html):

> [@](#):
>
> If _fildes_ refers to a shared memory object, the result of the _lseek_() function is unspecified.

---

<div class="post-metadata">

**Author:** ![Laurent.O](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/laurent.o/32/18_2.png) [@Laurent.O](https://racket.discourse.group/u/Laurent.O)\
**Post date:** [November 29, 2024, 5:31pm UTC](https://racket.discourse.group/t/ffi-file-size-of-a-non-file-file-descriptor/3341/9 "2024-11-29T17:31:44Z")

</div>

It works, thank you so much!
