#help_index "File/Program Routines"

U0 OFFlatten(LTDirEntry *tempm,LTDirEntry **a,I8 *i)
{
  LTDirEntry *tempm1;
  while (tempm) {
    tempm1=tempm->next;
    if (tempm->attr&LT_ATTR_DIR) {
      OFFlatten(tempm->sub,a,i);
      LTDirEntryDel(tempm);
    } else {
      a[*i]=tempm;
      *i=*i+1;
    }
    tempm=tempm1;
  }
}


public I8 LTFileCnt(LTDirEntry *tempm)
{
  I8 cnt=0;
  while (tempm) {
    if (tempm->attr&LT_ATTR_DIR)
      cnt+=LTFileCnt(tempm->sub);
    else
      cnt++;
    tempm=tempm->next;
  }
  return cnt;
}

I8 OFCompare(LTDirEntry *e1,LTDirEntry *e2)
{
  return e1->cluster-e2->cluster;
}

public LTDirEntry **FilesOrder(LTDirEntry *tempm,I8 *_cnt=NULL)
{ //See ::/LT/Demo/Disk/OrderedIO.CPZ.
  I8 cnt=LTFileCnt(tempm),i=0;
  LTDirEntry **a=MAlloc(sizeof(LTDirEntry *)*cnt);
  OFFlatten(tempm,a,&i);
  QSortU8(a,cnt,&OFCompare);
  if (_cnt) *_cnt=cnt;
  return a;
}


#help_index "File/Cmd Line (Typically);Cmd Line (Typically)"

public BoolI8 Copy(U1 *f1,U1 *f2=".")
{
  BoolI1 result=TRUE;
  LTFileAccess *fa;
  LTDirEntry *tempm,*tempm1;
  U1 *st;
  if (!(tempm=FilesFind(f1,0)))
    return FALSE;
  if (IsDir(f2)) {
    fa=LTFileAccessNew(f2,TRUE);
    if (fa) {
      while (tempm) {
        tempm1=tempm->next;
        if (!(tempm->attr & LT_ATTR_DIR)) {
          st=FileNameAbs(tempm->name);
          if (!CopySingle(tempm->full_name,st))
            result=FALSE;
          Free(st);
        }
        LTDirEntryDel(tempm);
        tempm=tempm1;
      }
      LTFileAccessDel(fa);
    }
    return result;
  } else
    return CopySingle(f1,f2);
}

public BoolI8 Move(U1 *f1,U1 *f2)
{
  if (Copy(f1,f2)) {
    Del(f1);
    return TRUE;
  }
  return FALSE;
}

U8 PutCopyTree(LTDirEntry *tempm,U8 src_dir_len,U8 dst_dir_len,U1 *dst_dir)
{
  U8 result=1;
  U1 *st;
  while (tempm) {
    st=MAlloc(StrLen(tempm->full_name)+dst_dir_len+2);
    MemCpy(st,dst_dir,dst_dir_len);
    StrCpy(st+dst_dir_len,tempm->full_name+src_dir_len);
    if (tempm->attr & LT_ATTR_DIR) {
      MkDir(st);
      result+=PutCopyTree(tempm->sub,src_dir_len,dst_dir_len,dst_dir);
    } else
      if (CopySingle(tempm->full_name,st))
        result++;
    Free(st);
    tempm=tempm->next;
  }
  return result;
}

public U8 CopyTree(U1 *src_mask,U1 *dst_mask)
{  //returns count of copied files (not dirs)
  LTFileAccess *fa;
  LTDirEntry *tempm=NULL;
  U8 result=0,i1,i2;
  U1 *st1,*st2;

  st1=DirNameAbs(src_mask);
  st2=DirNameAbs(dst_mask);
  i1=StrLen(st1);
  if (!StrNCmp(st1,st2,i1) && (st2[i1]=='/' || !st2[i1]) ) {
    Free(st1);
    Free(st2);
    return 0;
  }
  Free(st1);
  Free(st2);

  fa=LTFileAccessNew(src_mask,TRUE);
  if (fa) {
    tempm=SysFilesFind(fa->mask,1<<FUf_RECURSE);
    st1=CurDir;
    LTFileAccessDel(fa);
    i1=StrLen(st1);
    if (i1==3) i1--;

    fa=LTFileAccessNew(dst_mask,TRUE,TRUE);
    if (fa) {
      st2=CurDir;
      i2=StrLen(st2);
      if (i2==3) i2--;
      result=PutCopyTree(tempm,i1,i2,st2);
      LTFileAccessDel(fa);
      Free(st2);
    }
    LTDirListDel(tempm);
    Free(st1);
  }
  return result;
}

U0 DelTreeDirs(LTDirEntry *tempm1)
{
  LTDirEntry *tempm2;
  while (tempm1) {
    tempm2=tempm1->next;
    if (tempm1->attr & LT_ATTR_DIR) {
      if (tempm1->sub)
        DelTreeDirs(tempm1->sub);
      SysDel(tempm1->full_name,TRUE);
    }
    LTDirEntryDel(tempm1);
    tempm1=tempm2;
  }
}

U0 DelTreeFiles(LTDirEntry *tempm1)
{
  LTDirEntry *tempm2;
  while (tempm1) {
    tempm2=tempm1->next;
    if (tempm1->attr & LT_ATTR_DIR) {
      if (tempm1->sub)
        DelTreeFiles(tempm1->sub);
    } else
      SysDel(tempm1->full_name,FALSE);
    LTDirEntryDel(tempm1);
    tempm1=tempm2;
  }
}

public U0 DelTree(U1 *mask)
{
  if (IsDir(mask)) {
    DelTreeDirs(FilesFind(mask,1<<FUf_RECURSE));
    SysDel(mask,TRUE);
    SysDel(mask,FALSE);
  } else
    DelTreeFiles(FilesFind(mask,1<<FUf_RECURSE));
}

U0 TouchFile(U1 *filename,U1 *attr,LTDate dt=0) //Just one file
{
  U1 *cur_dir=StrNew(filename);
  LTPartition *p=Drive2Partition(*filename);
  LTDirEntry de;
  U1 buf[64];
  if (FileFind(filename,&de,FALSE,TRUE)) {
    if (!StrCmp(attr,"+?"))
      PrintF("%-32ts %s\r\n",filename,SPrintFFlags(buf,Define("ST_FILE_ATTRS"),de.attr));
    else {
      StrFirstRem(cur_dir,":");
      StrLastRem(cur_dir,"/");
      if (!*cur_dir)
        StrCpy(cur_dir,"/");
      GetFFlags(&de.attr,Define("ST_FILE_ATTRS"),attr);
      if (dt)
        de.datetime=dt;
      else
        de.datetime=GetCurTimeLTDate;
      LTDirEntryNew(p,cur_dir,&de,FALSE);
    }
  } else PutDefineErr("ST_FILE_NOT_FOUND");
}

U0 TouchList(LTDirEntry *tempm1,U1 *attr,LTDate dt=0)
{
  LTDirEntry *tempm2;
  while (tempm1) {
    tempm2=tempm1->next;
    if (tempm1->attr & LT_ATTR_DIR) {
      if (tempm1->sub) {
        coutln Define("ST_SCANNING_DIR"),tempm1->full_name;
        TouchList(tempm1->sub,attr,dt);
      }
    } else
      TouchFile(tempm1->full_name,attr,dt);
    LTDirEntryDel(tempm1);
    tempm1=tempm2;
  }
}

//Attr "+?" =show
//     "+T" = resident
//flags "+r"=recurse
public U0 Touch(U1 *wild,U1 *attr="+?",U1 *flags=NULL,LTDate dt=0)
{
  U8 f=0;
  GetFFlags(&f,Define("ST_FILE_UTIL_FLAGS"),flags);
  TouchList(FilesFind(wild,f),attr,dt);
}

U8 FFList(LTDirEntry *tempm1)
{
  U8 cnt=0;
  LTDirEntry *tempm2;

  while (tempm1) {
    tempm2=tempm1->next;
    if (tempm1->attr & LT_ATTR_DIR) {
      if (tempm1->sub)
        cnt+=FFList(tempm1->sub);
    } else {
      PutFileLink(tempm1->full_name);
      CrLf;
      cnt++;
    }
    LTDirEntryDel(tempm1);
    tempm1=tempm2;
  }
  return cnt;
}

public U8 FF(U1 *wild,U1 *flags=NULL)
//Files Find
//"+r"=recurse
{
  U8 cnt=0,f=0;
  GetFFlags(&f,Define("ST_FILE_UTIL_FLAGS"),"+r");
  GetFFlags(&f,Define("ST_FILE_UTIL_FLAGS"),flags);
  cnt+=FFList(FilesFind(wild,f));
  return cnt;
}

public U0 SetDriveTextAttr(U1 drive_letter=0,U1 attr)
{ //This is to color the border text according to the current drive
  LTPartition *p;
  try {
    p=Drive2Partition(drive_letter);
    p->text_attr=attr;
  } catch
    Fs->catch_except=TRUE;
}

U0 PrintFDriveTextAttr(U1 drive_letter=0)
{
  LTPartition *p=Drive2Partition(drive_letter);
  U1 fg=p->text_attr&0xF,bg=p->text_attr>>4;
  if (fg!=bg)
    PrintF("$$FG,%d$$$$BG,%d$$",fg,bg);
}

I8 LTFSUnusedDriveSpace(U1 drive_letter=0)
{
  LTPartition *p=Drive2Partition(drive_letter);
  U8 result=0,i,l;
  U1 *bitmap;
  try {
    l=(p->size+p->spc-1)/p->spc;
    i=((l+7)>>3+BLK_SIZE-1)>>BLK_SIZE_BITS;
    bitmap=MAlloc(i<<BLK_SIZE_BITS);
    RBlks(p,bitmap,p->map1,i);
    for (i=0;i<l;i++)
      if (!Bt(bitmap,i))
        result++;
    Free(bitmap);
  } catch
    PartitionUnlock(p);
  return result*BLK_SIZE*p->spc;
}

I8 FAT32UnusedDriveSpace(U1 drive_letter=0)
{
  LTPartition *p=Drive2Partition(drive_letter);
  U8 result=0,i,l;
  U4 *bitmap;
  try {
    l=(p->size+p->spc-1)/p->spc;
    i=(l*4+BLK_SIZE-1)>>BLK_SIZE_BITS;
    bitmap=MAlloc(i<<BLK_SIZE_BITS);
    RBlks(p,bitmap,p->map1,i);
    for (i=0;i<l;i++)
      if (!bitmap[i])
        result++;
    Free(bitmap);
  } catch
    PartitionUnlock(p);
  return result*BLK_SIZE*p->spc;
}

public I8 UnusedDriveSpace(U1 drive_letter=0)
{ //returns size in bytes
  I8 result=0;
  LTPartition *p=Drive2Partition(drive_letter),*p_old=Fs->cur_partition;
  Drive(drive_letter);
  switch (p->type) {
    case PT_LT:
      result=LTFSUnusedDriveSpace(drive_letter);
      break;
    case PT_FAT32:
      result=FAT32UnusedDriveSpace(drive_letter);
      break;
    default:
      PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
  }
  Drive(Partition2Drive(p_old));
  return result;
}

#help_index "File/Program Routines"

U8 TreeSizeFiles(LTDirEntry *tempm,U8 f,I8 round_to)
{
  U8 result=0,i;
  while (tempm) {
    if (round_to)
      i=RoundUpU8(tempm->size,round_to);
    else
      i=tempm->size;
    if (tempm->attr&LT_ATTR_DIR)
      i+=TreeSizeFiles(tempm->sub,f,round_to);
    tempm->user_data=i;
    result+=i;
    tempm=tempm->next;
  }
  return result;
}

public U8 TreeSize(U1 *src_mask="/LT/*",U1 *flags=NULL,I8 round_to=0)
//+r=recurse
{
//Does not include directory size of base directory, but
//does include size of sub directories.
  U8 f=0,result=0;
  LTDirEntry *tempm1=NULL;
  GetFFlags(&f,Define("ST_FILE_UTIL_FLAGS"),"+r");
  GetFFlags(&f,Define("ST_FILE_UTIL_FLAGS"),flags);

  if (tempm1=FilesFind(src_mask,f)) {
    result=TreeSizeFiles(tempm1,f,round_to);
    LTDirListDel(tempm1);
  }
  return result;
}

#help_index ""
Historical capture: 2010-02-13. Home | Power on LoseThos | Sources and changes