diff --git a/src/uu/lslocks/src/lslocks.rs b/src/uu/lslocks/src/lslocks.rs
index 716d745..a2e35a3 100644
--- a/src/uu/lslocks/src/lslocks.rs
+++ b/src/uu/lslocks/src/lslocks.rs
@@ -3,12 +3,151 @@
 // For the full copyright and license information, please view the LICENSE
 // file that was distributed with this source code.
 
+use std::{fs, str::FromStr};
+
 use clap::{crate_version, Command};
 use uucore::error::UResult;
 
+// See https://www.man7.org/linux/man-pages/man5/proc_locks.5.html for details on each field's meaning
+#[derive(Debug)]
+struct Lock {
+    ord: usize,
+    lock_type: LockType,
+    strictness: Strictness,
+    variant: Variant,
+    pid: Option<usize>, // This value is -1 for OFD locks, hence the Option
+    major_minor: String,
+    inode: usize,
+    start_offset: usize,       // Byte offset to start of lock
+    end_offset: Option<usize>, // None = lock does not have an explicit end offset and applies until the end of the file
+}
+
+impl FromStr for Lock {
+    type Err = ();
+    fn from_str(input: &str) -> Result<Self, Self::Err> {
+        let mut parts = input.split_whitespace();
+
+        // Ordinal position comes in the form of `<value>:`, so we need to strip away the `:`
+        let ord = parts
+            .next()
+            .and_then(|s| s.strip_suffix(":"))
+            .unwrap()
+            .parse::<usize>()
+            .unwrap();
+        let lock_type = parts
+            .next()
+            .and_then(|part| LockType::from_str(part).ok())
+            .unwrap();
+        let strictness = parts
+            .next()
+            .and_then(|part| Strictness::from_str(part).ok())
+            .unwrap();
+        let variant = parts
+            .next()
+            .and_then(|part| Variant::from_str(part).ok())
+            .unwrap();
+        let pid: Option<usize> = parts.next().and_then(|pid_str| match pid_str {
+            "-1" => None,
+            other => other.parse::<usize>().ok(),
+        });
+
+        if lock_type == LockType::OFDLCK && pid.is_some() {
+            println!("Unexpected PID value on OFD lock: '{}'", input);
+            return Err(());
+        };
+
+        // This field has a format of MAJOR:MINOR:INODE
+        let maj_min_inode: Vec<_> = parts.next().unwrap().split(":").collect();
+        assert_eq!(maj_min_inode.len(), 3);
+        let major_minor = [maj_min_inode[0], maj_min_inode[1]].join(":");
+        let inode = maj_min_inode[2].parse::<usize>().unwrap();
+
+        let start_offset = parts.next().unwrap().parse::<usize>().unwrap();
+        let end_offset: Option<usize> = parts.next().and_then(|offset_str| match offset_str {
+            "EOF" => None,
+            other => other.parse::<usize>().ok(),
+        });
+
+        Ok(Self {
+            ord,
+            lock_type,
+            strictness,
+            variant,
+            pid,
+            major_minor,
+            inode,
+            start_offset,
+            end_offset,
+        })
+    }
+}
+
+#[derive(Debug, PartialEq, Eq)]
+enum LockType {
+    FLOCK,  // BSD file lock
+    OFDLCK, // Open file descriptor
+    POSIX,  // POSIX byte-range lock
+}
+
+impl FromStr for LockType {
+    type Err = ();
+    fn from_str(input: &str) -> Result<Self, Self::Err> {
+        match input {
+            "FLOCK" => Ok(Self::FLOCK),
+            "OFDLCK" => Ok(Self::OFDLCK),
+            "POSIX" => Ok(Self::POSIX),
+            _ => Err(()),
+        }
+    }
+}
+
+#[derive(Debug)]
+enum Strictness {
+    Advisory,
+    Mandatory,
+}
+
+impl FromStr for Strictness {
+    type Err = ();
+    fn from_str(input: &str) -> Result<Self, Self::Err> {
+        match input {
+            "ADVISORY" => Ok(Self::Advisory),
+            "MANDATORY" => Ok(Self::Mandatory),
+            _ => Err(()),
+        }
+    }
+}
+
+#[derive(Debug)]
+enum Variant {
+    Read,
+    Write,
+}
+
+impl FromStr for Variant {
+    type Err = ();
+    fn from_str(input: &str) -> Result<Self, Self::Err> {
+        match input {
+            "WRITE" => Ok(Self::Write),
+            "READ" => Ok(Self::Read),
+            _ => Err(()),
+        }
+    }
+}
+
 #[uucore::main]
 pub fn uumain(_args: impl uucore::Args) -> UResult<()> {
-    println!("lslocks: Hello world");
+    let locks: Vec<_> = match fs::read_to_string("/proc/locks") {
+        Ok(content) => content
+            .lines()
+            .map(|line| Lock::from_str(line).unwrap())
+            .collect(),
+        Err(e) => panic!("Could not read /proc/locks: {}", e),
+    };
+
+    for lock in locks {
+        println!("{:?}", lock);
+    }
     Ok(())
 }