[Vm-dev] [squeak-dev] opening a write-only file

Eliot Miranda eliot.miranda at gmail.com
Fri Jun 6 18:25:23 UTC 2014


On Fri, Jun 6, 2014 at 9:33 AM, Douglas McPherson <djm1329 at san.rr.com>
wrote:

>
>
> On Jun 5, 2014, at 21:03 , David T. Lewis wrote:
>
> > On Thu, Jun 05, 2014 at 06:50:31PM +0200, Bert Freudenberg wrote:
> >>
> >>
> >> On 04.06.2014, at 18:19, Douglas McPherson <djm1329 at san.rr.com> wrote:
> >>
> >>> Hi All,
> >>>
> >>> I've tested a fix for this on OS X and Linux. The fix simply adds an
> extra attempt to open the file after the "w+b" attempt using this code:
> >>>
> >>>         if (getFile(f) == NULL) {
> >>>            setFile(f, fopen(cFileName, "wb"));
> >>>         }
> >>>
> >>> If the previous attempts to open the file failed (because the file
> exists with write-only permission, no read permission) then the above will
> actually open the file write-only. Adding the extra attempt preserves
> existing behaviour for the success paths, so the change should be
> transparent to existing code.
> >>>
> >>> BTW, AFAICT the same issue exists in Pharo.
> >>>
> >>> Thoughts?
> >>>
> >>> Doug
> >>
> >> Sounds reasonable to me.
> >>
> >> - Bert -
> >
> > I have not tested it yet, but I think that this would truncate an
> existing file,
> > so that if the write-only file exists and contains data, the data would
> be lost.
> >
> > Doug, could you check this with your patched VM?
> >
> > Thanks,
> > Dave
> >
>
> Hi Dave,
>
> Yes you are right, I didn't think of that. That is indeed what happens.
>
> We could use "ab" instead of "wb" to get append behaviour if the file
> already exists. I think "a" is still a write-only mode. This is probably
> safer.
>

OK.  Then I propose to commit the following:

--- platforms/Cross/plugins/FilePlugin/sqFilePluginBasicPrims.c (revision
2888)
+++ platforms/Cross/plugins/FilePlugin/sqFilePluginBasicPrims.c (working
copy)
@@ -245,6 +245,9 @@
                           try opening it in write mode to create a new,
empty file.
                        */
                        setFile(f, fopen(cFileName, "w+b"));
+                       /* and if w+b fails, try ab (not wb which deletes
read-only files) */
+                       if (getFile(f) == NULL)
+                               setFile(f, fopen(cFileName, "ab"));
                        if (getFile(f) != NULL) {
                            char type[4],creator[4];
                                dir_GetMacFileTypeAndCreator(sqFileName,
sqFileNameSize, type, creator);

>
> The larger issue of course is that FileStream and its subclasses have no
> protocol for the user to specifically request opening of a a write-only
> file, whether in append mode or overwrite mode. Currently all files that
> are opened must have at least read permission. Should we add something?  If
> so, any suggestions? I'm ok with the simple tweak above rather than adding
> new protocol, though it is really a hack.
>

IMO, some time we should replace the FilePlugin.  The directory interface
sucks.   Buffering sucks.  We should go the VW route of having proper
buffered files above the raw system calls (ReadFile & WriteFile in
win32/64, read & write in unix et al).

Once we have ephemerons then closing buffered files through finalization is
easier, cuz one can flush the buffer on the about-to-be-collcted file.
 That means one can have a registry of open files and easily flush them
before quit (ephemerons are fancy Associations).


> Thanks,
> Doug
>
>
>
>
>
> >>
> >>
> >>>
> >>>
> >>> On Jun 1, 2014, at 19:44 , Douglas McPherson wrote:
> >>>
> >>>> It turns out #forceNewFileNamed: does not work either.
> >>>>
> >>>> I believe the immediate cause of the problem is in the function you
> pointed me at: sqFileOpen() in
> platforms/Cross/plugins/FilePlugin/sqFilePluginBasicPrims.c:
> >>>>
> >>>>    if (writeFlag) {
> >>>>            /* First try to open an existing file read/write: */
> >>>>            setFile(f, fopen(cFileName, "r+b"));
> >>>>            if (getFile(f) == NULL) {
> >>>>                    /* Previous call fails if file does not exist. In
> that case,
> >>>>                       try opening it in write mode to create a new,
> empty file.
> >>>>                    */
> >>>>                    setFile(f, fopen(cFileName, "w+b"));
> >>>>                    if (getFile(f) != NULL) {
> >>>>                        char type[4],creator[4];
> >>>>                            dir_GetMacFileTypeAndCreator(sqFileName,
> sqFileNameSize, type, creator);
> >>>>                            if (strncmp(type,"BINA",4) == 0 ||
> strncmp(type,"????",4) == 0 || *(int *)type == 0 )
> >>>>
>  dir_SetMacFileTypeAndCreator(sqFileName, sqFileNameSize,"TEXT","R*ch");
> >>>>                    }
> >>>>            }
> >>>>
> >>>> The first call to fopen() indeed fails if the file does not exist.
> But it also fails if the file exists but does not have both read and write
> "r+b" permission. So in that case the intent, as you mentioned, is to try
> to open in write-only but "w+b" is not the write-only mode, it is also a
> read and write mode, see [1]. So this fopen() attempt also fails if the
> file has write-only permission. A fix may be to use mode "wb" instead of
> "w+b", but I'm not sure if there are unintended consequences to doing this.
> >>>>
> >>>> [1]
> http://en.wikibooks.org/wiki/C_Programming/C_Reference/stdio.h/fopen
> >>>>
> >>>> On May 31, 2014, at 14:45 , Douglas McPherson wrote:
> >>>>
> >>>>> Ahh, thanks. I'll try it out when back in front of my machine.
> >>>>>
> >>>>> Thanks,
> >>>>> Doug
> >>>>>
> >>>>> Sent from my iPhone
> >>>>>
> >>>>> On May 31, 2014, at 14:23, Eliot Miranda <eliot.miranda at gmail.com>
> wrote:
> >>>>>
> >>>>>> Hi Doug,
> >>>>>>
> >>>>>>
> >>>>>> On Sat, May 31, 2014 at 10:00 AM, Douglas McPherson <
> djm1329 at san.rr.com> wrote:
> >>>>>> Is there a way to open a write-only file in Squeak? On both Mac and
> Linux attempting to open such a file fails.
> >>>>>>
> >>>>>> Squeak has forceNewFileNamed: & forceNewFileNamed:do:.  If you look
> at sqFileOpen in
> platforms/Cross/plugins/FilePlugin/sqFilePluginBasicPrims.c you'll see it
> first attempts to open read-write and if that fails, opens write-only.  So
> it should work.
> >>>>>>
> >>>>>> HTH
> >>>>>>
> >>>>>> For example, if you create a write-only file, i.e. in a shell,
> after cd to default directory
> >>>>>>
> >>>>>> echo nada > foo
> >>>>>> chmod 200 foo
> >>>>>>
> >>>>>> Then from Squeak
> >>>>>>
> >>>>>> StandardFileStream fileNamed: 'foo'
> >>>>>>
> >>>>>> returns nil.
> >>>>>>
> >>>>>> If the file is given read permission (i.e. chmod 600 foo) then
> Squeak can open it.
> >>>>>>
> >>>>>> Anyone know a workaround?
> >>>>>>
> >>>>>> Thanks,
> >>>>>> Doug
> >>>>>>
> >>>>>>
> >>>>>> --
> >>>>>> best,
> >>>>>> Eliot
> >>>>>>
> >>>>>
> >>>>
> >>>>
> >>>
> >>>
> >>
> >>
> >>
> >
> >
> >
> >
>
>


-- 
best,
Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20140606/5d3bcda8/attachment.htm


More information about the Vm-dev mailing list