33
44from __future__ import annotations
55
6+
67import os
78import sys
89import traceback
10+ import subprocess
11+ import getpass
912from datetime import datetime , date
1013from typing import Optional , Tuple , List
1114
15+
1216# Proviamo a usare anytree, se non disponibile fallback a treelib
1317USING_ANYTREE = False
1418USING_TREELIB = False
1519
1620try :
1721 from anytree import Node , PreOrderIter
1822 USING_ANYTREE = True
19- except Exception : # pragma: no cover - fallback
23+ except Exception :
2024 try :
2125 from treelib import Node as TLNode , Tree as TLTree
2226 USING_TREELIB = True
3236# ------------------------- Utility di formattazione ------------------------- #
3337
3438def sizeof_fmt (num : int ) -> str :
35- """Rende una dimensione in byte in formato leggibile (B, KB, MB, GB, TB)."""
3639 for unit in ["B" , "KB" , "MB" , "GB" , "TB" , "PB" ]:
3740 if num < 1024.0 :
3841 return f"{ num :3.1f} { unit } "
@@ -41,19 +44,12 @@ def sizeof_fmt(num: int) -> str:
4144
4245
4346def get_creation_time (path : str ) -> float :
44- """Restituisce un timestamp di creazione compatibile multi-OS.
45-
46- Windows: usa st_ctime.
47- macOS: preferisce st_birthtime se presente, altrimenti st_mtime.
48- Linux: spesso non espone il birthtime; fallback a st_mtime.
49- """
5047 try :
5148 stat = os .stat (path )
5249 if hasattr (stat , "st_birthtime" ) and stat .st_birthtime :
5350 return stat .st_birthtime
5451 return stat .st_ctime if os .name == "nt" else stat .st_mtime
5552 except Exception :
56- # Se non accessibile, usa mtime come ultima risorsa 0
5753 try :
5854 return os .path .getmtime (path )
5955 except Exception :
@@ -63,7 +59,6 @@ def get_creation_time(path: str) -> float:
6359def fmt_datetime (ts : float ) -> str :
6460 if not ts :
6561 return "-"
66- # Formato ISO locale leggibile
6762 return datetime .fromtimestamp (ts ).strftime ("%Y-%m-%d %H:%M" )
6863
6964
@@ -354,21 +349,49 @@ def render_html(root_obj, root_path: str, total_nodes: int, skipped: int) -> str
354349
355350# ------------------------------- Validazione ------------------------------- #
356351
352+ def try_mount_unc (path : str ) -> None :
353+ """Se il percorso è UNC e non accessibile, chiede credenziali e prova a montarlo con net use."""
354+ if os .name != "nt" :
355+ return # solo Windows
356+
357+ if not (path .startswith ("\\ \\ " ) or path .startswith ("//" )):
358+ return
359+
360+ # Percorso UNC non accessibile → chiediamo credenziali
361+ print (f"Il percorso { path } non è accessibile. Inserisci credenziali per la condivisione." )
362+ user = input ("Utente (DOMINIO\\ utente o utente): " ).strip ()
363+ pwd = getpass .getpass ("Password: " )
364+
365+ try :
366+ cmd = ["net" , "use" , path , pwd , f"/user:{ user } " ]
367+ result = subprocess .run (cmd , capture_output = True , text = True )
368+ if result .returncode != 0 :
369+ print ("Errore nel montaggio con net use:" , result .stderr , file = sys .stderr )
370+ else :
371+ print ("Condivisione montata con successo." )
372+ except Exception as e :
373+ print (f"Errore nell'esecuzione di net use: { e } " , file = sys .stderr )
374+
375+
357376def validate_path (p : str ) -> str :
358377 p = p .strip ().strip ('"' ).strip ("'" )
359378 if not p :
360379 raise ValueError ("Percorso vuoto." )
361380 p = os .path .expanduser (p )
362- # Accetta anche percorsi UNC (\\\\server\\share) su Windows
363381 abs_p = os .path .abspath (p )
382+
383+ if not os .path .exists (abs_p ):
384+ try_mount_unc (p )
385+
364386 if not os .path .exists (abs_p ):
365387 raise FileNotFoundError (f"Il percorso non esiste o non è accessibile: { abs_p } " )
366- # Richiediamo una directory come radice di scansione
388+
367389 if not os .path .isdir (abs_p ):
368390 raise NotADirectoryError (f"Il percorso deve essere una cartella: { abs_p } " )
369- # Controllo di accesso in lettura
391+
370392 if not os .access (abs_p , os .R_OK ):
371393 raise PermissionError (f"Permesso negato per la lettura: { abs_p } " )
394+
372395 return abs_p
373396
374397
@@ -386,7 +409,6 @@ def main():
386409 print ("Scansione in corso... Questa operazione può richiedere tempo per strutture molto grandi." )
387410 root_obj , total_nodes , skipped , errors = scan_directory (root_path )
388411
389- # Log essenziali su stderr per non inquinare STDOUT
390412 if errors :
391413 print (f"Avvisi/Errori durante la scansione: { len (errors )} " , file = sys .stderr )
392414
0 commit comments