Skip to content

Commit a863e96

Browse files
committed
Revert "Release 2.2.8"
This reverts commit 4a9c05a.
1 parent 4a9c05a commit a863e96

File tree

1 file changed

+272
-11
lines changed

1 file changed

+272
-11
lines changed

FSExchangeObjectsCompat.c

+272-11
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,273 @@
1+
/*
2+
* FSExchangeObjectsCompat.c
3+
* based on MoreFilesX
4+
*/
5+
6+
#include "FSExchangeObjectsCompat.h"
7+
#include <sys/attr.h>
8+
#include <sys/stat.h>
9+
#include <sys/mount.h>
10+
11+
__private_extern__ u_int32_t volumeCapabilities(const char *path)
12+
{
13+
struct attrlist alist;
14+
bzero(&alist, sizeof(alist));
15+
alist.bitmapcount = ATTR_BIT_MAP_COUNT;
16+
alist.volattr = ATTR_VOL_INFO|ATTR_VOL_CAPABILITIES; // XXX: VOL_INFO must always be set
17+
18+
struct {
19+
u_int32_t v_size;
20+
/* Fixed storage */
21+
vol_capabilities_attr_t v_caps;
22+
} vinfo;
23+
bzero(&vinfo, sizeof(vinfo));
24+
if (0 == getattrlist(path, &alist, &vinfo, sizeof(vinfo), 0)
25+
&& 0 != (alist.volattr & ATTR_VOL_CAPABILITIES)) {
26+
return (vinfo.v_caps.capabilities[VOL_CAPABILITIES_INTERFACES]);
27+
}
28+
29+
return (0);
30+
}
31+
32+
static OSErr GenerateUniqueHFSUniStr(long *startSeed, const FSRef *dir1, const FSRef *dir2, HFSUniStr255 *uniqueName) {
33+
OSErr result;
34+
long i;
35+
FSRefParam pb;
36+
FSRef newRef;
37+
unsigned char hexStr[17] = "0123456789ABCDEF";
38+
39+
/* set up the parameter block */
40+
pb.name = uniqueName->unicode;
41+
pb.nameLength = 8; /* always 8 characters */
42+
pb.textEncodingHint = kTextEncodingUnknown;
43+
pb.newRef = &newRef;
44+
45+
/* loop until we get fnfErr with a filename in both directories */
46+
result = noErr;
47+
while ( fnfErr != result )
48+
{
49+
/* convert startSeed to 8 character Unicode string */
50+
uniqueName->length = 8;
51+
for ( i = 0; i < 8; ++i )
52+
{
53+
uniqueName->unicode[i] = hexStr[((*startSeed >> ((7-i)*4)) & 0xf)];
54+
}
55+
56+
/* try in dir1 */
57+
pb.ref = dir1;
58+
result = PBMakeFSRefUnicodeSync(&pb);
59+
if ( fnfErr == result )
60+
{
61+
/* try in dir2 */
62+
pb.ref = dir2;
63+
result = PBMakeFSRefUnicodeSync(&pb);
64+
if ( fnfErr != result )
65+
{
66+
/* exit if anything other than noErr or fnfErr */
67+
require_noerr(result, Dir2PBMakeFSRefUnicodeSyncFailed);
68+
}
69+
}
70+
else
71+
{
72+
/* exit if anything other than noErr or fnfErr */
73+
require_noerr(result, Dir1PBMakeFSRefUnicodeSyncFailed);
74+
}
75+
76+
/* increment seed for next pass through loop, */
77+
/* or for next call to GenerateUniqueHFSUniStr */
78+
++(*startSeed);
79+
}
80+
81+
/* we have a unique file name which doesn't exist in dir1 or dir2 */
82+
result = noErr;
83+
84+
Dir2PBMakeFSRefUnicodeSyncFailed:
85+
Dir1PBMakeFSRefUnicodeSyncFailed:
86+
87+
return ( result );
88+
}
89+
90+
OSErr FSExchangeObjectsEmulate(const FSRef *sourceRef, const FSRef *destRef, FSRef *newSourceRef, FSRef *newDestRef) {
91+
92+
enum {
93+
/* get all settable info except for mod dates, plus the volume refNum and parent directory ID */
94+
kGetCatInformationMask = (kFSCatInfoSettableInfo |
95+
kFSCatInfoVolume |
96+
kFSCatInfoParentDirID) &
97+
~(kFSCatInfoContentMod | kFSCatInfoAttrMod),
98+
/* set everything possible except for mod dates */
99+
kSetCatinformationMask = kFSCatInfoSettableInfo &
100+
~(kFSCatInfoContentMod | kFSCatInfoAttrMod)
101+
};
102+
103+
OSErr result;
104+
FSCatalogInfo sourceCatalogInfo; /* source file's catalog information */
105+
FSCatalogInfo destCatalogInfo; /* destination file's catalog information */
106+
HFSUniStr255 sourceName; /* source file's Unicode name */
107+
HFSUniStr255 destName; /* destination file's Unicode name */
108+
FSRef sourceCurrentRef; /* FSRef to current location of source file throughout this function */
109+
FSRef destCurrentRef; /* FSRef to current location of destination file throughout this function */
110+
FSRef sourceParentRef; /* FSRef to parent directory of source file */
111+
FSRef destParentRef; /* FSRef to parent directory of destination file */
112+
HFSUniStr255 sourceUniqueName; /* unique name given to source file while exchanging it with destination */
113+
HFSUniStr255 destUniqueName; /* unique name given to destination file while exchanging it with source */
114+
long theSeed; /* the seed for generating unique names */
115+
Boolean sameParentDirs; /* true if source and destinatin parent directory is the same */
116+
117+
/* check parameters */
118+
require_action((NULL != newSourceRef) && (NULL != newDestRef), BadParameter, result = paramErr);
119+
120+
/* output refs and current refs = input refs to start with */
121+
memcpy(newSourceRef, sourceRef, sizeof(FSRef));
122+
memcpy(&sourceCurrentRef, sourceRef, sizeof(FSRef));
123+
124+
memcpy(newDestRef, destRef, sizeof(FSRef));
125+
memcpy(&destCurrentRef, destRef, sizeof(FSRef));
126+
127+
/* Note: The compatibility case won't work for files with *Btree control blocks. */
128+
/* Right now the only *Btree files are created by the system. */
129+
130+
/* get all catalog information and Unicode names for each file */
131+
result = FSGetCatalogInfo(&sourceCurrentRef, kGetCatInformationMask, &sourceCatalogInfo, &sourceName, NULL, &sourceParentRef);
132+
require_noerr(result, SourceFSGetCatalogInfoFailed);
133+
134+
result = FSGetCatalogInfo(&destCurrentRef, kGetCatInformationMask, &destCatalogInfo, &destName, NULL, &destParentRef);
135+
require_noerr(result, DestFSGetCatalogInfoFailed);
136+
137+
/* make sure source and destination are on same volume */
138+
require_action(sourceCatalogInfo.volume == destCatalogInfo.volume, NotSameVolume, result = diffVolErr);
139+
140+
/* make sure both files are *really* files */
141+
require_action((0 == (sourceCatalogInfo.nodeFlags & kFSNodeIsDirectoryMask)) &&
142+
(0 == (destCatalogInfo.nodeFlags & kFSNodeIsDirectoryMask)), NotAFile, result = notAFileErr);
143+
144+
/* generate 2 names that are unique in both directories */
145+
theSeed = 0x4a696d4c; /* a fine unlikely filename */
146+
147+
result = GenerateUniqueHFSUniStr(&theSeed, &sourceParentRef, &destParentRef, &sourceUniqueName);
148+
require_noerr(result, GenerateUniqueHFSUniStr1Failed);
149+
150+
result = GenerateUniqueHFSUniStr(&theSeed, &sourceParentRef, &destParentRef, &destUniqueName);
151+
require_noerr(result, GenerateUniqueHFSUniStr2Failed);
152+
153+
/* rename sourceCurrentRef to sourceUniqueName */
154+
result = FSRenameUnicode(&sourceCurrentRef, sourceUniqueName.length, sourceUniqueName.unicode, kTextEncodingUnknown, newSourceRef);
155+
require_noerr(result, FSRenameUnicode1Failed);
156+
memcpy(&sourceCurrentRef, newSourceRef, sizeof(FSRef));
157+
158+
/* rename destCurrentRef to destUniqueName */
159+
result = FSRenameUnicode(&destCurrentRef, destUniqueName.length, destUniqueName.unicode, kTextEncodingUnknown, newDestRef);
160+
require_noerr(result, FSRenameUnicode2Failed);
161+
memcpy(&destCurrentRef, newDestRef, sizeof(FSRef));
162+
163+
/* are the source and destination parent directories the same? */
164+
sameParentDirs = ( sourceCatalogInfo.parentDirID == destCatalogInfo.parentDirID );
165+
if ( !sameParentDirs )
166+
{
167+
/* move source file to dest parent directory */
168+
result = FSMoveObject(&sourceCurrentRef, &destParentRef, newSourceRef);
169+
require_noerr(result, FSMoveObject1Failed);
170+
memcpy(&sourceCurrentRef, newSourceRef, sizeof(FSRef));
171+
172+
/* move dest file to source parent directory */
173+
result = FSMoveObject(&destCurrentRef, &sourceParentRef, newDestRef);
174+
require_noerr(result, FSMoveObject2Failed);
175+
memcpy(&destCurrentRef, newDestRef, sizeof(FSRef));
176+
}
177+
178+
/* At this point, the files are in their new locations (if they were moved). */
179+
/* The source file is named sourceUniqueName and is in the directory referred to */
180+
/* by destParentRef. The destination file is named destUniqueName and is in the */
181+
/* directory referred to by sourceParentRef. */
182+
183+
/* give source file the dest file's catalog information except for mod dates */
184+
result = FSSetCatalogInfo(&sourceCurrentRef, kSetCatinformationMask, &destCatalogInfo);
185+
require_noerr(result, FSSetCatalogInfo1Failed);
186+
187+
/* give dest file the source file's catalog information except for mod dates */
188+
result = FSSetCatalogInfo(&destCurrentRef, kSetCatinformationMask, &sourceCatalogInfo);
189+
require_noerr(result, FSSetCatalogInfo2Failed);
190+
191+
/* rename source file with dest file's name */
192+
result = FSRenameUnicode(&sourceCurrentRef, destName.length, destName.unicode, destCatalogInfo.textEncodingHint, newSourceRef);
193+
require_noerr(result, FSRenameUnicode3Failed);
194+
memcpy(&sourceCurrentRef, newSourceRef, sizeof(FSRef));
195+
196+
/* rename dest file with source file's name */
197+
result = FSRenameUnicode(&destCurrentRef, sourceName.length, sourceName.unicode, sourceCatalogInfo.textEncodingHint, newDestRef);
198+
require_noerr(result, FSRenameUnicode4Failed);
199+
200+
/* we're done with no errors, so swap newSourceRef and newDestRef */
201+
memcpy(newSourceRef, newDestRef, sizeof(FSRef));
202+
memcpy(newDestRef, &sourceCurrentRef, sizeof(FSRef));
203+
204+
return ( result );
205+
206+
/**********************/
207+
208+
/* If there are any failures while emulating FSExchangeObjects, attempt to reverse any steps */
209+
/* already taken. In any case, newSourceRef and newDestRef will refer to the files in whatever */
210+
/* state and location they ended up in so that both files can be found by the calling code. */
211+
212+
FSRenameUnicode4Failed:
213+
214+
/* attempt to rename source file to sourceUniqueName */
215+
if ( noErr == FSRenameUnicode(&sourceCurrentRef, sourceUniqueName.length, sourceUniqueName.unicode, kTextEncodingUnknown, newSourceRef) )
216+
{
217+
memcpy(&sourceCurrentRef, newSourceRef, sizeof(FSRef));
218+
}
219+
220+
FSRenameUnicode3Failed:
221+
222+
/* attempt to restore dest file's catalog information */
223+
verify_noerr(FSSetCatalogInfo(&destCurrentRef, kFSCatInfoSettableInfo, &destCatalogInfo));
224+
225+
FSSetCatalogInfo2Failed:
226+
227+
/* attempt to restore source file's catalog information */
228+
verify_noerr(FSSetCatalogInfo(&sourceCurrentRef, kFSCatInfoSettableInfo, &sourceCatalogInfo));
229+
230+
FSSetCatalogInfo1Failed:
231+
232+
if ( !sameParentDirs )
233+
{
234+
/* attempt to move dest file back to dest directory */
235+
if ( noErr == FSMoveObject(&destCurrentRef, &destParentRef, newDestRef) )
236+
{
237+
memcpy(&destCurrentRef, newDestRef, sizeof(FSRef));
238+
}
239+
}
240+
241+
FSMoveObject2Failed:
242+
243+
if ( !sameParentDirs )
244+
{
245+
/* attempt to move source file back to source directory */
246+
if ( noErr == FSMoveObject(&sourceCurrentRef, &sourceParentRef, newSourceRef) )
247+
{
248+
memcpy(&sourceCurrentRef, newSourceRef, sizeof(FSRef));
249+
}
250+
}
251+
252+
FSMoveObject1Failed:
253+
254+
/* attempt to rename dest file to original name */
255+
verify_noerr(FSRenameUnicode(&destCurrentRef, destName.length, destName.unicode, destCatalogInfo.textEncodingHint, newDestRef));
256+
257+
FSRenameUnicode2Failed:
258+
259+
/* attempt to rename source file to original name */
260+
verify_noerr(FSRenameUnicode(&sourceCurrentRef, sourceName.length, sourceName.unicode, sourceCatalogInfo.textEncodingHint, newSourceRef));
261+
262+
FSRenameUnicode1Failed:
263+
GenerateUniqueHFSUniStr2Failed:
264+
GenerateUniqueHFSUniStr1Failed:
265+
NotAFile:
266+
NotSameVolume:
267+
DestFSGetCatalogInfoFailed:
268+
SourceFSGetCatalogInfoFailed:
269+
BadParameter:
270+
271+
return ( result );
272+
}
1273

2-
2.2.8 / 2017-09-19
3-
==================
4-
5-
* fix for high sierra
6-
* HTTPS updates, remove fieldEditor issues for 10.13
7-
* version bump
8-
* Fix not focusing control field when activating from hotkey or statusitem
9-
* Merge pull request #414 from troy/2.2.5
10-
* Clarify that on-the-wire communication with Simplenote is encrypted (#207)
11-
* bump version numbers
12-
* statusitem fix

0 commit comments

Comments
 (0)