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
31 #include <rtl/bootstrap.hxx>
32 #endif
33 #include <rtl/ustring.hxx>
34 #include <tools/diagnose_ex.h>
35 #include <unotools/bootstrap.hxx>
36 
37 #include "userinstall.hxx"
38 
40 
41 namespace {
42 
43 #if !(defined ANDROID || defined IOS)
44 osl::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 
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;
106  }
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;
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 
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;
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 PathStatus locateUserInstallation(OUString &_rURL)
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)
static std::shared_ptr< ConfigurationChanges > create(css::uno::Reference< css::uno::XComponentContext > const &context=comphelper::getProcessComponentContext())
#define SAL_CONFIGFILE(name)
#define TOOLS_WARN_EXCEPTION(area, stream)
static PathStatus locateBaseInstallation(OUString &_rURL)