/* * Delete.c -- for BlackHole.c. * $Revision: 1.1 */ #include "header.h" #include "prog-protos.h" /* Prototypes */ Prototype LONG delete (struct HoleArg *); Local LONG delete_file (struct WBArg *); Local LONG delete_icon (struct WBArg *); Local LONG delete_dir (struct WBArg *); Local LONG delete_contents (BPTR , BOOL ); /* Globals */ BOOL ignore_protection; #define EXALL_NUM 16 /* examine 16 files at a time (I think) */ /* Entry point */ LONG delete (struct HoleArg *harg) { set_current (NULL, SET_START); /* reset current file */ ignore_protection = harg->prefs.ignore_prot; return (delete_file (&(harg->wbarg))); } /* Local functions */ /* delete_contents -- delete the contents of a directory with lock lock. */ /* If byicons is FALSE, search for ~(#?.info) & delete both name found and */ /* name.info, if byicons is true, delete any file of pattern #?.info */ LONG delete_contents (BPTR lock, BOOL byicons) { BPTR old_lock = CurrentDir (lock); struct ExAllControl *eac = 0; struct ExAllData *eadata = 0; struct WBArg *arg = 0; LONG error = 0; BOOL more; BYTE pattern[50]; if (!(eac = (struct ExAllControl *) AllocDosObject (DOS_EXALLCONTROL, NULL))) goto fail; if (!(eadata = (struct ExAllData *) malloc (EXALL_NUM * sizeof (struct ExAllData)))) goto fail; if (!(arg = (struct WBArg *)malloc (sizeof (struct WBArg)))) goto fail; if (byicons) ParsePatternNoCase ("#?.info", pattern, 49); else ParsePatternNoCase ("~(#?.info)", pattern, 49); eac->eac_LastKey = 0; eac->eac_MatchString = pattern; eac->eac_MatchFunc = NULL; do { register struct ExAllData *ead; more = ExAll (lock, eadata, EXALL_NUM * sizeof (struct ExAllData), ED_TYPE, eac); if (!more) { if ((error = IoErr()) != ERROR_NO_MORE_ENTRIES) break; else error = 0; } if (eac->eac_Entries == 0) continue; /* have we finished? */ ead = eadata; do { if (ead->ed_Type >=0) /* is it a directory? */ { arg->wa_Lock = Lock (ead->ed_Name, SHARED_LOCK); arg->wa_Name = NULL; if (arg->wa_Lock) { if (error = delete_file (arg)) { more = FALSE; break; UnLock (arg->wa_Lock); } } } else /* it must be a file. */ { arg->wa_Lock = lock; arg->wa_Name = ead->ed_Name; if (byicons) { if (error = delete_icon (arg)) { more = FALSE; break; } } else { if (error = delete_file (arg)) { more = FALSE; break; } } } } while (ead = ead->ed_Next); /* go to next entry */ } while (more); /* take next read from ExAll */ fail: if (arg) free (arg); else error = ERROR_NO_FREE_STORE; if (eadata) free (eadata); if (eac) FreeDosObject (DOS_EXALLCONTROL, eac); CurrentDir (old_lock); return (error); } /* delete_dir -- delete a directory from lock. lock MUST be a directory */ /* or else! Returns an error from IoErr(), or 0 for ok. */ LONG delete_dir (struct WBArg *wa) { LONG error = 0; char buf[256]; struct WBArg *parent = 0; if (error = delete_contents (wa->wa_Lock, FALSE)) goto fail; /* delete files with/without icons */ if (error = delete_contents (wa->wa_Lock, TRUE)) goto fail; /* delete any lone .info files */ if (!(parent = (struct WBArg *)malloc (sizeof (struct WBArg)))) goto fail; if (parent->wa_Lock = ParentDir (wa->wa_Lock)) { if (NameFromLock (wa->wa_Lock, buf, 254)) { UnLock (wa->wa_Lock); /* UnLock the dir as it is about to be deleted */ wa->wa_Lock = NULL; /* Tell everyone we've unlocked it. */ parent->wa_Name = FilePart (buf); set_current (NULL, SET_EXIT_DIR); error = delete_file (parent); /* delete ourselves */ if (error) /* if failed, restore lock to directory */ { BPTR olddir = CurrentDir (parent->wa_Lock); wa->wa_Lock = Lock (parent->wa_Name, SHARED_LOCK); /* fingers crossed! */ CurrentDir (olddir); } } else error = IoErr(); UnLock (parent->wa_Lock); } else error = IoErr(); fail: if (parent) free (parent); return (error); } /* delete_icon -- delete an icon with name (MUST have a .info extension) */ /* which lives in dir locked in lock */ LONG delete_icon (struct WBArg *wa) { LONG error = 0; char *dot; if (error = set_current (wa, SET_NEWFILE)) goto fail; if (dot = strrchr (wa->wa_Name, '.')) { *dot = '\0'; /* temporarily remove .info extension */ error = delete_file (wa); *dot = '.'; /* restore .info, in case it is needed later */ } else error = ERROR_OBJECT_WRONG_TYPE; fail: return (error); } /* delete_file -- delete a file or dir given a lock to the dir + a name */ /* Returns an error code from IoErr() if failed, or 0 for ok. */ LONG delete_file (struct WBArg *wa) { LONG error = 0; BOOL nofile = FALSE; if (error = set_current (wa, SET_NEWFILE)) goto fail; if ((wa->wa_Name[0] == '\0') || !(wa->wa_Name)) /* is it a directory? */ { error = delete_dir (wa); } else { /* cd to lock and store old lock */ BPTR old_lock = CurrentDir (wa->wa_Lock); if (!DeleteFile (wa->wa_Name)) /* if delete file fails */ { error = IoErr(); if ((error == ERROR_DELETE_PROTECTED) && ignore_protection) { error = 0; if (SetProtection (wa->wa_Name, 0)) { /* try again to delete it */ if (!DeleteFile (wa->wa_Name)) error = IoErr(); } else error = IoErr(); } if (error == ERROR_OBJECT_NOT_FOUND) { error = 0; nofile = TRUE; /* object is just an icon */ } } if (!error) { char dotinfo[100]; strcpy (dotinfo, wa->wa_Name); strcat (dotinfo, ".info"); /* create name of icon */ if (!DeleteDiskObject (wa->wa_Name)) /* delete icon */ { error = IoErr(); if ((error == ERROR_DELETE_PROTECTED) && ignore_protection) { error = 0; if (SetProtection (dotinfo, 0)) { /* try again */ if (!DeleteDiskObject (wa->wa_Name)) error = IoErr(); } else error = IoErr(); } /* If no icon was found and there was a file that was deleted */ if ((error == ERROR_OBJECT_NOT_FOUND) && !nofile) { BPTR fh = Open (dotinfo, MODE_NEWFILE); /* make pseudo icon */ if (fh) { Close (fh); if (!DeleteDiskObject (wa->wa_Name)) /* now delete it! */ error = IoErr(); else error = 0; } else error = IoErr(); } } } CurrentDir (old_lock); /* restore old cd */ } fail: return (error); }