path, with the extension given by ext
appended if the path doesn't already have one.
Including the dot in the extension is optional.
This function always allocates a new string, except in the case when path is immutable and already has an extension.