This file is indexed.

/usr/share/pyshared/CedarBackup2/actions/util.py is in cedar-backup2 2.26.5-3.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
# -*- coding: iso-8859-1 -*-
# vim: set ft=python ts=3 sw=3 expandtab:
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
#              C E D A R
#          S O L U T I O N S       "Software done right."
#           S O F T W A R E
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# Copyright (c) 2007,2010 Kenneth J. Pronovici.
# All rights reserved.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License,
# Version 2, as published by the Free Software Foundation.
#
# 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.
#
# Copies of the GNU General Public License are available from
# the Free Software Foundation website, http://www.gnu.org/.
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# Author   : Kenneth J. Pronovici <pronovic@ieee.org>
# Language : Python 2 (>= 2.7)
# Project  : Cedar Backup, release 2
# Purpose  : Implements action-related utilities
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

########################################################################
# Module documentation
########################################################################

"""
Implements action-related utilities
@sort: findDailyDirs
@author: Kenneth J. Pronovici <pronovic@ieee.org>
"""


########################################################################
# Imported modules
########################################################################

# System modules
import os
import time
import tempfile
import logging

# Cedar Backup modules
from CedarBackup2.filesystem import FilesystemList
from CedarBackup2.util import changeOwnership
from CedarBackup2.util import deviceMounted
from CedarBackup2.writers.util import readMediaLabel
from CedarBackup2.writers.cdwriter import CdWriter
from CedarBackup2.writers.dvdwriter import DvdWriter
from CedarBackup2.writers.cdwriter import MEDIA_CDR_74, MEDIA_CDR_80, MEDIA_CDRW_74, MEDIA_CDRW_80
from CedarBackup2.writers.dvdwriter import MEDIA_DVDPLUSR, MEDIA_DVDPLUSRW
from CedarBackup2.config import DEFAULT_MEDIA_TYPE, DEFAULT_DEVICE_TYPE, REWRITABLE_MEDIA_TYPES
from CedarBackup2.actions.constants import INDICATOR_PATTERN


########################################################################
# Module-wide constants and variables
########################################################################

logger = logging.getLogger("CedarBackup2.log.actions.util")
MEDIA_LABEL_PREFIX   = "CEDAR BACKUP"


########################################################################
# Public utility functions
########################################################################

###########################
# findDailyDirs() function
###########################

def findDailyDirs(stagingDir, indicatorFile):
   """
   Returns a list of all daily staging directories that do not contain
   the indicated indicator file.

   @param stagingDir: Configured staging directory (config.targetDir)

   @return: List of absolute paths to daily staging directories.
   """
   results = FilesystemList()
   yearDirs = FilesystemList()
   yearDirs.excludeFiles = True
   yearDirs.excludeLinks = True
   yearDirs.addDirContents(path=stagingDir, recursive=False, addSelf=False)
   for yearDir in yearDirs:
      monthDirs = FilesystemList()
      monthDirs.excludeFiles = True
      monthDirs.excludeLinks = True
      monthDirs.addDirContents(path=yearDir, recursive=False, addSelf=False)
      for monthDir in monthDirs:
         dailyDirs = FilesystemList()
         dailyDirs.excludeFiles = True
         dailyDirs.excludeLinks = True
         dailyDirs.addDirContents(path=monthDir, recursive=False, addSelf=False)
         for dailyDir in dailyDirs:
            if os.path.exists(os.path.join(dailyDir, indicatorFile)):
               logger.debug("Skipping directory [%s]; contains %s.", dailyDir, indicatorFile)
            else:
               logger.debug("Adding [%s] to list of daily directories.", dailyDir)
               results.append(dailyDir) # just put it in the list, no fancy operations
   return results


###########################
# createWriter() function
###########################

def createWriter(config):
   """
   Creates a writer object based on current configuration.

   This function creates and returns a writer based on configuration.  This is
   done to abstract action functionality from knowing what kind of writer is in
   use.  Since all writers implement the same interface, there's no need for
   actions to care which one they're working with.

   Currently, the C{cdwriter} and C{dvdwriter} device types are allowed.  An
   exception will be raised if any other device type is used.

   This function also checks to make sure that the device isn't mounted before
   creating a writer object for it.  Experience shows that sometimes if the
   device is mounted, we have problems with the backup.  We may as well do the
   check here first, before instantiating the writer.

   @param config: Config object.

   @return: Writer that can be used to write a directory to some media.

   @raise ValueError: If there is a problem getting the writer.
   @raise IOError: If there is a problem creating the writer object.
   """
   devicePath = config.store.devicePath
   deviceScsiId = config.store.deviceScsiId
   driveSpeed = config.store.driveSpeed
   noEject = config.store.noEject
   refreshMediaDelay = config.store.refreshMediaDelay
   ejectDelay = config.store.ejectDelay
   deviceType = _getDeviceType(config)
   mediaType = _getMediaType(config)
   if deviceMounted(devicePath):
      raise IOError("Device [%s] is currently mounted." % (devicePath))
   if deviceType == "cdwriter":
      return CdWriter(devicePath, deviceScsiId, driveSpeed, mediaType, noEject, refreshMediaDelay, ejectDelay)
   elif deviceType == "dvdwriter":
      return DvdWriter(devicePath, deviceScsiId, driveSpeed, mediaType, noEject, refreshMediaDelay, ejectDelay)
   else:
      raise ValueError("Device type [%s] is invalid." % deviceType)


################################
# writeIndicatorFile() function
################################

def writeIndicatorFile(targetDir, indicatorFile, backupUser, backupGroup):
   """
   Writes an indicator file into a target directory.
   @param targetDir: Target directory in which to write indicator
   @param indicatorFile: Name of the indicator file
   @param backupUser: User that indicator file should be owned by
   @param backupGroup: Group that indicator file should be owned by
   @raise IOException: If there is a problem writing the indicator file
   """
   filename = os.path.join(targetDir, indicatorFile)
   logger.debug("Writing indicator file [%s].", filename)
   try:
      open(filename, "w").write("")
      changeOwnership(filename, backupUser, backupGroup)
   except Exception, e:
      logger.error("Error writing [%s]: %s", filename, e)
      raise e


############################
# getBackupFiles() function
############################

def getBackupFiles(targetDir):
   """
   Gets a list of backup files in a target directory.

   Files that match INDICATOR_PATTERN (i.e. C{"cback.store"}, C{"cback.stage"},
   etc.) are assumed to be indicator files and are ignored.

   @param targetDir: Directory to look in

   @return: List of backup files in the directory

   @raise ValueError: If the target directory does not exist
   """
   if not os.path.isdir(targetDir):
      raise ValueError("Target directory [%s] is not a directory or does not exist." % targetDir)
   fileList = FilesystemList()
   fileList.excludeDirs = True
   fileList.excludeLinks = True
   fileList.excludeBasenamePatterns = INDICATOR_PATTERN
   fileList.addDirContents(targetDir)
   return fileList


####################
# checkMediaState()
####################

def checkMediaState(storeConfig):
   """
   Checks state of the media in the backup device to confirm whether it has
   been initialized for use with Cedar Backup.

   We can tell whether the media has been initialized by looking at its media
   label.  If the media label starts with MEDIA_LABEL_PREFIX, then it has been
   initialized.

   The check varies depending on whether the media is rewritable or not.  For
   non-rewritable media, we also accept a C{None} media label, since this kind
   of media cannot safely be initialized.

   @param storeConfig: Store configuration

   @raise ValueError: If media is not initialized.
   """
   mediaLabel = readMediaLabel(storeConfig.devicePath)
   if storeConfig.mediaType in REWRITABLE_MEDIA_TYPES:
      if mediaLabel is None:
         raise ValueError("Media has not been initialized: no media label available")
      elif not mediaLabel.startswith(MEDIA_LABEL_PREFIX):
         raise ValueError("Media has not been initialized: unrecognized media label [%s]" % mediaLabel)
   else:
      if mediaLabel is None:
         logger.info("Media has no media label; assuming OK since media is not rewritable.")
      elif not mediaLabel.startswith(MEDIA_LABEL_PREFIX):
         raise ValueError("Media has not been initialized: unrecognized media label [%s]" % mediaLabel)


#########################
# initializeMediaState()
#########################

def initializeMediaState(config):
   """
   Initializes state of the media in the backup device so Cedar Backup can
   recognize it.

   This is done by writing an mostly-empty image (it contains a "Cedar Backup"
   directory) to the media with a known media label.

   @note: Only rewritable media (CD-RW, DVD+RW) can be initialized.  It
   doesn't make any sense to initialize media that cannot be rewritten (CD-R,
   DVD+R), since Cedar Backup would then not be able to use that media for a
   backup.

   @param config: Cedar Backup configuration

   @raise ValueError: If media could not be initialized.
   @raise ValueError: If the configured media type is not rewritable
   """
   if not config.store.mediaType in REWRITABLE_MEDIA_TYPES:
      raise ValueError("Only rewritable media types can be initialized.")
   mediaLabel = buildMediaLabel()
   writer = createWriter(config)
   writer.refreshMedia()
   writer.initializeImage(True, config.options.workingDir, mediaLabel) # always create a new disc
   tempdir = tempfile.mkdtemp(dir=config.options.workingDir)
   try:
      writer.addImageEntry(tempdir, "CedarBackup")
      writer.writeImage()
   finally:
      if os.path.exists(tempdir):
         try:
            os.rmdir(tempdir)
         except: pass


####################
# buildMediaLabel()
####################

def buildMediaLabel():
   """
   Builds a media label to be used on Cedar Backup media.
   @return: Media label as a string.
   """
   currentDate = time.strftime("%d-%b-%Y").upper()
   return "%s %s" % (MEDIA_LABEL_PREFIX, currentDate)


########################################################################
# Private attribute "getter" functions
########################################################################

############################
# _getDeviceType() function
############################

def _getDeviceType(config):
   """
   Gets the device type that should be used for storing.

   Use the configured device type if not C{None}, otherwise use
   L{config.DEFAULT_DEVICE_TYPE}.

   @param config: Config object.
   @return: Device type to be used.
   """
   if config.store.deviceType is None:
      deviceType = DEFAULT_DEVICE_TYPE
   else:
      deviceType = config.store.deviceType
   logger.debug("Device type is [%s]", deviceType)
   return deviceType


###########################
# _getMediaType() function
###########################

def _getMediaType(config):
   """
   Gets the media type that should be used for storing.

   Use the configured media type if not C{None}, otherwise use
   C{DEFAULT_MEDIA_TYPE}.

   Once we figure out what configuration value to use, we return a media type
   value that is valid in one of the supported writers::

      MEDIA_CDR_74
      MEDIA_CDRW_74
      MEDIA_CDR_80
      MEDIA_CDRW_80
      MEDIA_DVDPLUSR
      MEDIA_DVDPLUSRW

   @param config: Config object.

   @return: Media type to be used as a writer media type value.
   @raise ValueError: If the media type is not valid.
   """
   if config.store.mediaType is None:
      mediaType = DEFAULT_MEDIA_TYPE
   else:
      mediaType = config.store.mediaType
   if mediaType == "cdr-74":
      logger.debug("Media type is MEDIA_CDR_74.")
      return MEDIA_CDR_74
   elif mediaType == "cdrw-74":
      logger.debug("Media type is MEDIA_CDRW_74.")
      return MEDIA_CDRW_74
   elif mediaType == "cdr-80":
      logger.debug("Media type is MEDIA_CDR_80.")
      return MEDIA_CDR_80
   elif mediaType == "cdrw-80":
      logger.debug("Media type is MEDIA_CDRW_80.")
      return MEDIA_CDRW_80
   elif mediaType == "dvd+r":
      logger.debug("Media type is MEDIA_DVDPLUSR.")
      return MEDIA_DVDPLUSR
   elif mediaType == "dvd+rw":
      logger.debug("Media type is MEDIA_DVDPLUSRW.")
      return MEDIA_DVDPLUSRW
   else:
      raise ValueError("Media type [%s] is not valid." % mediaType)