bump product version to 7.2.5.1
[LibreOffice.git] / desktop / source / app / userinstall.cxx
blobbcfd7e3e5596acc45d5a89097b00450fda9ddd9b
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.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
22 #include <cassert>
24 #include <com/sun/star/uno/Exception.hpp>
25 #include <comphelper/configuration.hxx>
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
31 #include <rtl/bootstrap.hxx>
32 #endif
33 #include <rtl/ustring.hxx>
34 #include <tools/diagnose_ex.h>
35 #include <unotools/bootstrap.hxx>
37 #include "userinstall.hxx"
39 namespace desktop::userinstall {
41 namespace {
43 #if !(defined ANDROID || defined IOS)
44 osl::FileBase::RC copyRecursive(
45 OUString const & srcUri, OUString const & dstUri)
47 osl::DirectoryItem item;
48 osl::FileBase::RC e = osl::DirectoryItem::get(srcUri, item);
49 if (e != osl::FileBase::E_None) {
50 return e;
52 osl::FileStatus stat1(osl_FileStatus_Mask_Type);
53 e = item.getFileStatus(stat1);
54 if (e != osl::FileBase::E_None) {
55 return e;
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;
62 osl::Directory dir(srcUri);
63 e = dir.open();
64 if (e != osl::FileBase::E_None) {
65 return e;
67 for (;;) {
68 e = dir.getNextItem(item);
69 if (e == osl::FileBase::E_NOENT) {
70 break;
72 if (e != osl::FileBase::E_None) {
73 return e;
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;
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;
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;
98 return e;
100 #endif
102 Status 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;
107 #if !(defined ANDROID || defined IOS)
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;
117 if (utl::Bootstrap::locateBaseInstallation(baseUri)
118 != utl::Bootstrap::PATH_EXISTS)
120 return ERROR_OTHER;
122 switch (copyRecursive(
123 baseUri + "/" LIBO_SHARE_PRESETS_FOLDER, uri + "/user"))
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;
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(
142 comphelper::ConfigurationChanges::create());
143 officecfg::Setup::Office::ooSetupInstCompleted::set(true, batch);
144 batch->commit();
145 return CREATED;
148 bool 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;
159 Status finalize() {
160 OUString uri;
161 switch (utl::Bootstrap::locateUserInstallation(uri)) {
162 case utl::Bootstrap::PATH_EXISTS:
163 if (isCreated()) {
164 return EXISTED;
166 [[fallthrough]];
167 case utl::Bootstrap::PATH_VALID:
168 return create(uri);
169 default:
170 return ERROR_OTHER;
176 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */