commit
d507425128
3
CHANGES
3
CHANGES
@ -10,6 +10,7 @@ This release contains contributions from (alphabetically by first name):
|
|||||||
- Caio Carvalho
|
- Caio Carvalho
|
||||||
- Kevin Kofler
|
- Kevin Kofler
|
||||||
- Philip Mueller
|
- Philip Mueller
|
||||||
|
- Scott Harvey
|
||||||
|
|
||||||
## Core ##
|
## Core ##
|
||||||
|
|
||||||
@ -25,6 +26,8 @@ There are no core changes in this version.
|
|||||||
size is close to the required installation size).
|
size is close to the required installation size).
|
||||||
* The *keyboard* module now handles the (bogus) Austrian keymap for
|
* The *keyboard* module now handles the (bogus) Austrian keymap for
|
||||||
the system console properly.
|
the system console properly.
|
||||||
|
* The *preservefiles* module now has a mechanism for setting the permissions
|
||||||
|
(and ownership) of preserved files.
|
||||||
* New module *fsresizer* can be used to resize filesystems. It is intended
|
* New module *fsresizer* can be used to resize filesystems. It is intended
|
||||||
for use in OEM installs where an image of fixed size is created,
|
for use in OEM installs where an image of fixed size is created,
|
||||||
and then sized to the actual SD card the user has used.
|
and then sized to the actual SD card the user has used.
|
||||||
|
@ -4,6 +4,7 @@ calamares_add_plugin( preservefiles
|
|||||||
TYPE job
|
TYPE job
|
||||||
EXPORT_MACRO PLUGINDLLEXPORT_PRO
|
EXPORT_MACRO PLUGINDLLEXPORT_PRO
|
||||||
SOURCES
|
SOURCES
|
||||||
|
permissions.cpp
|
||||||
PreserveFiles.cpp
|
PreserveFiles.cpp
|
||||||
LINK_PRIVATE_LIBRARIES
|
LINK_PRIVATE_LIBRARIES
|
||||||
calamares
|
calamares
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
#include "PreserveFiles.h"
|
#include "PreserveFiles.h"
|
||||||
|
|
||||||
|
#include "permissions.h"
|
||||||
|
|
||||||
#include "CalamaresVersion.h"
|
#include "CalamaresVersion.h"
|
||||||
#include "JobQueue.h"
|
#include "JobQueue.h"
|
||||||
#include "GlobalStorage.h"
|
#include "GlobalStorage.h"
|
||||||
@ -83,6 +85,38 @@ PreserveFiles::prettyName() const
|
|||||||
return tr( "Saving files for later ..." );
|
return tr( "Saving files for later ..." );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
copy_file( const QString& source, const QString& dest )
|
||||||
|
{
|
||||||
|
QFile sourcef( source );
|
||||||
|
if ( !sourcef.open( QFile::ReadOnly ) )
|
||||||
|
{
|
||||||
|
cWarning() << "Could not read" << source;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFile destf( dest );
|
||||||
|
if ( !destf.open( QFile::WriteOnly ) )
|
||||||
|
{
|
||||||
|
sourcef.close();
|
||||||
|
cWarning() << "Could not open" << destf.fileName() << "for writing; could not copy" << source;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray b;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
b = sourcef.read( 1_MiB );
|
||||||
|
destf.write( b );
|
||||||
|
}
|
||||||
|
while ( b.count() > 0 );
|
||||||
|
|
||||||
|
sourcef.close();
|
||||||
|
destf.close();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Calamares::JobResult PreserveFiles::exec()
|
Calamares::JobResult PreserveFiles::exec()
|
||||||
{
|
{
|
||||||
if ( m_items.isEmpty() )
|
if ( m_items.isEmpty() )
|
||||||
@ -96,7 +130,8 @@ Calamares::JobResult PreserveFiles::exec()
|
|||||||
for ( const auto& it : m_items )
|
for ( const auto& it : m_items )
|
||||||
{
|
{
|
||||||
QString source = it.source;
|
QString source = it.source;
|
||||||
QString dest = prefix + atReplacements( it.dest );
|
QString bare_dest = atReplacements( it.dest );
|
||||||
|
QString dest = prefix + bare_dest;
|
||||||
|
|
||||||
if ( it.type == ItemType::Log )
|
if ( it.type == ItemType::Log )
|
||||||
source = Logger::logFile();
|
source = Logger::logFile();
|
||||||
@ -111,32 +146,29 @@ Calamares::JobResult PreserveFiles::exec()
|
|||||||
cWarning() << "Skipping unnamed source file for" << dest;
|
cWarning() << "Skipping unnamed source file for" << dest;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QFile sourcef( source );
|
if ( copy_file( source, dest ) )
|
||||||
if ( !sourcef.open( QFile::ReadOnly ) )
|
|
||||||
{
|
{
|
||||||
cWarning() << "Could not read" << source;
|
if ( it.perm.isValid() )
|
||||||
continue;
|
{
|
||||||
|
auto s_p = CalamaresUtils::System::instance();
|
||||||
|
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = s_p->targetEnvCall( QStringList{ "chown", it.perm.username(), bare_dest } );
|
||||||
|
if ( r )
|
||||||
|
cWarning() << "Could not chown target" << bare_dest;
|
||||||
|
|
||||||
|
r = s_p->targetEnvCall( QStringList{ "chgrp", it.perm.group(), bare_dest } );
|
||||||
|
if ( r )
|
||||||
|
cWarning() << "Could not chgrp target" << bare_dest;
|
||||||
|
|
||||||
|
r = s_p->targetEnvCall( QStringList{ "chmod", it.perm.octal(), bare_dest } );
|
||||||
|
if ( r )
|
||||||
|
cWarning() << "Could not chmod target" << bare_dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
++count;
|
||||||
}
|
}
|
||||||
|
|
||||||
QFile destf( dest );
|
|
||||||
if ( !destf.open( QFile::WriteOnly ) )
|
|
||||||
{
|
|
||||||
sourcef.close();
|
|
||||||
cWarning() << "Could not open" << destf.fileName() << "for writing; could not copy" << source;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray b;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
b = sourcef.read( 1_MiB );
|
|
||||||
destf.write( b );
|
|
||||||
}
|
|
||||||
while ( b.count() > 0 );
|
|
||||||
|
|
||||||
sourcef.close();
|
|
||||||
destf.close();
|
|
||||||
++count;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,6 +192,10 @@ void PreserveFiles::setConfigurationMap(const QVariantMap& configurationMap)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString defaultPermissions = configurationMap[ "perm" ].toString();
|
||||||
|
if ( defaultPermissions.isEmpty() )
|
||||||
|
defaultPermissions = QStringLiteral( "root:root:0400" );
|
||||||
|
|
||||||
QVariantList l = files.toList();
|
QVariantList l = files.toList();
|
||||||
unsigned int c = 0;
|
unsigned int c = 0;
|
||||||
for ( const auto& li : l )
|
for ( const auto& li : l )
|
||||||
@ -168,7 +204,7 @@ void PreserveFiles::setConfigurationMap(const QVariantMap& configurationMap)
|
|||||||
{
|
{
|
||||||
QString filename = li.toString();
|
QString filename = li.toString();
|
||||||
if ( !filename.isEmpty() )
|
if ( !filename.isEmpty() )
|
||||||
m_items.append( Item{ filename, filename, ItemType::Path } );
|
m_items.append( Item{ filename, filename, Permissions( defaultPermissions ), ItemType::Path } );
|
||||||
else
|
else
|
||||||
cDebug() << "Empty filename for preservefiles, item" << c;
|
cDebug() << "Empty filename for preservefiles, item" << c;
|
||||||
}
|
}
|
||||||
@ -181,6 +217,9 @@ void PreserveFiles::setConfigurationMap(const QVariantMap& configurationMap)
|
|||||||
( from == "log" ) ? ItemType::Log :
|
( from == "log" ) ? ItemType::Log :
|
||||||
( from == "config" ) ? ItemType::Config :
|
( from == "config" ) ? ItemType::Config :
|
||||||
ItemType::None;
|
ItemType::None;
|
||||||
|
QString perm = map[ "perm" ].toString();
|
||||||
|
if ( perm.isEmpty() )
|
||||||
|
perm = defaultPermissions;
|
||||||
|
|
||||||
if ( dest.isEmpty() )
|
if ( dest.isEmpty() )
|
||||||
{
|
{
|
||||||
@ -192,7 +231,7 @@ void PreserveFiles::setConfigurationMap(const QVariantMap& configurationMap)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_items.append( Item{ QString(), dest, t } );
|
m_items.append( Item{ QString(), dest, Permissions( perm ), t } );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -24,11 +24,11 @@
|
|||||||
#include <QVariantMap>
|
#include <QVariantMap>
|
||||||
|
|
||||||
#include "CppJob.h"
|
#include "CppJob.h"
|
||||||
|
#include "PluginDllMacro.h"
|
||||||
|
|
||||||
#include "utils/PluginFactory.h"
|
#include "utils/PluginFactory.h"
|
||||||
|
|
||||||
#include "PluginDllMacro.h"
|
#include "permissions.h"
|
||||||
|
|
||||||
|
|
||||||
class PLUGINDLLEXPORT PreserveFiles : public Calamares::CppJob
|
class PLUGINDLLEXPORT PreserveFiles : public Calamares::CppJob
|
||||||
{
|
{
|
||||||
@ -46,6 +46,7 @@ class PLUGINDLLEXPORT PreserveFiles : public Calamares::CppJob
|
|||||||
{
|
{
|
||||||
QString source;
|
QString source;
|
||||||
QString dest;
|
QString dest;
|
||||||
|
Permissions perm;
|
||||||
ItemType type;
|
ItemType type;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
75
src/modules/preservefiles/permissions.cpp
Normal file
75
src/modules/preservefiles/permissions.cpp
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018 Scott Harvey <scott@spharvey.me>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QStringList>
|
||||||
|
#include "permissions.h"
|
||||||
|
|
||||||
|
Permissions::Permissions() :
|
||||||
|
m_username(),
|
||||||
|
m_group(),
|
||||||
|
m_valid(false),
|
||||||
|
m_value(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Permissions::Permissions(QString p) : Permissions()
|
||||||
|
{
|
||||||
|
parsePermissions(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Permissions::parsePermissions(const QString& p) {
|
||||||
|
|
||||||
|
QStringList segments = p.split(":");
|
||||||
|
|
||||||
|
if (segments.length() != 3) {
|
||||||
|
m_valid = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (segments[0].isEmpty() || segments[1].isEmpty()) {
|
||||||
|
m_valid = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ok;
|
||||||
|
int octal = segments[2].toInt(&ok, 8);
|
||||||
|
if (!ok || octal == 0) {
|
||||||
|
m_valid = false;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
m_value = octal;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have exactly three segments and the third is valid octal,
|
||||||
|
// so we can declare the string valid and set the user and group names
|
||||||
|
m_valid = true;
|
||||||
|
m_username = segments[0];
|
||||||
|
m_group = segments[1];
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
62
src/modules/preservefiles/permissions.h
Normal file
62
src/modules/preservefiles/permissions.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018 Scott Harvey <scott@spharvey.me>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PERMISSIONS_H
|
||||||
|
#define PERMISSIONS_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The Permissions class takes a QString @p in the form of
|
||||||
|
* <user>:<group>:<permissions>, checks it for validity, and makes the three
|
||||||
|
* components available indivdually.
|
||||||
|
*/
|
||||||
|
class Permissions
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** @brief Constructor
|
||||||
|
*
|
||||||
|
* Splits the string @p at the colon (":") into separate elements for
|
||||||
|
* <user>, <group>, and <value> (permissions), where <value> is returned as
|
||||||
|
* an **octal** integer.
|
||||||
|
*/
|
||||||
|
Permissions(QString p);
|
||||||
|
|
||||||
|
/** @brief Default constructor of an invalid Permissions. */
|
||||||
|
Permissions();
|
||||||
|
|
||||||
|
bool isValid() const { return m_valid; }
|
||||||
|
QString username() const { return m_username; }
|
||||||
|
QString group() const { return m_group; }
|
||||||
|
int value() const { return m_value; }
|
||||||
|
QString octal() const { return QString::number( m_value, 8 ); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void parsePermissions(QString const &p);
|
||||||
|
|
||||||
|
QString m_username;
|
||||||
|
QString m_group;
|
||||||
|
bool m_valid;
|
||||||
|
int m_value;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PERMISSIONS_H
|
@ -9,13 +9,18 @@
|
|||||||
# as the source).
|
# as the source).
|
||||||
# - a map with a *dest* key. The *dest* value is a path interpreted in the
|
# - a map with a *dest* key. The *dest* value is a path interpreted in the
|
||||||
# target system (if dontChroot is true, in the host system). Relative paths
|
# target system (if dontChroot is true, in the host system). Relative paths
|
||||||
# are not recommended. There are two possible other keys in the map:
|
# are not recommended. There are three possible other keys in the map:
|
||||||
# - *from*, which must have one of the values, below; it is used to
|
# - *from*, which must have one of the values, below; it is used to
|
||||||
# preserve files whose pathname is known to Calamares internally.
|
# preserve files whose pathname is known to Calamares internally.
|
||||||
# - *src*, to refer to a path interpreted in the host system. Relative
|
# - *src*, to refer to a path interpreted in the host system. Relative
|
||||||
# paths are not recommended, and are interpreted relative to where
|
# paths are not recommended, and are interpreted relative to where
|
||||||
# Calamares is being run.
|
# Calamares is being run.
|
||||||
# Only one of the two other keys (either *from* or *src*) may be set.
|
# - *perm*, is a colon-separated tuple of <user>:<group>:<mode>
|
||||||
|
# where <mode> is in octal (e.g. 4777 for wide-open, 0400 for read-only
|
||||||
|
# by owner). If set, the file's ownership and permissions are set to
|
||||||
|
# those values within the target system; if not set, no permissions
|
||||||
|
# are changed.
|
||||||
|
# Only one of the two source keys (either *from* or *src*) may be set.
|
||||||
#
|
#
|
||||||
# The target filename is modified as follows:
|
# The target filename is modified as follows:
|
||||||
# - `@@ROOT@@` is replaced by the path to the target root (may be /)
|
# - `@@ROOT@@` is replaced by the path to the target root (may be /)
|
||||||
@ -32,5 +37,13 @@ files:
|
|||||||
- /etc/oem-information
|
- /etc/oem-information
|
||||||
- from: log
|
- from: log
|
||||||
dest: /root/install.log
|
dest: /root/install.log
|
||||||
|
perm: root:wheel:644
|
||||||
- from: config
|
- from: config
|
||||||
dest: /root/install.cfg
|
dest: /root/install.cfg
|
||||||
|
perm: root:wheel:400
|
||||||
|
|
||||||
|
# The *perm* key contains a default value to apply to all files listed
|
||||||
|
# above that do not have a *perm* key of their own. If not set,
|
||||||
|
# root:root:0400 (highly restrictive) is used.
|
||||||
|
#
|
||||||
|
# perm: "root:root:0400"
|
||||||
|
Loading…
Reference in New Issue
Block a user