---
name: "cam"
section: "3"
platform: "freebsd"
package: "base"
version: "16.0-CURRENT-20261027-61c70dc16a79"
release: "FreeBSD 16.0-CURRENT (2026-10-27)"
platforms: ["freebsd"]
url: "https://new.carta.tech/cam/3"
---

# cam(3)

CAM user library

## NAME

**cam\_open\_device**, **cam\_open\_spec\_device**, **cam\_open\_btl**, **cam\_open\_pass**, **cam\_close\_device**, **cam\_close\_spec\_device**, **cam\_getccb**, **cam\_send\_ccb**, **cam\_freeccb**, **cam\_path\_string**, **cam\_device\_dup**, **cam\_device\_copy**, **cam\_get\_device** – CAM user library

## LIBRARY

library “libcam”

## SYNOPSIS

**#include \<stdio.h\>**

**#include \<camlib.h\>**

*struct* *cam\_device* *\**\

**cam\_open\_device**(*const char \*path*, *int flags*);

*struct* *cam\_device* *\**\

**cam\_open\_spec\_device**(*const char \*dev\_name*, *int unit*, *int flags*, *struct cam\_device \*device*);

*struct* *cam\_device* *\**\

**cam\_open\_btl**(*path\_id\_t path\_id*, *target\_id\_t target\_id*, *lun\_id\_t target\_lun*, *int flags*, *struct cam\_device \*device*);

*struct* *cam\_device* *\**\

**cam\_open\_pass**(*const char \*path*, *int flags*, *struct cam\_device \*device*);

*void*\

**cam\_close\_device**(*struct cam\_device \*dev*);

*void*\

**cam\_close\_spec\_device**(*struct cam\_device \*dev*);

*union* *ccb* *\**\

**cam\_getccb**(*struct cam\_device \*dev*);

*int*\

**cam\_send\_ccb**(*struct cam\_device \*device*, *union ccb \*ccb*);

*void*\

**cam\_freeccb**(*union ccb \*ccb*);

*char* *\**\

**cam\_path\_string**(*struct cam\_device \*dev*, *char \*str*, *int len*);

*struct* *cam\_device* *\**\

**cam\_device\_dup**(*struct cam\_device \*device*);

*void*\

**cam\_device\_copy**(*struct cam\_device \*src*, *struct cam\_device \*dst*);

*int*\

**cam\_get\_device**(*const char \*path*, *char \*dev\_name*, *int devnamelen*, *int \*unit*);

## DESCRIPTION

The CAM library consists of a number of functions designed to aid in programming with the CAM subsystem described in [cam(4)](/cam/4.md). This man page covers the basic set of library functions. More functions are documented in the man pages listed below.

Many of the CAM library functions use the *cam\_device* structure:

```
struct cam_device {
	char		device_path[MAXPATHLEN+1];/*
						   * Pathname of the
						   * device given by the
						   * user. This may be
						   * null if the user
						   * states the device
						   * name and unit number
						   * separately.
						   */
	char		given_dev_name[DEV_IDLEN+1];/*
						     * Device name given by
						     * the user.
						     */
	uint32_t	given_unit_number;	    /*
						     * Unit number given by
						     * the user.
						     */
	char		device_name[DEV_IDLEN+1];/*
						  * Name of the device,
						  * e.g., 'pass'
						  */
	uint32_t	dev_unit_num;	/* Unit number of the passthrough
					 * device associated with this
					 * particular device.
					 */
	char		sim_name[SIM_IDLEN+1];/*
					       * Controller name, e.g., 'ahc'
					       */
	uint32_t	sim_unit_number; /* Controller unit number */
	uint32_t	bus_id;		 /* Controller bus number */
	lun_id_t	target_lun;	 /* Logical Unit Number */
	target_id_t	target_id;	 /* Target ID */
	path_id_t	path_id;	 /* System SCSI bus number */
	uint16_t	pd_type;	 /* type of peripheral device */
	struct scsi_inquiry_data inq_data;  /* SCSI Inquiry data */
	uint8_t		serial_num[252]; /* device serial number */
	uint8_t		serial_num_len;  /* length of the serial number */
	uint8_t		sync_period;	 /* Negotiated sync period */
	uint8_t		sync_offset;	 /* Negotiated sync offset */
	uint8_t		bus_width;	 /* Negotiated bus width */
	int		fd;		 /* file descriptor for device */
};
```

**cam\_open\_device**() takes as arguments a string describing the device it is to open, and *flags* suitable for passing to [open(2)](/open/2.md). The "path" passed in may actually be most any type of string that contains a device name and unit number to be opened. The string will be parsed by **cam\_get\_device**() into a device name and unit number. Once the device name and unit number are determined, a lookup is performed to determine the passthrough device that corresponds to the given device.

**cam\_open\_spec\_device**() opens the [pass(4)](/pass/4.md) device that corresponds to the device name and unit number passed in. The *flags* should be flags suitable for passing to [open(2)](/open/2.md). The *device* argument is optional. The user may supply pre-allocated space for the *cam\_device* structure. If the *device* argument is NULL, **cam\_open\_spec\_device**() will allocate space for the *cam\_device* structure using [malloc(3)](/malloc/3.md).

**cam\_open\_btl**() is similar to **cam\_open\_spec\_device**(), except that it takes a SCSI bus, target and logical unit instead of a device name and unit number as arguments. The *path\_id* argument is the CAM equivalent of a SCSI bus number. It represents the logical bus number in the system. The *flags* should be flags suitable for passing to [open(2)](/open/2.md). As with **cam\_open\_spec\_device**(), the *device* argument is optional.

**cam\_open\_pass**() takes as an argument the *path* of a [pass(4)](/pass/4.md) device to open. No translation or lookup is performed, so the path passed in must be that of a CAM [pass(4)](/pass/4.md) device. The *flags* should be flags suitable for passing to [open(2)](/open/2.md). The *device* argument, as with **cam\_open\_spec\_device**() and **cam\_open\_btl**(), should be NULL if the user wants the CAM library to allocate space for the *cam\_device* structure.

**cam\_close\_device**() frees the *cam\_device* structure allocated by one of the above [open(2)](/open/2.md) calls, and closes the file descriptor to the passthrough device. This routine should not be called if the user allocated space for the *cam\_device* structure. Instead, the user should call **cam\_close\_spec\_device**().

**cam\_close\_spec\_device**() merely closes the file descriptor opened in one of the [open(2)](/open/2.md) routines described above. This function should be called when the *cam\_device* structure was allocated by the caller, rather than the CAM library.

**cam\_getccb**() allocates a prezeroed CCB using [calloc(3)](/calloc/3.md) and sets fields in the CCB header using values from the *cam\_device* structure.

**cam\_send\_ccb**() sends the given *ccb* to the *device* described in the *cam\_device* structure.

**cam\_freeccb**() frees CCBs allocated by **cam\_getccb**(). If *ccb* is NULL, no action is taken.

**cam\_path\_string**() takes as arguments a *cam\_device* structure, and a string with length *len*. It creates a colon-terminated printing prefix string similar to the ones used by the kernel. e.g.: "(cd0:ahc1:0:4:0): ". **cam\_path\_string**() will place at most *len*-1 characters into *str*. The *len*'th character will be the terminating ‘\\0’.

**cam\_device\_dup**() operates in a fashion similar to [strdup(3)](/strdup/3.md). It allocates space for a *cam\_device* structure and copies the contents of the passed-in *device* structure to the newly allocated structure.

**cam\_device\_copy**() copies the *src* structure to *dst*.

**cam\_get\_device**() takes a *path* argument containing a string with a device name followed by a unit number. It then breaks the string down into a device name and unit number, and passes them back in *dev\_name* and *unit*, respectively. **cam\_get\_device**() can handle strings of the following forms, at least:

- /dev/foo1

  - foo0

  - nsa2

  **cam\_get\_device**() is provided as a convenience function for applications that need to provide functionality similar to **cam\_open\_device**().

## RETURN VALUES

**cam\_open\_device**(), **cam\_open\_spec\_device**(), **cam\_open\_btl**(), and **cam\_open\_pass**() return a pointer to a *cam\_device* structure, or NULL if there was an error.

**cam\_getccb**() returns an allocated and partially initialized CCB, or NULL if allocation of the CCB failed.

**cam\_send\_ccb**() returns a value of -1 if an error occurred, and *errno* is set to indicate the error.

**cam\_path\_string**() returns a filled printing prefix string as a convenience. This is the same *str* that is passed into **cam\_path\_string**().

**cam\_device\_dup**() returns a copy of the *device* passed in, or NULL if an error occurred.

**cam\_get\_device**() returns 0 for success, and -1 to indicate failure.

If an error is returned from one of the base CAM library functions described here, the reason for the error is generally printed in the global string *cam\_errbuf* which is CAM\_ERRBUF\_SIZE characters long.

## SEE ALSO

[cam\_cdbparse(3)](/cam_cdbparse/3.md), [pass(4)](/pass/4.md), [camcontrol(8)](/camcontrol/8.md)

## HISTORY

The CAM library first appeared in FreeBSD 3.0.

## AUTHORS

Kenneth Merry ⟨*ken@FreeBSD.org*⟩

## BUGS

**cam\_open\_device**() does not check to see if the *path* passed in is a symlink to something. It also does not check to see if the *path* passed in is an actual [pass(4)](/pass/4.md) device. The former would be rather easy to implement, but the latter would require a definitive way to identify a device node as a [pass(4)](/pass/4.md) device.

Some of the functions are possibly misnamed or poorly named.
