source: trunk/debathena/third/schroot/sbuild/sbuild-util.h @ 24314

Revision 24314, 18.3 KB checked in by geofft, 14 years ago (diff)
In schroot: * Merge with Debian unstable; remaining changes: - Backport to Karmic, and adjust build-deps.
Line 
1/* Copyright © 2005-2007  Roger Leigh <rleigh@debian.org>
2 *
3 * schroot is free software: you can redistribute it and/or modify it
4 * under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * schroot is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 * General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program.  If not, see
15 * <http://www.gnu.org/licenses/>.
16 *
17 *********************************************************************/
18
19#ifndef SBUILD_UTIL_H
20#define SBUILD_UTIL_H
21
22#include <sbuild/sbuild-environment.h>
23#include <sbuild/sbuild-error.h>
24#include <sbuild/sbuild-regex.h>
25#include <sbuild/sbuild-types.h>
26
27#include <string>
28#include <cerrno>
29
30#include <sys/types.h>
31#include <sys/stat.h>
32#include <pwd.h>
33#include <grp.h>
34#include <unistd.h>
35
36namespace sbuild
37{
38
39  /**
40   * Strip the directory path from a filename.  This is similar to
41   * basename(3).
42   *
43   * @param name the filename to strip of its path.
44   * @returns the base name.
45   */
46  std::string
47  basename (std::string name);
48
49  /**
50   * Strip the fileame from a pathname.  This is similar to
51   * dirname(3).
52   *
53   * @param name the path to strip of its filename.
54   * @returns the directory name.
55   */
56  std::string
57  dirname (std::string name);
58
59  /**
60   * Normalise a pathname.  This strips all trailing separators, and
61   * duplicate separators within a path.
62   *
63   * @param name the path to normalise.
64   * @returns the normalised name.
65   */
66  std::string
67  normalname (std::string name);
68
69  /**
70   * Check if a pathname is absolute.
71   *
72   * @param name the path to check.
73   * @returns true if the name is absolute or false if it is not, or
74   * if name is empty.
75   */
76  bool
77  is_absname (std::string const& name);
78
79  /**
80   * Check if a filename matches the allowed pattern(s).  This will
81   * not match dotfiles, backup files, dpkg configuration backup
82   * files, etc.  This uses the same rules as run-parts(8).
83   *
84   * @param name the filename to check.
85   * @param lsb_mode true to use LSB mode, otherwise false.
86   * @returns true if it matches, false if not.
87   */
88  bool
89  is_valid_filename (std::string const& name,
90                     bool               lsb_mode = true);
91
92  /**
93   * Get the current working directory.  If it can't be found, fall
94   * back to root.
95   *
96   * @returns the current working directory.
97   */
98  std::string
99  getcwd ();
100
101
102  /**
103   * Get a unique string for use as a session identifier.  Depending
104   * upon the available facilities, this may be a UUID or a combinatin
105   * of the process ID and system time.
106   *
107   * @returns a session identifier.
108   */
109  std::string
110  unique_identifier ();
111
112  /**
113   * Convert a string_list into a string.  The strings are
114   * concatenated using separator as a delimiter.
115   *
116   * @param list the list to concatenate.
117   * @param separator the delimiting character.
118   * @returns a string.
119   */
120  std::string
121  string_list_to_string (string_list const& list,
122                         std::string const& separator);
123
124  /**
125   * Split a string into a string_list.  The string is split using
126   * separator as a delimiter.  Note that only non-zero-length strings
127   * are preserved, so multiple concatenated delimiters or delimiters
128   * at the beginning and end of the string will not result in empty
129   * strings in the list.
130   *
131   * @param value the string to split.
132   * @param separator the delimiting character or characters.
133   * @returns a string_list.
134   *
135   * @todo Provide an alternative that splits the string in place
136   * using an iterator interface.
137   */
138  template <typename S>
139  std::vector<S>
140  split_string (S const& value,
141                S const& separator)
142  {
143    std::vector<S> ret;
144
145    // Skip any separators at the start
146    typename S::size_type last_pos =
147      value.find_first_not_of(separator, 0);
148    // Find first separator.
149    typename S::size_type pos = value.find_first_of(separator, last_pos);
150
151    while (pos !=S::npos || last_pos != S::npos)
152      {
153        // Add to list
154        ret.push_back(value.substr(last_pos, pos - last_pos));
155        // Find next
156        last_pos = value.find_first_not_of(separator, pos);
157        pos = value.find_first_of(separator, last_pos);
158      }
159
160    return ret;
161  }
162
163  // template
164  std::vector<std::string>
165  split_string (std::string const& value,
166                std::string const& separator);
167
168  /**
169   * Split a string into a string_list.  The string is split using
170   * separator as a delimiter.  All delimiters are used as string
171   * separators, so delimiters at the beginning or end of a string, or
172   * which are concatenated together, will result in empty strings in
173   * the string list.
174   *
175   * @param value the string to split.
176   * @param separator the delimiting character or characters.
177   * @returns a string_list.
178   *
179   * @todo Provide an alternative that splits the string in place
180   * using an iterator interface.
181   */
182  template <typename S>
183  std::vector<S>
184  split_string_strict (S const& value,
185                       S const& separator)
186  {
187    std::vector<S> ret;
188
189    // Skip any separators at the start
190    typename S::size_type last_pos = 0;
191    // Find first separator.
192    typename S::size_type pos = value.find_first_of(separator, last_pos);
193
194    while (pos !=S::npos || last_pos != S::npos)
195      {
196        // Add to list
197        if (pos == std::string::npos)
198          // Entire string from last_pos
199          ret.push_back(value.substr(last_pos, pos));
200        else
201          // Between pos and last_pos
202          ret.push_back(value.substr(last_pos, pos - last_pos));
203
204        // Find next
205        last_pos = pos + separator.length();
206        pos = value.find_first_of(separator, last_pos);
207      }
208
209    return ret;
210  }
211
212  // template
213  std::vector<std::string>
214  split_string_strict (std::string const& value,
215                       std::string const& separator);
216
217  /**
218   * Widen a string.  The narrow string is converted into a wide
219   * string.  Note that any conversion error will cause the string to
220   * be clipped at the point of error.
221   *
222   * @param str the string to widen.
223   * @param locale the locale to use for the conversion.
224   * @returns a wide string.
225   */
226  std::wstring
227  widen_string (std::string const& str,
228                std::locale        locale);
229
230  /**
231   * Narrow a string.  The wide string is converted into a narrow
232   * string.  Note that any conversion error will cause the string to
233   * be clipped at the point of error.
234   *
235   * @param str the string to narrow.
236   * @param locale the locale to use for the conversion.
237   * @returns a narrow string.
238   */
239  std::string
240  narrow_string (std::wstring const& str,
241                 std::locale         locale);
242
243  /**
244   * Find a program in the PATH search path.
245   *
246   * @param program the program to search for.
247   * @param path the search path; typically the value of $PATH.
248   * @param prefix a directory prefix the add to the search path.
249   * This may be left empty to search the root filesystem.
250   * @returns the absolute path of the program, or an empty string if
251   * the program could not be found.
252   */
253  std::string
254  find_program_in_path (std::string const& program,
255                        std::string const& path,
256                        std::string const& prefix);
257
258  /**
259   * Create a string vector from a string_list.  The strings in the
260   * vector, as well as the vector itself, are allocated with new, and
261   * should be freed as a whole with strv_delete.
262   *
263   * @param str the string_list to use.
264   */
265  char **
266  string_list_to_strv (string_list const& str);
267
268  /**
269   * Delete a string vector.  The strings in the vector, as well as
270   * the vector itself, must have been previously allocated with new,
271   * for example sbuild::environment::get_strv.
272   *
273   * @param strv the string vector to delete.
274   */
275  void
276  strv_delete (char **strv);
277
278  /**
279   * execve wrapper.  Run the command specified by file (an absolute
280   * pathname), using command and env as the argv and environment,
281   * respectively.
282   *
283   * @param file the program to execute.
284   * @param command the arguments to pass to the executable.
285   * @param env the environment.
286   * @returns the return value of the execve system call on failure.
287   */
288  int
289  exec (std::string const& file,
290        string_list const& command,
291        environment const& env);
292
293  /**
294   * Get file status.  stat(2) wrapper.
295   */
296  class stat
297  {
298  public:
299    /// Error codes.
300    enum error_code
301      {
302        FILE, ///< Failed to stat file.
303        FD    ///< Failed to stat file descriptor.
304      };
305
306    /// Mode bits.
307    enum mode_bits
308      {
309        FILE_TYPE_MASK      = S_IFMT,   ///< Mask for file type bit fields.
310        FILE_TYPE_SOCKET    = S_IFSOCK, ///< Socket file type.
311        FILE_TYPE_LINK      = S_IFLNK,  ///< Symbolic link file type.
312        FILE_TYPE_REGULAR   = S_IFREG,  ///< Regular file type.
313        FILE_TYPE_BLOCK     = S_IFBLK,  ///< Block device file type.
314        FILE_TYPE_DIRECTORY = S_IFDIR,  ///< Directory file type.
315        FILE_TYPE_CHARACTER = S_IFCHR,  ///< Character device file type.
316        FILE_TYPE_FIFO      = S_IFIFO,  ///< Named pipe (FIFO) file type.
317        PERM_SETUID         = S_ISUID,  ///< Set user ID permission.
318        PERM_SETGIT         = S_ISGID,  ///< Set group ID permission.
319        PERM_STICKY         = S_ISVTX,  ///< Sticky permission.
320        PERM_USER_MASK      = S_IRWXU,  ///< Mask for user permissions.
321        PERM_USER_READ      = S_IRUSR,  ///< User read permission.
322        PERM_USER_WRITE     = S_IWUSR,  ///< User write permission.
323        PERM_USER_EXECUTE   = S_IXUSR,  ///< User execute permission.
324        PERM_GROUP_MASK     = S_IRWXG,  ///< Mask for group permissions.
325        PERM_GROUP_READ     = S_IRGRP,  ///< Group read permission.
326        PERM_GROUP_WRITE    = S_IWGRP,  ///< Group write permission.
327        PERM_GROUP_EXECUTE  = S_IXGRP,  ///< Group execute permission.
328        PERM_OTHER_MASK     = S_IRWXO,  ///< Mask for other permissions.
329        PERM_OTHER_READ     = S_IROTH,  ///< Other read permission.
330        PERM_OTHER_WRITE    = S_IWOTH,  ///< Other write permission.
331        PERM_OTHER_EXECUTE  = S_IXOTH   ///< Other execute permission.
332      };
333
334    /// Exception type.
335    typedef custom_error<error_code> error;
336
337    /**
338     * The constructor.
339     * @param file the filename to use.
340     */
341    stat (const char *file);
342
343    /**
344     * The constructor.
345     * @param file the filename to use.
346     */
347    stat (std::string const& file);
348
349    /**
350     * The constructor.
351     * @param file the filename to use (only used for error
352     * reporting).
353     * @param fd the file descriptor to use.
354     */
355    stat (std::string const& file,
356          int                fd);
357
358    /**
359     * The constructor.
360     * @param fd the file descriptor to use.
361     */
362    stat (int fd);
363
364    /// The destructor.
365    virtual ~stat ();
366
367    /**
368     * Check if the file status was obtained.
369     * An error will be thrown if stat(2) failed to get the file
370     * status.
371     */
372    void check () const
373    {
374      if (this->errorno)
375        {
376          if (!this->file.empty())
377            throw error(this->file, FILE, strerror(this->errorno));
378          else
379            {
380              std::ostringstream str;
381              str << "fd " << fd;
382              throw error(str.str(), FD, strerror(this->errorno));
383            }
384        }
385    }
386
387    /**
388     * Get the struct stat used internally.  This is returned by
389     * stat(2).
390     * @returns the stat struct.
391     */
392    struct ::stat const& get_detail()
393    { return this->status; }
394
395    /**
396     * Get the device the file resides on.
397     * @returns the device.
398     */
399    dev_t
400    device () const
401    { check(); return status.st_dev; }
402
403    /**
404     * Get the inode of the file.
405     * @returns the inode.
406     */
407    ino_t
408    inode () const
409    { check(); return status.st_ino; }
410
411    /**
412     * Get the mode of the file.
413     * @returns the mode.
414     */
415    mode_t
416    mode () const
417    { check(); return status.st_mode; }
418
419    /**
420     * Get the number of hard links to the file.
421     * @returns the hard link count.
422     */
423    nlink_t
424    links () const
425    { check(); return status.st_nlink; }
426
427    /**
428     * Get the user id owning the file.
429     * @returns the uid.
430     */
431    uid_t
432    uid () const
433    { check(); return status.st_uid; }
434
435    /**
436     * Get the group id owning the file.
437     * @returns the uid.
438     */
439    gid_t
440    gid () const
441    { check(); return status.st_gid; }
442
443    /**
444     * Get the file size.
445     * @returns the file size.
446     */
447    off_t
448    size () const
449    { check(); return status.st_size; }
450
451    /**
452     * Get the file block size.
453     * @returns the block size.
454     */
455    blksize_t
456    blocksize () const
457    { check(); return status.st_blksize; }
458
459    /**
460     * Get the file block count.
461     * @returns the block count.
462     */
463    blkcnt_t
464    blocks () const
465    { check(); return status.st_blocks; }
466
467    /**
468     * Get the file access time.
469     * @returns the access time.
470     */
471    time_t
472    atime () const
473    { check(); return status.st_atime; }
474
475    /**
476     * Get the file modification time.
477     * @returns the modification time.
478     */
479    time_t
480    mtime () const
481    { check(); return status.st_mtime; }
482
483    /**
484     * Get the file creation time.
485     * @returns the creation time.
486     */
487    time_t
488    ctime () const
489    { check(); return status.st_ctime; }
490
491    /**
492     * Is the file a regular file?
493     * @returns true if regular, otherwise false.
494     */
495    inline bool
496    is_regular () const;
497
498    /**
499     * Is the file a directory?
500     * @returns true if a directory, otherwise false.
501     */
502    inline bool
503    is_directory () const;
504
505    /**
506     * Is the file a character device?
507     * @returns true if a character device, otherwise false.
508     */
509    inline bool
510    is_character () const;
511
512    /**
513     * Is the file a block device?
514     * @returns true if a block device, otherwise false.
515     */
516    inline bool
517    is_block () const;
518
519    /**
520     * Is the file a named pipe (FIFO)?
521     * @returns true if a named pipe, otherwise false.
522     */
523    inline bool
524    is_fifo () const;
525
526    /**
527     * Is the file a symbolic link?
528     * @returns true if a symbolic link, otherwise false.
529     */
530    inline bool
531    is_link () const;
532
533    /**
534     * Is the file a socket?
535     * @returns true if a socket, otherwise false.
536     */
537    inline bool
538    is_socket () const;
539
540    /**
541     * Check if particular mode bits are set.
542     * @param mask A bitmask containing the bits to check are set.
543     * @returns true if all the bits in mask are set, otherwise false.
544     */
545    inline bool check_mode (mode_bits mask) const;
546
547  private:
548
549    /// The filename being checked (if specified).
550    std::string file;
551    /// The file descriptor being checked (if specified).
552    int fd;
553    /// The error number set after stat(2) error.
554    int errorno;
555    /// The stat(2) results.
556    struct ::stat status;
557  };
558
559  /**
560   * Bitwise-OR of specifed mode bits
561   * @param lhs mode bits
562   * @param rhs mode bits
563   * @returns result of OR.
564   */
565  stat::mode_bits
566  inline operator | (stat::mode_bits const& lhs,
567                     stat::mode_bits const& rhs)
568  {
569    return static_cast<stat::mode_bits>
570      (static_cast<int>(lhs) | static_cast<int>(rhs));
571  }
572
573  /**
574   * Bitwise-OR of specifed mode bits
575   * @param lhs mode bits
576   * @param rhs mode bits
577   * @returns result of OR.
578   */
579  stat::mode_bits
580  inline operator | (mode_t const&          lhs,
581                     stat::mode_bits const& rhs)
582  {
583    return static_cast<stat::mode_bits>
584      (lhs | static_cast<int>(rhs));
585  }
586
587  /**
588   * Bitwise-OR of specifed mode bits
589   * @param lhs mode bits
590   * @param rhs mode bits
591   * @returns result of OR.
592   */
593  stat::mode_bits
594  inline operator | (stat::mode_bits const& lhs,
595                     mode_t const&          rhs)
596  {
597    return static_cast<stat::mode_bits>
598      (static_cast<int>(lhs) | rhs);
599  }
600
601  /**
602   * Bitwise-AND of specifed mode bits
603   * @param lhs mode bits
604   * @param rhs mode bits
605   * @returns result of AND.
606   */
607  stat::mode_bits
608  inline operator & (stat::mode_bits const& lhs,
609                     stat::mode_bits const& rhs)
610  {
611    return static_cast<stat::mode_bits>
612      (static_cast<int>(lhs) & static_cast<int>(rhs));
613  }
614
615  /**
616   * Bitwise-AND of specifed mode bits
617   * @param lhs mode bits
618   * @param rhs mode bits
619   * @returns result of AND.
620   */
621  stat::mode_bits
622  inline operator & (mode_t const&          lhs,
623                     stat::mode_bits const& rhs)
624  {
625    return static_cast<stat::mode_bits>
626      (lhs & static_cast<int>(rhs));
627  }
628
629  /**
630   * Bitwise-AND of specifed mode bits
631   * @param lhs mode bits
632   * @param rhs mode bits
633   * @returns result of AND.
634   */
635  stat::mode_bits
636  inline operator & (stat::mode_bits const& lhs,
637                     mode_t const&          rhs)
638  {
639    return static_cast<stat::mode_bits>
640      (static_cast<int>(lhs) & rhs);
641  }
642
643  inline bool
644  stat::is_regular () const
645  { return check_mode(FILE_TYPE_REGULAR & FILE_TYPE_MASK); }
646
647  inline bool
648  stat::is_directory () const
649  { return check_mode(FILE_TYPE_DIRECTORY & FILE_TYPE_MASK); }
650
651  inline bool
652  stat::is_character () const
653  { return check_mode(FILE_TYPE_CHARACTER & FILE_TYPE_MASK); }
654
655  inline bool
656  stat::is_block () const
657  { return check_mode(FILE_TYPE_BLOCK & FILE_TYPE_MASK); }
658
659  inline bool
660  stat::is_fifo () const
661  { return check_mode(FILE_TYPE_FIFO & FILE_TYPE_MASK); }
662
663  inline bool
664  stat::is_link () const
665  { return check_mode(FILE_TYPE_LINK & FILE_TYPE_MASK); }
666
667  inline bool
668  stat::is_socket () const
669  { return check_mode(FILE_TYPE_SOCKET & FILE_TYPE_MASK); }
670
671  inline bool
672  stat::check_mode (mode_bits mask) const
673  {
674    check();
675    return (static_cast<stat::mode_bits>(status.st_mode) & mask) == mask;
676  }
677
678  /**
679   * System passwd database entry
680   */
681  class passwd : public ::passwd
682  {
683  public:
684    typedef std::vector<char> buffer_type;
685
686    passwd ();
687
688    passwd (uid_t uid);
689
690    passwd (const char *name);
691
692    passwd (std::string const& name);
693
694    void
695    clear ();
696
697    void
698    query_uid (uid_t uid);
699
700    void
701    query_name (const char *name);
702
703    void
704    query_name (std::string const& name);
705
706    bool
707    operator ! () const;
708
709  private:
710    buffer_type buffer;
711    bool        valid;
712  };
713
714  /**
715   * System group database entry
716   */
717  class group : public ::group
718  {
719  public:
720    typedef std::vector<char> buffer_type;
721
722    group ();
723
724    group (gid_t gid);
725
726    group (const char *name);
727
728    group (std::string const& name);
729
730    void
731    clear ();
732
733    void
734    query_gid (gid_t gid);
735
736    void
737    query_name (const char *name);
738
739    void
740    query_name (std::string const& name);
741
742    bool
743    operator ! () const;
744
745  private:
746    buffer_type buffer;
747    bool        valid;
748  };
749
750}
751
752#endif /* SBUILD_UTIL_H */
753
754/*
755 * Local Variables:
756 * mode:C++
757 * End:
758 */
Note: See TracBrowser for help on using the repository browser.