LibreOffice Module desktop (master) 1
userinstall.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <sal/config.h>
21
22#include <cassert>
23
24#include <com/sun/star/uno/Exception.hpp>
26#include <config_folders.h>
27#include <officecfg/Setup.hxx>
28#include <osl/file.h>
29#include <osl/file.hxx>
30#if defined ANDROID || defined IOS || defined EMSCRIPTEN
31#include <rtl/bootstrap.hxx>
32#endif
33#include <rtl/ustring.hxx>
36
37#include "userinstall.hxx"
38
40
41namespace {
42
43#if !(defined ANDROID || defined IOS || defined EMSCRIPTEN)
44osl::FileBase::RC copyRecursive(
45 OUString const & srcUri, OUString const & dstUri)
46{
47 osl::DirectoryItem item;
48 osl::FileBase::RC e = osl::DirectoryItem::get(srcUri, item);
49 if (e != osl::FileBase::E_None) {
50 return e;
51 }
52 osl::FileStatus stat1(osl_FileStatus_Mask_Type);
53 e = item.getFileStatus(stat1);
54 if (e != osl::FileBase::E_None) {
55 return e;
56 }
57 if (stat1.getFileType() == osl::FileStatus::Directory) {
58 e = osl::Directory::create(dstUri);
59 if (e != osl::FileBase::E_None && e != osl::FileBase::E_EXIST) {
60 return e;
61 }
62 osl::Directory dir(srcUri);
63 e = dir.open();
64 if (e != osl::FileBase::E_None) {
65 return e;
66 }
67 for (;;) {
68 e = dir.getNextItem(item);
69 if (e == osl::FileBase::E_NOENT) {
70 break;
71 }
72 if (e != osl::FileBase::E_None) {
73 return e;
74 }
75 osl::FileStatus stat2(
76 osl_FileStatus_Mask_FileName | osl_FileStatus_Mask_FileURL);
77 e = item.getFileStatus(stat2);
78 if (e != osl::FileBase::E_None) {
79 return e;
80 }
81 assert(!dstUri.endsWith("/"));
82 e = copyRecursive(
83 stat2.getFileURL(), dstUri + "/" + stat2.getFileName());
84 // assumes that all files under presets/ have names that can be
85 // copied unencoded into file URLs
86 if (e != osl::FileBase::E_None) {
87 return e;
88 }
89 }
90 e = dir.close();
91 } else {
92 e = osl::File::copy(srcUri, dstUri);
93 if (e == osl::FileBase::E_EXIST) {
94 // Assume an earlier attempt failed half-way through:
95 e = osl::FileBase::E_None;
96 }
97 }
98 return e;
99}
100#endif
101
102Status create(OUString const & uri) {
103 osl::FileBase::RC e = osl::Directory::createPath(uri);
104 if (e != osl::FileBase::E_None && e != osl::FileBase::E_EXIST) {
105 return ERROR_OTHER;
106 }
107#if !(defined ANDROID || defined IOS || defined EMSCRIPTEN)
108#if defined UNIX
109 // Set safer permissions for the user directory by default:
110 osl::File::setAttributes(
111 uri,
112 (osl_File_Attribute_OwnWrite | osl_File_Attribute_OwnRead
113 | osl_File_Attribute_OwnExe));
114#endif
115 // As of now osl_copyFile does not work on Android => don't do this:
116 OUString baseUri;
119 {
120 return ERROR_OTHER;
121 }
122 switch (copyRecursive(
123 baseUri + "/" LIBO_SHARE_PRESETS_FOLDER, uri + "/user"))
124 {
125 case osl::FileBase::E_None:
126 break;
127 case osl::FileBase::E_ACCES:
128 return ERROR_CANT_WRITE;
129 case osl::FileBase::E_NOSPC:
130 return ERROR_NO_SPACE;
131 default:
132 return ERROR_OTHER;
133 }
134#else
135 // On (Android and) iOS, just create the user directory. Later code fails mysteriously if it
136 // doesn't exist.
137 OUString userDir("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/user");
138 rtl::Bootstrap::expandMacros(userDir);
139 osl::Directory::createPath(userDir);
140#endif
141 std::shared_ptr<comphelper::ConfigurationChanges> batch(
143 officecfg::Setup::Office::ooSetupInstCompleted::set(true, batch);
144 batch->commit();
145 return CREATED;
146}
147
148bool isCreated() {
149 try {
150 return officecfg::Setup::Office::ooSetupInstCompleted::get();
151 } catch (const css::uno::Exception &) {
152 TOOLS_WARN_EXCEPTION("desktop.app", "ignoring");
153 return false;
154 }
155}
156
157}
158
160 OUString uri;
163 if (isCreated()) {
164 return EXISTED;
165 }
166 [[fallthrough]];
168 return create(uri);
169 default:
170 return ERROR_OTHER;
171 }
172}
173
174}
175
176/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static std::shared_ptr< ConfigurationChanges > create()
static PathStatus locateUserInstallation(OUString &_rURL)
static PathStatus locateBaseInstallation(OUString &_rURL)
#define SAL_CONFIGFILE(name)
#define TOOLS_WARN_EXCEPTION(area, stream)
css::uno::Reference< css::deployment::XPackageRegistry > create(css::uno::Reference< css::deployment::XPackageRegistry > const &xRootRegistry, OUString const &context, OUString const &cachePath, css::uno::Reference< css::uno::XComponentContext > const &xComponentContext)