
    \j                    *   U d dl mZ d dlZd dlZd dlZd dlZd dlmZmZm	Z	 d dl
mZ d dlmZ ddZddZddZdd	Zdd
ddZej&                  dk7  xr ej(                  ej*                  v Zded<   ej(                  ej0                  v Zded<   g dZy)    )annotationsN)EACCESEIOEISDIR)Path)Finalc                    t        |      }|r4t        j                  | |      x}dk(  rt        t        d      ||d }|r3yy)ac  
    Write the whole buffer to *fd*, looping over the short writes ``os.write`` is allowed to make.

    A marker written with a bare ``os.write`` can land partially: a peer reading it mid-write parses a truncated record
    as malformed or as a foreign holder. Looping until the buffer drains keeps the record atomic in the process and
    kernel view. No ``fsync``: filelock needs a complete record, not crash-durable storage.

    :param fd: file descriptor open for writing.
    :param data: bytes to write in full.

    :raises OSError: if a write reports zero progress before the record is complete.

    r   z5os.write wrote 0 bytes before the record was completeN)
memoryviewoswriteOSErrorr   )fddata	remainingwrittens       A/root/.hermes/venv/lib/python3.12/site-packages/filelock/_util.py	write_allr      sH     4 I
xxI..G14#VWWgh'	     c                R   	 t        j                  |       }|j                  t        j
                  z  st        t        d|       t	        j                  |j                        r5t        j                  dk(  rt        t        d|       t        t        d|       y# t        $ r Y yw xY w)a  
    Raise an exception if attempting to open the file for writing would fail.

    Separates files that can never be written from files that are writable but currently locked.

    :param filename: file to check

    :raises OSError: as if the file was opened for writing.

    NzPermission deniedwin32zIs a directory)r   lstatr   st_modestatS_IWUSRPermissionErrorr   S_ISDIRsysplatformIsADirectoryErrorr   )filename	file_stats     r   raise_on_not_writable_filer"   !   s    
 HHX&	 ,f&98DD||I%%&<<7"!&*=xHH(8(CC '  s   B 	B&%B&c                P    t        |       j                  j                  dd       y)zp
    Ensure the directory containing the file exists (create it if necessary).

    :param filename: file.

    T)parentsexist_okN)r   parentmkdir)r    s    r   ensure_directory_existsr(   A   s!     	Nt<r   c                P   |  dt        j                          dt        j                  d       }t	        |       j                  |       	 t        j                  |      }|j                  |kD  s|j                  |k7  ryt	        |      j                          y# t        $ r Y yw xY w)aA  
    Atomically break a stale lock file judged stale at modification time *mtime_before*.

    Rename the file to a process-private name before unlinking it, so two processes breaking the same lock cannot
    delete each other's work: only one rename of a given inode wins, the loser gets ``OSError``. After the rename,
    re-check the file. A newer modification time, or a different inode than *ino_before*, means a peer recreated the
    lock between the stale decision and the rename, so we grabbed a live file and abort, leaving the renamed file in
    place. A rollback rename is itself racy, the same trade-off as the soft read/write marker break. The inode check
    matters because filesystems with coarse modification-time granularity (NFS, FAT) can give a same-second recreation
    the old mtime, so mtime alone would miss it and unlink a live lock; the inode is the reliable identity, mirroring
    the token re-check in the soft read/write marker break. ``lstat`` avoids following a hostile symlink swapped in
    after the decision.

    The break name carries a random token so it is unguessable and unique per attempt. Without it two breakers in the
    same process share ``<lock>.break.<pid>``, and a second break can rename a recreated live lock onto that path in
    the window between the re-verify ``lstat`` above and the ``unlink`` below, deleting a live lock the inode check
    just approved. A private name keeps anyone else from targeting our break path, matching the soft read/write marker
    break.

    :param lock_file: path to the lock file to break.
    :param mtime_before: modification time observed when the lock was judged stale.
    :param ino_before: inode number observed when the lock was judged stale.

    :raises OSError: if the rename fails (e.g. the file vanished or is not owned in a sticky directory).

    z.break..   N)r   getpidsecrets	token_hexr   renamer   r   st_mtimest_inounlink)	lock_filemtime_before
ino_before
break_pathst_afters        r   break_lock_filer8   K   s    6 ;gbiik]!G4E4Eb4I3JKJO:&88J' <'8??j+H	  s   B 	B%$B%)r   c               |    |t         rt        j                  |d        y t        j                  | d t                y )N)follow_symlinks)_SUPPORTS_UTIME_FDr   utime_SUPPORTS_UTIME_NOFOLLOW)namer   s     r   touchr?   q   s1    
 
~,
THHT4-E)EFr   r   zFinal[bool]r;   r=   )r8   r(   r"   r?   r   )r   intr   bytesreturnNone)r    strrB   rC   )r    z
Path | strrB   rC   )r3   rD   r4   floatr5   r@   rB   rC   )r>   rD   r   z
int | NonerB   rC   )
__future__r   r   r-   r   r   errnor   r   r   pathlibr   typingr   r   r"   r(   r8   r?   r   r<   supports_fdr;   __annotations__supports_follow_symlinksr=   __all__ r   r   <module>rO      s    " 	   
 % %  (*D@=#L *. G #&,,'"9"Xbhh"..>X K X(*B4O4O(O + Or   