Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 81 additions & 27 deletions documentation/source/library-reference/system/file-system.rst
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ properties of the file.
- :func:`file-properties`
- :func:`file-property`
- :func:`file-type`
- :func:`link-target`
- :gf:`link-target`
- :gf:`resolve-file`

File system locators
--------------------
Expand Down Expand Up @@ -646,16 +647,26 @@ File-System module.

Returns a sequence of files and subdirectories contained in a directory.

:signature: directory-contents *directory* => *locators*
:signature: directory-contents *directory* #key *resolve-links?* => *locators*

:parameter directory: An instance of :type:`<pathname>`.
:parameter #key resolve-links?: An instance of :drm:`<boolean>`. The default is :drm:`#f`.
:value locators: A :drm:`<sequence>` of :class:`<locator>`.

:description:

In the result, each file is represented by a :class:`<file-locator>` and
each directory is represented by a :class:`<directory-locator>`. The "."
and ".." directories are not included in the result.
Returns a sequence of locators describing the files contained in *directory*. The
"." and ".." directories are not included in the result.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use the :file: role for these


If *resolve-links?* is false then symbolic links are returned as instances of
:class:`<file-locator>`. If true, then symbolic links are resolved and the correct
class of locator, :class:`<file-locator>` or :class:`<directory-locator>`, is
determined based on the file type of the (fully resolved) link target.

Note that if a symlink points to another file in *directory* then the resulting
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use "symbolic link" consistently rather than the colloquial "symlink".

sequence may contain duplicates (in the sense of naming the same file system
entity, not in the sense of Dylan object equality) when *resolve-links?* is
true.

.. generic-function:: directory-empty?

Expand Down Expand Up @@ -758,26 +769,27 @@ File-System module.

.. generic-function:: expand-pathname

Given a pathname, returns its fully expanded form.

:signature: expand-pathname *path* => *expanded-path*

:param path: An instance of :class:`<pathname>`.
:value expanded-path: An instance of :class:`<pathname>`.
Replaces an initial pathname component of ``~`` or ``~user`` with that user's home
directory.

.. method:: expand-pathname
:specializer: <file-system-locator>
:signature: expand-pathname *pathname* => *locator*

Expand a file path to its fully expanded form.
:param path: An instance of :type:`<pathname>`.
:value expanded: An instance of :class:`<locator>`.

:param path: An instance of :class:`<file-system-locator>`.
:description:

.. method:: expand-pathname
:specializer: <string>
.. note:: On Windows only ``~`` is replaced; expansion of ``~user`` is not yet
implemented.

Expands a pathname given as a string.
If *pathname* is an instance of :drm:`<string>` it is first converted to a
:class:`<file-system-locator>`. If the first component of this locator begins with
`~` it is replaced by either the specified user's home directory (for ``~user``) or
the current user's home directory (for ``~``). Otherwise the locator is returned
unmodified.

:param path: An instance of :class:`<string>`.
If the specified ``~user`` doesn't exist no error is signaled and the locator is
returned without expansion being performed.

.. generic-function:: file-error-locator

Expand Down Expand Up @@ -841,7 +853,7 @@ File-System module.
:signature: file-exists? *file* #key *follow-links?* => *exists?*

:parameter file: An instance of :type:`<pathname>`.
:parameter follow-links?: An instance of :drm:`<boolean>`. Defaults to
:parameter #key follow-links?: An instance of :drm:`<boolean>`. Defaults to
:drm:`#t`.
:value exists?: An instance of :drm:`<boolean>`.

Expand Down Expand Up @@ -1059,6 +1071,9 @@ File-System module.
file system entity can either be a file, a directory, or a link to
another file or directory.

This function does not resolve symbolic links. To find the file type of the link
target call :gf:`link-target` or :gf:`resolve-file` on *file* first.

.. type:: <file-type>

The type representing all possible types of a file system entity.
Expand Down Expand Up @@ -1105,21 +1120,60 @@ File-System module.
permissions set on the file are incorrect or insufficient for
your operation.

.. function:: link-target
.. generic-function:: link-target

Returns the target of a symbolic link.

:signature: link-target *file* => *target*
.. note:: On Windows this function is not implemented; it always signals an error.

:signature: link-target *file* #key *follow-links?* => *target*
:parameter file: An instance of type :type:`<pathname>`.
:value target: An instance of type :type:`<pathname>`.
:parameter #key follow-links?: An instance of type :drm:`<boolean>`. The default is
:drm:`#t`.
:value target: :drm:`#f` or an instance of type :class:`<file-system-locator>`.
:description:

Repeatedly follows symbolic links starting with *file* until it finds a
non-link file or directory, or a non-existent link target.
Returns a locator identifying the target of symbolic link *file*.

Signals :class:`<file-system-error>` if the system call to read the link target
fails for any reason. For example, if *file* is not a symbolic link or if *file*
does not exist.

If ``follow-links?`` is true (the default) then links are followed until a file
that is not a symbolic link is found, and the locator for that file is returned. If
the final link in a chain of one or more symbolic links points to a non-existent
file, :drm:`#f` is returned.

If ``follow-links?`` is false, no attempt is made to follow the link or to check
whether the link target file exists. A locator representing the target is
returned.

:seealso:

- :func:`create-symbolic-link`
- :gf:`resolve-file`

.. generic-function:: resolve-file
:open:

Resolves a file path to its simplest representation containing no symbolic links.

:signature: resolve-file *path* => *resolved-path*

:description:

Resolves all links, parent references (``..``), self references (``.``), and
removes unnecessary path separators. Similar to :func:`simplify-locator` except
that it consults the file system to resolve links. A :class:`<file-system-error>`
is signaled if for any reason the path can't be resolved. Examples include
non-existent directory components, access denied, I/O error, etc. In short, this
function follows the semantics of POSIX ``realpath(3)``.

:parameter path: An instance of :type:`<pathname>`.
:value resolved-path: An instance of :class:`<file-system-locator>`. More
specifically, the return value will be an instance of :class:`<file-locator>` or
:class:`<directory-locator>` depending on the type of the resolved file system
entity.

.. _make:

Expand Down Expand Up @@ -1276,7 +1330,7 @@ File-System module.
- :func:`file-property-setter`
- :func:`file-type`
- :func:`home-directory`
- :func:`link-target`
- :gf:`link-target`
- :func:`rename-file`
- :func:`create-symbolic-link`

Expand Down Expand Up @@ -1315,7 +1369,7 @@ File-System module.

:parameter old-file: An instance of :type:`<pathname>`.
:parameter new-file: An instance of :type:`<pathname>`.
:parameter if-exists: An instance of
:parameter #key if-exists: An instance of
:type:`<copy/rename-disposition>`. Default value: ``#"signal"``.

:description:
Expand Down
17 changes: 3 additions & 14 deletions documentation/source/library-reference/system/locators.rst
Original file line number Diff line number Diff line change
Expand Up @@ -384,22 +384,11 @@ The locators Module
:parameter locator: An instance of :class:`<physical-locator>`.
:value simplified-locator: An instance of :class:`<physical-locator>`.

.. generic-function:: resolve-locator
:open:

Resolves all links, parent references (``..``), self references (``.``), and
removes unnecessary path separators. Similar to :func:`simplify-locator`
except that it consults the file system to resolve links. A
:class:`<file-system-error>` is signaled if for any reason the path can't be
resolved. Examples include non-existent directory components, access denied,
I/O error, etc. In short, this function follows the semantics of POSIX
``realpath(3)``.

:signature: resolve-locator (locator) => (resolved-locator)
.. constant:: resolve-locator

:parameter locator: An instance of :class:`<physical-locator>`.
:value simplified-locator: An instance of :class:`<physical-locator>`.
.. deprecated:: 2025.2

:seealso: :gf:`resolve-file`

.. generic-function:: string-as-locator
:open:
Expand Down
38 changes: 36 additions & 2 deletions documentation/source/release-notes/2025.2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,42 @@ Compiler
Tools
=====

Library Updates
===============
Libraries
=========

System
------

* :gf:`resolve-file` (in the ``file-system`` module) replaces :const:`resolve-locator`
(in the ``locators`` module) because it is fundamentally a file-system operation.

:gf:`resolve-file` now returns the correct class of locator, a subclass of
:class:`<file-locator>` or class:`<directory-locator>`, depending on the actual file
type of the fully resolved file. It previously returned an instance of the same
class as the locator it was provided, but that is not always accurate when symbolic
links are followed.

* :gf:`directory-contents` has a new keyword argument ``resolve-links?``. If true,
symbolic links are resolved as with :gf:`resolve-file`.

* :gf:`expand-pathname` is no longer called by other ``file-system`` functions. Whether
or not to expand ``~`` or ``~user`` in a pathname is up to the user. The function has
been modified such that the :type:`<pathname>` comprised of the exact string ``"~"`` or
``"~user"`` expands to the user's home directory. Previously these were returned as
unexpanded instances of :class:`<file-locator>`.

:gf:`expand-pathname` now uses the thread safe function ``getpwnam_r`` on Unix systems.

On Windows :gf:`expand-pathname` simply returns its argument (converted to a
:class:`<locator>` if it was a :drm:`<string>`). In a future release it will be fixed
to do the same thing as the Unix implementation. Previously it erroniously did the
same thing as :gf:`resolve-locator`.

* `Issue 1408 <https://github.com/dylan-lang/opendylan/issues/1408>`_, which could result
in an infinite loop in :gf:`link-target`, has been fixed. In addition, the
:gf:`link-target` function accepts a new keyword argument, ``follow-links?``, which
specifies whether to follow all links until a non-symlink file is found (the default)
or just return the direct target of the given symlink.

Contributors
============
2 changes: 1 addition & 1 deletion dylan-package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"dependencies": [
"[email protected]",
"[email protected]",
"deft@0.12",
"deft@0.13",
"[email protected]",
"[email protected]",
"[email protected]",
Expand Down
1 change: 0 additions & 1 deletion sources/system/aarch64-linux-magic-numbers.dylan
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ License: Public Domain
define constant $ENOENT = 2;
define constant $EINTR = 4;
define constant $EACCES = 13;
define constant $EINVAL = 22;
define constant $ETXTBSY = 26;
define constant $EROFS = 30;
define constant $path-max = 4096;
Expand Down
1 change: 0 additions & 1 deletion sources/system/arm-linux-magic-numbers.dylan
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ License: Public Domain
define constant $ENOENT = 2;
define constant $EINTR = 4;
define constant $EACCES = 13;
define constant $EINVAL = 22;
define constant $ETXTBSY = 26;
define constant $EROFS = 30;
define constant $path-max = 4096;
Expand Down
82 changes: 38 additions & 44 deletions sources/system/dump-magic-numbers.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,60 +10,54 @@
#include <time.h>
#include <sys/stat.h>

#define PRINT_USEDBY(file) \
printf("\n// Used by %s\n", file)
#define PRINT_CONSTANT(value, name) \
printf("define constant $%s = %d;\n", name, value);
printf("define constant %s :: <integer> = %d;\n", name, value);
#define PRINT_SIZEOF(type, name) \
printf("define constant $%s-size = %zu;\n", name, sizeof(type))
printf("define constant %s :: <integer> = %zu;\n", name, sizeof(type))
#define PRINT_OFFSETOF(type, member, name) \
printf("define constant $%s-offset = %zu;\n", name, offsetof(type, member))
printf("define constant %s :: <integer> = %zu;\n", name, offsetof(type, member))

int
main(void) {

printf("Module: system-internals\n");
printf("License: Public Domain\n");

printf("\n// WARNING! This file is generated!\n");

PRINT_USEDBY("file-system/unix-ffi.dylan");

PRINT_CONSTANT(ENOENT, "ENOENT");
PRINT_CONSTANT(EINTR, "EINTR");
PRINT_CONSTANT(EACCES, "EACCES");
PRINT_CONSTANT(EINVAL, "EINVAL");
PRINT_CONSTANT(ETXTBSY, "ETXTBSY");
PRINT_CONSTANT(EROFS, "EROFS");

PRINT_CONSTANT(PATH_MAX, "path-max");

PRINT_SIZEOF(struct stat, "stat");
PRINT_OFFSETOF(struct stat, st_mode, "st-mode");
PRINT_OFFSETOF(struct stat, st_uid, "st-uid");
PRINT_OFFSETOF(struct stat, st_gid, "st-gid");
PRINT_OFFSETOF(struct stat, st_size, "st-size");
PRINT_OFFSETOF(struct stat, st_atime, "st-atime");
PRINT_OFFSETOF(struct stat, st_mtime, "st-mtime");
PRINT_OFFSETOF(struct stat, st_ctime, "st-ctime");

PRINT_OFFSETOF(struct passwd, pw_name, "pw-name");
PRINT_OFFSETOF(struct passwd, pw_dir, "pw-dir");

PRINT_OFFSETOF(struct group, gr_name, "gr-name");


PRINT_USEDBY("unix-date-interface.dylan");

PRINT_OFFSETOF(struct tm, tm_sec, "tm-sec");
PRINT_OFFSETOF(struct tm, tm_min, "tm-min");
PRINT_OFFSETOF(struct tm, tm_hour, "tm-hour");
PRINT_OFFSETOF(struct tm, tm_mday, "tm-mday");
PRINT_OFFSETOF(struct tm, tm_mon, "tm-mon");
PRINT_OFFSETOF(struct tm, tm_year, "tm-year");
PRINT_OFFSETOF(struct tm, tm_isdst, "tm-isdst");
PRINT_OFFSETOF(struct tm, tm_gmtoff, "tm-gmtoff");
PRINT_OFFSETOF(struct tm, tm_zone, "tm-zone");
printf("\n// WARNING! This file is generated by running dump-magic-numbers.c!\n");

printf("\n");
PRINT_CONSTANT(ENOENT, "$ENOENT");
PRINT_CONSTANT(EINTR, "$EINTR");
PRINT_CONSTANT(EACCES, "$EACCES");
PRINT_CONSTANT(ETXTBSY, "$ETXTBSY");
PRINT_CONSTANT(EROFS, "$EROFS");

printf("\n");
PRINT_CONSTANT(PATH_MAX, "$path-max");

printf("\n");
PRINT_SIZEOF(struct stat, "$stat-size");
PRINT_OFFSETOF(struct stat, st_mode, "$st-mode-offset");
PRINT_OFFSETOF(struct stat, st_uid, "$st-uid-offset");
PRINT_OFFSETOF(struct stat, st_gid, "$st-gid-offset");
PRINT_OFFSETOF(struct stat, st_size, "$st-size-offset");
PRINT_OFFSETOF(struct stat, st_atime, "$st-atime-offset");
PRINT_OFFSETOF(struct stat, st_mtime, "$st-mtime-offset");
PRINT_OFFSETOF(struct stat, st_ctime, "$st-ctime-offset");

printf("\n");
PRINT_OFFSETOF(struct group, gr_name, "$gr-name-offset");

printf("\n");
PRINT_OFFSETOF(struct tm, tm_sec, "$tm-sec-offset");
PRINT_OFFSETOF(struct tm, tm_min, "$tm-min-offset");
PRINT_OFFSETOF(struct tm, tm_hour, "$tm-hour-offset");
PRINT_OFFSETOF(struct tm, tm_mday, "$tm-mday-offset");
PRINT_OFFSETOF(struct tm, tm_mon, "$tm-mon-offset");
PRINT_OFFSETOF(struct tm, tm_year, "$tm-year-offset");
PRINT_OFFSETOF(struct tm, tm_isdst, "$tm-isdst-offset");
PRINT_OFFSETOF(struct tm, tm_gmtoff, "$tm-gmtoff-offset");
PRINT_OFFSETOF(struct tm, tm_zone, "$tm-zone-offset");

return 0;
}
Loading
Loading