1.1 --- a/conf/fsaccess.txt Mon Mar 21 00:15:43 2022 +0100
1.2 +++ b/conf/fsaccess.txt Mon Mar 21 00:17:42 2022 +0100
1.3 @@ -1,7 +1,13 @@
1.4 ls home/paulb/many
1.5 ls home/paulb
1.6 -mkdir home/paulb/newdir
1.7 +mkdir home/paulb/fsaccess
1.8 ls home/paulb
1.9 -ls home/paulb/newdir
1.10 +ls home/paulb/fsaccess
1.11 stat home/paulb
1.12 -stat home/paulb/newdir
1.13 +stat home/paulb/fsaccess
1.14 +copy-in rom/fsaccess.txt home/paulb/fsaccess
1.15 +ls home/paulb/fsaccess
1.16 +stat home/paulb/fsaccess/fsaccess.txt
1.17 +copy-in rom/fsaccess.txt home/paulb/fsaccess/script.txt
1.18 +ls home/paulb/fsaccess
1.19 +stat home/paulb/fsaccess/script.txt
2.1 --- a/fsaccess/Makefile Mon Mar 21 00:15:43 2022 +0100
2.2 +++ b/fsaccess/Makefile Mon Mar 21 00:17:42 2022 +0100
2.3 @@ -6,10 +6,10 @@
2.4 MODE = static
2.5
2.6 SRC_C = \
2.7 - fsaccess.c input.c session.c \
2.8 - ops.c op_list_objects.c op_make_dirs.c op_script.c \
2.9 + file.c fsaccess.c input.c session.c ops.c \
2.10 + op_copy_in.c op_list_objects.c op_make_dirs.c op_script.c \
2.11 op_stat_objects.c
2.12
2.13 -REQUIRES_LIBS = l4re_c-util libfsclient libmem libipc libsystypes libe2access_blockserver
2.14 +REQUIRES_LIBS = l4re_c-util libfsclient libmem libipc libsystypes libe2access libe2access_blockserver
2.15
2.16 include $(L4DIR)/mk/prog.mk
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/fsaccess/file.c Mon Mar 21 00:17:42 2022 +0100
3.3 @@ -0,0 +1,82 @@
3.4 +/*
3.5 + * Generic file access functions.
3.6 + *
3.7 + * Copyright (C) 2019, 2022 Paul Boddie <paul@boddie.org.uk>
3.8 + *
3.9 + * This program is free software; you can redistribute it and/or
3.10 + * modify it under the terms of the GNU General Public License as
3.11 + * published by the Free Software Foundation; either version 2 of
3.12 + * the License, or (at your option) any later version.
3.13 + *
3.14 + * This program is distributed in the hope that it will be useful,
3.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3.17 + * GNU General Public License for more details.
3.18 + *
3.19 + * You should have received a copy of the GNU General Public License
3.20 + * along with this program; if not, write to the Free Software
3.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
3.22 + * Boston, MA 02110-1301, USA
3.23 + */
3.24 +
3.25 +#include <stdio.h>
3.26 +#include <string.h>
3.27 +#include <sys/stat.h>
3.28 +#include <sys/types.h>
3.29 +
3.30 +#include "file.h"
3.31 +
3.32 +
3.33 +
3.34 +/* Test object types in the external environment. */
3.35 +
3.36 +int isdir(const char *name)
3.37 +{
3.38 + struct stat st;
3.39 +
3.40 + if (!lstat(name, &st))
3.41 + return S_ISDIR(st.st_mode);
3.42 + else
3.43 + return 0;
3.44 +}
3.45 +
3.46 +int isdir_dirname(const char *name)
3.47 +{
3.48 + char dirname[strlen(name) + 1];
3.49 + char *s;
3.50 +
3.51 + strcpy(dirname, name);
3.52 + s = strrchr(dirname, (int) '/');
3.53 +
3.54 + if (s != NULL)
3.55 + *s = '\0';
3.56 +
3.57 + return isdir(dirname);
3.58 +}
3.59 +
3.60 +int isfile(const char *name)
3.61 +{
3.62 + struct stat st;
3.63 +
3.64 + if (!lstat(name, &st))
3.65 + return S_ISREG(st.st_mode);
3.66 + else
3.67 + return 0;
3.68 +}
3.69 +
3.70 +/* Open a file in the external environment. */
3.71 +
3.72 +FILE *open_file_in_dir(const char *dirname, const char *basename,
3.73 + const char *mode)
3.74 +{
3.75 + char pathname[strlen(dirname) + strlen(basename) + 1];
3.76 +
3.77 + strcpy(pathname, dirname);
3.78 + strcat(pathname, "/");
3.79 + strcat(pathname, basename);
3.80 +
3.81 + return fopen(pathname, mode);
3.82 +}
3.83 +
3.84 +/* vim: tabstop=4 expandtab shiftwidth=4
3.85 +*/
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/fsaccess/file.h Mon Mar 21 00:17:42 2022 +0100
4.3 @@ -0,0 +1,34 @@
4.4 +/*
4.5 + * File access functions.
4.6 + *
4.7 + * Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk>
4.8 + *
4.9 + * This program is free software; you can redistribute it and/or
4.10 + * modify it under the terms of the GNU General Public License as
4.11 + * published by the Free Software Foundation; either version 2 of
4.12 + * the License, or (at your option) any later version.
4.13 + *
4.14 + * This program is distributed in the hope that it will be useful,
4.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4.17 + * GNU General Public License for more details.
4.18 + *
4.19 + * You should have received a copy of the GNU General Public License
4.20 + * along with this program; if not, write to the Free Software
4.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
4.22 + * Boston, MA 02110-1301, USA
4.23 + */
4.24 +
4.25 +#pragma once
4.26 +
4.27 +#include <stdio.h>
4.28 +
4.29 +int isdir(const char *name);
4.30 +int isdir_dirname(const char *name);
4.31 +int isfile(const char *name);
4.32 +
4.33 +FILE *open_file_in_dir(const char *dirname, const char *basename,
4.34 + const char *mode);
4.35 +
4.36 +/* vim: tabstop=4 expandtab shiftwidth=4
4.37 +*/
5.1 --- a/fsaccess/fsaccess.c Mon Mar 21 00:15:43 2022 +0100
5.2 +++ b/fsaccess/fsaccess.c Mon Mar 21 00:17:42 2022 +0100
5.3 @@ -57,8 +57,8 @@
5.4 /* Operations exposed by the program. */
5.5
5.6 struct operation operations[] = {
5.7 + {"copy-in", copy_in},
5.8 #if 0
5.9 - {"copy-in", copy_in},
5.10 {"copy-out", copy_out},
5.11 #endif
5.12 {"ls", list_objects},
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/fsaccess/op_copy_in.c Mon Mar 21 00:17:42 2022 +0100
6.3 @@ -0,0 +1,267 @@
6.4 +/*
6.5 + * Copy a file into a filesystem.
6.6 + *
6.7 + * Copyright (C) 2019, 2022 Paul Boddie <paul@boddie.org.uk>
6.8 + *
6.9 + * This program is free software; you can redistribute it and/or
6.10 + * modify it under the terms of the GNU General Public License as
6.11 + * published by the Free Software Foundation; either version 2 of
6.12 + * the License, or (at your option) any later version.
6.13 + *
6.14 + * This program is distributed in the hope that it will be useful,
6.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6.17 + * GNU General Public License for more details.
6.18 + *
6.19 + * You should have received a copy of the GNU General Public License
6.20 + * along with this program; if not, write to the Free Software
6.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
6.22 + * Boston, MA 02110-1301, USA
6.23 + */
6.24 +
6.25 +#include <stdio.h>
6.26 +#include <string.h>
6.27 +
6.28 +#include <sys/stat.h>
6.29 +
6.30 +#include <e2access/path.h>
6.31 +#include <fsclient/client.h>
6.32 +#include <systypes/fcntl.h>
6.33 +
6.34 +#include "file.h"
6.35 +#include "ops.h"
6.36 +#include "session.h"
6.37 +
6.38 +
6.39 +
6.40 +/* Copy buffer size. */
6.41 +
6.42 +static int BUFSIZE = 4096;
6.43 +
6.44 +
6.45 +
6.46 +/* Alternative metadata set by options. */
6.47 +
6.48 +extern struct metadata md;
6.49 +
6.50 +
6.51 +
6.52 +/* Copy a file into the filesystem image. */
6.53 +
6.54 +static int _copy_file_in(const char *source, const char *target, flags_t flags)
6.55 +{
6.56 + int retval = 0;
6.57 +
6.58 + /* Copying details. */
6.59 +
6.60 + FILE *fp;
6.61 + file_t *target_fp;
6.62 + char buf[BUFSIZE];
6.63 + size_t got;
6.64 + offset_t written;
6.65 +
6.66 + /* Open a file in the target directory. */
6.67 +
6.68 + target_fp = client_open(target, flags);
6.69 +
6.70 + if (target_fp == NULL)
6.71 + return 1;
6.72 +
6.73 + /* Open the file in the source directory. */
6.74 +
6.75 + fp = fopen(source, "r");
6.76 +
6.77 + /* Copy the file content. */
6.78 +
6.79 + if (fp != NULL)
6.80 + {
6.81 + while ((got = fread(buf, sizeof(char), BUFSIZE, fp)))
6.82 + {
6.83 + while (got)
6.84 + {
6.85 + written = client_write(target_fp, buf, got);
6.86 +
6.87 + if (!written)
6.88 + {
6.89 + retval = 1;
6.90 + goto close_files;
6.91 + }
6.92 + got -= written;
6.93 + }
6.94 + }
6.95 + }
6.96 +
6.97 +close_files:
6.98 + fclose(fp);
6.99 + client_close(target_fp);
6.100 +
6.101 + return retval;
6.102 +}
6.103 +
6.104 +/* Copy a source file from the external environment into the filesystem. */
6.105 +
6.106 +static int _copy_in(const char *source, const char *target,
6.107 + const char *basename)
6.108 +{
6.109 + /* Obtain basename and eventual target path. */
6.110 +
6.111 + const char *source_basename = path_basename(source);
6.112 + char target_plus_basename[strlen(target) + 1 +
6.113 + (basename != NULL ? strlen(basename)
6.114 + : strlen(source_basename)) + 1];
6.115 + const char *target_path;
6.116 +
6.117 + /* Target file properties. */
6.118 +
6.119 + flags_t flags;
6.120 + struct stat st;
6.121 + long err;
6.122 +
6.123 + /* By default, treat the target as a new object. */
6.124 +
6.125 + int target_is_new = 1;
6.126 +
6.127 + /* Without a basename, the target exists and is either a directory, into
6.128 + which the source file shall be copied, or it is a file that shall be
6.129 + overwritten. */
6.130 +
6.131 + if (basename == NULL)
6.132 + {
6.133 + err = client_stat(target, &st);
6.134 +
6.135 + if (err)
6.136 + {
6.137 + fprintf(stderr, "Could not stat target: %s\n", target);
6.138 + return 1;
6.139 + }
6.140 +
6.141 + target_is_new = S_ISDIR(st.st_mode);
6.142 +
6.143 + if (target_is_new)
6.144 + basename = path_basename(source);
6.145 + }
6.146 +
6.147 + /* Obtain the target path. */
6.148 +
6.149 + if (basename != NULL)
6.150 + {
6.151 + sprintf(target_plus_basename, "%s/%s", target, basename);
6.152 + target_path = target_plus_basename;
6.153 + }
6.154 + else
6.155 + target_path = target;
6.156 +
6.157 + /* Directories are created with the same metadata. */
6.158 +
6.159 + if (isdir(source))
6.160 + {
6.161 + if (!target_is_new)
6.162 + {
6.163 + fprintf(stderr, "Directory cannot be copied as it already exists: %s\n", target_path);
6.164 + return 1;
6.165 + }
6.166 +
6.167 + err = client_stat(source, &st);
6.168 +
6.169 + if (err)
6.170 + {
6.171 + fprintf(stderr, "Could not stat source: %s\n", source);
6.172 + return 1;
6.173 + }
6.174 +
6.175 + if (client_mkdir(target_path, st.st_mode & ~md.mask))
6.176 + return 1;
6.177 + }
6.178 +
6.179 + /* Files are copied. */
6.180 +
6.181 + else if (isfile(source))
6.182 + {
6.183 + flags = O_WRONLY;
6.184 +
6.185 + /* Obtain the inode for the target file. */
6.186 +
6.187 + if (target_is_new)
6.188 + flags |= O_CREAT;
6.189 +
6.190 + /* NOTE: Overwrite/update metadata where appropriate. */
6.191 +
6.192 + if (_copy_file_in(source, target_path, flags))
6.193 + {
6.194 + fprintf(stderr, "Failed to copy file: %s\n", source);
6.195 + return 1;
6.196 + }
6.197 + }
6.198 +
6.199 + return 0;
6.200 +}
6.201 +
6.202 +/* Copy source files from the external environment into the filesystem image. */
6.203 +
6.204 +int copy_in(int argc, char *argv[])
6.205 +{
6.206 + int i;
6.207 +
6.208 + /* Target filename details. */
6.209 +
6.210 + char *target = argv[argc - 1];
6.211 + const char *basename;
6.212 + struct stat st;
6.213 +
6.214 + /* Locate the target and test whether it is a file or a directory. */
6.215 +
6.216 + long err = client_stat(target, &st);
6.217 +
6.218 + /* Only a non-existent file in an existing directory is permitted. */
6.219 +
6.220 + if (err == -L4_ENOENT)
6.221 + {
6.222 + /* Split the path, making target the parent directory. */
6.223 +
6.224 + basename = path_split(target);
6.225 + err = client_stat(target, &st);
6.226 +
6.227 + if (err)
6.228 + {
6.229 + fprintf(stderr, "Could not stat target parent: %s\n", target);
6.230 + return 1;
6.231 + }
6.232 +
6.233 + if (!S_ISDIR(st.st_mode))
6.234 + {
6.235 + fprintf(stderr, "Target parent is not directory: %s\n", target);
6.236 + return 1;
6.237 + }
6.238 + }
6.239 + else if (err)
6.240 + {
6.241 + fprintf(stderr, "Could not stat target: %s\n", target);
6.242 + return 1;
6.243 + }
6.244 +
6.245 + /* An existing object can be a file or directory. */
6.246 +
6.247 + else
6.248 + {
6.249 + basename = NULL;
6.250 +
6.251 + /* Only permit a target file when one source file is given. */
6.252 +
6.253 + if (!S_ISDIR(st.st_mode) && (argc > 2))
6.254 + {
6.255 + fprintf(stderr, "Target can only be a file when copying a single file: %s\n", target);
6.256 + return 1;
6.257 + }
6.258 + }
6.259 +
6.260 + /* Copy each source object to the target directory. */
6.261 +
6.262 + for (i = 0; i < argc - 1; i++)
6.263 + if (_copy_in(argv[i], target, basename))
6.264 + return 1;
6.265 +
6.266 + return 0;
6.267 +}
6.268 +
6.269 +/* vim: tabstop=4 expandtab shiftwidth=4
6.270 +*/