Index: uspace/lib/c/generic/vfs/vfs.c
===================================================================
--- uspace/lib/c/generic/vfs/vfs.c	(revision f9b2cb4cf365498e1fe141b1aa66950fbc3dcb17)
+++ uspace/lib/c/generic/vfs/vfs.c	(revision 03289871c675b83ed939beb60680fb3245e1eea6)
@@ -93,5 +93,5 @@
 }
 
-char *absolutize(const char *path, size_t *retlen)
+char *vfs_absolutize(const char *path, size_t *retlen)
 {
 	char *ncwd_path;
@@ -101,10 +101,10 @@
 	size_t size = str_size(path);
 	if (*path != '/') {
-		if (!cwd_path) {
+		if (cwd_path == NULL) {
 			fibril_mutex_unlock(&cwd_mutex);
 			return NULL;
 		}
 		ncwd_path_nc = malloc(cwd_size + 1 + size + 1);
-		if (!ncwd_path_nc) {
+		if (ncwd_path_nc == NULL) {
 			fibril_mutex_unlock(&cwd_mutex);
 			return NULL;
@@ -115,5 +115,5 @@
 	} else {
 		ncwd_path_nc = malloc(size + 1);
-		if (!ncwd_path_nc) {
+		if (ncwd_path_nc == NULL) {
 			fibril_mutex_unlock(&cwd_mutex);
 			return NULL;
@@ -123,5 +123,5 @@
 	str_append(ncwd_path_nc, cwd_size + 1 + size + 1, path);
 	ncwd_path = canonify(ncwd_path_nc, retlen);
-	if (!ncwd_path) {
+	if (ncwd_path == NULL) {
 		fibril_mutex_unlock(&cwd_mutex);
 		free(ncwd_path_nc);
@@ -135,5 +135,5 @@
 	ncwd_path = str_dup(ncwd_path);
 	free(ncwd_path_nc);
-	if (!ncwd_path) {
+	if (ncwd_path == NULL) {
 		fibril_mutex_unlock(&cwd_mutex);
 		return NULL;
@@ -143,5 +143,5 @@
 }
 
-int mount(const char *fs_name, const char *mp, const char *fqsn,
+int vfs_mount(const char *fs_name, const char *mp, const char *fqsn,
     const char *opts, unsigned int flags, unsigned int instance)
 {
@@ -171,6 +171,6 @@
 	
 	size_t mpa_size;
-	char *mpa = absolutize(mp, &mpa_size);
-	if (!mpa) {
+	char *mpa = vfs_absolutize(mp, &mpa_size);
+	if (mpa == NULL) {
 		if (null_id != -1)
 			loc_null_destroy(null_id);
@@ -255,5 +255,5 @@
 }
 
-int unmount(const char *mp)
+int vfs_unmount(const char *mp)
 {
 	sysarg_t rc;
@@ -263,6 +263,6 @@
 	char *mpa;
 	
-	mpa = absolutize(mp, &mpa_size);
-	if (!mpa)
+	mpa = vfs_absolutize(mp, &mpa_size);
+	if (mpa == NULL)
 		return ENOMEM;
 	
@@ -289,5 +289,16 @@
 }
 
-static int open_internal(const char *abs, size_t abs_size, int lflag, int oflag)
+/** Open file (internal).
+ *
+ * @param abs Absolute path to file
+ * @param abs_size Size of @a abs string
+ * @param lflag L_xxx flags
+ * @param oflag O_xxx flags
+ * @param fd Place to store new file descriptor
+ *
+ * @return EOK on success, non-zero error code on error
+ */
+static int open_internal(const char *abs, size_t abs_size, int lflag, int oflag,
+    int *fd)
 {
 	async_exch_t *exch = vfs_exchange_begin();
@@ -315,20 +326,44 @@
 	    return (int) rc;
 	
-	return (int) IPC_GET_ARG1(answer);
-}
-
+	*fd = (int) IPC_GET_ARG1(answer);
+	return EOK;
+}
+
+/** Open file.
+ *
+ * @param path File path
+ * @param oflag O_xxx flags
+ * @param mode File mode (only with O_CREAT)
+ *
+ * @return Nonnegative file descriptor on success. On error -1 is returned
+ *         and errno is set.
+ */
 int open(const char *path, int oflag, ...)
 {
 	size_t abs_size;
-	char *abs = absolutize(path, &abs_size);
-	if (!abs)
-		return ENOMEM;
-	
-	int ret = open_internal(abs, abs_size, L_FILE, oflag);
+	char *abs = vfs_absolutize(path, &abs_size);
+	int fd = -1;
+	
+	if (abs == NULL) {
+		errno = ENOMEM;
+		return -1;
+	}
+	
+	int rc = open_internal(abs, abs_size, L_FILE, oflag, &fd);
 	free(abs);
 	
-	return ret;
-}
-
+	if (rc != EOK) {
+		errno = rc;
+		return -1;
+	}
+	
+	return fd;
+}
+
+/** Close file.
+ *
+ * @param fildes File descriptor
+ * @return Zero on success. On error -1 is returned and errno is set.
+ */
 int close(int fildes)
 {
@@ -339,8 +374,27 @@
 	vfs_exchange_end(exch);
 	
-	return (int) rc;
-}
-
-ssize_t read(int fildes, void *buf, size_t nbyte)
+	if (rc != EOK) {
+		errno = rc;
+		return -1;
+	}
+	
+	return 0;
+}
+
+/** Read bytes from file.
+ *
+ * Read up to @a nbyte bytes from file. The actual number of bytes read
+ * may be lower, but greater than zero if there are any bytes available.
+ * If there are no bytes available for reading, then the function will
+ * return success with zero bytes read.
+ *
+ * @param fildes File descriptor
+ * @param buf Buffer
+ * @param nbyte Maximum number of bytes to read
+ * @param nread Place to store actual number of bytes read (0 or more)
+ *
+ * @return EOK on success, non-zero error code on error.
+ */
+static int _read_short(int fildes, void *buf, size_t nbyte, ssize_t *nread)
 {
 	sysarg_t rc;
@@ -357,22 +411,38 @@
 	if (rc != EOK) {
 		vfs_exchange_end(exch);
-
+		
 		sysarg_t rc_orig;
 		async_wait_for(req, &rc_orig);
-
+		
 		if (rc_orig == EOK)
-			return (ssize_t) rc;
+			return rc;
 		else
-			return (ssize_t) rc_orig;
-	}
+			return rc_orig;
+	}
+	
 	vfs_exchange_end(exch);
 	async_wait_for(req, &rc);
-	if (rc == EOK)
-		return (ssize_t) IPC_GET_ARG1(answer);
-	else
+	
+	if (rc != EOK)
 		return rc;
-}
-
-ssize_t write(int fildes, const void *buf, size_t nbyte) 
+	
+	*nread = (ssize_t) IPC_GET_ARG1(answer);
+	return EOK;
+}
+
+/** Write bytes to file.
+ *
+ * Write up to @a nbyte bytes from file. The actual number of bytes written
+ * may be lower, but greater than zero.
+ *
+ * @param fildes File descriptor
+ * @param buf Buffer
+ * @param nbyte Maximum number of bytes to write
+ * @param nread Place to store actual number of bytes written (0 or more)
+ *
+ * @return EOK on success, non-zero error code on error.
+ */
+static int _write_short(int fildes, const void *buf, size_t nbyte,
+    ssize_t *nwritten)
 {
 	sysarg_t rc;
@@ -389,25 +459,28 @@
 	if (rc != EOK) {
 		vfs_exchange_end(exch);
-
+		
 		sysarg_t rc_orig;
 		async_wait_for(req, &rc_orig);
-
+		
 		if (rc_orig == EOK)
-			return (ssize_t) rc;
+			return rc;
 		else
-			return (ssize_t) rc_orig;
-	}
+			return rc_orig;
+	}
+	
 	vfs_exchange_end(exch);
 	async_wait_for(req, &rc);
-	if (rc == EOK)
-		return (ssize_t) IPC_GET_ARG1(answer);
-	else
-		return -1;
-}
-
-/** Read entire buffer.
- *
- * In face of short reads this function continues reading until either
- * the entire buffer is read or no more data is available (at end of file).
+	
+	if (rc != EOK)
+		return rc;
+	
+	*nwritten = (ssize_t) IPC_GET_ARG1(answer);
+	return EOK;
+}
+
+/** Read data.
+ *
+ * Read up to @a nbytes bytes from file if available. This function always reads
+ * all the available bytes up to @a nbytes.
  *
  * @param fildes	File descriptor
@@ -415,26 +488,29 @@
  * @param nbytes	Number of bytes to read
  *
- * @return		On success, positive number of bytes read.
- *			On failure, negative error code from read().
- */
-ssize_t read_all(int fildes, void *buf, size_t nbyte)
+ * @return		On success, nonnegative number of bytes read.
+ *			On failure, -1 and sets errno.
+ */
+ssize_t read(int fildes, void *buf, size_t nbyte)
 {
 	ssize_t cnt = 0;
 	size_t nread = 0;
 	uint8_t *bp = (uint8_t *) buf;
-
+	int rc;
+	
 	do {
 		bp += cnt;
 		nread += cnt;
-		cnt = read(fildes, bp, nbyte - nread);
-	} while (cnt > 0 && (nbyte - nread - cnt) > 0);
-
-	if (cnt < 0)
-		return cnt;
-
+		rc = _read_short(fildes, bp, nbyte - nread, &cnt);
+	} while (rc == EOK && cnt > 0 && (nbyte - nread - cnt) > 0);
+	
+	if (rc != EOK) {
+		errno = rc;
+		return -1;
+	}
+	
 	return nread + cnt;
 }
 
-/** Write entire buffer.
+/** Write data.
  *
  * This function fails if it cannot write exactly @a len bytes to the file.
@@ -444,28 +520,33 @@
  * @param nbytes	Number of bytes to write
  *
- * @return		EOK on error, return value from write() if writing
- *			failed.
- */
-ssize_t write_all(int fildes, const void *buf, size_t nbyte)
+ * @return		On success, nonnegative number of bytes written.
+ *			On failure, -1 and sets errno.
+ */
+ssize_t write(int fildes, const void *buf, size_t nbyte)
 {
 	ssize_t cnt = 0;
 	ssize_t nwritten = 0;
 	const uint8_t *bp = (uint8_t *) buf;
+	int rc;
 
 	do {
 		bp += cnt;
 		nwritten += cnt;
-		cnt = write(fildes, bp, nbyte - nwritten);
-	} while (cnt > 0 && ((ssize_t )nbyte - nwritten - cnt) > 0);
-
-	if (cnt < 0)
-		return cnt;
-
-	if ((ssize_t)nbyte - nwritten - cnt > 0)
-		return EIO;
+		rc = _write_short(fildes, bp, nbyte - nwritten, &cnt);
+	} while (rc == EOK && ((ssize_t )nbyte - nwritten - cnt) > 0);
+
+	if (rc != EOK) {
+		errno = rc;
+		return -1;
+	}
 
 	return nbyte;
 }
 
+/** Synchronize file.
+ *
+ * @param fildes File descriptor
+ * @return 0 on success. On error returns -1 and sets errno.
+ */
 int fsync(int fildes)
 {
@@ -474,7 +555,21 @@
 	vfs_exchange_end(exch);
 	
-	return (int) rc;
-}
-
+	if (rc != EOK) {
+		errno = rc;
+		return -1;
+	}
+	
+	return 0;
+}
+
+/** Seek to a position.
+ *
+ * @param fildes File descriptor
+ * @param offset Offset
+ * @param whence SEEK_SET, SEEK_CUR or SEEK_END
+ *
+ * @return On success the nonnegative offset from start of file. On error
+ *         returns (off64_t)-1 and sets errno.
+ */
 off64_t lseek(int fildes, off64_t offset, int whence)
 {
@@ -489,10 +584,21 @@
 	vfs_exchange_end(exch);
 	
-	if (rc != EOK)
+	if (rc != EOK) {
+		errno = rc;
 		return (off64_t) -1;
+	}
 	
 	return (off64_t) MERGE_LOUP32(newoff_lo, newoff_hi);
 }
 
+/** Truncate file to a specified length.
+ *
+ * Truncate file so that its size is exactly @a length
+ *
+ * @param fildes File descriptor
+ * @param length Length
+ *
+ * @return 0 on success, -1 on error and sets errno.
+ */
 int ftruncate(int fildes, aoff64_t length)
 {
@@ -504,7 +610,19 @@
 	vfs_exchange_end(exch);
 	
-	return (int) rc;
-}
-
+	if (rc != EOK) {
+		errno = rc;
+		return -1;
+	}
+	
+	return 0;
+}
+
+/** Get file status.
+ *
+ * @param fildes File descriptor
+ * @param stat Place to store file information
+ *
+ * @return 0 on success, -1 on error and sets errno.
+ */
 int fstat(int fildes, struct stat *stat)
 {
@@ -518,19 +636,36 @@
 	if (rc != EOK) {
 		vfs_exchange_end(exch);
-
+		
 		sysarg_t rc_orig;
 		async_wait_for(req, &rc_orig);
-
-		if (rc_orig == EOK)
-			return (ssize_t) rc;
-		else
-			return (ssize_t) rc_orig;
-	}
+		
+		if (rc_orig != EOK)
+			rc = rc_orig;
+		if (rc != EOK) {
+			errno = rc;
+			return -1;
+		}
+		
+		return 0;
+	}
+	
 	vfs_exchange_end(exch);
 	async_wait_for(req, &rc);
-
-	return rc;
-}
-
+	
+	if (rc != EOK) {
+		errno = rc;
+		return -1;
+	}
+	
+	return 0;
+}
+
+/** Get file status.
+ *
+ * @param path Path to file
+ * @param stat Place to store file information
+ *
+ * @return 0 on success, -1 on error and sets errno.
+ */
 int stat(const char *path, struct stat *stat)
 {
@@ -540,7 +675,9 @@
 	
 	size_t pa_size;
-	char *pa = absolutize(path, &pa_size);
-	if (!pa)
-		return ENOMEM;
+	char *pa = vfs_absolutize(path, &pa_size);
+	if (pa == NULL) {
+		errno = ENOMEM;
+		return -1;
+	}
 	
 	async_exch_t *exch = vfs_exchange_begin();
@@ -552,4 +689,195 @@
 		free(pa);
 		async_wait_for(req, &rc_orig);
+		if (rc_orig != EOK)
+			rc = rc_orig;
+		if (rc != EOK) {
+			errno = rc;
+			return -1;
+		}
+	}
+	rc = async_data_read_start(exch, stat, sizeof(struct stat));
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
+		free(pa);
+		async_wait_for(req, &rc_orig);
+		if (rc_orig != EOK)
+			rc = rc_orig;
+		if (rc != EOK) {
+			errno = rc;
+			return -1;
+		}
+	}
+	vfs_exchange_end(exch);
+	free(pa);
+	async_wait_for(req, &rc);
+	if (rc != EOK) {
+		errno = rc;
+		return -1;
+	}
+	return 0;
+}
+
+/** Open directory.
+ *
+ * @param dirname Directory pathname
+ *
+ * @return Non-NULL pointer on success. On error returns @c NULL and sets errno.
+ */
+DIR *opendir(const char *dirname)
+{
+	DIR *dirp = malloc(sizeof(DIR));
+	int fd = -1;
+	
+	if (dirp == NULL) {
+		errno = ENOMEM;
+		return NULL;
+	}
+	
+	size_t abs_size;
+	char *abs = vfs_absolutize(dirname, &abs_size);
+	if (abs == NULL) {
+		free(dirp);
+		errno = ENOMEM;
+		return NULL;
+	}
+	
+	int rc = open_internal(abs, abs_size, L_DIRECTORY, 0, &fd);
+	free(abs);
+	
+	if (rc != EOK) {
+		free(dirp);
+		errno = rc;
+		return NULL;
+	}
+	
+	dirp->fd = fd;
+	return dirp;
+}
+
+/** Read directory entry.
+ *
+ * @param dirp Open directory
+ * @return Non-NULL pointer to directory entry on success. On error returns
+ *         @c NULL and sets errno.
+ */
+struct dirent *readdir(DIR *dirp)
+{
+	int rc;
+	ssize_t len;
+	
+	rc = _read_short(dirp->fd, &dirp->res.d_name[0], NAME_MAX + 1, &len);
+	if (rc != EOK) {
+		errno = rc;
+		return NULL;
+	}
+	
+	(void) len;
+	return &dirp->res;
+}
+
+/** Rewind directory position to the beginning.
+ *
+ * @param dirp Open directory
+ */
+void rewinddir(DIR *dirp)
+{
+	(void) lseek(dirp->fd, 0, SEEK_SET);
+}
+
+/** Close directory.
+ *
+ * @param dirp Open directory
+ * @return 0 on success. On error returns -1 and sets errno.
+ */
+int closedir(DIR *dirp)
+{
+	int rc;
+	
+	rc = close(dirp->fd);
+	free(dirp);
+
+	/* On error errno was set by close() */
+	return rc;
+}
+
+/** Create directory.
+ *
+ * @param path Path
+ * @param mode File mode
+ * @return 0 on success. On error returns -1 and sets errno.
+ */
+int mkdir(const char *path, mode_t mode)
+{
+	sysarg_t rc;
+	aid_t req;
+	
+	size_t pa_size;
+	char *pa = vfs_absolutize(path, &pa_size);
+	if (pa == NULL) {
+		errno = ENOMEM;
+		return -1;
+	}
+	
+	async_exch_t *exch = vfs_exchange_begin();
+	
+	req = async_send_1(exch, VFS_IN_MKDIR, mode, NULL);
+	rc = async_data_write_start(exch, pa, pa_size);
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
+		free(pa);
+		
+		sysarg_t rc_orig;
+		async_wait_for(req, &rc_orig);
+		
+		if (rc_orig != EOK)
+			rc = rc_orig;
+		
+		if (rc != EOK) {
+			errno = rc;
+			return -1;
+		}
+		
+		return 0;
+	}
+	
+	vfs_exchange_end(exch);
+	free(pa);
+	async_wait_for(req, &rc);
+	
+	if (rc != EOK) {
+		errno = rc;
+		return -1;
+	}
+	
+	return 0;
+}
+
+/** Unlink a file or directory.
+ *
+ * @param path Path to file or empty directory
+ * @param lflag L_xxx flag (L_NONE, L_FILE or L_DIRECTORY)
+ * @return EOK on success, non-zero error code on error
+ */
+static int _unlink(const char *path, int lflag)
+{
+	sysarg_t rc;
+	aid_t req;
+	
+	size_t pa_size;
+	char *pa = vfs_absolutize(path, &pa_size);
+	if (pa == NULL)
+		return ENOMEM;
+	
+	async_exch_t *exch = vfs_exchange_begin();
+	
+	req = async_send_1(exch, VFS_IN_UNLINK, lflag, NULL);
+	rc = async_data_write_start(exch, pa, pa_size);
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
+		free(pa);
+
+		sysarg_t rc_orig;
+		async_wait_for(req, &rc_orig);
+
 		if (rc_orig == EOK)
 			return (int) rc;
@@ -557,14 +885,4 @@
 			return (int) rc_orig;
 	}
-	rc = async_data_read_start(exch, stat, sizeof(struct stat));
-	if (rc != EOK) {
-		vfs_exchange_end(exch);
-		free(pa);
-		async_wait_for(req, &rc_orig);
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
 	vfs_exchange_end(exch);
 	free(pa);
@@ -573,123 +891,47 @@
 }
 
-DIR *opendir(const char *dirname)
-{
-	DIR *dirp = malloc(sizeof(DIR));
-	if (!dirp)
-		return NULL;
-	
-	size_t abs_size;
-	char *abs = absolutize(dirname, &abs_size);
-	if (!abs) {
-		free(dirp);
-		return NULL;
-	}
-	
-	int ret = open_internal(abs, abs_size, L_DIRECTORY, 0);
-	free(abs);
-	
-	if (ret < 0) {
-		free(dirp);
-		return NULL;
-	}
-	
-	dirp->fd = ret;
-	return dirp;
-}
-
-struct dirent *readdir(DIR *dirp)
-{
-	ssize_t len = read(dirp->fd, &dirp->res.d_name[0], NAME_MAX + 1);
-	if (len <= 0)
-		return NULL;
-	return &dirp->res;
-}
-
-void rewinddir(DIR *dirp)
-{
-	(void) lseek(dirp->fd, 0, SEEK_SET);
-}
-
-int closedir(DIR *dirp)
-{
-	(void) close(dirp->fd);
-	free(dirp);
+/** Unlink file or directory.
+ *
+ * @param path Path
+ * @return EOk on success, error code on error
+ */
+int unlink(const char *path)
+{
+	int rc;
+
+	rc = _unlink(path, L_NONE);
+	if (rc != EOK) {
+		errno = rc;
+		return -1;
+	}
+
 	return 0;
 }
 
-int mkdir(const char *path, mode_t mode)
-{
-	sysarg_t rc;
-	aid_t req;
-	
-	size_t pa_size;
-	char *pa = absolutize(path, &pa_size);
-	if (!pa)
-		return ENOMEM;
-	
-	async_exch_t *exch = vfs_exchange_begin();
-	
-	req = async_send_1(exch, VFS_IN_MKDIR, mode, NULL);
-	rc = async_data_write_start(exch, pa, pa_size);
-	if (rc != EOK) {
-		vfs_exchange_end(exch);
-		free(pa);
-
-		sysarg_t rc_orig;
-		async_wait_for(req, &rc_orig);
-
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
-	vfs_exchange_end(exch);
-	free(pa);
-	async_wait_for(req, &rc);
-	return rc;
-}
-
-static int _unlink(const char *path, int lflag)
-{
-	sysarg_t rc;
-	aid_t req;
-	
-	size_t pa_size;
-	char *pa = absolutize(path, &pa_size);
-	if (!pa)
-		return ENOMEM;
-	
-	async_exch_t *exch = vfs_exchange_begin();
-	
-	req = async_send_1(exch, VFS_IN_UNLINK, lflag, NULL);
-	rc = async_data_write_start(exch, pa, pa_size);
-	if (rc != EOK) {
-		vfs_exchange_end(exch);
-		free(pa);
-
-		sysarg_t rc_orig;
-		async_wait_for(req, &rc_orig);
-
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
-	vfs_exchange_end(exch);
-	free(pa);
-	async_wait_for(req, &rc);
-	return rc;
-}
-
-int unlink(const char *path)
-{
-	return _unlink(path, L_NONE);
-}
-
+/** Remove empty directory.
+ *
+ * @param path Path
+ * @return 0 on success. On error returns -1 and sets errno.
+ */
 int rmdir(const char *path)
 {
-	return _unlink(path, L_DIRECTORY);
-}
-
+	int rc;
+
+	rc = _unlink(path, L_DIRECTORY);
+	if (rc != EOK) {
+		errno = rc;
+		return -1;
+	}
+
+	return 0;
+}
+
+/** Rename directory entry.
+ *
+ * @param old Old name
+ * @param new New name
+ *
+ * @return 0 on success. On error returns -1 and sets errno.
+ */
 int rename(const char *old, const char *new)
 {
@@ -699,13 +941,16 @@
 	
 	size_t olda_size;
-	char *olda = absolutize(old, &olda_size);
-	if (!olda)
-		return ENOMEM;
+	char *olda = vfs_absolutize(old, &olda_size);
+	if (olda == NULL) {
+		errno = ENOMEM;
+		return -1;
+	}
 
 	size_t newa_size;
-	char *newa = absolutize(new, &newa_size);
-	if (!newa) {
+	char *newa = vfs_absolutize(new, &newa_size);
+	if (newa == NULL) {
 		free(olda);
-		return ENOMEM;
+		errno = ENOMEM;
+		return -1;
 	}
 	
@@ -719,8 +964,11 @@
 		free(newa);
 		async_wait_for(req, &rc_orig);
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
+		if (rc_orig != EOK)
+			rc = rc_orig;
+		if (rc != EOK) {
+			errno = rc;
+			return -1;
+		}
+		return 0;
 	}
 	rc = async_data_write_start(exch, newa, newa_size);
@@ -730,8 +978,11 @@
 		free(newa);
 		async_wait_for(req, &rc_orig);
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
+		if (rc_orig != EOK)
+			rc = rc_orig;
+		if (rc != EOK) {
+			errno = rc;
+			return -1;
+		}
+		return 0;
 	}
 	vfs_exchange_end(exch);
@@ -739,7 +990,18 @@
 	free(newa);
 	async_wait_for(req, &rc);
-	return rc;
-}
-
+
+	if (rc != EOK) {
+		errno = rc;
+		return -1;
+	}
+
+	return 0;
+}
+
+/** Remove directory entry.
+ *
+ * @param path Path
+ * @return 0 on success. On error returns -1 and sets errno.
+ */
 int remove(const char *path)
 {
@@ -747,16 +1009,26 @@
 }
 
+/** Change working directory.
+ *
+ * @param path Path
+ * @return 0 on success. On error returns -1 and sets errno.
+ */
 int chdir(const char *path)
 {
 	size_t abs_size;
-	char *abs = absolutize(path, &abs_size);
-	if (!abs)
-		return ENOMEM;
-	
-	int fd = open_internal(abs, abs_size, L_DIRECTORY, O_DESC);
-	
-	if (fd < 0) {
+	char *abs = vfs_absolutize(path, &abs_size);
+	int fd = -1;
+	
+	if (abs == NULL) {
+		errno = ENOMEM;
+		return -1;
+	}
+	
+	int rc = open_internal(abs, abs_size, L_DIRECTORY, O_DESC, &fd);
+	
+	if (rc != EOK) {
 		free(abs);
-		return ENOENT;
+		errno = rc;
+		return -1;
 	}
 	
@@ -765,5 +1037,4 @@
 	if (cwd_fd >= 0)
 		close(cwd_fd);
-	
 	
 	if (cwd_path)
@@ -775,11 +1046,19 @@
 	
 	fibril_mutex_unlock(&cwd_mutex);
-	return EOK;
-}
-
+	return 0;
+}
+
+/** Get current working directory path.
+ *
+ * @param buf Buffer
+ * @param size Size of @a buf
+ * @return On success returns @a buf. On failure returns @c NULL and sets errno.
+ */
 char *getcwd(char *buf, size_t size)
 {
-	if (size == 0)
+	if (size == 0) {
+		errno = EINVAL;
 		return NULL;
+	}
 	
 	fibril_mutex_lock(&cwd_mutex);
@@ -787,4 +1066,5 @@
 	if ((cwd_size == 0) || (size < cwd_size + 1)) {
 		fibril_mutex_unlock(&cwd_mutex);
+		errno = ERANGE;
 		return NULL;
 	}
@@ -796,21 +1076,34 @@
 }
 
-async_sess_t *fd_session(int fildes, iface_t iface)
+/** Open session to service represented by a special file.
+ *
+ * Given that the file referred to by @a fildes represents a service,
+ * open a session to that service.
+ *
+ * @param fildes File descriptor
+ * @param iface Interface to connect to (XXX Should be automatic)
+ * @return On success returns session pointer. On error returns @c NULL.
+ */
+async_sess_t *vfs_fd_session(int fildes, iface_t iface)
 {
 	struct stat stat;
 	int rc = fstat(fildes, &stat);
-	if (rc != 0) {
-		errno = rc;
+	if (rc != 0)
 		return NULL;
-	}
-	
-	if (!stat.service) {
-		errno = ENOENT;
+	
+	if (stat.service == 0)
 		return NULL;
-	}
 	
 	return loc_service_connect(stat.service, iface, 0);
 }
 
+/** Duplicate open file.
+ *
+ * Duplicate open file under a new file descriptor.
+ *
+ * @param oldfd Old file descriptor
+ * @param newfd New file descriptor
+ * @return 0 on success. On error -1 is returned and errno is set
+ */
 int dup2(int oldfd, int newfd)
 {
@@ -823,10 +1116,15 @@
 	
 	if (rc == EOK)
-		return (int) ret;
-	
-	return (int) rc;
-}
-
-int fd_wait(void)
+		rc = ret;
+	
+	if (rc != EOK) {
+		errno = rc;
+		return -1;
+	}
+	
+	return 0;
+}
+
+int vfs_fd_wait(void)
 {
 	async_exch_t *exch = vfs_exchange_begin();
@@ -843,5 +1141,5 @@
 }
 
-int get_mtab_list(list_t *mtab_list)
+int vfs_get_mtab_list(list_t *mtab_list)
 {
 	sysarg_t rc;
@@ -863,5 +1161,5 @@
 
 		mtab_ent = malloc(sizeof(mtab_ent_t));
-		if (!mtab_ent) {
+		if (mtab_ent == NULL) {
 			rc = ENOMEM;
 			goto exit;
@@ -904,4 +1202,10 @@
 }
 
+/** Get filesystem statistics.
+ *
+ * @param path Mount point path
+ * @param st Buffer for storing information
+ * @return 0 on success. On error -1 is returned and errno is set.
+ */
 int statfs(const char *path, struct statfs *st)
 {
@@ -910,7 +1214,9 @@
 	size_t pa_size;
 
-	char *pa = absolutize(path, &pa_size);
-	if (!pa)
-		return ENOMEM;
+	char *pa = vfs_absolutize(path, &pa_size);
+	if (pa == NULL) {
+		errno = ENOMEM;
+		return -1;
+	}
 
 	async_exch_t *exch = vfs_exchange_begin();
@@ -927,5 +1233,12 @@
 	free(pa);
 	async_wait_for(req, &rc_orig);
-	return (int) (rc_orig != EOK ? rc_orig : rc);
+	rc = (rc_orig != EOK ? rc_orig : rc);
+
+	if (rc != EOK) {
+		errno = rc;
+		return -1;
+	}
+
+	return 0;
 }
 
