2007-11-24 12:14:45 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2007 Vreixo Formoso
|
2024-07-16 13:05:11 +00:00
|
|
|
* Copyright (c) 2009 - 2024 Thomas Schmitt
|
2007-11-24 12:14:45 +00:00
|
|
|
*
|
|
|
|
* This file is part of the libisofs project; you can redistribute it and/or
|
2010-01-27 05:48:59 +00:00
|
|
|
* modify it under the terms of the GNU General Public License version 2
|
|
|
|
* or later as published by the Free Software Foundation.
|
|
|
|
* See COPYING file for details.
|
2007-11-24 12:14:45 +00:00
|
|
|
*/
|
|
|
|
|
2007-11-24 15:58:36 +00:00
|
|
|
/*
|
|
|
|
* Filesystem/FileSource implementation to access the local filesystem.
|
|
|
|
*/
|
2007-11-24 12:14:45 +00:00
|
|
|
|
2010-05-16 08:20:12 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "../config.h"
|
|
|
|
#endif
|
|
|
|
|
2007-11-24 15:58:36 +00:00
|
|
|
#include "fsource.h"
|
2007-12-31 15:27:08 +00:00
|
|
|
#include "util.h"
|
2009-01-16 12:24:30 +00:00
|
|
|
#include "aaip_0_2.h"
|
|
|
|
|
2007-11-25 15:46:21 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <dirent.h>
|
|
|
|
#include <unistd.h>
|
2007-11-26 20:16:38 +00:00
|
|
|
#include <libgen.h>
|
2007-11-25 15:46:21 +00:00
|
|
|
#include <string.h>
|
|
|
|
|
2014-11-26 13:44:43 +00:00
|
|
|
/* O_BINARY is needed for Cygwin but undefined elsewhere */
|
|
|
|
#ifndef O_BINARY
|
|
|
|
#define O_BINARY 0
|
|
|
|
#endif
|
|
|
|
|
2007-12-31 15:29:47 +00:00
|
|
|
static
|
2008-01-11 18:48:52 +00:00
|
|
|
int iso_file_source_new_lfs(IsoFileSource *parent, const char *name,
|
|
|
|
IsoFileSource **src);
|
2007-12-31 15:29:47 +00:00
|
|
|
|
2007-12-02 16:59:36 +00:00
|
|
|
/*
|
|
|
|
* We can share a local filesystem object, as it has no private atts.
|
|
|
|
*/
|
2007-12-28 21:10:17 +00:00
|
|
|
IsoFilesystem *lfs= NULL;
|
2007-12-02 16:59:36 +00:00
|
|
|
|
2011-02-01 18:16:45 +00:00
|
|
|
/* IMPORTANT: Any change must be reflected by lfs_clone_src() */
|
2007-11-25 15:46:21 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
2008-01-11 18:48:52 +00:00
|
|
|
/** reference to the parent (if root it points to itself) */
|
|
|
|
IsoFileSource *parent;
|
|
|
|
char *name;
|
2019-10-28 14:56:58 +00:00
|
|
|
unsigned int openned :2; /* 0: not opened, 1: file, 2:dir */
|
2007-12-28 21:10:17 +00:00
|
|
|
union
|
|
|
|
{
|
2007-11-25 15:46:21 +00:00
|
|
|
int fd;
|
|
|
|
DIR *dir;
|
|
|
|
} info;
|
|
|
|
} _LocalFsFileSource;
|
|
|
|
|
|
|
|
static
|
2007-12-31 15:27:08 +00:00
|
|
|
char* lfs_get_path(IsoFileSource *src)
|
2007-11-25 15:46:21 +00:00
|
|
|
{
|
|
|
|
_LocalFsFileSource *data;
|
|
|
|
data = src->data;
|
2008-01-11 18:48:52 +00:00
|
|
|
|
|
|
|
if (data->parent == src) {
|
|
|
|
return strdup("/");
|
|
|
|
} else {
|
2010-09-01 08:45:10 +00:00
|
|
|
char *path, *new_path;
|
|
|
|
int pathlen;
|
|
|
|
|
|
|
|
path = lfs_get_path(data->parent);
|
|
|
|
if (path == NULL)
|
|
|
|
return NULL;
|
|
|
|
pathlen = strlen(path);
|
|
|
|
new_path = realloc(path, pathlen + strlen(data->name) + 2);
|
|
|
|
if (new_path == NULL) {
|
|
|
|
free(path);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
path= new_path;
|
2008-01-11 18:48:52 +00:00
|
|
|
if (pathlen != 1) {
|
|
|
|
/* pathlen can only be 1 for root */
|
|
|
|
path[pathlen] = '/';
|
|
|
|
path[pathlen + 1] = '\0';
|
|
|
|
}
|
|
|
|
return strcat(path, data->name);
|
|
|
|
}
|
2007-11-25 15:46:21 +00:00
|
|
|
}
|
|
|
|
|
2007-11-26 20:16:38 +00:00
|
|
|
static
|
|
|
|
char* lfs_get_name(IsoFileSource *src)
|
|
|
|
{
|
|
|
|
_LocalFsFileSource *data;
|
|
|
|
data = src->data;
|
2008-01-11 18:48:52 +00:00
|
|
|
return strdup(data->name);
|
2007-11-26 20:16:38 +00:00
|
|
|
}
|
2007-12-28 21:10:17 +00:00
|
|
|
|
2007-11-25 15:46:21 +00:00
|
|
|
static
|
|
|
|
int lfs_lstat(IsoFileSource *src, struct stat *info)
|
|
|
|
{
|
2008-01-11 18:48:52 +00:00
|
|
|
char *path;
|
2007-11-25 15:46:21 +00:00
|
|
|
|
|
|
|
if (src == NULL || info == NULL) {
|
|
|
|
return ISO_NULL_POINTER;
|
|
|
|
}
|
2008-01-11 18:48:52 +00:00
|
|
|
path = lfs_get_path(src);
|
2011-05-22 18:23:48 +00:00
|
|
|
if (path == NULL)
|
|
|
|
return ISO_OUT_OF_MEM;
|
2007-11-25 15:46:21 +00:00
|
|
|
|
2008-01-11 18:48:52 +00:00
|
|
|
if (lstat(path, info) != 0) {
|
2007-11-25 15:46:21 +00:00
|
|
|
int err;
|
|
|
|
|
|
|
|
/* error, choose an appropriate return code */
|
2007-12-28 21:10:17 +00:00
|
|
|
switch (errno) {
|
2007-11-25 15:46:21 +00:00
|
|
|
case EACCES:
|
|
|
|
err = ISO_FILE_ACCESS_DENIED;
|
|
|
|
break;
|
|
|
|
case ENOTDIR:
|
|
|
|
case ENAMETOOLONG:
|
|
|
|
case ELOOP:
|
|
|
|
err = ISO_FILE_BAD_PATH;
|
|
|
|
break;
|
|
|
|
case ENOENT:
|
|
|
|
err = ISO_FILE_DOESNT_EXIST;
|
|
|
|
break;
|
|
|
|
case EFAULT:
|
|
|
|
case ENOMEM:
|
2008-01-20 21:28:27 +00:00
|
|
|
err = ISO_OUT_OF_MEM;
|
2007-11-25 15:46:21 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
err = ISO_FILE_ERROR;
|
|
|
|
break;
|
|
|
|
}
|
2011-05-22 18:23:48 +00:00
|
|
|
free(path);
|
2007-11-25 15:46:21 +00:00
|
|
|
return err;
|
|
|
|
}
|
2008-01-11 18:48:52 +00:00
|
|
|
free(path);
|
2007-11-25 15:46:21 +00:00
|
|
|
return ISO_SUCCESS;
|
|
|
|
}
|
2007-12-28 21:10:17 +00:00
|
|
|
|
2007-12-02 21:03:29 +00:00
|
|
|
static
|
|
|
|
int lfs_stat(IsoFileSource *src, struct stat *info)
|
|
|
|
{
|
2008-01-11 18:48:52 +00:00
|
|
|
char *path;
|
2007-12-02 21:03:29 +00:00
|
|
|
|
|
|
|
if (src == NULL || info == NULL) {
|
|
|
|
return ISO_NULL_POINTER;
|
|
|
|
}
|
2008-01-11 18:48:52 +00:00
|
|
|
path = lfs_get_path(src);
|
2011-05-22 18:23:48 +00:00
|
|
|
if (path == NULL)
|
|
|
|
return ISO_OUT_OF_MEM;
|
2007-12-02 21:03:29 +00:00
|
|
|
|
2008-01-11 18:48:52 +00:00
|
|
|
if (stat(path, info) != 0) {
|
2007-12-02 21:03:29 +00:00
|
|
|
int err;
|
|
|
|
|
|
|
|
/* error, choose an appropriate return code */
|
2007-12-28 21:10:17 +00:00
|
|
|
switch (errno) {
|
2007-12-02 21:03:29 +00:00
|
|
|
case EACCES:
|
|
|
|
err = ISO_FILE_ACCESS_DENIED;
|
|
|
|
break;
|
|
|
|
case ENOTDIR:
|
|
|
|
case ENAMETOOLONG:
|
|
|
|
case ELOOP:
|
|
|
|
err = ISO_FILE_BAD_PATH;
|
|
|
|
break;
|
|
|
|
case ENOENT:
|
|
|
|
err = ISO_FILE_DOESNT_EXIST;
|
|
|
|
break;
|
|
|
|
case EFAULT:
|
|
|
|
case ENOMEM:
|
2008-01-20 21:28:27 +00:00
|
|
|
err = ISO_OUT_OF_MEM;
|
2007-12-02 21:03:29 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
err = ISO_FILE_ERROR;
|
|
|
|
break;
|
|
|
|
}
|
2011-05-22 18:23:48 +00:00
|
|
|
free(path);
|
2007-12-02 21:03:29 +00:00
|
|
|
return err;
|
|
|
|
}
|
2008-01-11 18:48:52 +00:00
|
|
|
free(path);
|
2007-12-02 21:03:29 +00:00
|
|
|
return ISO_SUCCESS;
|
|
|
|
}
|
2007-11-25 15:46:21 +00:00
|
|
|
|
2007-12-29 15:30:13 +00:00
|
|
|
static
|
|
|
|
int lfs_access(IsoFileSource *src)
|
|
|
|
{
|
2008-01-11 18:48:52 +00:00
|
|
|
int ret;
|
|
|
|
char *path;
|
2007-12-29 15:30:13 +00:00
|
|
|
|
|
|
|
if (src == NULL) {
|
|
|
|
return ISO_NULL_POINTER;
|
|
|
|
}
|
2008-01-11 18:48:52 +00:00
|
|
|
path = lfs_get_path(src);
|
2007-12-29 15:30:13 +00:00
|
|
|
|
2008-01-11 18:48:52 +00:00
|
|
|
ret = iso_eaccess(path);
|
|
|
|
free(path);
|
|
|
|
return ret;
|
2007-12-29 15:30:13 +00:00
|
|
|
}
|
|
|
|
|
2007-11-25 15:46:21 +00:00
|
|
|
static
|
|
|
|
int lfs_open(IsoFileSource *src)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
struct stat info;
|
|
|
|
_LocalFsFileSource *data;
|
2008-01-11 18:48:52 +00:00
|
|
|
char *path;
|
2007-11-25 15:46:21 +00:00
|
|
|
|
|
|
|
if (src == NULL) {
|
|
|
|
return ISO_NULL_POINTER;
|
|
|
|
}
|
|
|
|
|
|
|
|
data = src->data;
|
|
|
|
if (data->openned) {
|
2008-03-01 16:12:44 +00:00
|
|
|
return ISO_FILE_ALREADY_OPENED;
|
2007-11-25 15:46:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* is a file or a dir ? */
|
2007-12-15 16:12:21 +00:00
|
|
|
err = lfs_stat(src, &info);
|
2007-11-25 15:46:21 +00:00
|
|
|
if (err < 0) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2008-01-11 18:48:52 +00:00
|
|
|
path = lfs_get_path(src);
|
2007-11-25 15:46:21 +00:00
|
|
|
if (S_ISDIR(info.st_mode)) {
|
2008-01-11 18:48:52 +00:00
|
|
|
data->info.dir = opendir(path);
|
2007-11-25 15:46:21 +00:00
|
|
|
data->openned = data->info.dir ? 2 : 0;
|
|
|
|
} else {
|
2014-11-26 13:44:43 +00:00
|
|
|
data->info.fd = open(path, O_RDONLY | O_BINARY);
|
2007-11-25 15:46:21 +00:00
|
|
|
data->openned = data->info.fd != -1 ? 1 : 0;
|
|
|
|
}
|
2008-01-11 18:48:52 +00:00
|
|
|
free(path);
|
2007-11-25 15:46:21 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* check for possible errors, note that many of possible ones are
|
|
|
|
* parsed in the lstat call above
|
|
|
|
*/
|
|
|
|
if (data->openned == 0) {
|
2007-12-28 21:10:17 +00:00
|
|
|
switch (errno) {
|
2007-11-25 15:46:21 +00:00
|
|
|
case EACCES:
|
|
|
|
err = ISO_FILE_ACCESS_DENIED;
|
|
|
|
break;
|
|
|
|
case EFAULT:
|
|
|
|
case ENOMEM:
|
2008-01-20 21:28:27 +00:00
|
|
|
err = ISO_OUT_OF_MEM;
|
2007-11-25 15:46:21 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
err = ISO_FILE_ERROR;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ISO_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
int lfs_close(IsoFileSource *src)
|
|
|
|
{
|
2007-11-26 20:46:26 +00:00
|
|
|
int ret;
|
2007-11-25 15:46:21 +00:00
|
|
|
_LocalFsFileSource *data;
|
|
|
|
|
|
|
|
if (src == NULL) {
|
|
|
|
return ISO_NULL_POINTER;
|
|
|
|
}
|
|
|
|
|
|
|
|
data = src->data;
|
2007-12-28 21:10:17 +00:00
|
|
|
switch (data->openned) {
|
2007-11-25 15:46:21 +00:00
|
|
|
case 1: /* not dir */
|
2007-11-26 20:46:26 +00:00
|
|
|
ret = close(data->info.fd) == 0 ? ISO_SUCCESS : ISO_FILE_ERROR;
|
|
|
|
break;
|
2007-11-25 15:46:21 +00:00
|
|
|
case 2: /* directory */
|
2007-11-26 20:46:26 +00:00
|
|
|
ret = closedir(data->info.dir) == 0 ? ISO_SUCCESS : ISO_FILE_ERROR;
|
|
|
|
break;
|
2007-11-25 15:46:21 +00:00
|
|
|
default:
|
2008-03-01 16:12:44 +00:00
|
|
|
ret = ISO_FILE_NOT_OPENED;
|
2007-11-26 20:46:26 +00:00
|
|
|
break;
|
2007-11-25 15:46:21 +00:00
|
|
|
}
|
2007-11-26 20:46:26 +00:00
|
|
|
if (ret == ISO_SUCCESS) {
|
|
|
|
data->openned = 0;
|
|
|
|
}
|
|
|
|
return ret;
|
2007-11-25 15:46:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
int lfs_read(IsoFileSource *src, void *buf, size_t count)
|
|
|
|
{
|
|
|
|
_LocalFsFileSource *data;
|
2014-11-20 12:15:35 +00:00
|
|
|
size_t to_read, done = 0;
|
|
|
|
int ret;
|
|
|
|
uint8_t *buf8;
|
2007-11-25 15:46:21 +00:00
|
|
|
|
|
|
|
if (src == NULL || buf == NULL) {
|
|
|
|
return ISO_NULL_POINTER;
|
|
|
|
}
|
2008-01-02 23:56:11 +00:00
|
|
|
if (count == 0) {
|
|
|
|
return ISO_WRONG_ARG_VALUE;
|
|
|
|
}
|
2007-11-25 15:46:21 +00:00
|
|
|
|
|
|
|
data = src->data;
|
2007-12-28 21:10:17 +00:00
|
|
|
switch (data->openned) {
|
2007-11-25 15:46:21 +00:00
|
|
|
case 1: /* not dir */
|
2014-11-20 12:15:35 +00:00
|
|
|
buf8 = (uint8_t *) buf; /* for pointer arithmetic */
|
|
|
|
for (to_read = count; to_read > 0; to_read = count - done) {
|
|
|
|
if (to_read > 1024 * 1024)
|
|
|
|
to_read = 1024 * 1024;
|
|
|
|
ret = read(data->info.fd, buf8 + done, to_read);
|
2007-11-25 15:46:21 +00:00
|
|
|
if (ret < 0) {
|
|
|
|
/* error on read */
|
2007-12-28 21:10:17 +00:00
|
|
|
switch (errno) {
|
2007-11-25 15:46:21 +00:00
|
|
|
case EINTR:
|
2014-11-20 12:15:35 +00:00
|
|
|
return ISO_INTERRUPTED;
|
2007-11-25 15:46:21 +00:00
|
|
|
case EFAULT:
|
2014-11-20 12:15:35 +00:00
|
|
|
return ISO_OUT_OF_MEM;
|
2007-11-25 15:46:21 +00:00
|
|
|
case EIO:
|
2014-11-20 12:15:35 +00:00
|
|
|
return ISO_FILE_READ_ERROR;
|
2007-11-25 15:46:21 +00:00
|
|
|
}
|
2014-11-20 12:15:35 +00:00
|
|
|
return ISO_FILE_ERROR;
|
2007-11-25 15:46:21 +00:00
|
|
|
}
|
2014-11-20 12:15:35 +00:00
|
|
|
if (ret == 0) /* EOF */
|
|
|
|
break;
|
|
|
|
done += ret;
|
2007-11-25 15:46:21 +00:00
|
|
|
}
|
2014-11-20 12:15:35 +00:00
|
|
|
return done;
|
2007-11-25 15:46:21 +00:00
|
|
|
case 2: /* directory */
|
|
|
|
return ISO_FILE_IS_DIR;
|
|
|
|
default:
|
2008-03-01 16:12:44 +00:00
|
|
|
return ISO_FILE_NOT_OPENED;
|
2007-11-25 15:46:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-03-08 17:34:41 +00:00
|
|
|
static
|
|
|
|
off_t lfs_lseek(IsoFileSource *src, off_t offset, int flag)
|
|
|
|
{
|
|
|
|
_LocalFsFileSource *data;
|
|
|
|
int whence;
|
|
|
|
|
|
|
|
if (src == NULL) {
|
2022-04-26 10:03:53 +00:00
|
|
|
return (off_t)((int) ISO_NULL_POINTER);
|
2008-03-08 17:34:41 +00:00
|
|
|
}
|
|
|
|
switch (flag) {
|
|
|
|
case 0:
|
|
|
|
whence = SEEK_SET; break;
|
|
|
|
case 1:
|
|
|
|
whence = SEEK_CUR; break;
|
|
|
|
case 2:
|
|
|
|
whence = SEEK_END; break;
|
|
|
|
default:
|
2022-04-26 10:03:53 +00:00
|
|
|
return (off_t)((int) ISO_WRONG_ARG_VALUE);
|
2008-03-08 17:34:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
data = src->data;
|
|
|
|
switch (data->openned) {
|
|
|
|
case 1: /* not dir */
|
|
|
|
{
|
|
|
|
off_t ret;
|
|
|
|
ret = lseek(data->info.fd, offset, whence);
|
|
|
|
if (ret < 0) {
|
|
|
|
/* error on read */
|
|
|
|
switch (errno) {
|
|
|
|
case ESPIPE:
|
2022-04-26 10:03:53 +00:00
|
|
|
ret = (off_t)((int) ISO_FILE_ERROR);
|
2008-03-08 17:34:41 +00:00
|
|
|
break;
|
|
|
|
default:
|
2022-04-26 10:03:53 +00:00
|
|
|
ret = (off_t)((int) ISO_ERROR);
|
2008-03-08 17:34:41 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
case 2: /* directory */
|
2022-04-26 10:03:53 +00:00
|
|
|
return (off_t)((int) ISO_FILE_IS_DIR);
|
2008-03-08 17:34:41 +00:00
|
|
|
default:
|
2022-04-26 10:03:53 +00:00
|
|
|
return (off_t)((int) ISO_FILE_NOT_OPENED);
|
2008-03-08 17:34:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-11-25 15:46:21 +00:00
|
|
|
static
|
|
|
|
int lfs_readdir(IsoFileSource *src, IsoFileSource **child)
|
|
|
|
{
|
|
|
|
_LocalFsFileSource *data;
|
|
|
|
|
|
|
|
if (src == NULL || child == NULL) {
|
|
|
|
return ISO_NULL_POINTER;
|
|
|
|
}
|
|
|
|
|
|
|
|
data = src->data;
|
2007-12-28 21:10:17 +00:00
|
|
|
switch (data->openned) {
|
2007-11-25 15:46:21 +00:00
|
|
|
case 1: /* not dir */
|
|
|
|
return ISO_FILE_IS_NOT_DIR;
|
|
|
|
case 2: /* directory */
|
|
|
|
{
|
|
|
|
struct dirent *entry;
|
|
|
|
int ret;
|
|
|
|
|
2007-12-11 21:41:18 +00:00
|
|
|
/* while to skip "." and ".." dirs */
|
|
|
|
while (1) {
|
|
|
|
entry = readdir(data->info.dir);
|
|
|
|
if (entry == NULL) {
|
|
|
|
if (errno == EBADF)
|
|
|
|
return ISO_FILE_ERROR;
|
|
|
|
else
|
|
|
|
return 0; /* EOF */
|
|
|
|
}
|
2007-12-28 21:10:17 +00:00
|
|
|
if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")) {
|
2007-12-11 21:41:18 +00:00
|
|
|
break;
|
|
|
|
}
|
2007-11-25 15:46:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* create the new FileSrc */
|
2008-01-11 18:48:52 +00:00
|
|
|
ret = iso_file_source_new_lfs(src, entry->d_name, child);
|
2007-11-25 15:46:21 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
default:
|
2008-03-01 16:12:44 +00:00
|
|
|
return ISO_FILE_NOT_OPENED;
|
2007-11-25 15:46:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
int lfs_readlink(IsoFileSource *src, char *buf, size_t bufsiz)
|
|
|
|
{
|
2011-04-03 09:02:15 +00:00
|
|
|
int size, ret;
|
2008-01-11 18:48:52 +00:00
|
|
|
char *path;
|
2007-11-25 15:46:21 +00:00
|
|
|
|
|
|
|
if (src == NULL || buf == NULL) {
|
|
|
|
return ISO_NULL_POINTER;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bufsiz <= 0) {
|
|
|
|
return ISO_WRONG_ARG_VALUE;
|
|
|
|
}
|
|
|
|
|
2008-01-11 18:48:52 +00:00
|
|
|
path = lfs_get_path(src);
|
2007-11-25 15:46:21 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* invoke readlink, with bufsiz -1 to reserve an space for
|
|
|
|
* the NULL character
|
|
|
|
*/
|
2011-04-03 09:02:15 +00:00
|
|
|
size = readlink(path, buf, bufsiz);
|
2008-01-11 18:48:52 +00:00
|
|
|
free(path);
|
2007-11-25 15:46:21 +00:00
|
|
|
if (size < 0) {
|
|
|
|
/* error */
|
2007-12-28 21:10:17 +00:00
|
|
|
switch (errno) {
|
2007-11-25 15:46:21 +00:00
|
|
|
case EACCES:
|
|
|
|
return ISO_FILE_ACCESS_DENIED;
|
|
|
|
case ENOTDIR:
|
|
|
|
case ENAMETOOLONG:
|
|
|
|
case ELOOP:
|
|
|
|
return ISO_FILE_BAD_PATH;
|
|
|
|
case ENOENT:
|
|
|
|
return ISO_FILE_DOESNT_EXIST;
|
|
|
|
case EINVAL:
|
|
|
|
return ISO_FILE_IS_NOT_SYMLINK;
|
|
|
|
case EFAULT:
|
|
|
|
case ENOMEM:
|
2008-01-20 21:28:27 +00:00
|
|
|
return ISO_OUT_OF_MEM;
|
2007-11-25 15:46:21 +00:00
|
|
|
default:
|
|
|
|
return ISO_FILE_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* NULL-terminate the buf */
|
2011-04-03 09:02:15 +00:00
|
|
|
ret = ISO_SUCCESS;
|
2011-05-21 21:13:40 +00:00
|
|
|
if ((size_t) size >= bufsiz) {
|
2011-04-03 09:02:15 +00:00
|
|
|
ret = ISO_RR_PATH_TOO_LONG;
|
|
|
|
size = bufsiz - 1;
|
|
|
|
}
|
2007-11-25 15:46:21 +00:00
|
|
|
buf[size] = '\0';
|
2011-04-03 09:02:15 +00:00
|
|
|
return ret;
|
2007-11-25 15:46:21 +00:00
|
|
|
}
|
|
|
|
|
2007-12-02 16:59:36 +00:00
|
|
|
static
|
|
|
|
IsoFilesystem* lfs_get_filesystem(IsoFileSource *src)
|
|
|
|
{
|
|
|
|
return src == NULL ? NULL : lfs;
|
|
|
|
}
|
|
|
|
|
2007-11-25 15:46:21 +00:00
|
|
|
static
|
|
|
|
void lfs_free(IsoFileSource *src)
|
|
|
|
{
|
|
|
|
_LocalFsFileSource *data;
|
|
|
|
|
|
|
|
data = src->data;
|
|
|
|
|
2019-10-28 14:56:58 +00:00
|
|
|
/* close the file if it is already opened */
|
2007-11-25 15:46:21 +00:00
|
|
|
if (data->openned) {
|
2007-12-20 19:47:39 +00:00
|
|
|
src->class->close(src);
|
2007-11-25 15:46:21 +00:00
|
|
|
}
|
2008-01-11 18:48:52 +00:00
|
|
|
if (data->parent != src) {
|
|
|
|
iso_file_source_unref(data->parent);
|
|
|
|
}
|
|
|
|
free(data->name);
|
2007-11-25 15:46:21 +00:00
|
|
|
free(data);
|
2007-12-02 16:59:36 +00:00
|
|
|
iso_filesystem_unref(lfs);
|
2007-11-25 15:46:21 +00:00
|
|
|
}
|
|
|
|
|
2009-01-16 12:24:30 +00:00
|
|
|
|
|
|
|
static
|
|
|
|
int lfs_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag)
|
|
|
|
{
|
2017-10-23 08:36:10 +00:00
|
|
|
int ret, no_non_user_perm= 0;
|
2015-10-15 06:38:56 +00:00
|
|
|
size_t num_attrs = 0, *value_lengths = NULL, result_len;
|
|
|
|
ssize_t sret;
|
2009-01-16 12:24:30 +00:00
|
|
|
char *path = NULL, **names = NULL, **values = NULL;
|
|
|
|
unsigned char *result = NULL;
|
|
|
|
|
|
|
|
*aa_string = NULL;
|
2009-01-23 08:32:32 +00:00
|
|
|
|
2024-07-16 13:05:11 +00:00
|
|
|
if ((flag & (2 | 4 | 16) ) == (2 | 4)) {
|
|
|
|
/* Neither ACL nor xattr shall be read, lfa_flags are not wanted */
|
2009-01-23 08:32:32 +00:00
|
|
|
ret = 1;
|
|
|
|
goto ex;
|
|
|
|
}
|
2009-01-16 12:24:30 +00:00
|
|
|
/* Obtain EAs and ACLs ("access" and "default"). ACLs encoded according
|
2009-01-18 17:39:06 +00:00
|
|
|
to AAIP ACL representation. Clean out st_mode ACL entries.
|
2024-07-16 13:05:11 +00:00
|
|
|
Obtain Linux style attribute flags.
|
2009-01-16 12:24:30 +00:00
|
|
|
*/
|
|
|
|
path = iso_file_source_get_path(src);
|
2011-06-01 09:37:30 +00:00
|
|
|
if (path == NULL) {
|
|
|
|
ret = ISO_NULL_POINTER;
|
|
|
|
goto ex;
|
|
|
|
}
|
2009-01-16 12:24:30 +00:00
|
|
|
ret = aaip_get_attr_list(path, &num_attrs, &names,
|
2009-01-23 08:32:32 +00:00
|
|
|
&value_lengths, &values,
|
2024-07-16 13:05:11 +00:00
|
|
|
(!(flag & 2)) | 2 | (flag & 4) | (flag & 8) | 16 |
|
|
|
|
((!(flag & 16)) << 6));
|
2009-01-16 12:24:30 +00:00
|
|
|
if (ret <= 0) {
|
2011-08-18 08:26:09 +00:00
|
|
|
if (ret == -2)
|
|
|
|
ret = ISO_AAIP_NO_GET_LOCAL;
|
|
|
|
else
|
|
|
|
ret = ISO_FILE_ERROR;
|
2009-01-16 12:24:30 +00:00
|
|
|
goto ex;
|
|
|
|
}
|
2017-10-23 08:36:10 +00:00
|
|
|
if(ret == 2)
|
|
|
|
no_non_user_perm= 1;
|
|
|
|
|
2009-01-23 12:17:22 +00:00
|
|
|
if (num_attrs == 0)
|
|
|
|
result = NULL;
|
|
|
|
else {
|
2009-01-30 17:58:11 +00:00
|
|
|
sret = aaip_encode(num_attrs, names,
|
2009-01-23 12:17:22 +00:00
|
|
|
value_lengths, values, &result_len, &result, 0);
|
2015-10-15 06:38:56 +00:00
|
|
|
if (sret < 0) {
|
|
|
|
ret = sret;
|
2009-01-23 12:17:22 +00:00
|
|
|
goto ex;
|
2015-10-15 06:38:56 +00:00
|
|
|
}
|
2009-01-16 12:24:30 +00:00
|
|
|
}
|
|
|
|
*aa_string = result;
|
2017-10-23 08:36:10 +00:00
|
|
|
ret = 1 + no_non_user_perm;
|
2009-01-16 12:24:30 +00:00
|
|
|
ex:;
|
|
|
|
if (path != NULL)
|
|
|
|
free(path);
|
|
|
|
if (names != NULL || value_lengths != NULL || values != NULL)
|
2015-10-15 09:53:56 +00:00
|
|
|
aaip_get_attr_list(NULL, &num_attrs, &names, &value_lengths, &values,
|
2009-01-16 12:24:30 +00:00
|
|
|
1 << 15); /* free memory */
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-02-01 18:16:45 +00:00
|
|
|
static
|
|
|
|
int lfs_clone_src(IsoFileSource *old_source,
|
|
|
|
IsoFileSource **new_source, int flag)
|
|
|
|
{
|
|
|
|
IsoFileSource *src = NULL;
|
|
|
|
char *new_name = NULL;
|
|
|
|
_LocalFsFileSource *old_data, *new_data = NULL;
|
|
|
|
|
|
|
|
if (flag)
|
|
|
|
return ISO_STREAM_NO_CLONE; /* unknown option required */
|
|
|
|
|
|
|
|
old_data = (_LocalFsFileSource *) old_source->data;
|
|
|
|
*new_source = NULL;
|
|
|
|
src = calloc(1, sizeof(IsoFileSource));
|
|
|
|
if (src == NULL)
|
|
|
|
goto no_mem;
|
|
|
|
new_name = strdup(old_data->name);
|
|
|
|
if (new_name == NULL)
|
|
|
|
goto no_mem;
|
|
|
|
|
|
|
|
new_data = calloc(1, sizeof(_LocalFsFileSource));
|
|
|
|
if (new_data == NULL)
|
|
|
|
goto no_mem;
|
|
|
|
new_data->openned = 0;
|
|
|
|
new_data->info.fd = -1; /* the value does not matter with (openned == 0) */
|
|
|
|
new_data->name = new_name;
|
|
|
|
new_data->parent = old_data->parent;
|
|
|
|
|
|
|
|
src->class = old_source->class;
|
|
|
|
src->refcount = 1;
|
|
|
|
src->data = new_data;
|
|
|
|
*new_source = src;
|
2011-02-01 21:16:05 +00:00
|
|
|
|
|
|
|
iso_file_source_ref(new_data->parent);
|
|
|
|
iso_filesystem_ref(lfs);
|
2011-02-01 18:16:45 +00:00
|
|
|
return ISO_SUCCESS;
|
|
|
|
no_mem:;
|
|
|
|
if (src != NULL)
|
|
|
|
free((char *) src);
|
|
|
|
if (new_data != NULL)
|
|
|
|
free((char *) new_data);
|
|
|
|
if (new_name != NULL)
|
|
|
|
free(new_name);
|
|
|
|
return ISO_OUT_OF_MEM;
|
|
|
|
}
|
|
|
|
|
2009-01-16 12:24:30 +00:00
|
|
|
|
2007-12-28 21:10:17 +00:00
|
|
|
IsoFileSourceIface lfs_class = {
|
2009-01-16 12:24:30 +00:00
|
|
|
|
2011-02-01 18:16:45 +00:00
|
|
|
2, /* version */
|
2007-12-20 19:47:39 +00:00
|
|
|
lfs_get_path,
|
|
|
|
lfs_get_name,
|
|
|
|
lfs_lstat,
|
|
|
|
lfs_stat,
|
2007-12-29 15:30:13 +00:00
|
|
|
lfs_access,
|
2007-12-20 19:47:39 +00:00
|
|
|
lfs_open,
|
|
|
|
lfs_close,
|
|
|
|
lfs_read,
|
|
|
|
lfs_readdir,
|
|
|
|
lfs_readlink,
|
|
|
|
lfs_get_filesystem,
|
2008-03-08 20:48:03 +00:00
|
|
|
lfs_free,
|
2009-02-18 22:01:14 +00:00
|
|
|
lfs_lseek,
|
2011-02-01 18:16:45 +00:00
|
|
|
lfs_get_aa_string,
|
|
|
|
lfs_clone_src
|
2009-01-16 12:24:30 +00:00
|
|
|
|
2007-12-20 19:47:39 +00:00
|
|
|
};
|
|
|
|
|
2009-01-16 12:24:30 +00:00
|
|
|
|
2007-11-25 15:46:21 +00:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @return
|
|
|
|
* 1 success, < 0 error
|
|
|
|
*/
|
2007-12-31 15:29:47 +00:00
|
|
|
static
|
2008-01-11 18:48:52 +00:00
|
|
|
int iso_file_source_new_lfs(IsoFileSource *parent, const char *name,
|
|
|
|
IsoFileSource **src)
|
2007-11-25 15:46:21 +00:00
|
|
|
{
|
|
|
|
IsoFileSource *lfs_src;
|
|
|
|
_LocalFsFileSource *data;
|
|
|
|
|
|
|
|
if (src == NULL) {
|
|
|
|
return ISO_NULL_POINTER;
|
|
|
|
}
|
|
|
|
|
2007-12-02 16:59:36 +00:00
|
|
|
if (lfs == NULL) {
|
|
|
|
/* this should never happen */
|
2008-01-20 21:28:27 +00:00
|
|
|
return ISO_ASSERT_FAILURE;
|
2007-12-02 16:59:36 +00:00
|
|
|
}
|
|
|
|
|
2007-11-25 15:46:21 +00:00
|
|
|
/* allocate memory */
|
|
|
|
data = malloc(sizeof(_LocalFsFileSource));
|
|
|
|
if (data == NULL) {
|
|
|
|
return ISO_OUT_OF_MEM;
|
|
|
|
}
|
|
|
|
lfs_src = malloc(sizeof(IsoFileSource));
|
|
|
|
if (lfs_src == NULL) {
|
|
|
|
free(data);
|
|
|
|
return ISO_OUT_OF_MEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* fill struct */
|
2008-01-11 18:48:52 +00:00
|
|
|
data->name = name ? strdup(name) : NULL;
|
2007-11-25 15:46:21 +00:00
|
|
|
data->openned = 0;
|
2008-01-11 18:48:52 +00:00
|
|
|
if (parent) {
|
|
|
|
data->parent = parent;
|
|
|
|
iso_file_source_ref(parent);
|
|
|
|
} else {
|
|
|
|
data->parent = lfs_src;
|
|
|
|
}
|
2007-11-25 15:46:21 +00:00
|
|
|
|
|
|
|
lfs_src->refcount = 1;
|
|
|
|
lfs_src->data = data;
|
2007-12-20 19:47:39 +00:00
|
|
|
lfs_src->class = &lfs_class;
|
2007-12-28 21:10:17 +00:00
|
|
|
|
2007-12-02 16:59:36 +00:00
|
|
|
/* take a ref to local filesystem */
|
|
|
|
iso_filesystem_ref(lfs);
|
2007-11-25 15:46:21 +00:00
|
|
|
|
|
|
|
/* return */
|
|
|
|
*src = lfs_src;
|
|
|
|
return ISO_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2007-11-25 18:54:13 +00:00
|
|
|
static
|
|
|
|
int lfs_get_root(IsoFilesystem *fs, IsoFileSource **root)
|
|
|
|
{
|
2007-12-28 21:10:17 +00:00
|
|
|
if (fs == NULL || root == NULL) {
|
2007-11-25 18:54:13 +00:00
|
|
|
return ISO_NULL_POINTER;
|
|
|
|
}
|
2008-01-11 18:48:52 +00:00
|
|
|
return iso_file_source_new_lfs(NULL, NULL, root);
|
2007-11-25 18:54:13 +00:00
|
|
|
}
|
2007-11-24 12:14:45 +00:00
|
|
|
|
2007-11-25 18:54:13 +00:00
|
|
|
static
|
|
|
|
int lfs_get_by_path(IsoFilesystem *fs, const char *path, IsoFileSource **file)
|
|
|
|
{
|
2008-01-11 18:48:52 +00:00
|
|
|
int ret;
|
|
|
|
IsoFileSource *src;
|
|
|
|
struct stat info;
|
|
|
|
char *ptr, *brk_info, *component;
|
|
|
|
|
2007-12-28 21:10:17 +00:00
|
|
|
if (fs == NULL || path == NULL || file == NULL) {
|
2007-11-25 18:54:13 +00:00
|
|
|
return ISO_NULL_POINTER;
|
|
|
|
}
|
2008-01-11 18:48:52 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* first of all check that it is a valid path.
|
|
|
|
*/
|
|
|
|
if (lstat(path, &info) != 0) {
|
|
|
|
int err;
|
|
|
|
|
|
|
|
/* error, choose an appropriate return code */
|
|
|
|
switch (errno) {
|
|
|
|
case EACCES:
|
|
|
|
err = ISO_FILE_ACCESS_DENIED;
|
|
|
|
break;
|
|
|
|
case ENOTDIR:
|
|
|
|
case ENAMETOOLONG:
|
|
|
|
case ELOOP:
|
|
|
|
err = ISO_FILE_BAD_PATH;
|
|
|
|
break;
|
|
|
|
case ENOENT:
|
|
|
|
err = ISO_FILE_DOESNT_EXIST;
|
|
|
|
break;
|
|
|
|
case EFAULT:
|
|
|
|
case ENOMEM:
|
2008-01-20 21:28:27 +00:00
|
|
|
err = ISO_OUT_OF_MEM;
|
2008-01-11 18:48:52 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
err = ISO_FILE_ERROR;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ok, path is valid. create the file source */
|
|
|
|
ret = lfs_get_root(fs, &src);
|
|
|
|
if (ret < 0) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
if (!strcmp(path, "/")) {
|
|
|
|
/* we are looking for root */
|
|
|
|
*file = src;
|
|
|
|
return ISO_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
ptr = strdup(path);
|
|
|
|
if (ptr == NULL) {
|
|
|
|
iso_file_source_unref(src);
|
2008-01-20 21:28:27 +00:00
|
|
|
return ISO_OUT_OF_MEM;
|
2008-01-11 18:48:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
component = strtok_r(ptr, "/", &brk_info);
|
|
|
|
while (component) {
|
|
|
|
IsoFileSource *child = NULL;
|
|
|
|
if (!strcmp(component, ".")) {
|
|
|
|
child = src;
|
|
|
|
} else if (!strcmp(component, "..")) {
|
|
|
|
child = ((_LocalFsFileSource*)src->data)->parent;
|
|
|
|
iso_file_source_ref(child);
|
|
|
|
iso_file_source_unref(src);
|
|
|
|
} else {
|
|
|
|
ret = iso_file_source_new_lfs(src, component, &child);
|
|
|
|
iso_file_source_unref(src);
|
|
|
|
if (ret < 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
src = child;
|
|
|
|
component = strtok_r(NULL, "/", &brk_info);
|
|
|
|
}
|
|
|
|
|
|
|
|
free(ptr);
|
|
|
|
if (ret > 0) {
|
|
|
|
*file = src;
|
|
|
|
}
|
|
|
|
return ret;
|
2007-11-25 18:54:13 +00:00
|
|
|
}
|
|
|
|
|
2007-12-15 11:51:48 +00:00
|
|
|
static
|
|
|
|
unsigned int lfs_get_id(IsoFilesystem *fs)
|
|
|
|
{
|
|
|
|
return ISO_LOCAL_FS_ID;
|
|
|
|
}
|
|
|
|
|
2008-01-19 15:56:46 +00:00
|
|
|
static
|
|
|
|
int lfs_fs_open(IsoFilesystem *fs)
|
|
|
|
{
|
|
|
|
/* open() operation is not needed */
|
|
|
|
return ISO_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
int lfs_fs_close(IsoFilesystem *fs)
|
|
|
|
{
|
|
|
|
/* close() operation is not needed */
|
|
|
|
return ISO_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2007-11-25 18:54:13 +00:00
|
|
|
static
|
|
|
|
void lfs_fs_free(IsoFilesystem *fs)
|
|
|
|
{
|
2007-12-28 21:10:17 +00:00
|
|
|
lfs = NULL;
|
2007-11-25 18:54:13 +00:00
|
|
|
}
|
2007-12-28 21:10:17 +00:00
|
|
|
|
2007-11-25 18:54:13 +00:00
|
|
|
int iso_local_filesystem_new(IsoFilesystem **fs)
|
|
|
|
{
|
2007-12-28 21:10:17 +00:00
|
|
|
if (fs == NULL) {
|
2007-11-25 18:54:13 +00:00
|
|
|
return ISO_NULL_POINTER;
|
|
|
|
}
|
2007-12-28 21:10:17 +00:00
|
|
|
|
2007-12-02 16:59:36 +00:00
|
|
|
if (lfs != NULL) {
|
|
|
|
/* just take a new ref */
|
|
|
|
iso_filesystem_ref(lfs);
|
|
|
|
} else {
|
2007-12-28 21:10:17 +00:00
|
|
|
|
|
|
|
lfs = malloc(sizeof(IsoFilesystem));
|
2007-12-02 16:59:36 +00:00
|
|
|
if (lfs == NULL) {
|
|
|
|
return ISO_OUT_OF_MEM;
|
|
|
|
}
|
2007-12-28 21:10:17 +00:00
|
|
|
|
2007-12-02 16:59:36 +00:00
|
|
|
/* fill struct */
|
2020-06-13 07:56:31 +00:00
|
|
|
memcpy(lfs->type, "file", 4);
|
2007-12-02 16:59:36 +00:00
|
|
|
lfs->refcount = 1;
|
2008-01-26 12:15:15 +00:00
|
|
|
lfs->version = 0;
|
2007-12-02 16:59:36 +00:00
|
|
|
lfs->data = NULL; /* we don't need private data */
|
|
|
|
lfs->get_root = lfs_get_root;
|
|
|
|
lfs->get_by_path = lfs_get_by_path;
|
2007-12-15 11:51:48 +00:00
|
|
|
lfs->get_id = lfs_get_id;
|
2008-01-19 15:56:46 +00:00
|
|
|
lfs->open = lfs_fs_open;
|
|
|
|
lfs->close = lfs_fs_close;
|
2007-12-02 16:59:36 +00:00
|
|
|
lfs->free = lfs_fs_free;
|
2007-11-25 18:54:13 +00:00
|
|
|
}
|
2007-12-28 21:10:17 +00:00
|
|
|
*fs = lfs;
|
|
|
|
return ISO_SUCCESS;
|
2007-11-25 18:54:13 +00:00
|
|
|
}
|
2009-02-16 07:29:21 +00:00
|
|
|
|
|
|
|
|
2011-08-18 13:07:31 +00:00
|
|
|
int iso_local_attr_support(int flag)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret= aaip_local_attr_support(flag & 255);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-02-16 07:29:21 +00:00
|
|
|
int iso_local_get_acl_text(char *disk_path, char **text, int flag)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = aaip_get_acl_text(disk_path, text, flag & (1 | 16 | 32 | (1 << 15)));
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int iso_local_set_acl_text(char *disk_path, char *text, int flag)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = aaip_set_acl_text(disk_path, text, flag & (1 | 32));
|
|
|
|
if (ret < 0)
|
|
|
|
return ISO_AAIP_NO_SET_LOCAL;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int iso_local_get_attrs(char *disk_path, size_t *num_attrs, char ***names,
|
|
|
|
size_t **value_lengths, char ***values, int flag)
|
|
|
|
{
|
2024-07-16 13:05:11 +00:00
|
|
|
int ret, lfa;
|
2009-02-16 07:29:21 +00:00
|
|
|
|
2024-07-16 13:05:11 +00:00
|
|
|
lfa = (flag & 64) ^ 64;
|
2009-02-16 07:29:21 +00:00
|
|
|
ret = aaip_get_attr_list(disk_path,
|
|
|
|
num_attrs, names, value_lengths, values,
|
2024-07-16 13:05:11 +00:00
|
|
|
(flag & (1 | 4 | 8 | 32 | (1 << 15))) |
|
|
|
|
2 | 16 | lfa);
|
2009-02-16 07:29:21 +00:00
|
|
|
if (ret <= 0)
|
|
|
|
return ISO_AAIP_NO_GET_LOCAL;
|
2017-10-23 08:36:10 +00:00
|
|
|
return 1 + (ret == 2);
|
2009-02-16 07:29:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-23 08:36:10 +00:00
|
|
|
int iso_local_set_attrs_errno(char *disk_path, size_t num_attrs, char **names,
|
|
|
|
size_t *value_lengths, char **values,
|
|
|
|
int *errnos, int flag)
|
2009-02-16 07:29:21 +00:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = aaip_set_attr_list(disk_path, num_attrs, names, value_lengths,
|
2017-10-23 08:36:10 +00:00
|
|
|
values, errnos,
|
|
|
|
(flag & (8 | 32 | 64 | 128)) | !(flag & 1));
|
2009-02-16 07:29:21 +00:00
|
|
|
if (ret <= 0) {
|
|
|
|
if (ret == -1)
|
|
|
|
return ISO_OUT_OF_MEM;
|
|
|
|
if (ret == -2)
|
|
|
|
return ISO_AAIP_BAD_AASTRING;
|
2011-08-24 07:23:02 +00:00
|
|
|
if (ret >= -5)
|
|
|
|
return ISO_AAIP_NO_SET_LOCAL;
|
2011-08-08 06:25:18 +00:00
|
|
|
if (ret == -6 || ret == -7)
|
|
|
|
return ISO_AAIP_NOT_ENABLED;
|
2011-08-22 15:10:13 +00:00
|
|
|
if (ret == -8)
|
|
|
|
return ISO_AAIP_BAD_ATTR_NAME;
|
2011-08-24 07:23:02 +00:00
|
|
|
return ret;
|
2009-02-16 07:29:21 +00:00
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-23 08:36:10 +00:00
|
|
|
int iso_local_set_attrs(char *disk_path, size_t num_attrs, char **names,
|
|
|
|
size_t *value_lengths, char **values, int flag)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
int *errnos = NULL;
|
|
|
|
|
|
|
|
if(num_attrs > 0) {
|
|
|
|
errnos= calloc(num_attrs, sizeof(int));
|
|
|
|
if(errnos == NULL)
|
|
|
|
return ISO_OUT_OF_MEM;
|
|
|
|
}
|
|
|
|
ret= iso_local_set_attrs_errno(disk_path, num_attrs, names, value_lengths,
|
|
|
|
values, errnos, flag);
|
|
|
|
if(errnos != NULL)
|
|
|
|
free(errnos);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-02-16 07:29:21 +00:00
|
|
|
int iso_local_get_perms_wo_acl(char *disk_path, mode_t *st_mode, int flag)
|
|
|
|
{
|
|
|
|
struct stat stbuf;
|
|
|
|
int ret;
|
|
|
|
char *a_text = NULL;
|
|
|
|
|
|
|
|
if (flag & 32)
|
|
|
|
ret = stat(disk_path, &stbuf);
|
|
|
|
else
|
|
|
|
ret = lstat(disk_path, &stbuf);
|
|
|
|
if (ret == -1)
|
|
|
|
return -1;
|
|
|
|
*st_mode = stbuf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
|
|
|
|
ret = iso_local_get_acl_text(disk_path, &a_text, 16 | (flag & 32));
|
|
|
|
if (a_text != NULL) {
|
|
|
|
aaip_cleanout_st_mode(a_text, st_mode, 4 | 16);
|
|
|
|
iso_local_get_acl_text(disk_path, &a_text, 1 << 15); /* free a_text */
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2024-07-16 13:05:11 +00:00
|
|
|
/*
|
|
|
|
* @param flag
|
|
|
|
* Bitfield for control purposes
|
|
|
|
* bit5= in case of symbolic link: inquire link target
|
|
|
|
* @return
|
|
|
|
* 1= ok, lfa_flags is valid
|
|
|
|
* 2= ok, but some local flags could not be mapped to the FS_*_FL bits
|
|
|
|
* 3= ok, symbolic link encountered, flag bit5 not set, lfa_flags set to 0
|
|
|
|
* 0= local flags retrieval not enabled at compile time
|
|
|
|
* <0= error with system calls
|
|
|
|
*/
|
|
|
|
int iso_local_get_lfa_flags(char *disk_path, uint64_t *lfa_flags, int *max_bit,
|
|
|
|
int *os_errno, int flag)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
struct stat stbuf;
|
|
|
|
|
|
|
|
*lfa_flags = 0;
|
|
|
|
*max_bit = -1;
|
|
|
|
*os_errno = 0;
|
|
|
|
if (flag & 32)
|
|
|
|
ret = stat(disk_path, &stbuf);
|
|
|
|
else
|
|
|
|
ret = lstat(disk_path, &stbuf);
|
|
|
|
if (ret == -1) {
|
|
|
|
*os_errno = errno;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if ((stbuf.st_mode & S_IFMT) == S_IFLNK && !(flag & 32))
|
|
|
|
return 3;
|
2024-07-19 20:24:02 +00:00
|
|
|
ret = aaip_get_lfa_flags(disk_path, lfa_flags, max_bit, os_errno, 0);
|
2024-07-16 13:05:11 +00:00
|
|
|
if(ret == 0)
|
|
|
|
return ISO_AAIP_NOT_ENABLED;
|
|
|
|
if (ret < 0)
|
|
|
|
return ISO_AAIP_NO_GET_LOCAL;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @param flag Bitfield for control purposes
|
2024-07-19 20:24:02 +00:00
|
|
|
* bit0= do not try to change known superuser flags
|
|
|
|
* bit1= change only known chattr settable flags
|
2024-07-16 13:05:11 +00:00
|
|
|
* bit5= in case of symbolic link: inquire link target
|
|
|
|
* @return
|
|
|
|
* 1 = ok, all lfa_flags bits were written
|
|
|
|
* 2 = ok, but some FS_*_FL bits could not be mapped to local flags
|
|
|
|
* 3 = ok, symbolic link encountered, flag bit5 not set, nothing done
|
|
|
|
* <0 = error
|
|
|
|
*/
|
|
|
|
int iso_local_set_lfa_flags(char *disk_path, uint64_t lfa_flags, int max_bit,
|
2024-07-19 20:24:02 +00:00
|
|
|
uint64_t change_mask, int *os_errno, int flag)
|
2024-07-16 13:05:11 +00:00
|
|
|
{
|
2024-07-19 20:24:02 +00:00
|
|
|
int ret, old_max_bit;
|
2024-07-16 13:05:11 +00:00
|
|
|
struct stat stbuf;
|
2024-07-19 20:24:02 +00:00
|
|
|
uint64_t known_user_mask, known_su_mask, non_settable, unknown, eff_flags;
|
2024-07-16 13:05:11 +00:00
|
|
|
|
2024-07-19 20:24:02 +00:00
|
|
|
iso_util_get_lfa_masks(&known_user_mask, &known_su_mask, &non_settable,
|
|
|
|
&unknown);
|
2024-07-16 13:05:11 +00:00
|
|
|
*os_errno = 0;
|
|
|
|
if (flag & 32)
|
|
|
|
ret = stat(disk_path, &stbuf);
|
|
|
|
else
|
|
|
|
ret = lstat(disk_path, &stbuf);
|
|
|
|
if (ret == -1) {
|
|
|
|
*os_errno = errno;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if ((stbuf.st_mode & S_IFMT) == S_IFLNK && !(flag & 32))
|
|
|
|
return 3;
|
|
|
|
if (flag & 1)
|
2024-07-19 20:24:02 +00:00
|
|
|
change_mask &= ~known_su_mask;
|
2024-07-16 13:05:11 +00:00
|
|
|
if (flag & 2)
|
2024-07-19 20:24:02 +00:00
|
|
|
change_mask &= (known_user_mask | known_su_mask);
|
|
|
|
if (change_mask == ~((uint64_t) 0)) {
|
|
|
|
eff_flags = lfa_flags;
|
|
|
|
} else {
|
|
|
|
ret = aaip_get_lfa_flags(disk_path, &eff_flags, &old_max_bit, os_errno,
|
|
|
|
0);
|
|
|
|
if (ret == 0)
|
|
|
|
return ISO_AAIP_NOT_ENABLED;
|
|
|
|
if (ret < 0)
|
|
|
|
return ISO_AAIP_NO_GET_LOCAL;
|
|
|
|
eff_flags &= ~change_mask;
|
|
|
|
eff_flags |= (lfa_flags & change_mask);
|
|
|
|
}
|
|
|
|
ret= aaip_set_lfa_flags(disk_path, eff_flags, max_bit, os_errno, 0);
|
2024-07-16 13:05:11 +00:00
|
|
|
if(ret == 0)
|
|
|
|
return ISO_AAIP_NOT_ENABLED;
|
|
|
|
if(ret < 0)
|
|
|
|
return ISO_AAIP_NO_SET_LOCAL;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|