Closed Bug 808321 Opened 12 years ago Closed 11 years ago

Expose validity of creationDate to applications

Categories

(Toolkit Graveyard :: OS.File, defect)

defect
Not set
normal

Tracking

(Not tracked)

RESOLVED WORKSFORME

People

(Reporter: rnewman, Unassigned)

References

Details

On some OS/FS combinations, an accurate file creation date cannot be returned.

In these situations, OS.File will return a 'bad' value (e.g., epoch), a 'wrong' value (e.g., mtime), or no value. See Bug 807456.

Calling applications will need to know whether the returned value is good, wrong, or bad, in order to implement alternative approaches.

OS.File should provide this information. Possible methods:

* A flag on the Info object
* 'Sentinel' return values (e.g., a specific class-owned Date instance, null, undefined)
* Metadata attached to the Date instance.
I'd like to suggest that .creationDate should just not be exposed on the JS object at all if it isn't going to be correct. Then you can feature-test for it using ('creationDate' in statResult)
API-wise, bsmedberg's remark makes sense. The only difficulty with this is that we already have a method |creationDate| in the code (which often returns incorrect results). Of course, this does not mean that we cannot introduce |fileCreationDate| or something such.

Now, another issue is: how do we determine that we do not have access to the creation date?
- under Linux, no creation date (easy);
- under MacOS X < 10.5.5, no creation date (easy);
- under MacOS X >= 10.5.5, with old file systems, no creation date (annoying);
- otherwise there is a creation date (easy).
(In reply to David Rajchenbach Teller [:Yoric] from comment #2)
> - under Linux, no creation date (easy);
> - under MacOS X < 10.5.5, no creation date (easy);
> - under MacOS X >= 10.5.5, with old file systems, no creation date
> (annoying);
> - otherwise there is a creation date (easy).

Not so easy. Creation time is filesystem specific. Different filesystems have different semantics. ctime on many Linux filesystems is the created time of the inode. The inode gets updated whenever metadata changes (chmod, etc). But, not all filesystems are like this. For example, ZFS has different fields for file {modification (content), changed (metadata), created}. See the znode_phys struct. I don't know how this gets mapped to a stat() return value.

Good luck!
I didn't mean to solve such sophisticated issues, only to expose the result of |stat().st_birthtime|.
(In reply to David Rajchenbach Teller [:Yoric] from comment #4)
> I didn't mean to solve such sophisticated issues, only to expose the result
> of |stat().st_birthtime|.

Even that's a little dodgy -- you're reflecting platform-specific wonkyness (even exposing the contents of kernel uninitialized memory!). On some filesystems, birthtime is transparently populated in `stat` with ctime (man 2 stat).

It would be awful-slash-crazy to implement cross-platform software that didn't check for this.

((
Random horror:

http://freebsd.monkey.org/freebsd-bugs/200803/msg00639.html
http://lists.samba.org/archive/samba-technical/2008-August/061041.html
))



I think Greg's point (and mine, to an extent) is that it's misleading to expose a high-level JS API that claims to give you "creationDate", and actually fill it with what could be unattributed garbage (literally true in those BSD examples), depending on hidden details of the browser's host environment.


That is, I should be able to expect that the following is true *on any platform*:

  OS.File.writeAtomic("file.txt", …);

  // Or fetch the date from the file.
  let now = Date.now();

  // Arbitrary OS operations, such as permissions changes and additional writes…
  // …

  // And the creation date is unchanged.
  OS.File.stat("file.txt").then(function onSuccess(info) {
    if (info.creationDate) {     // Or whatever test…
      do_check_eq(now, info.creationDate);
    }
  });


I would be happy with a compromise: return the contents of birthtime, and additionally include a flag that's true iff that value is known to be a true birthtime (that is, if OS + FS + access libraries all agree that it is). But call that info.birthtime.

For most uses, we're probably fine just getting a best-effort value, but it would be disingenuous to claim that it's categorically the creation date if you're not sure that it is.
I'm fine with calling it |birthtime|, although I still have no clue how to detect that we are on an appropriate file system. It would not be acceptable to detect the file system each time we call |OS.File.stat|, for instance, as this would kill our performance for most applications of the function.
Blocks: 827805
OS.File has supported for quite some time the ability to detect whether the operating system offers the creation date: check whether fields |macBirthDate| or |winBirthDate| are defined.

However, as I have discussed with members of the FHR team, this is really a very very fragile mechanism that should be avoided, as there is no acceptable way to detect whether the *file system* supports creation date or what kind of data is returned when creation date is not supported. Relying on this feature is a good recipe to create subtle and impossible-to-reproduce user bugs.

Closing this bug as FIXED.
Status: NEW → RESOLVED
Closed: 11 years ago
Resolution: --- → FIXED
Resolution: FIXED → WORKSFORME
Product: Toolkit → Toolkit Graveyard
You need to log in before you can comment on or make changes to this bug.