L4Re/departure

Changeset

299:5c3d7f228d1f
2022-03-21 Paul Boddie raw files shortlog changelog graph Added copy-in support to fsaccess.
conf/fsaccess.txt (file) fsaccess/Makefile (file) fsaccess/file.c (file) fsaccess/file.h (file) fsaccess/fsaccess.c (file) fsaccess/op_copy_in.c (file)
     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 +*/