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 #include <rtl/bootstrap.hxx>
31 #include <rtl/ustring.hxx>
32 #include <sal/log.hxx>
33 #include <tools/diagnose_ex.h>
34 #include <unotools/bootstrap.hxx>
35 
36 #include "userinstall.hxx"
37 
38 namespace desktop { namespace userinstall {
39 
40 namespace {
41 
42 #if !(defined ANDROID || defined IOS)
43 osl::FileBase::RC copyRecursive(
44  OUString const & srcUri, OUString const & dstUri)
45 {
46  osl::DirectoryItem item;
47  osl::FileBase::RC e = osl::DirectoryItem::get(srcUri, item);
48  if (e != osl::FileBase::E_None) {
49  return e;
50  }
51  osl::FileStatus stat1(osl_FileStatus_Mask_Type);
52  e = item.getFileStatus(stat1);
53  if (e != osl::FileBase::E_None) {
54  return e;
55  }
56  if (stat1.getFileType() == osl::FileStatus::Directory) {
57  e = osl::Directory::create(dstUri);
58  if (e != osl::FileBase::E_None && e != osl::FileBase::E_EXIST) {
59  return e;
60  }
61  osl::Directory dir(srcUri);
62  e = dir.open();
63  if (e != osl::FileBase::E_None) {
64  return e;
65  }
66  for (;;) {
67  e = dir.getNextItem(item);
68  if (e == osl::FileBase::E_NOENT) {
69  break;
70  }
71  if (e != osl::FileBase::E_None) {
72  return e;
73  }
74  osl::FileStatus stat2(
75  osl_FileStatus_Mask_FileName | osl_FileStatus_Mask_FileURL);
76  e = item.getFileStatus(stat2);
77  if (e != osl::FileBase::E_None) {
78  return e;
79  }
80  assert(!dstUri.endsWith("/"));
81  e = copyRecursive(
82  stat2.getFileURL(), dstUri + "/" + stat2.getFileName());
83  // assumes that all files under presets/ have names that can be
84  // copied unencoded into file URLs
85  if (e != osl::FileBase::E_None) {
86  return e;
87  }
88  }
89  e = dir.close();
90  } else {
91  e = osl::File::copy(srcUri, dstUri);
92  if (e == osl::FileBase::E_EXIST) {
93  // Assume an earlier attempt failed half-way through:
94  e = osl::FileBase::E_None;
95  }
96  }
97  return e;
98 }
99 #endif
100 
101 Status create(OUString const & uri) {
102  osl::FileBase::RC e = osl::Directory::createPath(uri);
103  if (e != osl::FileBase::E_None && e != osl::FileBase::E_EXIST) {
104  return ERROR_OTHER;
105  }
106 #if !(defined ANDROID || defined IOS)
107 #if defined UNIX
108  // Set safer permissions for the user directory by default:
109  osl::File::setAttributes(
110  uri,
111  (osl_File_Attribute_OwnWrite | osl_File_Attribute_OwnRead
112  | osl_File_Attribute_OwnExe));
113 #endif
114  // As of now osl_copyFile does not work on Android => don't do this:
115  OUString baseUri;
118  {
119  return ERROR_OTHER;
120  }
121  switch (copyRecursive(
122  baseUri + "/" LIBO_SHARE_PRESETS_FOLDER, uri + "/user"))
123  {
124  case osl::FileBase::E_None:
125  break;
126  case osl::FileBase::E_ACCES:
127  return ERROR_CANT_WRITE;
128  case osl::FileBase::E_NOSPC:
129  return ERROR_NO_SPACE;
130  default:
131  return ERROR_OTHER;
132  }
133 #else
134  // On (Android and) iOS, just create the user directory. Later code fails mysteriously if it
135  // doesn't exist.
136  OUString userDir("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/user");
137  rtl::Bootstrap::expandMacros(userDir);
138  osl::Directory::createPath(userDir);
139 #endif
140  std::shared_ptr<comphelper::ConfigurationChanges> batch(
142  officecfg::Setup::Office::ooSetupInstCompleted::set(true, batch);
143  batch->commit();
144  return CREATED;
145 }
146 
147 bool isCreated() {
148  try {
149  return officecfg::Setup::Office::ooSetupInstCompleted::get();
150  } catch (const css::uno::Exception &) {
151  TOOLS_WARN_EXCEPTION("desktop.app", "ignoring");
152  return false;
153  }
154 }
155 
156 }
157 
159  OUString uri;
162  if (isCreated()) {
163  return EXISTED;
164  }
165  [[fallthrough]];
167  return create(uri);
168  default:
169  return ERROR_OTHER;
170  }
171 }
172 
173 } }
174 
175 /* 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)
Definition: app.cxx:166
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)