# The Storage Kit: BSymLink

Derived from: BNode

Declared in: be/storage/SymLink.h

Library: libbe.so

## Overview

A "symbolic link" or symlink is a file that "points to" some other entry. The pointed-to (or, better, "linked-to") entry can be a plain file, directory, or another symlink (which links to yet another entry, and so on). Furthermore, the entry can be abstract--you can create a symlink to an entry that doesn't exist.

The data in a symlink is the pathname to the linked-to entry. The pathname can be absolute or relative. If it's relative, the linked-to entry is found by reckoning the pathname of off the directory in which the symlink lives. Relative pathnames can contain "." and ".." components.

The thing to keep in mind, when dealing with symlinks, is that they link to entries, not nodes. If you link a symlink to an (existing) entry named "/boot/home/fido" and then the user moves fido to rover (or deletes fido), the symlink is not updated. It will still link to "/boot/home/fido".

Furthermore, symlinks that contain relative pathnames have a further "problem": Let's say you create a symlink in /boot/home that links to "fido". If you move the symlink to some other directory, it will link to the entry named "fido" in the new directory.

The BSymLink class creates objects that know how to read a symlink's data. The class does not create new symlinks; to create a symlink, you use BDirectory's `CreateSymLink()` function.

|  | BSymLink objects are no smarter than the symlinks files themselves. For example, BSymLinks can't resolve the fido/rover "problem".

The only really useful BSymLink function is `ReadLink()`. This function returns the data that the symlink contains. The other functions are convenient, but they're not essential.

### Initialization and File Descriptors

When you initialize a BSymLink object, you pass in a pathname or `entry_ref` (or whatever) that refers to an existing symlink. The BSymLink object then represents that symlink--it doesn't represent the (node of the) linked-to entry. Furthermore, you can't ask a BSymLink to "resolve itself"--it can't pass you back a BEntry object that represents the linked-to entry.

If you want the BEntry of the linked-to entry, simply initialize a BEntry object with the ref (or whatever) to the symlink and tell it to traverse (set the trailing argument to `true`).

For example, in the following code, `link` is a BSymLink to the symlink "/boot/home/fidoLink" and `entry` is a BEntry to the entry that the symlink links-to:

       BSymLink link("/boot/home/fidoLink");
       BEntry entry("/boot/home/fidoLink", true);

Like all nodes, BSymLink allocates a file descriptor. Remember, this is a file descriptor that's open on the symlink node itself, not the (node of the) linked-to entry.

## Constructor and Destructor

### BSymLink()

          BSymLink(void)
          BSymLink(const BSymLink &link)

          BSymLink(const entry_ref *ref)
          BSymLink(const BEntry *entry)
          BSymLink(const char *path)
          BSymLink(const BDirectory *dir, const char *path)

Creates a new BSymLink object, initializes it according to the arguments, and sets `InitCheck()` to return the status of the initialization.

- The default constructor does nothing and sets `InitCheck()` to `B_NO_INIT`. To initialize the object, call `SetTo()`.

- The copy constructor creates a new BSymLink that's open on the same node as that of the argument.

- For information on the other constructors, see the analogous `SetTo()` functions in the BNode class; BSymLink inherits them without change.

### ~BSymLink()

          virtual ~BSymLink()

Closes the object's file descriptor and destroys the object.

## Member Functions

### IsAbsolute()

          bool IsAbsolute(void)

Returns true if the symlink contains an absolute pathname.

### MakeLinkedPath()

          ssize_t MakeLinkedPath(const BDirectory *dir, BPath *path) const
          ssize_t MakeLinkedPath(const char *dirPath, BPath *path) const

This function creates an absolute pathname to the linked-to entry and returns it as a BPath object. For this to work you have to tell the object which directory you want to reckon off of (in case the symlink specifies a relative path). This should be the directory in which the symlink itself lives.

|  | Remember--a BSymLink is a node, and nodes don't know what directory they live in. That's why you have to tell it here.

If the symlink contains an absolute path, then the dir or dirPath arguments are ignored. Nonetheless, they must be supplied.

The function returns the length of the pathname that's set in BPath (or an error).

RETURN CODES

- `B_FILE_ERROR`. The object is uninitialized.
- `B_BAD_VALUE`. The object doesn't refer to a symlink, or dir/dirPath is NULL.
- `B_NAME_TOO_LONG`. They concatenated pathname is too long.

### ReadLink()

          ssize_t ReadLink(char *buf, size_t length)

Copies the contents of the symlink into buf. length is the size of the buffer; to be perfectly safe, the buffer should be `B_PATH_NAME_LENGTH` characters long. The function returns the number of bytes that were copied (or it returns an error).

The symlink's contents is the pathname (relative or absolute) to the linked-to entry. Note that since the pathname might be relative, `ReadLink()` can't give you a BPath object. If you want a BPath to the linked-to entry, see `MakeLinkedPath()`.

RETURN CODES

- `B_FILE_ERROR`. The object is uninitialized.
- `B_BAD_VALUE`. The object doesn't refer to a symlink.

The Be Book, in lovely HTML, for BeOS Release 3.

Copyright © 1998 Be, Inc. All rights reserved.

Last modified March 26, 1998.