first check-in of feisty meow codebase. many things broken still due to recent
[feisty_meow.git] / core / library / filesystem / file_time.cpp
1 /*****************************************************************************\
2 *                                                                             *
3 *  Name   : file_time                                                         *
4 *  Author : Chris Koeritz                                                     *
5 *                                                                             *
6 *******************************************************************************
7 * Copyright (c) 1992-$now By Author.  This program is free software; you can  *
8 * redistribute it and/or modify it under the terms of the GNU General Public  *
9 * License as published by the Free Software Foundation; either version 2 of   *
10 * the License or (at your option) any later version.  This is online at:      *
11 *     http://www.fsf.org/copyleft/gpl.html                                    *
12 * Please send any updates to: fred@gruntose.com                               *
13 \*****************************************************************************/
14
15 #include "file_time.h"
16
17 #include <basis/astring.h>
18 #include <basis/byte_array.h>
19 #include <basis/functions.h>
20 #include <basis/guards.h>
21 #include <basis/astring.h>
22 #include <structures/object_packers.h>
23
24 #include <stdio.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #ifdef __UNIX__
28   #include <utime.h>
29 #endif
30 #ifdef __WIN32__
31   #include <sys/utime.h>
32 #endif
33
34 #undef LOG
35 #define LOG(to_print) printf("%s::%s: %s\n", static_class_name(), func, astring(to_print).s())
36
37 using namespace basis;
38
39 namespace filesystem {
40
41 file_time::file_time() : _when(0) { reset(""); } 
42
43 file_time::file_time(FILE *the_FILE) : _when(0) { reset(the_FILE); }
44
45 file_time::file_time(const time_t &t) : _when(t) {}
46
47 file_time::file_time(const astring &filename)
48 : _when(0)
49 {
50   FILE *ptr = fopen(filename.s(), "r");
51   if (ptr) {
52     reset(ptr);
53     fclose(ptr);
54   }
55 }
56
57 file_time::~file_time() {}
58
59 bool file_time::set_time(const basis::astring &filename)
60 {
61   // prepare the access time and modified time to match our stamp.
62   utimbuf held_time;
63   held_time.actime = raw();
64   held_time.modtime = raw();
65   // stuff our timestamp on the file.
66   return !utime(filename.s(), &held_time);
67 }
68
69 void file_time::reset(const time_t &t) { _when = t; }
70
71 void file_time::reset(const astring &filename)
72 {
73   FILE *ptr = fopen(filename.s(), "r");
74   if (ptr) {
75     reset(ptr);
76     fclose(ptr);
77   }
78 }
79
80 void file_time::reset(FILE *the_FILE_in)
81 {
82   FUNCDEF("reset");
83   _when = 0;
84   FILE *the_file = (FILE *)the_FILE_in;
85   if (!the_file) {
86     return;
87   }
88   struct stat stat_buffer;
89   if (fstat(fileno(the_file), &stat_buffer) < 0) {
90     LOG("stat failure on file");
91   }
92   _when = stat_buffer.st_mtime;
93 }
94
95 int file_time::compare(const file_time &b) const
96 {
97   if (_when > b._when) return 1;
98   else if (_when == b._when) return 0;
99   else return -1;
100 }
101
102 bool file_time::less_than(const orderable &ft2) const
103 {
104   const file_time *cast = dynamic_cast<const file_time *>(&ft2);
105   if (!cast) return false;
106   return bool(compare(*cast) < 0);
107 }
108
109 bool file_time::equal_to(const equalizable &ft2) const
110 {
111   const file_time *cast = dynamic_cast<const file_time *>(&ft2);
112   if (!cast) return false;
113   return bool(compare(*cast) == 0);
114 }
115
116 void file_time::text_form(basis::base_string &time_string) const
117 {
118   time_string.assign(basis::astring(class_name()) + basis::a_sprintf("@%x", _when));
119 }
120
121 void file_time::readable_text_form(basis::base_string &time_string) const
122 {
123   tm *now = localtime(&_when);  // convert to time round hereparts.
124   time_string.assign(a_sprintf("%d.%02d.%02d %02d:%02d:%02d",
125       now->tm_year+1900, now->tm_mon+1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec));
126 }
127
128 // magic value unfortunately, but this is the length of a packed string with 10 characters.
129 // we do this because the size of 2^32 in decimal requires that many characters, and we also
130 // want to just have a fixed length chunk for this.  we are not worried about larger pieces
131 // than that because we cannot conveniently handle them anyhow.
132 int file_time::packed_size() const { return 11; }
133
134 void file_time::pack(byte_array &packed_form) const
135 { a_sprintf("%010d", _when).pack(packed_form); }
136
137 bool file_time::unpack(byte_array &packed_form)
138 {
139   astring tempo;
140   if (!tempo.unpack(packed_form)) return false;
141   _when = tempo.convert(0L);
142   return true;
143 }
144
145 } //namespace
146