alsa.audio: move handling of XRUN when writting to the slave task
[AROS.git] / rom / filesys / SFS / SFSfindobjects / SFSfindobjects.c
blobf5330611cb51973df51ed86cf245c707d7e689bc
1 #include <devices/scsidisk.h>
2 #include <devices/trackdisk.h>
3 #include <dos/dos.h>
4 #include <dos/dosextens.h>
5 #include <dos/filehandler.h>
6 #include <exec/errors.h>
7 #include <exec/io.h>
8 #include <exec/memory.h>
9 #include <proto/dos.h>
10 #include <clib-org/exec_protos.h>
11 #include "stdio.h"
14 /* Almost ALL functions in this source are support functions
15 which were quickly copied from the main SFS source. The
16 most interesting function is findobjects(), which performs
17 the actual function of this program. */
20 #include "/fs/objects.h"
21 #include "/fs/deviceio.h"
22 #include "/fs/fs.h"
23 #include "/fs/btreenodes.h"
25 #include <devices/newstyle.h> /* Doesn't include exec/types.h which is why it is placed here */
27 #include "/fs/bitfuncs.c"
29 #define BLCKFACCURACY (5) /* 2^5 = 32 */
33 /* ASM prototypes */
35 extern ULONG __asm RANDOM(register __d0 ULONG);
36 extern LONG __asm STACKSWAP(void);
37 extern ULONG __asm CALCCHECKSUM(register __d0 ULONG,register __a0 ULONG *);
38 extern ULONG __asm MULU64(register __d0 ULONG,register __d1 ULONG,register __a0 ULONG *);
39 extern WORD __asm COMPRESSFROMZERO(register __a0 UWORD *,register __a1 UBYTE *,register __d0 ULONG);
43 LONG safedoio(UWORD action,UBYTE *buffer,ULONG blocks,ULONG blockoffset);
44 void findobjects(UBYTE *pattern);
46 struct DosEnvec *dosenvec;
48 /* blocks_ = the number of blocks of something (blocks can contain 1 or more sectors)
49 block_ = a block number of something (relative to start of partition)
50 sectors_ = the number of sectors of something (1 or more sectors form a logical block)
51 sector_ = a sector number (relative to the start of the disk)
52 bytes_ = the number of bytes of something
53 byte_ = a byte number of something
54 shifts_ = the number of bytes written as 2^x of something
55 mask_ = a mask for something */
57 ULONG sectors_total; /* size of the partition in sectors */
58 UWORD sectors_block; /* number of sectors in a block */
59 UWORD pad4;
61 ULONG blocks_total; /* size of the partition in blocks */
62 ULONG blocks_reserved_start; /* number of blocks reserved at start (=reserved) */
63 ULONG blocks_reserved_end; /* number of blocks reserved at end (=prealloc) */
64 ULONG blocks_used; /* number of blocks in use excluding reserved blocks
65 (=numblockused) */
66 ULONG blocks_maxtransfer=1048576; /* max. blocks which may be transfered to the device at once (limits io_Length) */
68 ULONG block_root; /* the block offset of the root block */
69 ULONG block_extentbnoderoot; /* the block offset of the root of the extent bnode tree */
71 ULONG byte_low; /* the byte offset of our partition on the disk */
72 ULONG byte_lowh; /* high 32 bits */
73 ULONG byte_high; /* the byte offset of the end of our partition (excluding) on the disk */
74 ULONG byte_highh; /* high 32 bits */
76 ULONG bytes_block; /* size of a block in bytes */
77 ULONG bytes_sector; /* size of a sector in bytes */
79 ULONG mask_block;
80 ULONG mask_block32; /* masks the least significant bits of a BLCKf pointer */
81 ULONG mask_mask=0xFFFFFFFF; /* mask as specified by mountlist */
82 ULONG mask_debug;
84 UWORD shifts_block; /* shift count needed to convert a blockoffset<->byteoffset */
85 UWORD shifts_block32; /* shift count needed to convert a blockoffset<->32byteoffset (only used by nodes.c!) */
87 ULONG disktype; /* the type of media inserted (same as id_DiskType in InfoData
88 structure) */
89 UBYTE newstyledevice=FALSE;
90 UBYTE does64bit=FALSE;
91 UBYTE is_casesensitive=FALSE;
92 UBYTE pad1;
93 UWORD cmdread=CMD_READ;
94 UWORD cmdwrite=CMD_WRITE;
97 struct MsgPort *msgport;
98 struct IOStdReq *ioreq;
99 void *pool;
101 ULONG block_objectnodesbase;
102 ULONG block_extentroot;
104 UBYTE *buffer;
105 ULONG *bitmap;
107 ULONG returncode=0;
109 LONG main() {
110 struct RDArgs *readarg;
111 UBYTE template[]="DEVICE=DRIVE/A,NAMEPATTERN/A\n";
113 struct {char *device;
114 char *name;} arglist={NULL};
116 if((DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",37))!=0) {
117 if((pool=CreatePool(0,16384,8192))!=0) {
118 if((readarg=ReadArgs(template,(LONG *)&arglist,0))!=0) {
119 struct MsgPort *msgport;
120 struct DeviceNode *dn;
121 UBYTE *devname=arglist.device;
123 while(*devname!=0) {
124 if(*devname==':') {
125 *devname=0;
126 break;
128 devname++;
131 dn=(struct DeviceNode *)LockDosList(LDF_DEVICES|LDF_READ);
132 if((dn=(struct DeviceNode *)FindDosEntry((struct DosList *)dn,arglist.device,LDF_DEVICES))!=0) {
133 struct FileSysStartupMsg *fssm;
135 fssm=(struct FileSysStartupMsg *)BADDR(dn->dn_Startup);
136 dosenvec=(struct DosEnvec *)BADDR(fssm->fssm_Environ);
138 UnLockDosList(LDF_DEVICES|LDF_READ);
140 if((msgport=CreateMsgPort())!=0) {
141 if((ioreq=CreateIORequest(msgport,sizeof(struct IOStdReq)))!=0) {
142 if(OpenDevice((UBYTE *)BADDR(fssm->fssm_Device)+1,fssm->fssm_Unit,(struct IORequest *)ioreq,fssm->fssm_Flags)==0) {
144 struct DosEnvec *de=dosenvec;
145 UWORD bs;
146 ULONG sectorspercilinder;
148 bytes_sector=de->de_SizeBlock<<2;
149 bytes_block=bytes_sector*de->de_SectorPerBlock;
151 bs=bytes_block;
153 shifts_block=0;
154 while((bs>>=1)!=0) {
155 shifts_block++;
157 shifts_block32=shifts_block-BLCKFACCURACY;
159 mask_block32=(1<<shifts_block32)-1;
160 mask_block=bytes_block-1;
162 /* Absolute offset on the entire disk are expressed in Sectors;
163 Offset relative to the start of the partition are expressed in Blocks */
165 sectorspercilinder=de->de_Surfaces*de->de_BlocksPerTrack; /* 32 bit */
166 sectors_total=sectorspercilinder*(de->de_HighCyl+1-de->de_LowCyl); /* 32 bit */
168 /* sectorspercilinder * bytes_sector cannot exceed 32-bit !! */
170 byte_lowh = MULU64(sectorspercilinder * bytes_sector, de->de_LowCyl, &byte_low);
171 byte_highh = MULU64(sectorspercilinder * bytes_sector, de->de_HighCyl+1, &byte_high);
173 sectors_block=de->de_SectorPerBlock;
175 blocks_total=sectors_total/de->de_SectorPerBlock;
176 blocks_reserved_start=de->de_Reserved;
177 blocks_reserved_end=de->de_PreAlloc;
179 if(blocks_reserved_start<1) {
180 blocks_reserved_start=1;
183 if(blocks_reserved_end<1) {
184 blocks_reserved_end=1;
187 blocks_used=0;
189 printf("Partition start offset : 0x%08lx:%08lx End offset : 0x%08lx:%08lx\n",byte_lowh,byte_low,byte_highh,byte_high);
190 printf("sectors/block : %ld\n",de->de_SectorPerBlock);
191 printf("bytes/sector : %ld\n",bytes_sector);
192 printf("bytes/block : %ld\n",bytes_block);
193 printf("Total blocks in partition : %ld\n",blocks_total);
198 /* If the partition's high byte is beyond the 4 GB border we will
199 try and detect a 64-bit device. */
201 if(byte_highh!=0) {
202 struct NSDeviceQueryResult nsdqr;
203 UWORD *cmdcheck;
204 LONG errorcode;
206 /* Checks for newstyle devices and 64-bit support */
208 nsdqr.SizeAvailable=0;
209 nsdqr.DevQueryFormat=0;
211 ioreq->io_Command=NSCMD_DEVICEQUERY;
212 ioreq->io_Length=sizeof(nsdqr);
213 ioreq->io_Data=(APTR)&nsdqr;
215 if(DoIO((struct IORequest *)ioreq)==0 && (ioreq->io_Actual >= 16) && (nsdqr.SizeAvailable == ioreq->io_Actual) && (nsdqr.DeviceType == NSDEVTYPE_TRACKDISK)) {
216 /* This must be a new style trackdisk device */
218 newstyledevice=TRUE;
220 printf("Device is a new style device (NSD)\n");
222 /* Is it safe to use 64 bits with this driver? We can reject
223 bad mounts pretty easily via this check. */
225 for(cmdcheck=nsdqr.SupportedCommands; *cmdcheck; cmdcheck++) {
226 if(*cmdcheck == NSCMD_TD_READ64) {
227 /* This trackdisk style device supports the complete 64-bit
228 command set without returning IOERR_NOCMD! */
230 printf("Device supports 64-bit commands\n");
232 does64bit=TRUE;
233 cmdread=NSCMD_TD_READ64;
234 cmdwrite=NSCMD_TD_WRITE64;
238 else {
239 /* Checks for TD64 supporting devices */
241 ioreq->io_Command=24; /* READ64 */
242 ioreq->io_Length=0;
243 ioreq->io_Actual=0;
244 ioreq->io_Offset=0;
245 ioreq->io_Data=0;
247 errorcode=DoIO((struct IORequest *)ioreq);
248 if(errorcode!=-1 && errorcode!=IOERR_NOCMD) {
249 printf("Device supports 64-bit commands\n");
251 does64bit=TRUE;
252 cmdread=24;
253 cmdwrite=25;
258 if((buffer=AllocVec(bytes_block,0))!=0) {
259 findobjects(arglist.name);
261 else {
262 printf("Not enough memory\n");
265 CloseDevice((struct IORequest *)ioreq);
267 DeleteIORequest(ioreq);
269 DeleteMsgPort(msgport);
272 else {
273 VPrintf("Unknown device %s\n",&arglist.device);
274 UnLockDosList(LDF_DEVICES|LDF_READ);
277 FreeArgs(readarg);
279 DeletePool(pool);
281 CloseLibrary((struct Library *)DOSBase);
283 return(returncode);
289 else if(SetSignal(0L,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
290 PutStr("\n***Break\n");
291 break;
296 BOOL validblock(ULONG block) {
297 if(block<blocks_total) {
298 return(TRUE);
300 return(FALSE);
306 LONG doio(void) {
307 // LONG errorcode;
309 return(DoIO((struct IORequest *)ioreq));
312 while((errorcode=DoIO((struct IORequest *)ioreq))!=0) {
313 if(errorcode==TDERR_WriteProt) {
314 if(request(PROGRAMNAME " request","%s\n"\
315 "is write protected.\n",
316 "Retry|Cancel",((UBYTE *)BADDR(devnode->dn_Name))+1)<=0) {
317 return(errorcode);
320 else if(errorcode==TDERR_DiskChanged) {
321 if(request(PROGRAMNAME " request","You MUST insert volume %s\n"\
322 "There still was some data which needs to be transfered!\n",
323 "Retry|Cancel",((UBYTE *)BADDR(devnode->dn_Name))+1)<=0) {
324 return(errorcode);
327 else {
328 if(request(PROGRAMNAME " request","%s\n"\
329 "returned an error while volume %s was accessing it.\n\n"\
330 "errorcode = %ld\n"\
331 "io_Command = %ld\n"\
332 "io_Offset = %ld\n"\
333 "io_Length = %ld\n"\
334 "io_Actual = %ld\n",
335 "Retry|Cancel",(UBYTE *)BADDR(startupmsg->fssm_Device)+1,((UBYTE *)BADDR(devnode->dn_Name))+1,errorcode,(ULONG)ioreq->io_Command,ioreq->io_Offset,ioreq->io_Length,ioreq->io_Actual)<=0) {
337 return(errorcode);
340 } */
346 LONG safedoio(UWORD action,UBYTE *buffer,ULONG blocks,ULONG blockoffset) {
347 ULONG command;
348 ULONG start,starthigh;
349 ULONG end,endhigh;
350 LONG errorcode;
352 if(action==DIO_READ) {
353 command=cmdread;
355 else if(action==DIO_WRITE) {
356 command=cmdwrite;
358 else {
359 return(-1);
363 start=(blockoffset<<shifts_block)+byte_low;
364 starthigh=(blockoffset>>(32-shifts_block))+byte_lowh; /* High offset */
365 if(start < byte_low) {
366 starthigh+=1; /* Add X bit :-) */
369 end=start+(blocks<<shifts_block);
370 endhigh=starthigh;
371 if(end < start) {
372 endhigh+=1; /* Add X bit */
375 ioreq->io_Data=buffer;
376 ioreq->io_Command=command;
377 ioreq->io_Length=blocks<<shifts_block;
378 ioreq->io_Offset=start;
379 ioreq->io_Actual=starthigh;
381 if( ( starthigh > byte_lowh || (starthigh == byte_lowh && start >= byte_low) ) &&
382 ( endhigh < byte_highh || (endhigh == byte_highh && end <= byte_high) ) ) {
384 /* We're about to do a physical disk access. (Re)set timeout. Since
385 the drive's motor will be turned off with the timeout as well we
386 always (re)set the timeout even if doio() would return an error. */
388 if((errorcode=doio())!=0) {
389 return(errorcode);
392 else {
393 // DEBUG(("byte_low = 0x%08lx:%08lx, byte_high = 0x%08lx:%08lx\n",byte_lowh,byte_low,byte_highh,byte_high));
394 // DEBUG(("start = 0x%08lx:%08lx, end = 0x%08lx:%08lx\n",starthigh,start,endhigh,end));
396 return(INTERR_OUTSIDE_PARTITION);
399 return(0);
405 BOOL checkchecksum(void *d) {
406 ULONG *data=(ULONG *)d;
408 if(CALCCHECKSUM(bytes_block,data)==0) {
409 return(TRUE);
411 return(FALSE);
416 struct fsObject *nextobject(struct fsObject *o) {
417 UBYTE *p;
419 /* skips the passed in fsObject and gives a pointer back to the place where
420 a next fsObject structure could be located */
422 p=(UBYTE *)&o->name[0];
424 /* skip the filename */
425 while(*p++!=0) {
428 /* skip the comment */
429 while(*p++!=0) {
432 /* ensure WORD boundary */
433 if((((ULONG)p) & 0x01)!=0) {
434 p++;
437 return((struct fsObject *)p);
442 WORD isobject(struct fsObject *o, struct fsObjectContainer *oc) {
443 UBYTE *endadr;
445 endadr=(UBYTE *)oc+bytes_block-sizeof(struct fsObject)-2;
447 if((UBYTE *)o<endadr && o->name[0]!=0) {
448 return(TRUE);
450 return(FALSE);
455 LONG findnode(BLCK nodeindex,UWORD nodesize,NODE nodeno,struct fsNode **returned_node) {
456 LONG errorcode;
458 /* Finds a specific node by number. It returns the cachebuffer which contains the fsNode
459 structure and a pointer to the fsNode structure directly. */
461 while((errorcode=read(nodeindex))==0) {
462 struct fsNodeContainer *nc=(struct fsNodeContainer *)buffer;
464 if(nc->nodes==1) {
465 /* We've descended the tree to a leaf NodeContainer */
467 *returned_node=(struct fsNode *)((UBYTE *)nc->node+nodesize*(nodeno-nc->nodenumber));
469 return(0);
471 else {
472 UWORD containerentry=(nodeno-nc->nodenumber)/nc->nodes;
474 nodeindex=nc->node[containerentry]>>shifts_block32;
478 return(errorcode);
483 void datetodatestamp(ULONG date, struct DateStamp *datestamp) {
484 ULONG seconds;
486 datestamp->ds_Days = date/86400;
488 seconds=date - (datestamp->ds_Days * 86400);
490 datestamp->ds_Minute = (ULONG)((UWORD)(seconds/60));
491 datestamp->ds_Tick = (ULONG)((UWORD)(seconds%60)*50);
496 void findobjects(UBYTE *pattern) {
497 struct DateTime dt;
498 UBYTE dest[512];
499 UBYTE date[20];
500 UBYTE time[20];
501 LONG errorcode;
503 if((ParsePatternNoCase(pattern, dest, 510))!=-1) {
504 ULONG stepsize;
505 UBYTE *buf;
507 stepsize=131072/bytes_block;
509 if((buf=AllocVec(131072,0))!=0) {
510 ULONG blockstoread;
511 ULONG n;
513 for(n=0; n<blocks_total; n+=stepsize) {
514 blockstoread=stepsize;
516 if(n+blockstoread > blocks_total) {
517 blockstoread=blocks_total-n;
520 if((errorcode=safedoio(DIO_READ, buf, blockstoread, n))==0) {
521 struct fsBlockHeader *bh;
522 ULONG m;
524 for(m=0; m<blockstoread; m++) {
525 bh=(struct fsBlockHeader *)(buf+(m<<shifts_block));
527 if(bh->id==OBJECTCONTAINER_ID && bh->ownblock==n+m && checkchecksum(bh)) {
528 struct fsObjectContainer *oc=(struct fsObjectContainer *)bh;
529 struct fsObject *o=oc->object;
531 /* It looks like a valid ObjectContainer block. Let's see if there
532 is a file in there which we are looking for. */
534 while(isobject(o,oc)!=FALSE) {
535 datetodatestamp(o->datemodified, &dt.dat_Stamp);
537 dt.dat_Format=FORMAT_DOS;
538 dt.dat_Flags=0;
539 dt.dat_StrDay=0;
540 dt.dat_StrDate=date;
541 dt.dat_StrTime=time;
543 DateToStr(&dt);
545 if((o->bits & OTYPE_DIR)==0) {
546 if((MatchPatternNoCase(dest, o->name))!=0) {
547 printf("Found file '%s' (%ld bytes, %s %s) in block %ld. ObjectNode %ld, FirstDataBlock %ld.\n", o->name, o->object.file.size, date, time, n+m, o->objectnode, o->object.file.data);
550 o=nextobject(o);
555 else {
556 PrintFault(errorcode, "Error while reading data");
560 FreeVec(buf);
562 else {
563 printf("Couldn't allocate memory for read buffer\n");
566 else {
567 PrintFault(IoErr(), "Couldn't parse pattern");